Skip to content

Commit fdbad90

Browse files
add tests of issue + bless one other test
1 parent f0bc5c7 commit fdbad90

5 files changed

Lines changed: 93 additions & 1 deletion

tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: lifetime may not live long enough
44
LL | doit(0, &|x, y| {
55
| - - has type `&'1 i32`
66
| |
7-
| has type `&Cell<&'2 i32>`
7+
| has type `&'2 Cell<&i32>`
88
LL | x.set(y);
99
| ^^^^^^^^ argument requires that `'1` must outlive `'2`
1010
|
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// The same as check-wf-of-closure-args-complex, but this example causes
2+
// a use-after-free if we don't perform the wf check.
3+
//
4+
#![feature(unboxed_closures)]
5+
6+
use std::sync::OnceLock;
7+
8+
type Payload = Box<i32>;
9+
10+
static STORAGE: OnceLock<&'static Payload> = OnceLock::new();
11+
12+
trait Store {
13+
fn store(&self);
14+
}
15+
impl Store for &'static Payload {
16+
fn store(&self) {
17+
STORAGE.set(*self).unwrap();
18+
}
19+
}
20+
21+
#[repr(transparent)]
22+
struct MyTy<T: Store>(T);
23+
impl<T: Store> Drop for MyTy<T> {
24+
fn drop(&mut self) {
25+
self.0.store();
26+
}
27+
}
28+
29+
trait IsFn: for<'x> Fn<(&'x Payload,)> {}
30+
31+
impl IsFn for for<'x> fn(&'x Payload) -> MyTy<&'x Payload> {}
32+
33+
fn foo(f: impl for<'x> Fn(&'x Payload)) {
34+
let a = Box::new(1);
35+
f(&a);
36+
}
37+
fn bar<F: IsFn>(f: F) {
38+
foo(|x| { f(x); });
39+
}
40+
41+
fn main() {
42+
// If no wf-check is done on this closure given to `bar`, this compiles fine and
43+
// a use-after-free will occur.
44+
bar::<for<'a> fn(&'a Payload) -> MyTy<&'a Payload>>(|x| unsafe { //~ ERROR: lifetime may not live long enough
45+
std::mem::transmute::<&Payload, MyTy<&Payload>>(x)
46+
});
47+
println!("{}", STORAGE.get().unwrap());
48+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/check-wf-of-closure-args-complex.rs:44:60
3+
|
4+
LL | bar::<for<'a> fn(&'a Payload) -> MyTy<&'a Payload>>(|x| unsafe {
5+
| - ^ requires that `'1` must outlive `'static`
6+
| |
7+
| has type `&'1 Box<i32>`
8+
9+
error: aborting due to 1 previous error
10+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Checks that we perform WF checks on closure args, regardless of wether they
2+
// are used in the closure it self.
3+
// related to issue #104478
4+
5+
struct MyTy<T: Trait>(T);
6+
trait Trait {}
7+
impl Trait for &'static str {}
8+
fn wf<T>(_: T) {}
9+
10+
fn main() {
11+
let _: for<'x> fn(MyTy<&'x str>) = |_| {}; //~ ERROR: lifetime may not live long enough
12+
13+
let _: for<'x> fn(MyTy<&'x str>) = |x| wf(x); //~ ERROR: lifetime may not live long enough
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/check-wf-of-closure-args.rs:11:41
3+
|
4+
LL | let _: for<'x> fn(MyTy<&'x str>) = |_| {};
5+
| ^
6+
| |
7+
| has type `MyTy<&'1 str>`
8+
| requires that `'1` must outlive `'static`
9+
10+
error: lifetime may not live long enough
11+
--> $DIR/check-wf-of-closure-args.rs:13:41
12+
|
13+
LL | let _: for<'x> fn(MyTy<&'x str>) = |x| wf(x);
14+
| ^
15+
| |
16+
| has type `MyTy<&'1 str>`
17+
| requires that `'1` must outlive `'static`
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)