Skip to content

Commit 33a0706

Browse files
authored
Unrolled build for #144666
Rollup merge of #144666 - compiler-errors:correct-late, r=lqd Make sure to account for the right item universal regions in borrowck Fixes #144608. The ICE comes from a mismatch between the liberated late bound regions (i.e. "`ReLateParam`"s) that come from promoting closure outlives, and the regions we have in our region vid mapping from `UniversalRegions`. When building `UniversalRegions`, we end up using the liberated regions from the binder of the closure's signature: https://github.com/rust-lang/rust/blob/c8bb4e8a126cf38cff70cea488a3a423a5321954/compiler/rustc_borrowck/src/universal_regions.rs#L521 Notably, this signature may be anonymized if the closure signature being deduced comes from an external constraints: https://github.com/rust-lang/rust/blob/c8bb4e8a126cf38cff70cea488a3a423a5321954/compiler/rustc_hir_typeck/src/closure.rs#L759-L762 This is true in the test file I committed, where the signature is influenced by the `impl FnMut(&mut ())` RPIT. However, when promoting a type outlives constraint we end up creating a late bound lifetime mapping that disagrees with those liberated late bound regions we constructed in `UniversalRegions`: https://github.com/rust-lang/rust/blob/c8bb4e8a126cf38cff70cea488a3a423a5321954/compiler/rustc_borrowck/src/universal_regions.rs#L299 Specifically, in `for_each_late_bound_region_in_item` (which is called by `for_each_late_bound_region_in_recursive_scope`), we were using `tcx.late_bound_vars` which uses the late bound regions *from the HIR*. This query both undercounts the late bound regions (e.g. those that end up being deduced from bounds), and also doesn't account for the fact that we anonymize them in the signature as mentioned above. https://github.com/rust-lang/rust/blob/c8bb4e8a126cf38cff70cea488a3a423a5321954/compiler/rustc_borrowck/src/universal_regions.rs#L977 This PR fixes that function to use the *correct signature*, which properly considers the bound vars that come from deducing the signature of the closure, and which comes from the closure's args from the `type_of` query.
2 parents 72716b1 + 98d08ff commit 33a0706

16 files changed

+97
-6
lines changed

compiler/rustc_borrowck/src/universal_regions.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -969,13 +969,28 @@ fn for_each_late_bound_region_in_item<'tcx>(
969969
mir_def_id: LocalDefId,
970970
mut f: impl FnMut(ty::Region<'tcx>),
971971
) {
972-
if !tcx.def_kind(mir_def_id).is_fn_like() {
973-
return;
974-
}
972+
let bound_vars = match tcx.def_kind(mir_def_id) {
973+
DefKind::Fn | DefKind::AssocFn => {
974+
tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id))
975+
}
976+
// We extract the bound vars from the deduced closure signature, since we may have
977+
// only deduced that a param in the closure signature is late-bound from a constraint
978+
// that we discover during typeck.
979+
DefKind::Closure => {
980+
let ty = tcx.type_of(mir_def_id).instantiate_identity();
981+
match *ty.kind() {
982+
ty::Closure(_, args) => args.as_closure().sig().bound_vars(),
983+
ty::CoroutineClosure(_, args) => {
984+
args.as_coroutine_closure().coroutine_closure_sig().bound_vars()
985+
}
986+
ty::Coroutine(_, _) | ty::Error(_) => return,
987+
_ => unreachable!("unexpected type for closure: {ty}"),
988+
}
989+
}
990+
_ => return,
991+
};
975992

976-
for (idx, bound_var) in
977-
tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate()
978-
{
993+
for (idx, bound_var) in bound_vars.iter().enumerate() {
979994
if let ty::BoundVariableKind::Region(kind) = bound_var {
980995
let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind);
981996
let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/144608>.
2+
3+
fn example<T: Copy>(x: T) -> impl FnMut(&mut ()) {
4+
move |_: &mut ()| {
5+
move || needs_static_lifetime(x);
6+
//~^ ERROR the parameter type `T` may not live long enough
7+
}
8+
}
9+
10+
fn needs_static_lifetime<T: 'static>(obj: T) {}
11+
12+
fn main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/liberated-region-from-outer-closure.rs:5:17
3+
|
4+
LL | move || needs_static_lifetime(x);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| the parameter type `T` must be valid for the static lifetime...
8+
| ...so that the type `T` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | fn example<T: Copy + 'static>(x: T) -> impl FnMut(&mut ()) {
13+
| +++++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0310`.

tests/ui/nll/closure-requirements/escape-argument-callee.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
99
for<Region(BrAnon), Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 mut &'^1 i32, &'^2 i32)),
1010
(),
1111
]
12+
= note: late-bound region is '?1
13+
= note: late-bound region is '?2
14+
= note: late-bound region is '?3
1215

1316
error: lifetime may not live long enough
1417
--> $DIR/escape-argument-callee.rs:26:45

tests/ui/nll/closure-requirements/escape-argument.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
99
for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 mut &'^1 i32, &'^1 i32)),
1010
(),
1111
]
12+
= note: late-bound region is '?1
13+
= note: late-bound region is '?2
1214

1315
note: no external requirements
1416
--> $DIR/escape-argument.rs:20:1

tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| {
99
for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 &'^0 u32>, std::cell::Cell<&'?2 &'^0 u32>, std::cell::Cell<&'^1 &'?3 u32>, std::cell::Cell<&'^0 u32>, std::cell::Cell<&'^1 u32>)),
1010
(),
1111
]
12+
= note: late-bound region is '?7
13+
= note: late-bound region is '?8
1214
= note: late-bound region is '?4
1315
= note: late-bound region is '?5
1416
= note: late-bound region is '?6

tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
99
for<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 std::cell::Cell<&'?1 &'^1 u32>, &'^2 std::cell::Cell<&'^3 &'?2 u32>, &'^4 std::cell::Cell<&'^1 u32>, &'^5 std::cell::Cell<&'^3 u32>)),
1010
(),
1111
]
12+
= note: late-bound region is '?5
13+
= note: late-bound region is '?6
14+
= note: late-bound region is '?7
15+
= note: late-bound region is '?8
16+
= note: late-bound region is '?9
17+
= note: late-bound region is '?10
1218
= note: late-bound region is '?3
1319
= note: late-bound region is '?4
1420
= note: number of external vids: 5

tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ LL | foo(cell, |cell_a, cell_x| {
99
for<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&'^0 u32>)),
1010
(),
1111
]
12+
= note: late-bound region is '?2
1213

1314
error[E0521]: borrowed data escapes outside of closure
1415
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:22:9
@@ -43,6 +44,7 @@ LL | foo(cell, |cell_a, cell_x| {
4344
for<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&'^0 u32>)),
4445
(),
4546
]
47+
= note: late-bound region is '?2
4648
= note: number of external vids: 2
4749
= note: where '?1: '?0
4850

tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
99
for<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 std::cell::Cell<&'?1 &'^1 u32>, &'^2 std::cell::Cell<&'^1 u32>, &'^3 std::cell::Cell<&'^4 u32>)),
1010
(),
1111
]
12+
= note: late-bound region is '?4
13+
= note: late-bound region is '?5
14+
= note: late-bound region is '?6
15+
= note: late-bound region is '?7
16+
= note: late-bound region is '?8
1217
= note: late-bound region is '?2
1318
= note: late-bound region is '?3
1419
= note: number of external vids: 4

tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
99
for<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 std::cell::Cell<&'?1 &'^1 u32>, &'^2 std::cell::Cell<&'?2 &'^3 u32>, &'^4 std::cell::Cell<&'^1 u32>, &'^5 std::cell::Cell<&'^3 u32>)),
1010
(),
1111
]
12+
= note: late-bound region is '?5
13+
= note: late-bound region is '?6
14+
= note: late-bound region is '?7
15+
= note: late-bound region is '?8
16+
= note: late-bound region is '?9
17+
= note: late-bound region is '?10
1218
= note: late-bound region is '?3
1319
= note: late-bound region is '?4
1420
= note: number of external vids: 5

0 commit comments

Comments
 (0)