summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorStuart Cook <Zalathar@users.noreply.github.com>2025-07-30 17:59:40 +1000
committerGitHub <noreply@github.com>2025-07-30 17:59:40 +1000
commit08e26fc67813470739e171be117cf76c4d96b9a9 (patch)
tree8a5dbb582a15c2401520268a6ac6350e60e7d8cf /tests
parentba8295019ec8fcd838bcf8ac0575138ddb91203c (diff)
parent98d08ff014840a15244374178e8b9ed02da3d4ca (diff)
downloadrust-08e26fc67813470739e171be117cf76c4d96b9a9.tar.gz
rust-08e26fc67813470739e171be117cf76c4d96b9a9.zip
Rollup merge of #144666 - compiler-errors:correct-late, r=lqd
Make sure to account for the right item universal regions in borrowck

Fixes https://github.com/rust-lang/rust/issues/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.
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/borrowck/liberated-region-from-outer-closure.rs12
-rw-r--r--tests/ui/borrowck/liberated-region-from-outer-closure.stderr17
-rw-r--r--tests/ui/nll/closure-requirements/escape-argument-callee.stderr3
-rw-r--r--tests/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr6
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr5
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr6
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr5
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr6
-rw-r--r--tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr2
-rw-r--r--tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr4
15 files changed, 76 insertions, 0 deletions
diff --git a/tests/ui/borrowck/liberated-region-from-outer-closure.rs b/tests/ui/borrowck/liberated-region-from-outer-closure.rs
new file mode 100644
index 00000000000..dcc6370b4a1
--- /dev/null
+++ b/tests/ui/borrowck/liberated-region-from-outer-closure.rs
@@ -0,0 +1,12 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/144608>.
+
+fn example<T: Copy>(x: T) -> impl FnMut(&mut ()) {
+    move |_: &mut ()| {
+        move || needs_static_lifetime(x);
+        //~^ ERROR the parameter type `T` may not live long enough
+    }
+}
+
+fn needs_static_lifetime<T: 'static>(obj: T) {}
+
+fn main() {}
diff --git a/tests/ui/borrowck/liberated-region-from-outer-closure.stderr b/tests/ui/borrowck/liberated-region-from-outer-closure.stderr
new file mode 100644
index 00000000000..98b45ac499d
--- /dev/null
+++ b/tests/ui/borrowck/liberated-region-from-outer-closure.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/liberated-region-from-outer-closure.rs:5:17
+   |
+LL |         move || needs_static_lifetime(x);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 |
+   |                 the parameter type `T` must be valid for the static lifetime...
+   |                 ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn example<T: Copy + 'static>(x: T) -> impl FnMut(&mut ()) {
+   |                    +++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
index a445534c8d8..2742162c821 100644
--- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -9,6 +9,9 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
                for<Region(BrAnon), Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 mut &'^1 i32, &'^2 i32)),
                (),
            ]
+   = note: late-bound region is '?1
+   = note: late-bound region is '?2
+   = note: late-bound region is '?3
 
 error: lifetime may not live long enough
   --> $DIR/escape-argument-callee.rs:26:45
diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr
index 7fd1cd8c3e4..22cb0367ad8 100644
--- a/tests/ui/nll/closure-requirements/escape-argument.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument.stderr
@@ -9,6 +9,8 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 mut &'^1 i32, &'^1 i32)),
                (),
            ]
+   = note: late-bound region is '?1
+   = note: late-bound region is '?2
 
 note: no external requirements
   --> $DIR/escape-argument.rs:20:1
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 60087ec992b..134ce99014d 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -9,6 +9,8 @@ LL |         |_outlives1, _outlives2, _outlives3, x, y| {
                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>)),
                (),
            ]
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
    = note: late-bound region is '?4
    = note: late-bound region is '?5
    = note: late-bound region is '?6
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 7325a9de8b2..f5527eeb2cd 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -9,6 +9,12 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
                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>)),
                (),
            ]
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
+   = note: late-bound region is '?9
+   = note: late-bound region is '?10
    = note: late-bound region is '?3
    = note: late-bound region is '?4
    = note: number of external vids: 5
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 621c1ea083b..e13653f3423 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -9,6 +9,7 @@ LL |     foo(cell, |cell_a, cell_x| {
                for<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&'^0 u32>)),
                (),
            ]
+   = note: late-bound region is '?2
 
 error[E0521]: borrowed data escapes outside of closure
   --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:22:9
@@ -43,6 +44,7 @@ LL |     foo(cell, |cell_a, cell_x| {
                for<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&'^0 u32>)),
                (),
            ]
+   = note: late-bound region is '?2
    = note: number of external vids: 2
    = note: where '?1: '?0
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index b9365c94a1b..9e9eae98597 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -9,6 +9,11 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
                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>)),
                (),
            ]
+   = note: late-bound region is '?4
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
    = note: late-bound region is '?2
    = note: late-bound region is '?3
    = note: number of external vids: 4
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index e5d2867103c..303fcd4cdfc 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -9,6 +9,12 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
                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>)),
                (),
            ]
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
+   = note: late-bound region is '?9
+   = note: late-bound region is '?10
    = note: late-bound region is '?3
    = note: late-bound region is '?4
    = note: number of external vids: 5
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
index a14bfb06e83..aa75b4c811c 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -9,6 +9,8 @@ LL |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 &'^0 u32>, std::cell::Cell<&'^1 &'?2 u32>, std::cell::Cell<&'^0 u32>, std::cell::Cell<&'^1 u32>)),
                (),
            ]
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
    = note: late-bound region is '?3
    = note: late-bound region is '?4
    = note: number of external vids: 5
diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index 49c65d77ddd..30ee259d3dc 100644
--- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -9,6 +9,8 @@ LL |         |_outlives1, _outlives2, x, y| {
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 &'^0 u32>, std::cell::Cell<&'^1 &'?2 u32>, std::cell::Cell<&'^0 u32>, std::cell::Cell<&'^1 u32>)),
                (),
            ]
+   = note: late-bound region is '?4
+   = note: late-bound region is '?5
    = note: late-bound region is '?3
    = note: number of external vids: 4
    = note: where '?1: '?2
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index f48ed2823dd..6b04e346c69 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -9,6 +9,11 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
                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<&'^3 u32>, &'^4 std::cell::Cell<&'^1 u32>)),
                (),
            ]
+   = note: late-bound region is '?4
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
    = note: late-bound region is '?2
    = note: late-bound region is '?3
 
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index a090e94593f..ae2129c65f2 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -9,6 +9,12 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
                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>)),
                (),
            ]
+   = note: late-bound region is '?5
+   = note: late-bound region is '?6
+   = note: late-bound region is '?7
+   = note: late-bound region is '?8
+   = note: late-bound region is '?9
+   = note: late-bound region is '?10
    = note: late-bound region is '?3
    = note: late-bound region is '?4
 
diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index bc5c04a27a3..1f1cce1e885 100644
--- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -9,6 +9,8 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((&'^0 i32, &'^1 i32)) -> &'^0 i32,
                (),
            ]
+   = note: late-bound region is '?1
+   = note: late-bound region is '?2
 
 error: lifetime may not live long enough
   --> $DIR/return-wrong-bound-region.rs:11:23
diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index e58764354c0..396e149554c 100644
--- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -9,6 +9,8 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &'^0 ()>>, &'^1 T)),
                (),
            ]
+   = note: late-bound region is '?2
+   = note: late-bound region is '?3
    = note: number of external vids: 2
    = note: where T: '?1
 
@@ -31,6 +33,8 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
                for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &'^0 ()>>, &'^1 T)),
                (),
            ]
+   = note: late-bound region is '?3
+   = note: late-bound region is '?4
    = note: late-bound region is '?2
    = note: number of external vids: 3
    = note: where T: '?1