Skip to content

Commit 84563da

Browse files
committed
build up a map of the region-bound pairs for each body-id
Presently unused.
1 parent 1fb4ea9 commit 84563da

File tree

2 files changed

+63
-11
lines changed

2 files changed

+63
-11
lines changed

src/librustc/infer/outlives/env.rs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
use infer::outlives::free_region_map::FreeRegionMap;
1212
use infer::{GenericKind, InferCtxt};
13-
use traits::query::outlives_bounds::{self, OutlivesBound};
14-
use ty::{self, Ty};
15-
13+
use rustc_data_structures::fx::FxHashMap;
1614
use syntax::ast;
1715
use syntax_pos::Span;
16+
use traits::query::outlives_bounds::{self, OutlivesBound};
17+
use ty::{self, Ty};
1818

1919
/// The `OutlivesEnvironment` collects information about what outlives
2020
/// what in a given type-checking setting. For example, if we have a
@@ -39,15 +39,51 @@ use syntax_pos::Span;
3939
pub struct OutlivesEnvironment<'tcx> {
4040
param_env: ty::ParamEnv<'tcx>,
4141
free_region_map: FreeRegionMap<'tcx>,
42-
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
42+
43+
// Contains, for each body B that we are checking (that is, the fn
44+
// item, but also any nested closures), the set of implied region
45+
// bounds that are in scope in that particular body.
46+
//
47+
// Example:
48+
//
49+
// ```
50+
// fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
51+
// bar(x, y, |y: &'b T| { .. } // body B1)
52+
// } // body B0
53+
// ```
54+
//
55+
// Here, for body B0, the list would be `[T: 'a]`, because we
56+
// infer that `T` must outlive `'a` from the implied bounds on the
57+
// fn declaration.
58+
//
59+
// For the body B1, the list would be `[T: 'a, T: 'b]`, because we
60+
// also can see that -- within the closure body! -- `T` must
61+
// outlive `'b`. This is not necessarily true outside the closure
62+
// body, since the closure may never be called.
63+
//
64+
// We collect this map as we descend the tree. We then use the
65+
// results when proving outlives obligations like `T: 'x` later
66+
// (e.g., if `T: 'x` must be proven within the body B1, then we
67+
// know it is true if either `'a: 'x` or `'b: 'x`).
68+
region_bound_pairs_map: FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
69+
70+
// Used to compute `region_bound_pairs_map`: contains the set of
71+
// in-scope region-bound pairs thus far.
72+
region_bound_pairs_accum: RegionBoundPairs<'tcx>,
4373
}
4474

75+
/// "Region-bound pairs" tracks outlives relations that are known to
76+
/// be true, either because of explicit where clauses like `T: 'a` or
77+
/// because of implied bounds.
78+
pub type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
79+
4580
impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
4681
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
4782
let mut env = OutlivesEnvironment {
4883
param_env,
4984
free_region_map: FreeRegionMap::new(),
50-
region_bound_pairs: vec![],
85+
region_bound_pairs_map: FxHashMap::default(),
86+
region_bound_pairs_accum: vec![],
5187
};
5288

5389
env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env));
@@ -62,7 +98,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
6298

6399
/// Borrows current value of the `region_bound_pairs`.
64100
pub fn region_bound_pairs(&self) -> &[(ty::Region<'tcx>, GenericKind<'tcx>)] {
65-
&self.region_bound_pairs
101+
&self.region_bound_pairs_accum
66102
}
67103

68104
/// Returns ownership of the `free_region_map`.
@@ -108,12 +144,12 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
108144
/// similar leaks around givens that seem equally suspicious, to
109145
/// be honest. --nmatsakis
110146
pub fn push_snapshot_pre_closure(&self) -> usize {
111-
self.region_bound_pairs.len()
147+
self.region_bound_pairs_accum.len()
112148
}
113149

114150
/// See `push_snapshot_pre_closure`.
115151
pub fn pop_snapshot_post_closure(&mut self, len: usize) {
116-
self.region_bound_pairs.truncate(len);
152+
self.region_bound_pairs_accum.truncate(len);
117153
}
118154

119155
/// This method adds "implied bounds" into the outlives environment.
@@ -149,6 +185,15 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
149185
}
150186
}
151187

188+
/// Save the current set of region-bound pairs under the given `body_id`.
189+
pub fn save_implied_bounds(&mut self, body_id: ast::NodeId) {
190+
let old = self.region_bound_pairs_map.insert(
191+
body_id,
192+
self.region_bound_pairs_accum.clone(),
193+
);
194+
assert!(old.is_none());
195+
}
196+
152197
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
153198
///
154199
/// The `infcx` parameter is optional; if the implied bounds may
@@ -174,11 +219,11 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
174219
.add_given(r_a, vid_b);
175220
}
176221
OutlivesBound::RegionSubParam(r_a, param_b) => {
177-
self.region_bound_pairs
222+
self.region_bound_pairs_accum
178223
.push((r_a, GenericKind::Param(param_b)));
179224
}
180225
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
181-
self.region_bound_pairs
226+
self.region_bound_pairs_accum
182227
.push((r_a, GenericKind::Projection(projection_b)));
183228
}
184229
OutlivesBound::RegionSubRegion(r_a, r_b) => {

src/librustc_typeck/check/regionck.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
130130
Subject(subject),
131131
self.param_env,
132132
);
133+
134+
// There are no add'l implied bounds when checking a
135+
// standalone expr (e.g., the `E` in a type like `[u32; E]`).
136+
rcx.outlives_environment.save_implied_bounds(id);
137+
133138
if self.err_count_since_creation() == 0 {
134139
// regionck assumes typeck succeeded
135140
rcx.visit_body(body);
@@ -155,6 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
155160
);
156161
rcx.outlives_environment
157162
.add_implied_bounds(self, wf_tys, item_id, span);
163+
rcx.outlives_environment.save_implied_bounds(item_id);
158164
rcx.visit_region_obligations(item_id);
159165
rcx.resolve_regions_and_report_errors();
160166
}
@@ -308,7 +314,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
308314
id: ast::NodeId, // the id of the fn itself
309315
body: &'gcx hir::Body,
310316
span: Span,
311-
) {
317+
) {
312318
// When we enter a function, we can derive
313319
debug!("visit_fn_body(id={})", id);
314320

@@ -349,6 +355,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
349355
body_id.node_id,
350356
span,
351357
);
358+
self.outlives_environment.save_implied_bounds(body_id.node_id);
352359
self.link_fn_args(
353360
region::Scope {
354361
id: body.value.hir_id.local_id,

0 commit comments

Comments
 (0)