]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | // A test exploiting the bug behind #25860 except with |
2 | // implied trait bounds which currently don't exist without `-Zchalk`. | |
3 | use std::marker::PhantomData; | |
4 | struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) | |
5 | where | |
6 | T: Convert<'a, 'b>; | |
7 | ||
8 | trait Convert<'a, 'b>: Sized { | |
9 | fn cast(&'a self) -> &'b Self; | |
10 | } | |
11 | impl<'long: 'short, 'short, T> Convert<'long, 'short> for T { | |
12 | fn cast(&'long self) -> &'short T { | |
13 | self | |
14 | } | |
15 | } | |
16 | ||
17 | // This function will compile once we add implied trait bounds. | |
18 | // | |
19 | // If we're not careful with our impl, the transformations | |
20 | // in `bad` would succeed, which is unsound ✨ | |
21 | // | |
22 | // FIXME: the error is pretty bad, this should say | |
23 | // | |
24 | // `T: Convert<'in_, 'out>` is not implemented | |
25 | // | |
26 | // help: needed by `Foo<'in_, 'out, T>` | |
27 | // | |
28 | // Please ping @lcnr if your changes end up causing `badboi` to compile. | |
29 | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { | |
30 | //~^ ERROR lifetime mismatch | |
31 | sadness.cast() | |
32 | } | |
33 | ||
487cf647 FG |
34 | fn badboi2<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) { |
35 | //~^ ERROR lifetime mismatch | |
36 | let _: &'out T = sadness.cast(); | |
37 | } | |
38 | ||
39 | fn badboi3<'in_, 'out, T>(a: Foo<'in_, 'out, (&'in_ T, &'out T)>, sadness: &'in_ T) { | |
40 | //~^ ERROR lifetime mismatch | |
41 | let _: &'out T = sadness.cast(); | |
42 | } | |
43 | ||
5099ac24 FG |
44 | fn bad<'short, T>(value: &'short T) -> &'static T { |
45 | let x: for<'in_, 'out> fn(Foo<'in_, 'out, T>, &'in_ T) -> &'out T = badboi; | |
46 | let x: for<'out> fn(Foo<'short, 'out, T>, &'short T) -> &'out T = x; | |
47 | let x: for<'out> fn(Foo<'static, 'out, T>, &'short T) -> &'out T = x; | |
48 | let x: fn(Foo<'static, 'static, T>, &'short T) -> &'static T = x; | |
49 | x(Foo(PhantomData), value) | |
50 | } | |
51 | ||
52 | // Use `bad` to cause a segfault. | |
53 | fn main() { | |
54 | let mut outer: Option<&'static u32> = Some(&3); | |
55 | let static_ref: &'static &'static u32 = match outer { | |
56 | Some(ref reference) => bad(reference), | |
57 | None => unreachable!(), | |
58 | }; | |
59 | outer = None; | |
60 | println!("{}", static_ref); | |
61 | } |