diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f138f2653203e..240c9a5223be0 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -969,13 +969,28 @@ fn for_each_late_bound_region_in_item<'tcx>( mir_def_id: LocalDefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if !tcx.def_kind(mir_def_id).is_fn_like() { - return; - } + let bound_vars = match tcx.def_kind(mir_def_id) { + DefKind::Fn | DefKind::AssocFn => { + tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)) + } + // We extract the bound vars from the deduced closure signature, since we may have + // only deduced that a param in the closure signature is late-bound from a constraint + // that we discover during typeck. + DefKind::Closure => { + let ty = tcx.type_of(mir_def_id).instantiate_identity(); + match *ty.kind() { + ty::Closure(_, args) => args.as_closure().sig().bound_vars(), + ty::CoroutineClosure(_, args) => { + args.as_coroutine_closure().coroutine_closure_sig().bound_vars() + } + ty::Coroutine(_, _) | ty::Error(_) => return, + _ => unreachable!("unexpected type for closure: {ty}"), + } + } + _ => return, + }; - for (idx, bound_var) in - tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)).iter().enumerate() - { + for (idx, bound_var) in bound_vars.iter().enumerate() { if let ty::BoundVariableKind::Region(kind) = bound_var { let kind = ty::LateParamRegionKind::from_bound(ty::BoundVar::from_usize(idx), kind); let liberated_region = ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), kind); 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 0000000000000..dcc6370b4a12a --- /dev/null +++ b/tests/ui/borrowck/liberated-region-from-outer-closure.rs @@ -0,0 +1,12 @@ +// Regression test for . + +fn example(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(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 0000000000000..98b45ac499dcf --- /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(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 a445534c8d801..2742162c82119 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 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 7fd1cd8c3e422..22cb0367ad875 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 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 60087ec992bd6..134ce99014d8a 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 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 7325a9de8b294..f5527eeb2cdba 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 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 621c1ea083b25..e13653f342342 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 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 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 b9365c94a1bed..9e9eae985973a 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 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 e5d2867103cfc..303fcd4cdfcf3 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 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 a14bfb06e831e..aa75b4c811c19 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 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 49c65d77ddded..30ee259d3dceb 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 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 f48ed2823ddb1..6b04e346c6971 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 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 a090e94593fe6..ae2129c65f2c0 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 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 bc5c04a27a3e6..1f1cce1e88546 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 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 e58764354c032..396e149554ce8 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 extern "rust-call" fn((std::option::Option>, &'^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 extern "rust-call" fn((std::option::Option>, &'^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