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