mir borrowck: cleanup late-bound region handling
This commit is contained in:
parent
e491caec14
commit
99657aa338
7 changed files with 33 additions and 47 deletions
|
@ -34,7 +34,6 @@ pub(crate) enum RegionCtxt {
|
||||||
Location(Location),
|
Location(Location),
|
||||||
TyContext(TyContext),
|
TyContext(TyContext),
|
||||||
Free(Symbol),
|
Free(Symbol),
|
||||||
Bound(Symbol),
|
|
||||||
LateBound(Symbol),
|
LateBound(Symbol),
|
||||||
Existential(Option<Symbol>),
|
Existential(Option<Symbol>),
|
||||||
Placeholder(Symbol),
|
Placeholder(Symbol),
|
||||||
|
|
|
@ -467,15 +467,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||||
self.infcx.tcx.local_parent(self.mir_def),
|
self.infcx.tcx.local_parent(self.mir_def),
|
||||||
|r| {
|
|r| {
|
||||||
debug!(?r);
|
debug!(?r);
|
||||||
if !indices.indices.contains_key(&r) {
|
let region_vid = {
|
||||||
let region_vid = {
|
let name = r.get_name_or_anon();
|
||||||
let name = r.get_name_or_anon();
|
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
};
|
||||||
};
|
|
||||||
|
|
||||||
debug!(?region_vid);
|
debug!(?region_vid);
|
||||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -484,21 +482,17 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||||
self.infcx.num_region_vars()
|
self.infcx.num_region_vars()
|
||||||
};
|
};
|
||||||
|
|
||||||
// "Liberate" the late-bound regions. These correspond to
|
// Converse of above, if this is a function/closure then the late-bound regions declared
|
||||||
// "local" free regions.
|
// on its signature are local.
|
||||||
|
//
|
||||||
|
// We manually loop over `bound_inputs_and_output` instead of using
|
||||||
|
// `for_each_late_bound_region_in_item` as we may need to add the otherwise
|
||||||
|
// implicit `ClosureEnv` region.
|
||||||
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
|
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
|
||||||
|
for (idx, bound_var) in bound_inputs_and_output.bound_vars().iter().enumerate() {
|
||||||
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
|
if let ty::BoundVariableKind::Region(kind) = bound_var {
|
||||||
FR,
|
let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
|
||||||
self.mir_def,
|
let r = ty::Region::new_late_param(self.infcx.tcx, self.mir_def.to_def_id(), kind);
|
||||||
bound_inputs_and_output,
|
|
||||||
&mut indices,
|
|
||||||
);
|
|
||||||
// Converse of above, if this is a function/closure then the late-bound regions declared on its
|
|
||||||
// signature are local.
|
|
||||||
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| {
|
|
||||||
debug!(?r);
|
|
||||||
if !indices.indices.contains_key(&r) {
|
|
||||||
let region_vid = {
|
let region_vid = {
|
||||||
let name = r.get_name_or_anon();
|
let name = r.get_name_or_anon();
|
||||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
self.infcx.next_nll_region_var(FR, || RegionCtxt::LateBound(name))
|
||||||
|
@ -507,7 +501,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||||
debug!(?region_vid);
|
debug!(?region_vid);
|
||||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
|
||||||
|
self.mir_def,
|
||||||
|
bound_inputs_and_output,
|
||||||
|
&indices,
|
||||||
|
);
|
||||||
|
|
||||||
let (unnormalized_output_ty, mut unnormalized_input_tys) =
|
let (unnormalized_output_ty, mut unnormalized_input_tys) =
|
||||||
inputs_and_output.split_last().unwrap();
|
inputs_and_output.split_last().unwrap();
|
||||||
|
@ -832,10 +831,9 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
|
||||||
#[instrument(level = "debug", skip(self, indices))]
|
#[instrument(level = "debug", skip(self, indices))]
|
||||||
fn replace_bound_regions_with_nll_infer_vars<T>(
|
fn replace_bound_regions_with_nll_infer_vars<T>(
|
||||||
&self,
|
&self,
|
||||||
origin: NllRegionVariableOrigin,
|
|
||||||
all_outlive_scope: LocalDefId,
|
all_outlive_scope: LocalDefId,
|
||||||
value: ty::Binder<'tcx, T>,
|
value: ty::Binder<'tcx, T>,
|
||||||
indices: &mut UniversalRegionIndices<'tcx>,
|
indices: &UniversalRegionIndices<'tcx>,
|
||||||
) -> T
|
) -> T
|
||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
@ -845,18 +843,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
|
||||||
let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
|
let kind = ty::LateParamRegionKind::from_bound(br.var, br.kind);
|
||||||
let liberated_region =
|
let liberated_region =
|
||||||
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
|
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), kind);
|
||||||
let region_vid = {
|
ty::Region::new_var(self.tcx, indices.to_region_vid(liberated_region))
|
||||||
let name = match br.kind.get_name() {
|
|
||||||
Some(name) => name,
|
|
||||||
_ => sym::anon,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.next_nll_region_var(origin, || RegionCtxt::Bound(name))
|
|
||||||
};
|
|
||||||
|
|
||||||
indices.insert_late_bound_region(liberated_region, region_vid.as_var());
|
|
||||||
debug!(?liberated_region, ?region_vid);
|
|
||||||
region_vid
|
|
||||||
});
|
});
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -870,7 +857,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
||||||
/// well. These are used for error reporting.
|
/// well. These are used for error reporting.
|
||||||
fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
|
fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
|
||||||
debug!("insert_late_bound_region({:?}, {:?})", r, vid);
|
debug!("insert_late_bound_region({:?}, {:?})", r, vid);
|
||||||
self.indices.insert(r, vid);
|
assert_eq!(self.indices.insert(r, vid), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `r` into a local inference variable: `r` can either
|
/// Converts `r` into a local inference variable: `r` can either
|
||||||
|
|
|
@ -9,7 +9,7 @@ LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; };
|
||||||
extern "rust-call" fn((&(),)),
|
extern "rust-call" fn((&(),)),
|
||||||
(),
|
(),
|
||||||
]
|
]
|
||||||
= note: late-bound region is '?4
|
= note: late-bound region is '?3
|
||||||
= note: late-bound region is '?2
|
= note: late-bound region is '?2
|
||||||
= note: number of external vids: 3
|
= note: number of external vids: 3
|
||||||
= note: where '?1: '?2
|
= note: where '?1: '?2
|
||||||
|
@ -26,7 +26,7 @@ LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; };
|
||||||
extern "rust-call" fn(()),
|
extern "rust-call" fn(()),
|
||||||
(),
|
(),
|
||||||
]
|
]
|
||||||
= note: late-bound region is '?2
|
= note: late-bound region is '?1
|
||||||
|
|
||||||
note: no external requirements
|
note: no external requirements
|
||||||
--> $DIR/nested-closures-regions.rs:7:1
|
--> $DIR/nested-closures-regions.rs:7:1
|
||||||
|
|
|
@ -17,7 +17,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
|
||||||
| - - ^^^^^^ assignment requires that `'1` must outlive `'2`
|
| - - ^^^^^^ assignment requires that `'1` must outlive `'2`
|
||||||
| | |
|
| | |
|
||||||
| | has type `&'1 i32`
|
| | has type `&'1 i32`
|
||||||
| has type `&'?2 mut &'2 i32`
|
| has type `&'?1 mut &'2 i32`
|
||||||
|
|
||||||
note: no external requirements
|
note: no external requirements
|
||||||
--> $DIR/escape-argument-callee.rs:20:1
|
--> $DIR/escape-argument-callee.rs:20:1
|
||||||
|
|
|
@ -20,7 +20,7 @@ LL | foo(cell, |cell_a, cell_x| {
|
||||||
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
|
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
|
||||||
|
|
|
|
||||||
= note: requirement occurs because of the type `Cell<&'?8 u32>`, which makes the generic argument `&'?8 u32` invariant
|
= note: requirement occurs because of the type `Cell<&'?9 u32>`, which makes the generic argument `&'?9 u32` invariant
|
||||||
= note: the struct `Cell<T>` is invariant over the parameter `T`
|
= note: the struct `Cell<T>` is invariant over the parameter `T`
|
||||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ error: lifetime may not live long enough
|
||||||
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
|
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
|
||||||
|
|
|
|
||||||
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
|
||||||
| --------- - has type `&'?7 Cell<&'1 u32>`
|
| --------- - has type `&'?6 Cell<&'1 u32>`
|
||||||
| |
|
| |
|
||||||
| has type `&'?5 Cell<&'2 &'?1 u32>`
|
| has type `&'?4 Cell<&'2 &'?1 u32>`
|
||||||
LL | // Only works if 'x: 'y:
|
LL | // Only works if 'x: 'y:
|
||||||
LL | demand_y(x, y, x.get())
|
LL | demand_y(x, y, x.get())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
||||||
|
|
|
@ -16,9 +16,9 @@ error: lifetime may not live long enough
|
||||||
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
|
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
|
||||||
|
|
|
|
||||||
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
|
||||||
| ---------- ---------- has type `&'?8 Cell<&'2 &'?2 u32>`
|
| ---------- ---------- has type `&'?7 Cell<&'2 &'?2 u32>`
|
||||||
| |
|
| |
|
||||||
| has type `&'?6 Cell<&'1 &'?1 u32>`
|
| has type `&'?5 Cell<&'1 &'?1 u32>`
|
||||||
LL | // Only works if 'x: 'y:
|
LL | // Only works if 'x: 'y:
|
||||||
LL | demand_y(x, y, x.get())
|
LL | demand_y(x, y, x.get())
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue