Skip to content

Commit

Permalink
add comments to region_infer, restructure a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Nov 2, 2017
1 parent cafbd99 commit bfc696a
Showing 1 changed file with 56 additions and 35 deletions.
91 changes: 56 additions & 35 deletions src/librustc_mir/transform/nll/region_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ pub struct Constraint {
point: Location,
}

impl<'tcx> RegionInferenceContext<'tcx> {
impl<'a, 'gcx, '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(free_regions: &FreeRegions<'tcx>,
num_region_variables: usize,
mir: &Mir<'tcx>)
-> Self {
pub fn new(
free_regions: &FreeRegions<'tcx>,
num_region_variables: usize,
mir: &Mir<'tcx>,
) -> Self {
let mut result = Self {
definitions: (0..num_region_variables)
.map(|_| RegionDefinition::default())
Expand All @@ -83,33 +84,49 @@ impl<'tcx> RegionInferenceContext<'tcx> {
result
}

fn init_free_regions(&mut self,
free_regions: &FreeRegions<'tcx>,
mir: &Mir<'tcx>)
{
let &FreeRegions { ref indices, ref free_region_map } = free_regions;

// For each free region variable X, it should contain:
//
// (a) the entire CFG
// (b) `end(Y)` for all regions Y such that X: Y (or Y <= X)
//
// we add however the regions for clause (b) somewhat in
// reverse, because of how the data structure in
// `free_regions` is organized.
/// 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.
///
/// For example:
///
/// fn foo<'a, 'b>(..) where 'a: 'b
///
/// would initialize two variables like so:
///
/// R0 = { CFG, R0 } // 'a
/// R1 = { CFG, R0, R1 } // 'b
///
/// Here, R0 represents `'a`, and it contains (a) the entire CFG
/// 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>, mir: &Mir<'tcx>) {
let &FreeRegions {
ref indices,
ref free_region_map,
} = free_regions;

// For each free region X:
for (free_region, index) in indices {
let variable = RegionIndex::new(*index);

self.free_regions.push(variable);

// Initialize the name and a few other details.
self.definitions[variable].name = Some(free_region);
self.definitions[variable].constant = true;

// Add all nodes in the CFG to `definition.value`.
for (block, block_data) in mir.basic_blocks().iter_enumerated() {
let definition = &mut self.definitions[variable];
for statement_index in 0 .. block_data.statements.len() + 1 {
let location = Location { block, statement_index };
for statement_index in 0..block_data.statements.len() + 1 {
let location = Location {
block,
statement_index,
};
definition.value.add_point(location);
}
}
Expand All @@ -121,13 +138,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Y: X is true). Add `end(X)` into the set for `Y`.
for superregion in free_region_map.regions_that_outlive(&free_region) {
let superregion_index = RegionIndex::new(indices[superregion]);
self.definitions[superregion_index].value.add_free_region(variable);
self.definitions[superregion_index]
.value
.add_free_region(variable);
}

debug!("init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`",
free_region,
variable,
self.definitions[variable].value);
debug!(
"init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`",
free_region,
variable,
self.definitions[variable].value
);
}
}

Expand Down Expand Up @@ -157,15 +178,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

/// Perform region inference.
pub(super) fn solve<'a, 'gcx>(
&mut self,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
)
where
'gcx: 'tcx + 'a,
'tcx: 'a,
{
pub(super) fn solve(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>) {
self.propagate_constraints(infcx, mir);
}

/// Propagate the region constraints: this will grow the values
/// for each region variable until all the constraints are
/// satisfied. Note that some values may grow **too** large to be
/// feasible, but we check this later.
fn propagate_constraints(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>) {
let mut changed = true;
let mut dfs = Dfs::new(infcx, mir);
while changed {
Expand Down

0 comments on commit bfc696a

Please sign in to comment.