]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/tests/ui/needless_lifetimes.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / clippy / tests / ui / needless_lifetimes.rs
CommitLineData
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
11fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
12
13fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
14
15// No error; same lifetime on two params.
16fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
17
18// No error; static involved.
19fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
20
21fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
22
23fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
24 x
25}
26
27// No error; multiple input refs.
28fn 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// ^^^
35fn 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// ^^^
42fn 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
47async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
48 args.get(0).cloned()
49}
50
f20569fa
XL
51// No error; static involved.
52fn 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// ^^^
59fn 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// ^^^
66fn 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.
71fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
72 x.unwrap()
73}
74
75fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
76 Ok(x)
77}
78
79// Where-clause, but without lifetimes.
80fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
81where
82 T: Copy,
83{
84 Ok(x)
85}
86
87type Ref<'r> = &'r u8;
88
89// No error; same lifetime on two params.
90fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
91
92fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
93
94// No error; bounded lifetime.
95fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
96
97// No error; bounded lifetime.
98fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
99where
100 'b: 'a,
101{
102}
103
104struct Lt<'a, I: 'static> {
105 x: &'a I,
106}
107
108// No error; fn bound references `'a`.
109fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
110where
111 F: Fn(Lt<'a, I>) -> Lt<'a, I>,
112{
113 unreachable!()
114}
115
116fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
117where
118 for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
119{
120 unreachable!()
121}
122
123// No error; see below.
124fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
125 f(x);
126}
127
128fn 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.
137fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
138 if cond { x } else { f() }
139}
140
141struct X {
142 x: u8,
143}
144
145impl 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
170struct Foo<'a>(&'a u8);
171
172impl<'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
179fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
180 unimplemented!()
181}
182
183fn 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`).
188fn 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`).
193fn 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// ^^
201fn 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// ^^^^
209fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
f20569fa
XL
210 unimplemented!()
211}
212
213trait WithLifetime<'a> {}
214
215type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;
216
217// Should not warn because it won't build without the lifetime.
218fn 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.
224fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
225 unimplemented!()
226}
227
228type FooAlias<'a> = Foo<'a>;
229
230fn 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`).
235fn 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`).
240fn 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// ^^
248fn 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// ^^^^^^^^^
256fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
f20569fa
XL
257 unimplemented!()
258}
259
260fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
261 unimplemented!()
262}
263
264fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
265 unimplemented!()
266}
267
268fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
269 unimplemented!()
270}
271fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
272 unimplemented!()
273}
274
275// Don't warn on these; see issue #292.
276fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
277 unimplemented!()
278}
279
280// See issue #740.
281struct Test {
282 vec: Vec<usize>,
283}
284
285impl Test {
286 fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
287 unimplemented!()
288 }
289}
290
291trait LintContext<'a> {}
292
293fn f<'a, T: LintContext<'a>>(_: &T) {}
294
295fn 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.
301struct Cow<'a> {
302 x: &'a str,
303}
304fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
305 unimplemented!()
306}
307
308// Make sure we still warn on implementations
309mod 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
319mod 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
334mod 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
417mod 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
428mod 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
471mod 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
479mod 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 498fn main() {}