]> git.lizzy.rs Git - rust.git/blob - tests/ui/generic-associated-types/self-outlives-lint.rs
Rollup merge of #103702 - WaffleLapkin:lift-sized-bounds-from-pointer-methods-where...
[rust.git] / tests / ui / generic-associated-types / self-outlives-lint.rs
1 // check-fail
2
3 use std::fmt::Debug;
4
5 // We have a `&'a self`, so we need a `Self: 'a`
6 trait Iterable {
7     type Item<'x>;
8     //~^ missing required
9     fn iter<'a>(&'a self) -> Self::Item<'a>;
10 }
11
12 /*
13 impl<T> Iterable for T {
14     type Item<'a> = &'a T;
15     fn iter<'a>(&'a self) -> Self::Item<'a> {
16         self
17     }
18 }
19 */
20
21 // We have a `&'a T`, so we need a `T: 'x`
22 trait Deserializer<T> {
23     type Out<'x>;
24     //~^ missing required
25     fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
26 }
27
28 /*
29 impl<T> Deserializer<T> for () {
30     type Out<'a> = &'a T;
31     fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input }
32 }
33 */
34
35 // We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
36 trait Deserializer2<T> {
37     type Out<'x>;
38     //~^ missing required
39     fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
40 }
41
42 // We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
43 trait Deserializer3<T, U> {
44     type Out<'x, 'y>;
45     //~^ missing required
46     fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
47 }
48
49 // `T` is a param on the function, so it can't be named by the associated type
50 trait Deserializer4 {
51     type Out<'x>;
52     fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>;
53 }
54
55 struct Wrap<T>(T);
56
57 // We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
58 trait Des {
59     type Out<'x, D>;
60     //~^ missing required
61     fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
62 }
63 /*
64 impl Des for () {
65     type Out<'x, D> = &'x D; // Not okay
66     fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> {
67         data
68     }
69 }
70 */
71
72 // We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an
73 // implied bound that `T: 'z`, so we require `D: 'x`
74 trait Des2 {
75     type Out<'x, D>;
76     //~^ missing required
77     fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
78 }
79 /*
80 impl Des2 for () {
81     type Out<'x, D> = &'x D;
82     fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> {
83         &data.0
84     }
85 }
86 */
87
88 // We see `&'z T`, so we require `D: 'x`
89 trait Des3 {
90     type Out<'x, D>;
91     //~^ missing required
92     fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
93 }
94 /*
95 impl Des3 for () {
96     type Out<'x, D> = &'x D;
97     fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> {
98           data
99     }
100 }
101 */
102
103 // Similar case to before, except with GAT.
104 trait NoGat<'a> {
105     type Bar;
106     fn method(&'a self) -> Self::Bar;
107 }
108
109 // Lifetime is not on function; except `Self: 'a`
110 // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
111 trait TraitLifetime<'a> {
112     type Bar<'b>;
113     //~^ missing required
114     fn method(&'a self) -> Self::Bar<'a>;
115 }
116
117 // Like above, but we have a where clause that can prove what we want
118 // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
119 trait TraitLifetimeWhere<'a> where Self: 'a {
120     type Bar<'b>;
121     //~^ missing required
122     fn method(&'a self) -> Self::Bar<'a>;
123 }
124
125 // Explicit bound instead of implicit; we want to still error
126 trait ExplicitBound {
127     type Bar<'b>;
128     //~^ missing required
129     fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
130 }
131
132 // The use of the GAT here is not in the return, we don't want to error
133 trait NotInReturn {
134     type Bar<'b>;
135     fn method<'b>(&'b self) where Self::Bar<'b>: Debug;
136 }
137
138 // We obviously error for `Iterator`, but we should also error for `Item`
139 trait IterableTwo {
140     type Item<'a>;
141     //~^ missing required
142     type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
143     //~^ missing required
144     fn iter<'a>(&'a self) -> Self::Iterator<'a>;
145 }
146
147 trait IterableTwoWhere {
148     type Item<'a>;
149     //~^ missing required
150     type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
151     fn iter<'a>(&'a self) -> Self::Iterator<'a>;
152 }
153
154 // We also should report region outlives clauses. Here, we know that `'y: 'x`,
155 // because of `&'x &'y`, so we require that `'b: 'a`.
156 trait RegionOutlives {
157     type Bar<'a, 'b>;
158     //~^ missing required
159     fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
160 }
161
162 /*
163 impl Foo for () {
164     type Bar<'a, 'b> = &'a &'b ();
165     fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> {
166         input
167     }
168 }
169 */
170
171 // Similar to the above, except with explicit bounds
172 trait ExplicitRegionOutlives<'ctx> {
173     type Fut<'out>;
174     //~^ missing required
175
176     fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out>
177     where
178         'ctx: 'out;
179 }
180
181
182 // If there are multiple methods that return the GAT, require a set of clauses
183 // that can be satisfied by *all* methods
184 trait MultipleMethods {
185     type Bar<'me>;
186
187     fn gimme<'a>(&'a self) -> Self::Bar<'a>;
188     fn gimme_default(&self) -> Self::Bar<'static>;
189 }
190
191 // We would normally require `Self: 'a`, but we can prove that `Self: 'static`
192 // because of the the bounds on the trait, so the bound is proven
193 trait Trait: 'static {
194     type Assoc<'a>;
195     fn make_assoc(_: &u32) -> Self::Assoc<'_>;
196 }
197
198 // We ignore `'static` lifetimes for any lints
199 trait StaticReturn<'a> {
200     type Y<'b>;
201     fn foo(&self) -> Self::Y<'static>;
202 }
203
204 // Same as above, but with extra method that takes GAT - just make sure this works
205 trait StaticReturnAndTakes<'a> {
206     type Y<'b>;
207     fn foo(&self) -> Self::Y<'static>;
208     fn bar<'b>(&self, arg: Self::Y<'b>);
209 }
210
211 // We require bounds when the GAT appears in the inputs
212 trait Input {
213     type Item<'a>;
214     //~^ missing required
215     fn takes_item<'a>(&'a self, item: Self::Item<'a>);
216 }
217
218 // We don't require bounds when the GAT appears in the where clauses
219 trait WhereClause {
220     type Item<'a>;
221     fn takes_item<'a>(&'a self) where Self::Item<'a>: ;
222 }
223
224 fn main() {}