]> git.lizzy.rs Git - rust.git/blob - tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs
Rollup merge of #106244 - atouchet:readme3, r=workingjubilee
[rust.git] / tests / ui / implied-bounds / hrlt-implied-trait-bounds-guard.rs
1 // A test exploiting the bug behind #25860 except with
2 // implied trait bounds which currently don't exist without `-Ztrait-solver=chalk`.
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
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
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 }