Skip to content

Commit 072bae2

Browse files
committed
formalize giving ownership of region vars to region inf. context
1 parent 31d6b17 commit 072bae2

File tree

7 files changed

+102
-88
lines changed

7 files changed

+102
-88
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10291029
let var_name = self.tcx.hir.name(var_node_id);
10301030
format!(" for capture of `{}` by closure", var_name)
10311031
}
1032+
infer::NLL(..) => bug!("NLL variable found in lexical phase"),
10321033
};
10331034

10341035
struct_span_err!(self.tcx.sess, var_origin.span(), E0495,

src/librustc/infer/mod.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ pub use self::SubregionOrigin::*;
1616
pub use self::ValuePairs::*;
1717
pub use ty::IntVarValue;
1818
pub use self::freshen::TypeFreshener;
19-
pub use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData};
2019

2120
use hir::def_id::DefId;
2221
use middle::free_region::{FreeRegionMap, RegionRelations};
@@ -25,7 +24,7 @@ use middle::lang_items;
2524
use mir::tcx::LvalueTy;
2625
use ty::subst::{Kind, Subst, Substs};
2726
use ty::{TyVid, IntVid, FloatVid};
28-
use ty::{self, RegionVid, Ty, TyCtxt};
27+
use ty::{self, Ty, TyCtxt};
2928
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
3029
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3130
use ty::relate::RelateResult;
@@ -42,6 +41,7 @@ use arena::DroplessArena;
4241
use self::combine::CombineFields;
4342
use self::higher_ranked::HrMatchResult;
4443
use self::region_constraints::{RegionConstraintCollector, RegionSnapshot};
44+
use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarOrigins};
4545
use self::lexical_region_resolve::LexicalRegionResolutions;
4646
use self::type_variable::TypeVariableOrigin;
4747
use self::unify_key::ToType;
@@ -321,7 +321,7 @@ pub enum LateBoundRegionConversionTime {
321321
/// Reasons to create a region inference variable
322322
///
323323
/// See `error_reporting` module for more details
324-
#[derive(Clone, Debug)]
324+
#[derive(Copy, Clone, Debug)]
325325
pub enum RegionVariableOrigin {
326326
// Region variables created for ill-categorized reasons,
327327
// mostly indicates places in need of refactoring
@@ -349,6 +349,20 @@ pub enum RegionVariableOrigin {
349349
UpvarRegion(ty::UpvarId, Span),
350350

351351
BoundRegionInCoherence(ast::Name),
352+
353+
// This origin is used for the inference variables that we create
354+
// during NLL region processing.
355+
NLL(NLLRegionVariableOrigin),
356+
}
357+
358+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
359+
pub enum NLLRegionVariableOrigin {
360+
// During NLL region processing, we create variables for free
361+
// regions that we encounter in the function signature and
362+
// elsewhere. This origin indices we've got one of those.
363+
FreeRegion,
364+
365+
Inferred(::mir::visit::TyContext),
352366
}
353367

354368
#[derive(Copy, Clone, Debug)]
@@ -1030,11 +1044,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10301044
.new_key(None)
10311045
}
10321046

1047+
/// Create a fresh region variable with the next available index.
1048+
///
1049+
/// # Parameters
1050+
///
1051+
/// - `origin`: information about why we created this variable, for use
1052+
/// during diagnostics / error-reporting.
10331053
pub fn next_region_var(&self, origin: RegionVariableOrigin)
10341054
-> ty::Region<'tcx> {
10351055
self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin)))
10361056
}
10371057

1058+
/// Just a convenient wrapper of `next_region_var` for using during NLL.
1059+
pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin)
1060+
-> ty::Region<'tcx> {
1061+
self.next_region_var(RegionVariableOrigin::NLL(origin))
1062+
}
1063+
10381064
/// Create a region inference variable for the given
10391065
/// region parameter definition.
10401066
pub fn region_var_for_def(&self,
@@ -1166,19 +1192,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11661192
self.borrow_region_constraints().take_and_reset_data()
11671193
}
11681194

1169-
/// Returns the number of region variables created thus far.
1170-
pub fn num_region_vars(&self) -> usize {
1171-
self.borrow_region_constraints().var_origins().len()
1172-
}
1173-
1174-
/// Returns an iterator over all region variables created thus far.
1175-
pub fn all_region_vars(&self) -> impl Iterator<Item = RegionVid> {
1176-
self.borrow_region_constraints().var_origins().indices()
1177-
}
1178-
1179-
/// Returns the origin of a given region variable.
1180-
pub fn region_var_origin(&self, var: RegionVid) -> RegionVariableOrigin {
1181-
self.borrow_region_constraints().var_origins()[var].clone()
1195+
/// Takes ownership of the list of variable regions. This implies
1196+
/// that all the region constriants have already been taken, and
1197+
/// hence that `resolve_regions_and_report_errors` can never be
1198+
/// called. This is used only during NLL processing to "hand off" ownership
1199+
/// of the set of region vairables into the NLL region context.
1200+
pub fn take_region_var_origins(&self) -> VarOrigins {
1201+
let (var_origins, data) = self.region_constraints.borrow_mut()
1202+
.take()
1203+
.expect("regions already resolved")
1204+
.into_origins_and_data();
1205+
assert!(data.is_empty());
1206+
var_origins
11821207
}
11831208

11841209
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
@@ -1609,7 +1634,8 @@ impl RegionVariableOrigin {
16091634
EarlyBoundRegion(a, ..) => a,
16101635
LateBoundRegion(a, ..) => a,
16111636
BoundRegionInCoherence(_) => syntax_pos::DUMMY_SP,
1612-
UpvarRegion(_, a) => a
1637+
UpvarRegion(_, a) => a,
1638+
NLL(..) => bug!("NLL variable used with `span`"),
16131639
}
16141640
}
16151641
}

src/librustc/mir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ make_mir_visitor!(MutVisitor,mut);
811811

812812
/// Extra information passed to `visit_ty` and friends to give context
813813
/// about where the type etc appears.
814-
#[derive(Copy, Clone, Debug)]
814+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
815815
pub enum TyContext {
816816
LocalDecl {
817817
/// The index of the local variable we are visiting.

src/librustc_mir/transform/nll/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
6363

6464
// Create the region inference context, generate the constraints,
6565
// and then solve them.
66-
let mut regioncx = RegionInferenceContext::new(infcx, free_regions, mir);
66+
let var_origins = infcx.take_region_var_origins();
67+
let mut regioncx = RegionInferenceContext::new(var_origins, free_regions, mir);
6768
constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness);
6869
regioncx.solve(infcx, &mir);
6970

src/librustc_mir/transform/nll/region_infer.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
use super::free_regions::FreeRegions;
1212
use rustc::infer::InferCtxt;
13+
use rustc::infer::RegionVariableOrigin;
14+
use rustc::infer::NLLRegionVariableOrigin;
15+
use rustc::infer::region_constraints::VarOrigins;
1316
use rustc::mir::{Location, Mir};
1417
use rustc::ty::{self, RegionVid};
1518
use rustc_data_structures::indexed_vec::IndexVec;
@@ -25,23 +28,17 @@ pub struct RegionInferenceContext<'tcx> {
2528
/// from as well as its final inferred value.
2629
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
2730

28-
/// The indices of all "free regions" in scope. These are the
29-
/// lifetime parameters (anonymous and named) declared in the
30-
/// function signature:
31-
///
32-
/// fn foo<'a, 'b>(x: &Foo<'a, 'b>)
33-
/// ^^ ^^ ^
34-
///
35-
/// These indices will be from 0..N, as it happens, but we collect
36-
/// them into a vector for convenience.
37-
free_regions: Vec<RegionVid>,
38-
3931
/// The constraints we have accumulated and used during solving.
4032
constraints: Vec<Constraint>,
4133
}
4234

43-
#[derive(Default)]
4435
struct RegionDefinition<'tcx> {
36+
/// Why we created this variable. Mostly these will be
37+
/// `RegionVariableOrigin::NLL`, but some variables get created
38+
/// elsewhere in the code with other causes (e.g., instantiation
39+
/// late-bound-regions).
40+
origin: RegionVariableOrigin,
41+
4542
/// If this is a free-region, then this is `Some(X)` where `X` is
4643
/// the name of the region.
4744
name: Option<ty::Region<'tcx>>,
@@ -112,15 +109,16 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
112109
/// `num_region_variables` valid inference variables; the first N
113110
/// of those will be constant regions representing the free
114111
/// regions defined in `free_regions`.
115-
pub fn new(
116-
infcx: &InferCtxt<'_, '_, 'tcx>,
117-
free_regions: &FreeRegions<'tcx>,
118-
mir: &Mir<'tcx>,
119-
) -> Self {
112+
pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) -> Self {
113+
// Create a RegionDefinition for each inference variable.
114+
let definitions = var_origins
115+
.into_iter()
116+
.map(|origin| RegionDefinition::new(origin))
117+
.collect();
118+
120119
let mut result = Self {
121-
definitions: infcx.all_region_vars().map(|_| RegionDefinition::default()).collect(),
120+
definitions: definitions,
122121
constraints: Vec::new(),
123-
free_regions: Vec::new(),
124122
};
125123

126124
result.init_free_regions(free_regions, mir);
@@ -155,7 +153,11 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
155153

156154
// For each free region X:
157155
for (free_region, &variable) in indices {
158-
self.free_regions.push(variable);
156+
// These should be free-region variables.
157+
assert!(match self.definitions[variable].origin {
158+
RegionVariableOrigin::NLL(NLLRegionVariableOrigin::FreeRegion) => true,
159+
_ => false,
160+
});
159161

160162
// Initialize the name and a few other details.
161163
self.definitions[variable].name = Some(free_region);
@@ -262,10 +264,7 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
262264
/// for each region variable until all the constraints are
263265
/// satisfied. Note that some values may grow **too** large to be
264266
/// feasible, but we check this later.
265-
fn propagate_constraints(
266-
&mut self,
267-
mir: &Mir<'tcx>,
268-
) -> Vec<(RegionVid, Span, RegionVid)> {
267+
fn propagate_constraints(&mut self, mir: &Mir<'tcx>) -> Vec<(RegionVid, Span, RegionVid)> {
269268
let mut changed = true;
270269
let mut dfs = Dfs::new(mir);
271270
let mut error_regions = FxHashSet();
@@ -393,3 +392,17 @@ impl<'a, 'tcx> Dfs<'a, 'tcx> {
393392
changed
394393
}
395394
}
395+
396+
impl<'tcx> RegionDefinition<'tcx> {
397+
fn new(origin: RegionVariableOrigin) -> Self {
398+
// Create a new region definition. Note that, for free
399+
// regions, these fields get updated later in
400+
// `init_free_regions`.
401+
Self {
402+
origin,
403+
name: None,
404+
constant: false,
405+
value: Region::default(),
406+
}
407+
}
408+
}

src/librustc_mir/transform/nll/renumber.rs

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@
99
// except according to those terms.
1010

1111
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
12-
use rustc::ty::subst::{Kind, Substs};
13-
use rustc::ty::{self, ClosureSubsts, RegionKind, RegionVid, Ty, TypeFoldable};
12+
use rustc::ty::subst::Substs;
13+
use rustc::ty::{self, ClosureSubsts, RegionVid, Ty, TypeFoldable};
1414
use rustc::mir::{BasicBlock, Local, Location, Mir, Rvalue, Statement, StatementKind};
1515
use rustc::mir::visit::{MutVisitor, TyContext};
16-
use rustc::infer::{self as rustc_infer, InferCtxt};
17-
use syntax_pos::DUMMY_SP;
18-
use std::collections::HashMap;
16+
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1917

18+
use super::ToRegionVid;
2019
use super::free_regions::FreeRegions;
2120

2221
/// Replaces all free regions appearing in the MIR with fresh
@@ -29,14 +28,16 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
2928
// Create inference variables for each of the free regions
3029
// declared on the function signature.
3130
let free_region_inference_vars = (0..free_regions.indices.len())
32-
.map(|_| {
33-
infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
31+
.map(RegionVid::new)
32+
.map(|vid_expected| {
33+
let r = infcx.next_nll_region_var(NLLRegionVariableOrigin::FreeRegion);
34+
assert_eq!(vid_expected, r.to_region_vid());
35+
r
3436
})
3537
.collect();
3638

3739
let mut visitor = NLLVisitor {
3840
infcx,
39-
lookup_map: HashMap::new(),
4041
free_regions,
4142
free_region_inference_vars,
4243
arg_count: mir.arg_count,
@@ -45,7 +46,6 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
4546
}
4647

4748
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
48-
lookup_map: HashMap<RegionVid, TyContext>,
4949
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
5050
free_regions: &'a FreeRegions<'tcx>,
5151
free_region_inference_vars: IndexVec<RegionVid, ty::Region<'tcx>>,
@@ -56,14 +56,15 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
5656
/// Replaces all regions appearing in `value` with fresh inference
5757
/// variables. This is what we do for almost the entire MIR, with
5858
/// the exception of the declared types of our arguments.
59-
fn renumber_regions<T>(&mut self, value: &T) -> T
59+
fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
6060
where
6161
T: TypeFoldable<'tcx>,
6262
{
6363
self.infcx
6464
.tcx
6565
.fold_regions(value, &mut false, |_region, _depth| {
66-
self.infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
66+
let origin = NLLRegionVariableOrigin::Inferred(ty_context);
67+
self.infcx.next_nll_region_var(origin)
6768
})
6869
}
6970

@@ -81,26 +82,6 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
8182
})
8283
}
8384

84-
fn store_region(&mut self, region: &RegionKind, lookup: TyContext) {
85-
if let RegionKind::ReVar(rid) = *region {
86-
self.lookup_map.entry(rid).or_insert(lookup);
87-
}
88-
}
89-
90-
fn store_ty_regions(&mut self, ty: &Ty<'tcx>, ty_context: TyContext) {
91-
for region in ty.regions() {
92-
self.store_region(region, ty_context);
93-
}
94-
}
95-
96-
fn store_kind_regions(&mut self, kind: &'tcx Kind, ty_context: TyContext) {
97-
if let Some(ty) = kind.as_type() {
98-
self.store_ty_regions(&ty, ty_context);
99-
} else if let Some(region) = kind.as_region() {
100-
self.store_region(region, ty_context);
101-
}
102-
}
103-
10485
fn is_argument_or_return_slot(&self, local: Local) -> bool {
10586
// The first argument is return slot, next N are arguments.
10687
local.index() <= self.arg_count
@@ -118,26 +99,21 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
11899
*ty = if is_arg {
119100
self.renumber_free_regions(&old_ty)
120101
} else {
121-
self.renumber_regions(&old_ty)
102+
self.renumber_regions(ty_context, &old_ty)
122103
};
123-
self.store_ty_regions(ty, ty_context);
124104
}
125105

126106
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
127-
*substs = self.renumber_regions(&{ *substs });
128107
let ty_context = TyContext::Location(location);
129-
for kind in *substs {
130-
self.store_kind_regions(kind, ty_context);
131-
}
108+
*substs = self.renumber_regions(ty_context, &{ *substs });
132109
}
133110

134111
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
135112
match *rvalue {
136113
Rvalue::Ref(ref mut r, _, _) => {
137114
let old_r = *r;
138-
*r = self.renumber_regions(&old_r);
139115
let ty_context = TyContext::Location(location);
140-
self.store_region(r, ty_context);
116+
*r = self.renumber_regions(ty_context, &old_r);
141117
}
142118
Rvalue::Use(..) |
143119
Rvalue::Repeat(..) |
@@ -156,11 +132,8 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
156132
}
157133

158134
fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
159-
*substs = self.renumber_regions(substs);
160135
let ty_context = TyContext::Location(location);
161-
for kind in substs.substs {
162-
self.store_kind_regions(kind, ty_context);
163-
}
136+
*substs = self.renumber_regions(ty_context, substs);
164137
}
165138

166139
fn visit_statement(

0 commit comments

Comments
 (0)