Auto merge of #149389 - ShoyuVanilla:local-region-param-wf, r=lcnr
WF check lifetime bounds for locals with type params FCP proposal in https://github.com/rust-lang/rust/pull/149389#issuecomment-3669689488 Fixes rust-lang/rust#115175 Fixes rust-lang/rust#148854
This commit is contained in:
commit
29fa07e3db
22 changed files with 123 additions and 26 deletions
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<()>);
|
||||
|
|
|
|||
|
|
@ -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<()>);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
11
tests/ui/regions/wf-bound-region-in-local-issue-115175.rs
Normal file
11
tests/ui/regions/wf-bound-region-in-local-issue-115175.rs
Normal 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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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}");
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue