build up a map of the region-bound pairs for each body-id
Presently unused.
This commit is contained in:
parent
1fb4ea91f2
commit
84563dac88
2 changed files with 63 additions and 11 deletions
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
use infer::outlives::free_region_map::FreeRegionMap;
|
use infer::outlives::free_region_map::FreeRegionMap;
|
||||||
use infer::{GenericKind, InferCtxt};
|
use infer::{GenericKind, InferCtxt};
|
||||||
use traits::query::outlives_bounds::{self, OutlivesBound};
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use ty::{self, Ty};
|
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
use traits::query::outlives_bounds::{self, OutlivesBound};
|
||||||
|
use ty::{self, Ty};
|
||||||
|
|
||||||
/// The `OutlivesEnvironment` collects information about what outlives
|
/// The `OutlivesEnvironment` collects information about what outlives
|
||||||
/// what in a given type-checking setting. For example, if we have a
|
/// what in a given type-checking setting. For example, if we have a
|
||||||
|
@ -39,15 +39,51 @@ use syntax_pos::Span;
|
||||||
pub struct OutlivesEnvironment<'tcx> {
|
pub struct OutlivesEnvironment<'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
free_region_map: FreeRegionMap<'tcx>,
|
free_region_map: FreeRegionMap<'tcx>,
|
||||||
region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
|
|
||||||
|
// Contains, for each body B that we are checking (that is, the fn
|
||||||
|
// item, but also any nested closures), the set of implied region
|
||||||
|
// bounds that are in scope in that particular body.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
|
||||||
|
// bar(x, y, |y: &'b T| { .. } // body B1)
|
||||||
|
// } // body B0
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Here, for body B0, the list would be `[T: 'a]`, because we
|
||||||
|
// infer that `T` must outlive `'a` from the implied bounds on the
|
||||||
|
// fn declaration.
|
||||||
|
//
|
||||||
|
// For the body B1, the list would be `[T: 'a, T: 'b]`, because we
|
||||||
|
// also can see that -- within the closure body! -- `T` must
|
||||||
|
// outlive `'b`. This is not necessarily true outside the closure
|
||||||
|
// body, since the closure may never be called.
|
||||||
|
//
|
||||||
|
// We collect this map as we descend the tree. We then use the
|
||||||
|
// results when proving outlives obligations like `T: 'x` later
|
||||||
|
// (e.g., if `T: 'x` must be proven within the body B1, then we
|
||||||
|
// know it is true if either `'a: 'x` or `'b: 'x`).
|
||||||
|
region_bound_pairs_map: FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
|
||||||
|
|
||||||
|
// Used to compute `region_bound_pairs_map`: contains the set of
|
||||||
|
// in-scope region-bound pairs thus far.
|
||||||
|
region_bound_pairs_accum: RegionBoundPairs<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// "Region-bound pairs" tracks outlives relations that are known to
|
||||||
|
/// be true, either because of explicit where clauses like `T: 'a` or
|
||||||
|
/// because of implied bounds.
|
||||||
|
pub type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
|
||||||
|
|
||||||
impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
||||||
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
|
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||||
let mut env = OutlivesEnvironment {
|
let mut env = OutlivesEnvironment {
|
||||||
param_env,
|
param_env,
|
||||||
free_region_map: FreeRegionMap::new(),
|
free_region_map: FreeRegionMap::new(),
|
||||||
region_bound_pairs: vec![],
|
region_bound_pairs_map: FxHashMap::default(),
|
||||||
|
region_bound_pairs_accum: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env));
|
env.add_outlives_bounds(None, outlives_bounds::explicit_outlives_bounds(param_env));
|
||||||
|
@ -62,7 +98,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
||||||
|
|
||||||
/// Borrows current value of the `region_bound_pairs`.
|
/// Borrows current value of the `region_bound_pairs`.
|
||||||
pub fn region_bound_pairs(&self) -> &[(ty::Region<'tcx>, GenericKind<'tcx>)] {
|
pub fn region_bound_pairs(&self) -> &[(ty::Region<'tcx>, GenericKind<'tcx>)] {
|
||||||
&self.region_bound_pairs
|
&self.region_bound_pairs_accum
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns ownership of the `free_region_map`.
|
/// Returns ownership of the `free_region_map`.
|
||||||
|
@ -108,12 +144,12 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
||||||
/// similar leaks around givens that seem equally suspicious, to
|
/// similar leaks around givens that seem equally suspicious, to
|
||||||
/// be honest. --nmatsakis
|
/// be honest. --nmatsakis
|
||||||
pub fn push_snapshot_pre_closure(&self) -> usize {
|
pub fn push_snapshot_pre_closure(&self) -> usize {
|
||||||
self.region_bound_pairs.len()
|
self.region_bound_pairs_accum.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See `push_snapshot_pre_closure`.
|
/// See `push_snapshot_pre_closure`.
|
||||||
pub fn pop_snapshot_post_closure(&mut self, len: usize) {
|
pub fn pop_snapshot_post_closure(&mut self, len: usize) {
|
||||||
self.region_bound_pairs.truncate(len);
|
self.region_bound_pairs_accum.truncate(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method adds "implied bounds" into the outlives environment.
|
/// This method adds "implied bounds" into the outlives environment.
|
||||||
|
@ -149,6 +185,15 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save the current set of region-bound pairs under the given `body_id`.
|
||||||
|
pub fn save_implied_bounds(&mut self, body_id: ast::NodeId) {
|
||||||
|
let old = self.region_bound_pairs_map.insert(
|
||||||
|
body_id,
|
||||||
|
self.region_bound_pairs_accum.clone(),
|
||||||
|
);
|
||||||
|
assert!(old.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
|
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
|
||||||
///
|
///
|
||||||
/// The `infcx` parameter is optional; if the implied bounds may
|
/// The `infcx` parameter is optional; if the implied bounds may
|
||||||
|
@ -174,11 +219,11 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
|
||||||
.add_given(r_a, vid_b);
|
.add_given(r_a, vid_b);
|
||||||
}
|
}
|
||||||
OutlivesBound::RegionSubParam(r_a, param_b) => {
|
OutlivesBound::RegionSubParam(r_a, param_b) => {
|
||||||
self.region_bound_pairs
|
self.region_bound_pairs_accum
|
||||||
.push((r_a, GenericKind::Param(param_b)));
|
.push((r_a, GenericKind::Param(param_b)));
|
||||||
}
|
}
|
||||||
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
|
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
|
||||||
self.region_bound_pairs
|
self.region_bound_pairs_accum
|
||||||
.push((r_a, GenericKind::Projection(projection_b)));
|
.push((r_a, GenericKind::Projection(projection_b)));
|
||||||
}
|
}
|
||||||
OutlivesBound::RegionSubRegion(r_a, r_b) => {
|
OutlivesBound::RegionSubRegion(r_a, r_b) => {
|
||||||
|
|
|
@ -130,6 +130,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Subject(subject),
|
Subject(subject),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// There are no add'l implied bounds when checking a
|
||||||
|
// standalone expr (e.g., the `E` in a type like `[u32; E]`).
|
||||||
|
rcx.outlives_environment.save_implied_bounds(id);
|
||||||
|
|
||||||
if self.err_count_since_creation() == 0 {
|
if self.err_count_since_creation() == 0 {
|
||||||
// regionck assumes typeck succeeded
|
// regionck assumes typeck succeeded
|
||||||
rcx.visit_body(body);
|
rcx.visit_body(body);
|
||||||
|
@ -155,6 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
rcx.outlives_environment
|
rcx.outlives_environment
|
||||||
.add_implied_bounds(self, wf_tys, item_id, span);
|
.add_implied_bounds(self, wf_tys, item_id, span);
|
||||||
|
rcx.outlives_environment.save_implied_bounds(item_id);
|
||||||
rcx.visit_region_obligations(item_id);
|
rcx.visit_region_obligations(item_id);
|
||||||
rcx.resolve_regions_and_report_errors();
|
rcx.resolve_regions_and_report_errors();
|
||||||
}
|
}
|
||||||
|
@ -308,7 +314,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
id: ast::NodeId, // the id of the fn itself
|
id: ast::NodeId, // the id of the fn itself
|
||||||
body: &'gcx hir::Body,
|
body: &'gcx hir::Body,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
// When we enter a function, we can derive
|
// When we enter a function, we can derive
|
||||||
debug!("visit_fn_body(id={})", id);
|
debug!("visit_fn_body(id={})", id);
|
||||||
|
|
||||||
|
@ -349,6 +355,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
body_id.node_id,
|
body_id.node_id,
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
|
self.outlives_environment.save_implied_bounds(body_id.node_id);
|
||||||
self.link_fn_args(
|
self.link_fn_args(
|
||||||
region::Scope {
|
region::Scope {
|
||||||
id: body.value.hir_id.local_id,
|
id: body.value.hir_id.local_id,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue