rename "free region" to "universally quantified region"
This has been bugging me. All the regions appear free in the source; the real difference is that some of them are universally quantified (those in the function signature) and some are existentially quantified (those for which we are inferring values).
This commit is contained in:
parent
fa813f74a2
commit
243bf3f718
@ -26,8 +26,8 @@ use self::mir_util::PassWhere;
|
||||
|
||||
mod constraint_generation;
|
||||
mod subtype_constraint_generation;
|
||||
mod free_regions;
|
||||
use self::free_regions::FreeRegions;
|
||||
mod universal_regions;
|
||||
use self::universal_regions::UniversalRegions;
|
||||
|
||||
pub(crate) mod region_infer;
|
||||
use self::region_infer::RegionInferenceContext;
|
||||
@ -42,14 +42,14 @@ pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
|
||||
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mir: &mut Mir<'tcx>,
|
||||
) -> FreeRegions<'tcx> {
|
||||
) -> UniversalRegions<'tcx> {
|
||||
// Compute named region information.
|
||||
let free_regions = free_regions::free_regions(infcx, def_id);
|
||||
let universal_regions = universal_regions::universal_regions(infcx, def_id);
|
||||
|
||||
// Replace all regions with fresh inference variables.
|
||||
renumber::renumber_mir(infcx, &free_regions, mir);
|
||||
renumber::renumber_mir(infcx, &universal_regions, mir);
|
||||
|
||||
free_regions
|
||||
universal_regions
|
||||
}
|
||||
|
||||
/// Computes the (non-lexical) regions from the input MIR.
|
||||
@ -58,7 +58,7 @@ pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
|
||||
pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
free_regions: FreeRegions<'tcx>,
|
||||
universal_regions: UniversalRegions<'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
param_env: ty::ParamEnv<'gcx>,
|
||||
flow_inits: &mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
|
||||
@ -71,8 +71,13 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||
// Create the region inference context, taking ownership of the region inference
|
||||
// data that was contained in `infcx`.
|
||||
let var_origins = infcx.take_region_var_origins();
|
||||
let mut regioncx = RegionInferenceContext::new(var_origins, &free_regions, mir);
|
||||
subtype_constraint_generation::generate(&mut regioncx, &free_regions, mir, constraint_sets);
|
||||
let mut regioncx = RegionInferenceContext::new(var_origins, &universal_regions, mir);
|
||||
subtype_constraint_generation::generate(
|
||||
&mut regioncx,
|
||||
&universal_regions,
|
||||
mir,
|
||||
constraint_sets,
|
||||
);
|
||||
|
||||
// Compute what is live where.
|
||||
let liveness = &LivenessResults {
|
||||
@ -178,8 +183,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
|
||||
writeln!(out, " | Live variables at {:?}: {}", location, s)?;
|
||||
}
|
||||
|
||||
PassWhere::AfterLocation(_) |
|
||||
PassWhere::AfterCFG => {}
|
||||
PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::free_regions::FreeRegions;
|
||||
use super::universal_regions::UniversalRegions;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::infer::RegionVariableOrigin;
|
||||
use rustc::infer::NLLRegionVariableOrigin;
|
||||
@ -33,8 +33,8 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
|
||||
/// The liveness constraints added to each region. For most
|
||||
/// regions, these start out empty and steadily grow, though for
|
||||
/// each free region R they start out containing the entire CFG
|
||||
/// and `end(R)`.
|
||||
/// each universally quantified region R they start out containing
|
||||
/// the entire CFG and `end(R)`.
|
||||
///
|
||||
/// In this `BitMatrix` representation, the rows are the region
|
||||
/// variables and the columns are the free regions and MIR locations.
|
||||
@ -52,7 +52,10 @@ pub struct RegionInferenceContext<'tcx> {
|
||||
/// the free regions.)
|
||||
point_indices: BTreeMap<Location, usize>,
|
||||
|
||||
num_free_regions: usize,
|
||||
/// Number of universally quantified regions. This is used to
|
||||
/// determine the meaning of the bits in `inferred_values` and
|
||||
/// friends.
|
||||
num_universal_regions: usize,
|
||||
|
||||
free_region_map: &'tcx FreeRegionMap<'tcx>,
|
||||
}
|
||||
@ -92,10 +95,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Creates a new region inference context with a total of
|
||||
/// `num_region_variables` valid inference variables; the first N
|
||||
/// of those will be constant regions representing the free
|
||||
/// regions defined in `free_regions`.
|
||||
pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) -> Self {
|
||||
/// regions defined in `universal_regions`.
|
||||
pub fn new(
|
||||
var_origins: VarOrigins,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
) -> Self {
|
||||
let num_region_variables = var_origins.len();
|
||||
let num_free_regions = free_regions.indices.len();
|
||||
let num_universal_regions = universal_regions.indices.len();
|
||||
|
||||
let mut num_points = 0;
|
||||
let mut point_indices = BTreeMap::new();
|
||||
@ -106,7 +113,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
block,
|
||||
statement_index,
|
||||
};
|
||||
point_indices.insert(location, num_free_regions + num_points);
|
||||
point_indices.insert(location, num_universal_regions + num_points);
|
||||
num_points += 1;
|
||||
}
|
||||
}
|
||||
@ -121,25 +128,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
definitions,
|
||||
liveness_constraints: BitMatrix::new(
|
||||
num_region_variables,
|
||||
num_free_regions + num_points,
|
||||
num_universal_regions + num_points,
|
||||
),
|
||||
inferred_values: None,
|
||||
constraints: Vec::new(),
|
||||
point_indices,
|
||||
num_free_regions,
|
||||
free_region_map: free_regions.free_region_map,
|
||||
num_universal_regions,
|
||||
free_region_map: universal_regions.free_region_map,
|
||||
};
|
||||
|
||||
result.init_free_regions(free_regions);
|
||||
result.init_universal_regions(universal_regions);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Initializes the region variables for each free region
|
||||
/// (lifetime parameter). The first N variables always correspond
|
||||
/// to the free regions appearing in the function signature (both
|
||||
/// named and anonymous) and where clauses. This function iterates
|
||||
/// over those regions and initializes them with minimum values.
|
||||
/// Initializes the region variables for each universally
|
||||
/// quantified region (lifetime parameter). The first N variables
|
||||
/// always correspond to the regions appearing in the function
|
||||
/// signature (both named and anonymous) and where clauses. This
|
||||
/// function iterates over those regions and initializes them with
|
||||
/// minimum values.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
@ -154,13 +162,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// and (b) any free regions that it outlives, which in this case
|
||||
/// is just itself. R1 (`'b`) in contrast also outlives `'a` and
|
||||
/// hence contains R0 and R1.
|
||||
fn init_free_regions(&mut self, free_regions: &FreeRegions<'tcx>) {
|
||||
let FreeRegions {
|
||||
fn init_universal_regions(&mut self, universal_regions: &UniversalRegions<'tcx>) {
|
||||
let UniversalRegions {
|
||||
indices,
|
||||
free_region_map: _,
|
||||
} = free_regions;
|
||||
} = universal_regions;
|
||||
|
||||
// For each free region X:
|
||||
// For each universally quantified region X:
|
||||
for (free_region, &variable) in indices {
|
||||
// These should be free-region variables.
|
||||
assert!(match self.definitions[variable].origin {
|
||||
@ -218,7 +226,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
&self,
|
||||
matrix: &BitMatrix,
|
||||
r: RegionVid,
|
||||
s: RegionVid
|
||||
s: RegionVid,
|
||||
) -> bool {
|
||||
matrix.contains(r.index(), s.index())
|
||||
}
|
||||
@ -240,7 +248,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
for fr in (0 .. self.num_free_regions).map(RegionVid::new) {
|
||||
for fr in (0..self.num_universal_regions).map(RegionVid::new) {
|
||||
if self.region_contains_region_in_matrix(inferred_values, r, fr) {
|
||||
result.push_str(&format!("{}{:?}", sep, fr));
|
||||
sep = ", ";
|
||||
@ -287,9 +295,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// Find the minimal regions that can solve the constraints. This is infallible.
|
||||
self.propagate_constraints(mir);
|
||||
|
||||
// Now, see whether any of the constraints were too strong. In particular,
|
||||
// we want to check for a case where a free region exceeded its bounds.
|
||||
// Consider:
|
||||
// Now, see whether any of the constraints were too strong. In
|
||||
// particular, we want to check for a case where a universally
|
||||
// quantified region exceeded its bounds. Consider:
|
||||
//
|
||||
// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
|
||||
//
|
||||
@ -300,7 +308,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// have no evidence that `'b` outlives `'a`, so we want to report
|
||||
// an error.
|
||||
|
||||
// The free regions are always found in a prefix of the full list.
|
||||
// The universal regions are always found in a prefix of the
|
||||
// full list.
|
||||
let free_region_definitions = self.definitions
|
||||
.iter_enumerated()
|
||||
.take_while(|(_, fr_definition)| fr_definition.name.is_some());
|
||||
@ -322,7 +331,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
// Find every region `o` such that `fr: o`
|
||||
// (because `fr` includes `end(o)`).
|
||||
for outlived_fr in fr_value.take_while(|&i| i < self.num_free_regions) {
|
||||
for outlived_fr in fr_value.take_while(|&i| i < self.num_universal_regions) {
|
||||
// `fr` includes `end(fr)`, that's not especially
|
||||
// interesting.
|
||||
if fr.index() == outlived_fr {
|
||||
@ -451,11 +460,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// If we reach the END point in the graph, then copy
|
||||
// over any skolemized end points in the `from_region`
|
||||
// and make sure they are included in the `to_region`.
|
||||
let free_region_indices = inferred_values
|
||||
let universal_region_indices = inferred_values
|
||||
.iter(from_region.index())
|
||||
.take_while(|&i| i < self.num_free_regions)
|
||||
.take_while(|&i| i < self.num_universal_regions)
|
||||
.collect::<Vec<_>>();
|
||||
for fr in &free_region_indices {
|
||||
for fr in &universal_region_indices {
|
||||
changed |= inferred_values.add(to_region.index(), *fr);
|
||||
}
|
||||
} else {
|
||||
@ -523,7 +532,7 @@ impl<'tcx> RegionDefinition<'tcx> {
|
||||
fn new(origin: RegionVariableOrigin) -> Self {
|
||||
// Create a new region definition. Note that, for free
|
||||
// regions, these fields get updated later in
|
||||
// `init_free_regions`.
|
||||
// `init_universal_regions`.
|
||||
Self { origin, name: None }
|
||||
}
|
||||
}
|
||||
|
@ -16,18 +16,18 @@ use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
|
||||
use super::ToRegionVid;
|
||||
use super::free_regions::FreeRegions;
|
||||
use super::universal_regions::UniversalRegions;
|
||||
|
||||
/// Replaces all free regions appearing in the MIR with fresh
|
||||
/// inference variables, returning the number of variables created.
|
||||
pub fn renumber_mir<'a, 'gcx, 'tcx>(
|
||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
free_regions: &FreeRegions<'tcx>,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
mir: &mut Mir<'tcx>,
|
||||
) {
|
||||
// Create inference variables for each of the free regions
|
||||
// declared on the function signature.
|
||||
let free_region_inference_vars = (0..free_regions.indices.len())
|
||||
let free_region_inference_vars = (0..universal_regions.indices.len())
|
||||
.map(RegionVid::new)
|
||||
.map(|vid_expected| {
|
||||
let r = infcx.next_nll_region_var(NLLRegionVariableOrigin::FreeRegion);
|
||||
@ -37,12 +37,12 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
|
||||
.collect();
|
||||
|
||||
debug!("renumber_mir()");
|
||||
debug!("renumber_mir: free_regions={:#?}", free_regions);
|
||||
debug!("renumber_mir: universal_regions={:#?}", universal_regions);
|
||||
debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
|
||||
|
||||
let mut visitor = NLLVisitor {
|
||||
infcx,
|
||||
free_regions,
|
||||
universal_regions,
|
||||
free_region_inference_vars,
|
||||
arg_count: mir.arg_count,
|
||||
};
|
||||
@ -51,7 +51,7 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
|
||||
|
||||
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
free_regions: &'a FreeRegions<'tcx>,
|
||||
universal_regions: &'a UniversalRegions<'tcx>,
|
||||
free_region_inference_vars: IndexVec<RegionVid, ty::Region<'tcx>>,
|
||||
arg_count: usize,
|
||||
}
|
||||
@ -76,16 +76,16 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
/// Renumbers the regions appearing in `value`, but those regions
|
||||
/// are expected to be free regions from the function signature.
|
||||
fn renumber_free_regions<T>(&mut self, value: &T) -> T
|
||||
fn renumber_universal_regions<T>(&mut self, value: &T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
debug!("renumber_free_regions(value={:?})", value);
|
||||
debug!("renumber_universal_regions(value={:?})", value);
|
||||
|
||||
self.infcx
|
||||
.tcx
|
||||
.fold_regions(value, &mut false, |region, _depth| {
|
||||
let index = self.free_regions.indices[®ion];
|
||||
let index = self.universal_regions.indices[®ion];
|
||||
self.free_region_inference_vars[index]
|
||||
})
|
||||
}
|
||||
@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
let old_ty = *ty;
|
||||
*ty = if is_arg {
|
||||
self.renumber_free_regions(&old_ty)
|
||||
self.renumber_universal_regions(&old_ty)
|
||||
} else {
|
||||
self.renumber_regions(ty_context, &old_ty)
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ use rustc::ty;
|
||||
use transform::type_check::MirTypeckRegionConstraints;
|
||||
use transform::type_check::OutlivesSet;
|
||||
|
||||
use super::free_regions::FreeRegions;
|
||||
use super::universal_regions::UniversalRegions;
|
||||
use super::region_infer::RegionInferenceContext;
|
||||
|
||||
/// When the MIR type-checker executes, it validates all the types in
|
||||
@ -25,20 +25,20 @@ use super::region_infer::RegionInferenceContext;
|
||||
/// them into the NLL `RegionInferenceContext`.
|
||||
pub(super) fn generate<'tcx>(
|
||||
regioncx: &mut RegionInferenceContext<'tcx>,
|
||||
free_regions: &FreeRegions<'tcx>,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
constraints: &MirTypeckRegionConstraints<'tcx>,
|
||||
) {
|
||||
SubtypeConstraintGenerator {
|
||||
regioncx,
|
||||
free_regions,
|
||||
universal_regions,
|
||||
mir,
|
||||
}.generate(constraints);
|
||||
}
|
||||
|
||||
struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> {
|
||||
regioncx: &'cx mut RegionInferenceContext<'tcx>,
|
||||
free_regions: &'cx FreeRegions<'tcx>,
|
||||
universal_regions: &'cx UniversalRegions<'tcx>,
|
||||
mir: &'cx Mir<'tcx>,
|
||||
}
|
||||
|
||||
@ -102,11 +102,11 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
|
||||
// Every region that we see in the constraints came from the
|
||||
// MIR or from the parameter environment. If the former, it
|
||||
// will be a region variable. If the latter, it will be in
|
||||
// the set of free regions *somewhere*.
|
||||
// the set of universal regions *somewhere*.
|
||||
if let ty::ReVar(vid) = r {
|
||||
*vid
|
||||
} else {
|
||||
self.free_regions.indices[&r]
|
||||
self.universal_regions.indices[&r]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Code to extract the free regions declared on a function and the
|
||||
//! relationships between them. For example:
|
||||
//! Code to extract the universally quantified regions declared on a
|
||||
//! function and the relationships between them. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! fn foo<'a, 'b, 'c: 'b>() { }
|
||||
@ -31,22 +31,22 @@ use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FreeRegions<'tcx> {
|
||||
/// Given a free region defined on this function (either early- or
|
||||
/// late-bound), this maps it to its internal region index. When
|
||||
/// the region context is created, the first N variables will be
|
||||
/// created based on these indices.
|
||||
pub struct UniversalRegions<'tcx> {
|
||||
/// Given a universally quantified region defined on this function
|
||||
/// (either early- or late-bound), this maps it to its internal
|
||||
/// region index. When the region context is created, the first N
|
||||
/// variables will be created based on these indices.
|
||||
pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
|
||||
|
||||
/// The map from the typeck tables telling us how to relate free regions.
|
||||
/// The map from the typeck tables telling us how to relate universal regions.
|
||||
pub free_region_map: &'tcx FreeRegionMap<'tcx>,
|
||||
}
|
||||
|
||||
pub fn free_regions<'a, 'gcx, 'tcx>(
|
||||
pub fn universal_regions<'a, 'gcx, 'tcx>(
|
||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
item_def_id: DefId,
|
||||
) -> FreeRegions<'tcx> {
|
||||
debug!("free_regions(item_def_id={:?})", item_def_id);
|
||||
) -> UniversalRegions<'tcx> {
|
||||
debug!("universal_regions(item_def_id={:?})", item_def_id);
|
||||
|
||||
let mut indices = FxHashMap();
|
||||
|
||||
@ -76,15 +76,15 @@ pub fn free_regions<'a, 'gcx, 'tcx>(
|
||||
}
|
||||
});
|
||||
|
||||
debug!("free_regions: indices={:#?}", indices);
|
||||
debug!("universal_regions: indices={:#?}", indices);
|
||||
|
||||
FreeRegions { indices, free_region_map: &tables.free_region_map }
|
||||
UniversalRegions { indices, free_region_map: &tables.free_region_map }
|
||||
}
|
||||
|
||||
fn insert_free_region<'tcx>(
|
||||
free_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
|
||||
universal_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
|
||||
region: ty::Region<'tcx>,
|
||||
) {
|
||||
let next = RegionVid::new(free_regions.len());
|
||||
free_regions.entry(region).or_insert(next);
|
||||
let next = RegionVid::new(universal_regions.len());
|
||||
universal_regions.entry(region).or_insert(next);
|
||||
}
|
Loading…
Reference in New Issue
Block a user