Skip to content

Commit a0d2d9f

Browse files
committed
implied bounds byebye nested hir ids
1 parent e78e0e2 commit a0d2d9f

File tree

7 files changed

+28
-129
lines changed

7 files changed

+28
-129
lines changed

compiler/rustc_infer/src/infer/outlives/env.rs

+10-78
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::infer::free_regions::FreeRegionMap;
22
use crate::infer::{GenericKind, InferCtxt};
33
use crate::traits::query::OutlivesBound;
4-
use rustc_data_structures::fx::FxHashMap;
5-
use rustc_hir as hir;
64
use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
75

86
use super::explicit_outlives_bounds;
@@ -31,9 +29,7 @@ pub struct OutlivesEnvironment<'tcx> {
3129
pub param_env: ty::ParamEnv<'tcx>,
3230
free_region_map: FreeRegionMap<'tcx>,
3331

34-
// Contains, for each body B that we are checking (that is, the fn
35-
// item, but also any nested closures), the set of implied region
36-
// bounds that are in scope in that particular body.
32+
// Contains the implied region bounds in scope for our current body.
3733
//
3834
// Example:
3935
//
@@ -43,24 +39,15 @@ pub struct OutlivesEnvironment<'tcx> {
4339
// } // body B0
4440
// ```
4541
//
46-
// Here, for body B0, the list would be `[T: 'a]`, because we
42+
// Here, when checking the body B0, the list would be `[T: 'a]`, because we
4743
// infer that `T` must outlive `'a` from the implied bounds on the
4844
// fn declaration.
4945
//
50-
// For the body B1, the list would be `[T: 'a, T: 'b]`, because we
46+
// For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
5147
// also can see that -- within the closure body! -- `T` must
5248
// outlive `'b`. This is not necessarily true outside the closure
5349
// body, since the closure may never be called.
54-
//
55-
// We collect this map as we descend the tree. We then use the
56-
// results when proving outlives obligations like `T: 'x` later
57-
// (e.g., if `T: 'x` must be proven within the body B1, then we
58-
// know it is true if either `'a: 'x` or `'b: 'x`).
59-
region_bound_pairs_map: FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
60-
61-
// Used to compute `region_bound_pairs_map`: contains the set of
62-
// in-scope region-bound pairs thus far.
63-
region_bound_pairs_accum: RegionBoundPairs<'tcx>,
50+
region_bound_pairs: RegionBoundPairs<'tcx>,
6451
}
6552

6653
/// "Region-bound pairs" tracks outlives relations that are known to
@@ -73,8 +60,7 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
7360
let mut env = OutlivesEnvironment {
7461
param_env,
7562
free_region_map: Default::default(),
76-
region_bound_pairs_map: Default::default(),
77-
region_bound_pairs_accum: vec![],
63+
region_bound_pairs: Default::default(),
7864
};
7965

8066
env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
@@ -87,62 +73,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
8773
&self.free_region_map
8874
}
8975

90-
/// Borrows current value of the `region_bound_pairs`.
91-
pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>> {
92-
&self.region_bound_pairs_map
93-
}
94-
95-
/// This is a hack to support the old-school regionck, which
96-
/// processes region constraints from the main function and the
97-
/// closure together. In that context, when we enter a closure, we
98-
/// want to be able to "save" the state of the surrounding a
99-
/// function. We can then add implied bounds and the like from the
100-
/// closure arguments into the environment -- these should only
101-
/// apply in the closure body, so once we exit, we invoke
102-
/// `pop_snapshot_post_typeck_child` to remove them.
103-
///
104-
/// Example:
105-
///
106-
/// ```ignore (pseudo-rust)
107-
/// fn foo<T>() {
108-
/// callback(for<'a> |x: &'a T| {
109-
/// // ^^^^^^^ not legal syntax, but probably should be
110-
/// // within this closure body, `T: 'a` holds
111-
/// })
112-
/// }
113-
/// ```
114-
///
115-
/// This "containment" of closure's effects only works so well. In
116-
/// particular, we (intentionally) leak relationships between free
117-
/// regions that are created by the closure's bounds. The case
118-
/// where this is useful is when you have (e.g.) a closure with a
119-
/// signature like `for<'a, 'b> fn(x: &'a &'b u32)` -- in this
120-
/// case, we want to keep the relationship `'b: 'a` in the
121-
/// free-region-map, so that later if we have to take `LUB('b,
122-
/// 'a)` we can get the result `'b`.
123-
///
124-
/// I have opted to keep **all modifications** to the
125-
/// free-region-map, however, and not just those that concern free
126-
/// variables bound in the closure. The latter seems more correct,
127-
/// but it is not the existing behavior, and I could not find a
128-
/// case where the existing behavior went wrong. In any case, it
129-
/// seems like it'd be readily fixed if we wanted. There are
130-
/// similar leaks around givens that seem equally suspicious, to
131-
/// be honest. --nmatsakis
132-
pub fn push_snapshot_pre_typeck_child(&self) -> usize {
133-
self.region_bound_pairs_accum.len()
134-
}
135-
136-
/// See `push_snapshot_pre_typeck_child`.
137-
pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) {
138-
self.region_bound_pairs_accum.truncate(len);
139-
}
140-
141-
/// Save the current set of region-bound pairs under the given `body_id`.
142-
pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
143-
let old =
144-
self.region_bound_pairs_map.insert(body_id, self.region_bound_pairs_accum.clone());
145-
assert!(old.is_none());
76+
/// Borrows current `region_bound_pairs`.
77+
pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
78+
&self.region_bound_pairs
14679
}
14780

14881
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
@@ -164,11 +97,10 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
16497
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
16598
match outlives_bound {
16699
OutlivesBound::RegionSubParam(r_a, param_b) => {
167-
self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b)));
100+
self.region_bound_pairs.push((r_a, GenericKind::Param(param_b)));
168101
}
169102
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
170-
self.region_bound_pairs_accum
171-
.push((r_a, GenericKind::Projection(projection_b)));
103+
self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b)));
172104
}
173105
OutlivesBound::RegionSubRegion(r_a, r_b) => {
174106
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {

compiler/rustc_infer/src/infer/outlives/obligations.rs

+10-19
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,17 @@
6060
//! imply that `'b: 'a`.
6161
6262
use crate::infer::outlives::components::{push_outlives_components, Component};
63+
use crate::infer::outlives::env::OutlivesEnvironment;
6364
use crate::infer::outlives::env::RegionBoundPairs;
6465
use crate::infer::outlives::verify::VerifyBoundCx;
6566
use crate::infer::{
6667
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
6768
};
6869
use crate::traits::{ObligationCause, ObligationCauseCode};
69-
use rustc_middle::ty::subst::GenericArgKind;
70-
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
71-
72-
use crate::infer::outlives::env::OutlivesEnvironment;
73-
use rustc_data_structures::fx::FxHashMap;
7470
use rustc_data_structures::undo_log::UndoLogs;
7571
use rustc_hir as hir;
72+
use rustc_middle::ty::subst::GenericArgKind;
73+
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
7674
use smallvec::smallvec;
7775

7876
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
@@ -145,10 +143,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
145143
/// - `param_env` is the parameter environment for the enclosing function.
146144
/// - `body_id` is the body-id whose region obligations are being
147145
/// processed.
148-
#[instrument(level = "debug", skip(self, region_bound_pairs_map))]
146+
#[instrument(level = "debug", skip(self, region_bound_pairs))]
149147
pub fn process_registered_region_obligations(
150148
&self,
151-
region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
149+
region_bound_pairs: &RegionBoundPairs<'tcx>,
152150
param_env: ty::ParamEnv<'tcx>,
153151
) {
154152
assert!(
@@ -158,24 +156,17 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
158156

159157
let my_region_obligations = self.take_registered_region_obligations();
160158

161-
for (body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations {
159+
for (_body_id, RegionObligation { sup_type, sub_region, origin }) in my_region_obligations {
162160
debug!(
163161
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
164162
sup_type, sub_region, origin
165163
);
166164

167165
let sup_type = self.resolve_vars_if_possible(sup_type);
168166

169-
if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
170-
let outlives =
171-
&mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
172-
outlives.type_must_outlive(origin, sup_type, sub_region);
173-
} else {
174-
self.tcx.sess.delay_span_bug(
175-
origin.span(),
176-
&format!("no region-bound-pairs for {:?}", body_id),
177-
);
178-
}
167+
let outlives =
168+
&mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
169+
outlives.type_must_outlive(origin, sup_type, sub_region);
179170
}
180171
}
181172

@@ -184,7 +175,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
184175
outlives_env: &OutlivesEnvironment<'tcx>,
185176
) {
186177
self.process_registered_region_obligations(
187-
outlives_env.region_bound_pairs_map(),
178+
outlives_env.region_bound_pairs(),
188179
outlives_env.param_env,
189180
);
190181

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
212212
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
213213
}
214214

215-
let body_id_map: FxHashMap<_, _> = infcx
216-
.inner
217-
.borrow()
218-
.region_obligations()
219-
.iter()
220-
.map(|&(id, _)| (id, vec![]))
221-
.collect();
222-
223-
infcx.process_registered_region_obligations(&body_id_map, full_env);
215+
infcx.process_registered_region_obligations(&Default::default(), full_env);
224216

225217
let region_data = infcx
226218
.inner

compiler/rustc_trait_selection/src/traits/coherence.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::traits::{
1616
//use rustc_data_structures::fx::FxHashMap;
1717
use rustc_errors::Diagnostic;
1818
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
19-
use rustc_hir::CRATE_HIR_ID;
2019
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
2120
use rustc_infer::traits::{util, TraitEngine};
2221
use rustc_middle::traits::specialization_graph::OverlapMode;
@@ -394,17 +393,9 @@ fn resolve_negative_obligation<'cx, 'tcx>(
394393
return false;
395394
}
396395

397-
let mut outlives_env = OutlivesEnvironment::new(param_env);
398-
// FIXME -- add "assumed to be well formed" types into the `outlives_env`
399-
400-
// "Save" the accumulated implied bounds into the outlives environment
401-
// (due to the FIXME above, there aren't any, but this step is still needed).
402-
// The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used
403-
// by the "dummy" causes elsewhere (body-id is only relevant when checking
404-
// function bodies with closures).
405-
outlives_env.save_implied_bounds(CRATE_HIR_ID);
406-
407-
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env);
396+
// FIXME -- also add "assumed to be well formed" types into the `outlives_env`
397+
let outlives_env = OutlivesEnvironment::new(param_env);
398+
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
408399

409400
let errors = infcx.resolve_regions(&outlives_env);
410401

compiler/rustc_typeck/src/check/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,7 @@ fn check_opaque_meets_bounds<'tcx>(
737737
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
738738
// Can have different predicates to their defining use
739739
hir::OpaqueTyOrigin::TyAlias => {
740-
let mut outlives_environment = OutlivesEnvironment::new(param_env);
741-
outlives_environment.save_implied_bounds(hir_id);
740+
let outlives_environment = OutlivesEnvironment::new(param_env);
742741
infcx.check_region_obligations_and_report_errors(&outlives_environment);
743742
}
744743
}

compiler/rustc_typeck/src/check/compare_method.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ fn compare_predicate_entailment<'tcx>(
403403
// lifetime parameters.
404404
let mut outlives_environment = OutlivesEnvironment::new(param_env);
405405
outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
406-
outlives_environment.save_implied_bounds(impl_m_hir_id);
407406
infcx.check_region_obligations_and_report_errors(&outlives_environment);
408407

409408
Ok(())
@@ -1159,8 +1158,7 @@ pub(crate) fn compare_const_impl<'tcx>(
11591158
return;
11601159
}
11611160

1162-
let mut outlives_environment = OutlivesEnvironment::new(param_env);
1163-
outlives_environment.save_implied_bounds(impl_c_hir_id);
1161+
let outlives_environment = OutlivesEnvironment::new(param_env);
11641162
infcx.resolve_regions_and_report_errors(&outlives_environment);
11651163
});
11661164
}
@@ -1279,8 +1277,7 @@ fn compare_type_predicate_entailment<'tcx>(
12791277

12801278
// Finally, resolve all regions. This catches wily misuses of
12811279
// lifetime parameters.
1282-
let mut outlives_environment = OutlivesEnvironment::new(param_env);
1283-
outlives_environment.save_implied_bounds(impl_ty_hir_id);
1280+
let outlives_environment = OutlivesEnvironment::new(param_env);
12841281
infcx.check_region_obligations_and_report_errors(&outlives_environment);
12851282

12861283
Ok(())
@@ -1514,7 +1511,6 @@ pub fn check_type_bounds<'tcx>(
15141511
};
15151512
let mut outlives_environment = OutlivesEnvironment::new(param_env);
15161513
outlives_environment.add_implied_bounds(infcx, implied_bounds, impl_ty_hir_id);
1517-
outlives_environment.save_implied_bounds(impl_ty_hir_id);
15181514
infcx.check_region_obligations_and_report_errors(&outlives_environment);
15191515

15201516
Ok(())

compiler/rustc_typeck/src/check/wfcheck.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
6565

6666
let mut outlives_environment = OutlivesEnvironment::new(param_env);
6767
outlives_environment.add_implied_bounds(&fcx.infcx, wf_tys, id);
68-
outlives_environment.save_implied_bounds(id);
6968
fcx.infcx.check_region_obligations_and_report_errors(&outlives_environment);
7069
});
7170
}
@@ -660,8 +659,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
660659
tcx.infer_ctxt().enter(|infcx| {
661660
let mut outlives_environment = OutlivesEnvironment::new(param_env);
662661
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
663-
outlives_environment.save_implied_bounds(id);
664-
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
662+
let region_bound_pairs = outlives_environment.region_bound_pairs();
665663

666664
add_constraints(&infcx, region_bound_pairs);
667665

0 commit comments

Comments
 (0)