-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
WF checks on closure arguments. #151510
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
WF checks on closure arguments. #151510
Changes from all commits
f456943
f0bc5c7
fdbad90
734d270
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| error: lifetime may not live long enough | ||
| --> $DIR/hrlt-implied-trait-bounds-roundtrip.rs:23:49 | ||
| | | ||
| LL | let bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = |_, _| {}; | ||
| | ^ | ||
| | | | ||
| | has type `Foo<'1>` | ||
| | requires that `'1` must outlive `'static` | ||
|
|
||
| error: aborting due to 1 previous error | ||
|
|
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like the name right now, so TODO. Also, this test, when run with current nightly, indeeds performs a use-after-free. But now we error on it, it can thus be removed to this: use std::sync::OnceLock;
type Payload = Box<i32>;
static STORAGE: OnceLock<& ()> = OnceLock::new();
trait Store {}
impl Store for &'static Payload {}
struct MyTy<T: Store>(T);
trait IsFn {}
impl IsFn for for<'x> fn(&'x Payload) -> MyTy<&'x Payload> {}
fn bar<F: IsFn>(_: F) {}
fn main() {
bar::<for<'a> fn(&'a Payload) -> MyTy<&'a Payload>>(|x| unsafe {
std::mem::transmute::<&Payload, MyTy<&Payload>>(x)
});
} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // The same as check-wf-of-closure-args-complex, but this example causes | ||
| // a use-after-free if we don't perform the wf check. | ||
| // | ||
| #![feature(unboxed_closures)] | ||
|
|
||
| use std::sync::OnceLock; | ||
|
|
||
| type Payload = Box<i32>; | ||
|
|
||
| static STORAGE: OnceLock<&'static Payload> = OnceLock::new(); | ||
|
|
||
| trait Store { | ||
| fn store(&self); | ||
| } | ||
| impl Store for &'static Payload { | ||
| fn store(&self) { | ||
| STORAGE.set(*self).unwrap(); | ||
| } | ||
| } | ||
|
|
||
| #[repr(transparent)] | ||
| struct MyTy<T: Store>(T); | ||
| impl<T: Store> Drop for MyTy<T> { | ||
| fn drop(&mut self) { | ||
| self.0.store(); | ||
| } | ||
| } | ||
|
|
||
| trait IsFn: for<'x> Fn<(&'x Payload,)> {} | ||
|
|
||
| impl IsFn for for<'x> fn(&'x Payload) -> MyTy<&'x Payload> {} | ||
|
|
||
| fn foo(f: impl for<'x> Fn(&'x Payload)) { | ||
| let a = Box::new(1); | ||
| f(&a); | ||
| } | ||
| fn bar<F: IsFn>(f: F) { | ||
| foo(|x| { f(x); }); | ||
| } | ||
|
|
||
| fn main() { | ||
| // If no wf-check is done on this closure given to `bar`, this compiles fine and | ||
| // a use-after-free will occur. | ||
| bar::<for<'a> fn(&'a Payload) -> MyTy<&'a Payload>>(|x| unsafe { //~ ERROR: lifetime may not live long enough | ||
| std::mem::transmute::<&Payload, MyTy<&Payload>>(x) | ||
| }); | ||
| println!("{}", STORAGE.get().unwrap()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| error: lifetime may not live long enough | ||
| --> $DIR/check-wf-of-closure-args-complex.rs:44:60 | ||
| | | ||
| LL | bar::<for<'a> fn(&'a Payload) -> MyTy<&'a Payload>>(|x| unsafe { | ||
| | - ^ requires that `'1` must outlive `'static` | ||
| | | | ||
| | has type `&'1 Box<i32>` | ||
|
|
||
| error: aborting due to 1 previous error | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // Checks that we perform WF checks on closure args, regardless of wether they | ||
| // are used in the closure it self. | ||
| // related to issue #104478 | ||
|
|
||
| struct MyTy<T: Trait>(T); | ||
| trait Trait {} | ||
| impl Trait for &'static str {} | ||
| fn wf<T>(_: T) {} | ||
|
|
||
| fn main() { | ||
| let _: for<'x> fn(MyTy<&'x str>) = |_| {}; //~ ERROR: lifetime may not live long enough | ||
|
|
||
| let _: for<'x> fn(MyTy<&'x str>) = |x| wf(x); //~ ERROR: lifetime may not live long enough | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| error: lifetime may not live long enough | ||
| --> $DIR/check-wf-of-closure-args.rs:11:41 | ||
| | | ||
| LL | let _: for<'x> fn(MyTy<&'x str>) = |_| {}; | ||
| | ^ | ||
| | | | ||
| | has type `MyTy<&'1 str>` | ||
| | requires that `'1` must outlive `'static` | ||
|
|
||
| error: lifetime may not live long enough | ||
| --> $DIR/check-wf-of-closure-args.rs:13:41 | ||
| | | ||
| LL | let _: for<'x> fn(MyTy<&'x str>) = |x| wf(x); | ||
| | ^ | ||
| | | | ||
| | has type `MyTy<&'1 str>` | ||
| | requires that `'1` must outlive `'static` | ||
|
|
||
| error: aborting due to 2 previous errors | ||
|
Comment on lines
+10
to
+19
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find that the error message is a bit worse now, compared to the old: |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also looks wrong, is it due to the removed normalization?