From f5a8b86695fb7109d494f8aed595318e76957d36 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 27 Nov 2025 22:57:19 +0900 Subject: [PATCH 1/2] WF check lifetime bounds for locals with type params --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 2 +- ....run2-{closure#0}.Inline.panic-unwind.diff | 2 +- ...undant.InstSimplify-after-simplifycfg.diff | 10 ++-- ...mut_range.PreCodegen.after.panic-abort.mir | 2 +- ...ut_range.PreCodegen.after.panic-unwind.mir | 2 +- ...dex_range.PreCodegen.after.panic-abort.mir | 2 +- ...ex_range.PreCodegen.after.panic-unwind.mir | 2 +- ...ked_range.PreCodegen.after.panic-abort.mir | 2 +- ...ed_range.PreCodegen.after.panic-unwind.mir | 2 +- tests/ui/consts/issue-102117.stderr | 4 +- ...om-env-universe-err-project.current.stderr | 7 +-- tests/ui/nll/issue-98693.stderr | 2 +- tests/ui/nll/type-test-universe.stderr | 2 +- .../ui/regions/forall-wf-ref-reflexive.stderr | 2 +- .../wf-bound-region-in-local-issue-115175.rs | 11 ++++ ...-bound-region-in-local-issue-115175.stderr | 17 +++++++ ...-region-in-local-soundness-issue-148854.rs | 51 +++++++++++++++++++ ...ion-in-local-soundness-issue-148854.stderr | 17 +++++++ .../implied_lifetime_wf_check3.stderr | 2 +- .../implied_lifetime_wf_check4_static.stderr | 2 +- 21 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 tests/ui/regions/wf-bound-region-in-local-issue-115175.rs create mode 100644 tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr create mode 100644 tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs create mode 100644 tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cfb798b31ea0..e8d5ff017cf8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -581,7 +581,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { where T: TypeVisitable>, { - t.has_free_regions() || t.has_aliases() || t.has_infer_types() + // FIXME(mgca): should this also count stuff with infer consts + t.has_free_regions() || t.has_aliases() || t.has_infer_types() || t.has_param() } pub(crate) fn node_ty(&self, id: HirId) -> Ty<'tcx> { diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 4c1b25c786ef..9f4d085e19d1 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -197,8 +197,8 @@ + StorageLive(_40); + _40 = &raw mut _19; + _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_40); + _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageDead(_40); + StorageLive(_42); + _42 = Option::<()>::None; + _35 = copy ((*_37).0: std::option::Option<()>); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 59417ce64651..50cf7164028a 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -208,8 +208,8 @@ + StorageLive(_40); + _40 = &raw mut _19; + _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_40); + _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageDead(_40); + StorageLive(_42); + _42 = Option::<()>::None; + _35 = copy ((*_37).0: std::option::Option<()>); diff --git a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff index afa25ecdbfba..75038e899b3e 100644 --- a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff @@ -9,6 +9,7 @@ let mut _4: *const &u8; scope 1 (inlined generic_cast::<&u8, &u8>) { let mut _5: *const &u8; + let mut _6: *const &u8; } bb0: { @@ -17,9 +18,12 @@ StorageLive(_4); _4 = copy _1; StorageLive(_5); - _5 = copy _4; -- _3 = move _5 as *const &u8 (PtrToPtr); -+ _3 = move _5; + StorageLive(_6); + _6 = copy _4; +- _5 = move _6 as *const &u8 (PtrToPtr); ++ _5 = move _6; + _3 = copy _5; + StorageDead(_6); StorageDead(_5); StorageDead(_4); - _2 = move _3 as *const &u8 (PtrToPtr); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 6fb1637a6e02..8444157a1550 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> let _8: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::) { - let _9: *mut u32; + let mut _9: *mut u32; scope 7 { let _10: *mut u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 6fb1637a6e02..8444157a1550 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> let _8: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::) { - let _9: *mut u32; + let mut _9: *mut u32; scope 7 { let _10: *mut u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir index 2df2c4b85b8f..54be39b4293f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir @@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range) -> &[u32] { let mut _6: usize; } scope 4 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _10: *const u32; + let mut _10: *const u32; scope 5 { let _11: *const u32; scope 6 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir index d4b86b9633ac..b258603a3d0d 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range) -> &[u32] { let mut _6: usize; } scope 4 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _10: *const u32; + let mut _10: *const u32; scope 5 { let _11: *const u32; scope 6 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir index ad1ca5dff43a..7e9d9d24d619 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir @@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - let _7: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _8: *const u32; + let mut _8: *const u32; scope 7 { let _9: *const u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir index ad1ca5dff43a..7e9d9d24d619 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir @@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - let _7: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _8: *const u32; + let mut _8: *const u32; scope 7 { let _9: *const u32; scope 8 { diff --git a/tests/ui/consts/issue-102117.stderr b/tests/ui/consts/issue-102117.stderr index cea355d01d7b..4440680bd7f1 100644 --- a/tests/ui/consts/issue-102117.stderr +++ b/tests/ui/consts/issue-102117.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:17:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds @@ -16,7 +16,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:17:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr index 395dd068e237..90d9eb3922e0 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr @@ -2,15 +2,10 @@ error[E0308]: mismatched types --> $DIR/candidate-from-env-universe-err-project.rs:38:5 | LL | projection_bound::(); - | ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected associated type `>::Assoc` found associated type `>::Assoc` -note: the lifetime requirement is introduced here - --> $DIR/candidate-from-env-universe-err-project.rs:19:42 - | -LL | fn projection_bound Trait<'a, Assoc = usize>>() {} - | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/candidate-from-env-universe-err-project.rs:52:30 diff --git a/tests/ui/nll/issue-98693.stderr b/tests/ui/nll/issue-98693.stderr index b5e281538f9c..cf69fbd5aeed 100644 --- a/tests/ui/nll/issue-98693.stderr +++ b/tests/ui/nll/issue-98693.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-98693.rs:16:9 | LL | assert_static::(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/nll/type-test-universe.stderr b/tests/ui/nll/type-test-universe.stderr index 54b48c1597bd..c9dcb69f08f5 100644 --- a/tests/ui/nll/type-test-universe.stderr +++ b/tests/ui/nll/type-test-universe.stderr @@ -2,7 +2,7 @@ error: `S` does not live long enough --> $DIR/type-test-universe.rs:11:5 | LL | outlives_forall::(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/type-test-universe.rs:17:5 diff --git a/tests/ui/regions/forall-wf-ref-reflexive.stderr b/tests/ui/regions/forall-wf-ref-reflexive.stderr index 5ee7cc7866c9..71debe7c297b 100644 --- a/tests/ui/regions/forall-wf-ref-reflexive.stderr +++ b/tests/ui/regions/forall-wf-ref-reflexive.stderr @@ -2,7 +2,7 @@ error: `T` does not live long enough --> $DIR/forall-wf-ref-reflexive.rs:12:5 | LL | self_wf2::(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs b/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs new file mode 100644 index 000000000000..b19f96357ad6 --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs @@ -0,0 +1,11 @@ +// A regression test for https://github.com/rust-lang/rust/issues/115175. +// This used to compile without error despite of unsatisfied outlives bound `T: 'static` on local. + +struct Static(T); + +fn test() { + let _ = None::>; + //~^ ERROR the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr b/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr new file mode 100644 index 000000000000..1a1b142b9d1d --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-bound-region-in-local-issue-115175.rs:7:13 + | +LL | let _ = None::>; + | ^^^^^^^^^^^^^^^^^ + | | + | 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 test() { + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs new file mode 100644 index 000000000000..b21669cf7842 --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs @@ -0,0 +1,51 @@ +// A regression test for https://github.com/rust-lang/rust/issues/148854. + +use std::cell::OnceCell; +use std::fmt::Display; +use std::marker::PhantomData; +use std::rc::Rc; + +type Storage = Rc>>; + +trait IntoDyn { + fn into_dyn(input: T, output: Storage); +} + +struct Inner(PhantomData); +impl IntoDyn for Inner { + fn into_dyn(input: T, output: Storage) { + output.set(Box::new(input)).ok().unwrap(); + } +} + +struct Outer> { + input: Option, + output: Storage, + _phantom: PhantomData, +} +impl> Drop for Outer { + fn drop(&mut self) { + U::into_dyn(self.input.take().unwrap(), self.output.clone()); + } +} + +fn extend(x: T) -> Box { + let storage = Rc::new(OnceCell::new()); + { + // This has to error due to an unsatisfied outlives bound on + // `Inner` as its implicit drop relies on that + // bound. + let _ = + Outer::> { input: Some(x), output: storage.clone(), _phantom: PhantomData }; + //~^ ERROR: the parameter type `T` may not live long enough + } + Rc::into_inner(storage).unwrap().into_inner().unwrap() +} + +fn main() { + let wrong = { + let data = String::from("abc"); + extend::<&String>(&data) + }; + println!("{wrong}"); +} diff --git a/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr new file mode 100644 index 000000000000..d79daaf2a6ad --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-bound-region-in-local-soundness-issue-148854.rs:39:13 + | +LL | Outer::> { input: Some(x), output: storage.clone(), _phantom: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | 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 extend(x: T) -> Box { + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr index 7311f5882f75..bbc0b91cd503 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -28,7 +28,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check3.rs:55:5 | LL | test_type_param::assert_static::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | the parameter type `A` must be valid for the static lifetime... | ...so that the type `A` will meet its required lifetime bounds diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index 3cec4bbb0993..710e4a5ce9e8 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -21,7 +21,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check4_static.rs:15:5 | LL | assert_static::() - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | | | the parameter type `A` must be valid for the static lifetime... | ...so that the type `A` will meet its required lifetime bounds From 6a3baf6f2764e404f282119165b78ef68436edcc Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 12 Feb 2026 13:48:12 +0100 Subject: [PATCH 2/2] CI: rfl: add temporary commit for compiler bug The compiler is fixing a bug [1] that Rust for Linux happened to trigger, thus temporarily add Benno's patch to the CI job. As usual, the patch will eventually make it to the Linux kernel so that both sides are good. Cc: Benno Lossin Link: https://github.com/rust-lang/rust/pull/149389 [1] Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 535250557740..0af0328c5f2f 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -3,7 +3,8 @@ set -euo pipefail # https://github.com/rust-lang/rust/pull/151534 -LINUX_VERSION=eb268c7972f65fa0b11b051c5ef2b92747bb2b62 +# https://github.com/rust-lang/rust/pull/149389 +LINUX_VERSION=167ea5357eb7c3a39200627a36dfbfe249576192 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt