Skip to content

Commit 88e9417

Browse files
authored
Rollup merge of #98835 - aliemjay:relate_closure_substs, r=nikomatsakis
relate `closure_substs.parent_substs()` to parent fn in NLL Fixes #98589 The discrepancy between early- and late-bound lifetimes is because we map early-bound lifetimes into those found in the `closure_substs` while late-bound lifetimes are mapped into liberated free regions: https://github.com/rust-lang/rust/blob/5f98537eb7b5f42c246a52c550813c3cff336069/compiler/rustc_borrowck/src/universal_regions.rs#L255-L261 r? `@rust-lang/types`
2 parents 7b0360e + 78adc01 commit 88e9417

File tree

5 files changed

+146
-1
lines changed

5 files changed

+146
-1
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+28
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,34 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
26192619
);
26202620
}
26212621

2622+
// Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
2623+
let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2624+
let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
2625+
2626+
let parent_substs = match tcx.def_kind(def_id) {
2627+
DefKind::Closure => substs.as_closure().parent_substs(),
2628+
DefKind::Generator => substs.as_generator().parent_substs(),
2629+
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
2630+
other => bug!("unexpected item {:?}", other),
2631+
};
2632+
let parent_substs = tcx.mk_substs(parent_substs.iter());
2633+
2634+
assert_eq!(typeck_root_substs.len(), parent_substs.len());
2635+
if let Err(_) = self.eq_substs(
2636+
typeck_root_substs,
2637+
parent_substs,
2638+
location.to_locations(),
2639+
ConstraintCategory::BoringNoLocation,
2640+
) {
2641+
span_mirbug!(
2642+
self,
2643+
def_id,
2644+
"could not relate closure to parent {:?} != {:?}",
2645+
typeck_root_substs,
2646+
parent_substs
2647+
);
2648+
}
2649+
26222650
tcx.predicates_of(def_id).instantiate(tcx, substs)
26232651
}
26242652

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+17
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
3838
.relate(a, b)?;
3939
Ok(())
4040
}
41+
42+
/// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
43+
pub(super) fn eq_substs(
44+
&mut self,
45+
a: ty::SubstsRef<'tcx>,
46+
b: ty::SubstsRef<'tcx>,
47+
locations: Locations,
48+
category: ConstraintCategory<'tcx>,
49+
) -> Fallible<()> {
50+
TypeRelating::new(
51+
self.infcx,
52+
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
53+
ty::Variance::Invariant,
54+
)
55+
.relate(a, b)?;
56+
Ok(())
57+
}
4158
}
4259

4360
struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {

src/librustdoc/clean/auto_trait.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ pub(crate) struct AutoTraitFinder<'a, 'tcx> {
2424
pub(crate) cx: &'a mut core::DocContext<'tcx>,
2525
}
2626

27-
impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
27+
impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx>
28+
where
29+
'tcx: 'a, // should be an implied bound; rustc bug #98852.
30+
{
2831
pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> Self {
2932
AutoTraitFinder { cx }
3033
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Regression test for #98589.
2+
// Previously, named lifetime `'a` that appears in the closure was unrelated to `'a`
3+
// that appears in the parent function iff `'a` is early-bound.
4+
// This made the following tests pass borrowck.
5+
6+
// check-fail
7+
8+
// The bound `'a: 'a` ensures that `'a` is early-bound.
9+
fn test_early_early<'a: 'a, 'b: 'b>() {
10+
|| { None::<&'a &'b ()>; };
11+
//~^ ERROR lifetime may not live long enough
12+
}
13+
14+
fn test_early_late<'a: 'a, 'b>() {
15+
|| { None::<&'a &'b ()>; };
16+
//~^ ERROR lifetime may not live long enough
17+
}
18+
19+
// No early-bound lifetime; included for completeness.
20+
fn test_late_late<'a, 'b>() {
21+
|| { None::<&'a &'b ()>; };
22+
//~^ ERROR lifetime may not live long enough
23+
}
24+
25+
fn test_early_type<'a: 'a, T>() {
26+
|| { None::<&'a T>; };
27+
//~^ ERROR the parameter type `T` may not live long enough
28+
}
29+
30+
// No early-bound lifetime; included for completeness.
31+
fn test_late_type<'a, T>() {
32+
|| { None::<&'a T>; };
33+
//~^ ERROR the parameter type `T` may not live long enough
34+
}
35+
36+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:5
3+
|
4+
LL | fn test_early_early<'a: 'a, 'b: 'b>() {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | || { None::<&'a &'b ()>; };
9+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
10+
|
11+
= help: consider adding the following bound: `'b: 'a`
12+
13+
error: lifetime may not live long enough
14+
--> $DIR/issue-98589-closures-relate-named-regions.rs:15:10
15+
|
16+
LL | fn test_early_late<'a: 'a, 'b>() {
17+
| -- -- lifetime `'b` defined here
18+
| |
19+
| lifetime `'a` defined here
20+
LL | || { None::<&'a &'b ()>; };
21+
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
22+
|
23+
= help: consider adding the following bound: `'b: 'a`
24+
25+
error: lifetime may not live long enough
26+
--> $DIR/issue-98589-closures-relate-named-regions.rs:21:10
27+
|
28+
LL | fn test_late_late<'a, 'b>() {
29+
| -- -- lifetime `'b` defined here
30+
| |
31+
| lifetime `'a` defined here
32+
LL | || { None::<&'a &'b ()>; };
33+
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
34+
|
35+
= help: consider adding the following bound: `'b: 'a`
36+
37+
error[E0309]: the parameter type `T` may not live long enough
38+
--> $DIR/issue-98589-closures-relate-named-regions.rs:26:5
39+
|
40+
LL | || { None::<&'a T>; };
41+
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
42+
|
43+
help: consider adding an explicit lifetime bound...
44+
|
45+
LL | fn test_early_type<'a: 'a, T: 'a>() {
46+
| ++++
47+
48+
error[E0309]: the parameter type `T` may not live long enough
49+
--> $DIR/issue-98589-closures-relate-named-regions.rs:32:5
50+
|
51+
LL | || { None::<&'a T>; };
52+
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
53+
|
54+
help: consider adding an explicit lifetime bound...
55+
|
56+
LL | fn test_late_type<'a, T: 'a>() {
57+
| ++++
58+
59+
error: aborting due to 5 previous errors
60+
61+
For more information about this error, try `rustc --explain E0309`.

0 commit comments

Comments
 (0)