]>
Commit | Line | Data |
---|---|---|
f20569fa | 1 | #![warn(clippy::needless_lifetimes)] |
5099ac24 FG |
2 | #![allow( |
3 | dead_code, | |
4 | clippy::boxed_local, | |
5 | clippy::needless_pass_by_value, | |
6 | clippy::unnecessary_wraps, | |
923072b8 FG |
7 | dyn_drop, |
8 | clippy::get_first | |
5099ac24 | 9 | )] |
f20569fa XL |
10 | |
11 | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} | |
12 | ||
13 | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {} | |
14 | ||
15 | // No error; same lifetime on two params. | |
16 | fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {} | |
17 | ||
18 | // No error; static involved. | |
19 | fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {} | |
20 | ||
21 | fn mut_and_static_input(_x: &mut u8, _y: &'static str) {} | |
22 | ||
23 | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 { | |
24 | x | |
25 | } | |
26 | ||
27 | // No error; multiple input refs. | |
28 | fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 { | |
29 | x | |
30 | } | |
31 | ||
6522a427 EL |
32 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
33 | // fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 | |
34 | // ^^^ | |
35 | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 { | |
f20569fa XL |
36 | x |
37 | } | |
38 | ||
6522a427 EL |
39 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
40 | // fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 | |
41 | // ^^^ | |
42 | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 { | |
43 | y | |
44 | } | |
45 | ||
3c0e092e XL |
46 | // No error; multiple input refs |
47 | async fn func<'a>(args: &[&'a str]) -> Option<&'a str> { | |
48 | args.get(0).cloned() | |
49 | } | |
50 | ||
f20569fa XL |
51 | // No error; static involved. |
52 | fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 { | |
53 | x | |
54 | } | |
55 | ||
6522a427 EL |
56 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
57 | // fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> | |
58 | // ^^^ | |
59 | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> { | |
f20569fa XL |
60 | Ok(x) |
61 | } | |
62 | ||
6522a427 EL |
63 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
64 | // fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> | |
65 | // ^^^ | |
66 | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> { | |
67 | Ok(y) | |
68 | } | |
69 | ||
f20569fa XL |
70 | // No error; two input refs. |
71 | fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 { | |
72 | x.unwrap() | |
73 | } | |
74 | ||
75 | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> { | |
76 | Ok(x) | |
77 | } | |
78 | ||
79 | // Where-clause, but without lifetimes. | |
80 | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> | |
81 | where | |
82 | T: Copy, | |
83 | { | |
84 | Ok(x) | |
85 | } | |
86 | ||
87 | type Ref<'r> = &'r u8; | |
88 | ||
89 | // No error; same lifetime on two params. | |
90 | fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {} | |
91 | ||
92 | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {} | |
93 | ||
94 | // No error; bounded lifetime. | |
95 | fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {} | |
96 | ||
97 | // No error; bounded lifetime. | |
98 | fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8) | |
99 | where | |
100 | 'b: 'a, | |
101 | { | |
102 | } | |
103 | ||
104 | struct Lt<'a, I: 'static> { | |
105 | x: &'a I, | |
106 | } | |
107 | ||
108 | // No error; fn bound references `'a`. | |
109 | fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> | |
110 | where | |
111 | F: Fn(Lt<'a, I>) -> Lt<'a, I>, | |
112 | { | |
113 | unreachable!() | |
114 | } | |
115 | ||
116 | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I> | |
117 | where | |
118 | for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>, | |
119 | { | |
120 | unreachable!() | |
121 | } | |
122 | ||
123 | // No error; see below. | |
124 | fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { | |
125 | f(x); | |
126 | } | |
127 | ||
128 | fn fn_bound_3_cannot_elide() { | |
129 | let x = 42; | |
130 | let p = &x; | |
131 | let mut q = &x; | |
132 | // This will fail if we elide lifetimes of `fn_bound_3`. | |
133 | fn_bound_3(p, |y| q = y); | |
134 | } | |
135 | ||
136 | // No error; multiple input refs. | |
137 | fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () { | |
138 | if cond { x } else { f() } | |
139 | } | |
140 | ||
141 | struct X { | |
142 | x: u8, | |
143 | } | |
144 | ||
145 | impl X { | |
146 | fn self_and_out<'s>(&'s self) -> &'s u8 { | |
147 | &self.x | |
148 | } | |
149 | ||
6522a427 EL |
150 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
151 | // fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 | |
152 | // ^^^ | |
153 | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 { | |
f20569fa XL |
154 | &self.x |
155 | } | |
156 | ||
6522a427 EL |
157 | // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid: |
158 | // fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 | |
159 | // ^^^^^ | |
160 | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 { | |
161 | x | |
162 | } | |
163 | ||
f20569fa XL |
164 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {} |
165 | ||
166 | // No error; same lifetimes on two params. | |
167 | fn self_and_same_in<'s>(&'s self, _x: &'s u8) {} | |
168 | } | |
169 | ||
170 | struct Foo<'a>(&'a u8); | |
171 | ||
172 | impl<'a> Foo<'a> { | |
173 | // No error; lifetime `'a` not defined in method. | |
174 | fn self_shared_lifetime(&self, _: &'a u8) {} | |
175 | // No error; bounds exist. | |
176 | fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {} | |
177 | } | |
178 | ||
179 | fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 { | |
180 | unimplemented!() | |
181 | } | |
182 | ||
183 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { | |
184 | unimplemented!() | |
185 | } | |
186 | ||
187 | // No warning; two input lifetimes (named on the reference, anonymous on `Foo`). | |
188 | fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str { | |
189 | unimplemented!() | |
190 | } | |
191 | ||
192 | // No warning; two input lifetimes (anonymous on the reference, named on `Foo`). | |
193 | fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str { | |
194 | unimplemented!() | |
195 | } | |
196 | ||
6522a427 EL |
197 | // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is |
198 | // valid: | |
199 | // fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str | |
200 | // ^^ | |
201 | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str { | |
202 | unimplemented!() | |
203 | } | |
204 | ||
205 | // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is | |
206 | // valid: | |
207 | // fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str | |
208 | // ^^^^ | |
209 | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str { | |
f20569fa XL |
210 | unimplemented!() |
211 | } | |
212 | ||
213 | trait WithLifetime<'a> {} | |
214 | ||
215 | type WithLifetimeAlias<'a> = dyn WithLifetime<'a>; | |
216 | ||
217 | // Should not warn because it won't build without the lifetime. | |
218 | fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str { | |
219 | unimplemented!() | |
220 | } | |
221 | ||
222 | // Should warn because there is no lifetime on `Drop`, so this would be | |
223 | // unambiguous if we elided the lifetime. | |
224 | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str { | |
225 | unimplemented!() | |
226 | } | |
227 | ||
228 | type FooAlias<'a> = Foo<'a>; | |
229 | ||
230 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { | |
231 | unimplemented!() | |
232 | } | |
233 | ||
234 | // No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`). | |
235 | fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str { | |
236 | unimplemented!() | |
237 | } | |
238 | ||
239 | // No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`). | |
240 | fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str { | |
241 | unimplemented!() | |
242 | } | |
243 | ||
6522a427 EL |
244 | // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is |
245 | // valid: | |
246 | // fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str | |
247 | // ^^ | |
248 | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str { | |
249 | unimplemented!() | |
250 | } | |
251 | ||
252 | // Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is | |
253 | // valid: | |
254 | // fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str | |
255 | // ^^^^^^^^^ | |
256 | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str { | |
f20569fa XL |
257 | unimplemented!() |
258 | } | |
259 | ||
260 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { | |
261 | unimplemented!() | |
262 | } | |
263 | ||
264 | fn elided_input_named_output<'a>(_arg: &str) -> &'a str { | |
265 | unimplemented!() | |
266 | } | |
267 | ||
268 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { | |
269 | unimplemented!() | |
270 | } | |
271 | fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) { | |
272 | unimplemented!() | |
273 | } | |
274 | ||
275 | // Don't warn on these; see issue #292. | |
276 | fn trait_bound_bug<'a, T: WithLifetime<'a>>() { | |
277 | unimplemented!() | |
278 | } | |
279 | ||
280 | // See issue #740. | |
281 | struct Test { | |
282 | vec: Vec<usize>, | |
283 | } | |
284 | ||
285 | impl Test { | |
286 | fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> { | |
287 | unimplemented!() | |
288 | } | |
289 | } | |
290 | ||
291 | trait LintContext<'a> {} | |
292 | ||
293 | fn f<'a, T: LintContext<'a>>(_: &T) {} | |
294 | ||
295 | fn test<'a>(x: &'a [u8]) -> u8 { | |
296 | let y: &'a u8 = &x[5]; | |
297 | *y | |
298 | } | |
299 | ||
300 | // Issue #3284: give hint regarding lifetime in return type. | |
301 | struct Cow<'a> { | |
302 | x: &'a str, | |
303 | } | |
304 | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> { | |
305 | unimplemented!() | |
306 | } | |
307 | ||
308 | // Make sure we still warn on implementations | |
309 | mod issue4291 { | |
310 | trait BadTrait { | |
311 | fn needless_lt<'a>(x: &'a u8) {} | |
312 | } | |
313 | ||
314 | impl BadTrait for () { | |
315 | fn needless_lt<'a>(_x: &'a u8) {} | |
316 | } | |
317 | } | |
318 | ||
319 | mod issue2944 { | |
320 | trait Foo {} | |
04454e1e | 321 | struct Bar; |
f20569fa XL |
322 | struct Baz<'a> { |
323 | bar: &'a Bar, | |
324 | } | |
325 | ||
326 | impl<'a> Foo for Baz<'a> {} | |
327 | impl Bar { | |
328 | fn baz<'a>(&'a self) -> impl Foo + 'a { | |
329 | Baz { bar: self } | |
330 | } | |
331 | } | |
332 | } | |
333 | ||
334 | mod nested_elision_sites { | |
335 | // issue #issue2944 | |
336 | ||
337 | // closure trait bounds subject to nested elision | |
338 | // don't lint because they refer to outer lifetimes | |
339 | fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 { | |
340 | move || i | |
341 | } | |
342 | fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 { | |
343 | move || i | |
344 | } | |
345 | fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 { | |
346 | move || i | |
347 | } | |
348 | ||
349 | // don't lint | |
350 | fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 { | |
351 | f() | |
352 | } | |
353 | fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 { | |
354 | move || i | |
355 | } | |
356 | // lint | |
357 | fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 { | |
358 | f(i) | |
359 | } | |
360 | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 { | |
361 | f(i) | |
362 | } | |
363 | ||
364 | // don't lint | |
365 | fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 { | |
366 | f() | |
367 | } | |
368 | // lint | |
369 | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 { | |
370 | f(i) | |
371 | } | |
372 | ||
373 | // don't lint | |
374 | fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32 | |
375 | where | |
376 | T: Fn() -> &'a i32, | |
377 | { | |
378 | f() | |
379 | } | |
380 | // lint | |
381 | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32 | |
382 | where | |
383 | T: Fn(&i32) -> &i32, | |
384 | { | |
385 | f(i) | |
386 | } | |
387 | ||
388 | // don't lint | |
389 | fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 { | |
390 | f(i) | |
391 | } | |
392 | fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 { | |
393 | |i| i | |
394 | } | |
395 | // lint | |
396 | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 { | |
397 | f(i) | |
398 | } | |
399 | ||
400 | // don't lint | |
401 | fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 { | |
402 | |f| 42 | |
403 | } | |
404 | fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) { | |
405 | |f| () | |
406 | } | |
407 | ||
408 | // lint | |
409 | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 { | |
410 | |f| 42 | |
411 | } | |
412 | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) { | |
413 | |f| () | |
414 | } | |
415 | } | |
416 | ||
417 | mod issue6159 { | |
418 | use std::ops::Deref; | |
419 | pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R | |
420 | where | |
421 | T: Deref, | |
422 | F: FnOnce(&'a T::Target) -> R, | |
423 | { | |
424 | f(x.deref()) | |
425 | } | |
426 | } | |
427 | ||
5099ac24 FG |
428 | mod issue7296 { |
429 | use std::rc::Rc; | |
430 | use std::sync::Arc; | |
431 | ||
432 | struct Foo; | |
433 | impl Foo { | |
434 | fn implicit<'a>(&'a self) -> &'a () { | |
435 | &() | |
436 | } | |
437 | fn implicit_mut<'a>(&'a mut self) -> &'a () { | |
438 | &() | |
439 | } | |
440 | ||
441 | fn explicit<'a>(self: &'a Arc<Self>) -> &'a () { | |
442 | &() | |
443 | } | |
444 | fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () { | |
445 | &() | |
446 | } | |
447 | ||
448 | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () { | |
449 | &() | |
450 | } | |
451 | } | |
452 | ||
453 | trait Bar { | |
454 | fn implicit<'a>(&'a self) -> &'a (); | |
455 | fn implicit_provided<'a>(&'a self) -> &'a () { | |
456 | &() | |
457 | } | |
458 | ||
459 | fn explicit<'a>(self: &'a Arc<Self>) -> &'a (); | |
460 | fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () { | |
461 | &() | |
462 | } | |
463 | ||
464 | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a (); | |
465 | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () { | |
466 | &() | |
467 | } | |
468 | } | |
469 | } | |
470 | ||
6522a427 EL |
471 | mod pr_9743_false_negative_fix { |
472 | #![allow(unused)] | |
473 | ||
474 | fn foo<'a>(x: &'a u8, y: &'_ u8) {} | |
475 | ||
476 | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {} | |
477 | } | |
478 | ||
479 | mod pr_9743_output_lifetime_checks { | |
480 | #![allow(unused)] | |
481 | ||
482 | // lint: only one input | |
483 | fn one_input<'a>(x: &'a u8) -> &'a u8 { | |
484 | unimplemented!() | |
485 | } | |
486 | ||
487 | // lint: multiple inputs, output would not be elided | |
488 | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 { | |
489 | unimplemented!() | |
490 | } | |
491 | ||
492 | // don't lint: multiple inputs, output would be elided (which would create an ambiguity) | |
493 | fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 { | |
494 | unimplemented!() | |
495 | } | |
496 | } | |
497 | ||
f20569fa | 498 | fn main() {} |