WF check lifetime bounds for locals with type params

This commit is contained in:
Shoyu Vanilla 2025-11-27 22:57:19 +09:00
parent 7ad4e69ad5
commit f5a8b86695
21 changed files with 121 additions and 25 deletions

View file

@ -581,7 +581,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
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> {

View file

@ -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<()>);

View file

@ -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<()>);

View file

@ -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);

View file

@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
let _8: usize;
scope 3 {
scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
let _9: *mut u32;
let mut _9: *mut u32;
scope 7 {
let _10: *mut u32;
scope 8 {

View file

@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
let _8: usize;
scope 3 {
scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
let _9: *mut u32;
let mut _9: *mut u32;
scope 7 {
let _10: *mut u32;
scope 8 {

View file

@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
let mut _6: usize;
}
scope 4 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _10: *const u32;
let mut _10: *const u32;
scope 5 {
let _11: *const u32;
scope 6 {

View file

@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
let mut _6: usize;
}
scope 4 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _10: *const u32;
let mut _10: *const u32;
scope 5 {
let _11: *const u32;
scope 6 {

View file

@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
let _7: usize;
scope 3 {
scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _8: *const u32;
let mut _8: *const u32;
scope 7 {
let _9: *const u32;
scope 8 {

View file

@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
let _7: usize;
scope 3 {
scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _8: *const u32;
let mut _8: *const u32;
scope 7 {
let _9: *const u32;
scope 8 {

View file

@ -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::<T>(),
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^
| |
| 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::<T>(),
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds

View file

@ -2,15 +2,10 @@ error[E0308]: mismatched types
--> $DIR/candidate-from-env-universe-err-project.rs:38:5
|
LL | projection_bound::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<T as Trait<'static>>::Assoc`
found associated type `<T as Trait<'a>>::Assoc`
note: the lifetime requirement is introduced here
--> $DIR/candidate-from-env-universe-err-project.rs:19:42
|
LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
| ^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/candidate-from-env-universe-err-project.rs:52:30

View file

@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue-98693.rs:16:9
|
LL | assert_static::<T>();
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the type `T` will meet its required lifetime bounds

View file

@ -2,7 +2,7 @@ error: `S` does not live long enough
--> $DIR/type-test-universe.rs:11:5
|
LL | outlives_forall::<S>();
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^
error: lifetime may not live long enough
--> $DIR/type-test-universe.rs:17:5

View file

@ -2,7 +2,7 @@ error: `T` does not live long enough
--> $DIR/forall-wf-ref-reflexive.rs:12:5
|
LL | self_wf2::<T>();
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -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: 'static>(T);
fn test<T>() {
let _ = None::<Static<T>>;
//~^ ERROR the parameter type `T` may not live long enough
}
fn main() {}

View file

@ -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::<Static<T>>;
| ^^^^^^^^^^^^^^^^^
| |
| 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<T: 'static>() {
| +++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0310`.

View file

@ -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<OnceCell<Box<dyn Display + 'static>>>;
trait IntoDyn<T> {
fn into_dyn(input: T, output: Storage);
}
struct Inner<T: Display + 'static>(PhantomData<T>);
impl<T: Display> IntoDyn<T> for Inner<T> {
fn into_dyn(input: T, output: Storage) {
output.set(Box::new(input)).ok().unwrap();
}
}
struct Outer<T, U: IntoDyn<T>> {
input: Option<T>,
output: Storage,
_phantom: PhantomData<U>,
}
impl<T, U: IntoDyn<T>> Drop for Outer<T, U> {
fn drop(&mut self) {
U::into_dyn(self.input.take().unwrap(), self.output.clone());
}
}
fn extend<T: Display>(x: T) -> Box<dyn Display + 'static> {
let storage = Rc::new(OnceCell::new());
{
// This has to error due to an unsatisfied outlives bound on
// `Inner<T: 'static>` as its implicit drop relies on that
// bound.
let _ =
Outer::<T, Inner<T>> { 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}");
}

View file

@ -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::<T, Inner<T>> { 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<T: Display + 'static>(x: T) -> Box<dyn Display + 'static> {
| +++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0310`.

View file

@ -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::<A>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the parameter type `A` must be valid for the static lifetime...
| ...so that the type `A` will meet its required lifetime bounds

View file

@ -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::<A>()
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^
| |
| the parameter type `A` must be valid for the static lifetime...
| ...so that the type `A` will meet its required lifetime bounds