NLL: relate closure to parent fn
This commit is contained in:
parent
fe3342816a
commit
f74d06c2d1
4 changed files with 136 additions and 0 deletions
|
@ -2619,6 +2619,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
|
||||||
|
let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
|
||||||
|
let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
|
||||||
|
|
||||||
|
let parent_substs = match tcx.def_kind(def_id) {
|
||||||
|
DefKind::Closure => substs.as_closure().parent_substs(),
|
||||||
|
DefKind::Generator => substs.as_generator().parent_substs(),
|
||||||
|
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
|
||||||
|
other => bug!("unexpected item {:?}", other),
|
||||||
|
};
|
||||||
|
let parent_substs = tcx.mk_substs(parent_substs.iter());
|
||||||
|
|
||||||
|
assert_eq!(typeck_root_substs.len(), parent_substs.len());
|
||||||
|
if let Err(_) = self.eq_substs(
|
||||||
|
typeck_root_substs,
|
||||||
|
parent_substs,
|
||||||
|
Locations::Single(location),
|
||||||
|
ConstraintCategory::BoringNoLocation,
|
||||||
|
) {
|
||||||
|
bug!("we shouldn't error, this should only impose region constraints");
|
||||||
|
}
|
||||||
|
|
||||||
tcx.predicates_of(def_id).instantiate(tcx, substs)
|
tcx.predicates_of(def_id).instantiate(tcx, substs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
.relate(a, b)?;
|
.relate(a, b)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
|
||||||
|
pub(super) fn eq_substs(
|
||||||
|
&mut self,
|
||||||
|
a: ty::SubstsRef<'tcx>,
|
||||||
|
b: ty::SubstsRef<'tcx>,
|
||||||
|
locations: Locations,
|
||||||
|
category: ConstraintCategory<'tcx>,
|
||||||
|
) -> Fallible<()> {
|
||||||
|
let mut relation = TypeRelating::new(
|
||||||
|
self.infcx,
|
||||||
|
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
|
||||||
|
ty::Variance::Invariant,
|
||||||
|
);
|
||||||
|
ty::relate::relate_substs(&mut relation, a, b)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
|
|
36
src/test/ui/nll/issue-98589-closures-relate-named-regions.rs
Normal file
36
src/test/ui/nll/issue-98589-closures-relate-named-regions.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Regression test for #98589.
|
||||||
|
// Previously, named lifetime `'a` that appears in the closure was unrelated to `'a`
|
||||||
|
// that appears in the parent function iff `'a` is early-bound.
|
||||||
|
// This made the following tests pass borrowck.
|
||||||
|
|
||||||
|
// check-fail
|
||||||
|
|
||||||
|
// The bound `'a: 'a` ensures that `'a` is early-bound.
|
||||||
|
fn test_early_early<'a: 'a, 'b: 'b>() {
|
||||||
|
|| { None::<&'a &'b ()>; };
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_early_late<'a: 'a, 'b>() {
|
||||||
|
|| { None::<&'a &'b ()>; };
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
// No early-bound lifetime; included for completeness.
|
||||||
|
fn test_late_late<'a, 'b>() {
|
||||||
|
|| { None::<&'a &'b ()>; };
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_early_type<'a: 'a, T>() {
|
||||||
|
|| { None::<&'a T>; };
|
||||||
|
//~^ ERROR the parameter type `T` may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
// No early-bound lifetime; included for completeness.
|
||||||
|
fn test_late_type<'a, T>() {
|
||||||
|
|| { None::<&'a T>; };
|
||||||
|
//~^ ERROR the parameter type `T` may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,61 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:5
|
||||||
|
|
|
||||||
|
LL | fn test_early_early<'a: 'a, 'b: 'b>() {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | || { None::<&'a &'b ()>; };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98589-closures-relate-named-regions.rs:15:10
|
||||||
|
|
|
||||||
|
LL | fn test_early_late<'a: 'a, 'b>() {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | || { None::<&'a &'b ()>; };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98589-closures-relate-named-regions.rs:21:10
|
||||||
|
|
|
||||||
|
LL | fn test_late_late<'a, 'b>() {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | || { None::<&'a &'b ()>; };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
|
error[E0309]: the parameter type `T` may not live long enough
|
||||||
|
--> $DIR/issue-98589-closures-relate-named-regions.rs:26:5
|
||||||
|
|
|
||||||
|
LL | || { None::<&'a T>; };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound...
|
||||||
|
|
|
||||||
|
LL | fn test_early_type<'a: 'a, T: 'a>() {
|
||||||
|
| ++++
|
||||||
|
|
||||||
|
error[E0309]: the parameter type `T` may not live long enough
|
||||||
|
--> $DIR/issue-98589-closures-relate-named-regions.rs:32:5
|
||||||
|
|
|
||||||
|
LL | || { None::<&'a T>; };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound...
|
||||||
|
|
|
||||||
|
LL | fn test_late_type<'a, T: 'a>() {
|
||||||
|
| ++++
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0309`.
|
Loading…
Add table
Add a link
Reference in a new issue