NLL: relate closure to parent fn
This commit is contained in:
parent
fe3342816a
commit
f74d06c2d1
@ -2619,6 +2619,28 @@ fn prove_closure_bounds(
|
||||
);
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,23 @@ pub(super) fn relate_types(
|
||||
.relate(a, b)?;
|
||||
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> {
|
||||
|
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…
Reference in New Issue
Block a user