]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/needless_borrow.rs
Rollup merge of #104967 - willcrichton:fix-scrape-examples, r=notriddle
[rust.git] / src / tools / clippy / tests / ui / needless_borrow.rs
1 // run-rustfix
2 #![feature(lint_reasons)]
3 #![allow(
4     unused,
5     clippy::uninlined_format_args,
6     clippy::unnecessary_mut_passed,
7     clippy::unnecessary_to_owned
8 )]
9 #![warn(clippy::needless_borrow)]
10
11 fn main() {
12     let a = 5;
13     let ref_a = &a;
14     let _ = x(&a); // no warning
15     let _ = x(&&a); // warn
16
17     let mut b = 5;
18     mut_ref(&mut b); // no warning
19     mut_ref(&mut &mut b); // warn
20
21     let s = &String::from("hi");
22     let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not
23     let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]`
24     let vec = Vec::new();
25     let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
26     h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
27     let garbl = match 42 {
28         44 => &a,
29         45 => {
30             println!("foo");
31             &&a
32         },
33         46 => &&a,
34         47 => {
35             println!("foo");
36             loop {
37                 println!("{}", a);
38                 if a == 25 {
39                     break &ref_a;
40                 }
41             }
42         },
43         _ => panic!(),
44     };
45
46     let _ = x(&&&a);
47     let _ = x(&mut &&a);
48     let _ = x(&&&mut b);
49     let _ = x(&&ref_a);
50     {
51         let b = &mut b;
52         x(&b);
53     }
54
55     // Issue #8191
56     let mut x = 5;
57     let mut x = &mut x;
58
59     mut_ref(&mut x);
60     mut_ref(&mut &mut x);
61     let y: &mut i32 = &mut x;
62     let y: &mut i32 = &mut &mut x;
63
64     let y = match 0 {
65         // Don't lint. Removing the borrow would move 'x'
66         0 => &mut x,
67         _ => &mut *x,
68     };
69     let y: &mut i32 = match 0 {
70         // Lint here. The type given above triggers auto-borrow.
71         0 => &mut x,
72         _ => &mut *x,
73     };
74     fn ref_mut_i32(_: &mut i32) {}
75     ref_mut_i32(match 0 {
76         // Lint here. The type given above triggers auto-borrow.
77         0 => &mut x,
78         _ => &mut *x,
79     });
80     // use 'x' after to make sure it's still usable in the fixed code.
81     *x = 5;
82
83     let s = String::new();
84     // let _ = (&s).len();
85     // let _ = (&s).capacity();
86     // let _ = (&&s).capacity();
87
88     let x = (1, 2);
89     let _ = (&x).0;
90     let x = &x as *const (i32, i32);
91     let _ = unsafe { (&*x).0 };
92
93     // Issue #8367
94     trait Foo {
95         fn foo(self);
96     }
97     impl Foo for &'_ () {
98         fn foo(self) {}
99     }
100     (&()).foo(); // Don't lint. `()` doesn't implement `Foo`
101     (&&()).foo();
102
103     impl Foo for i32 {
104         fn foo(self) {}
105     }
106     impl Foo for &'_ i32 {
107         fn foo(self) {}
108     }
109     (&5).foo(); // Don't lint. `5` will call `<i32 as Foo>::foo`
110     (&&5).foo();
111
112     trait FooRef {
113         fn foo_ref(&self);
114     }
115     impl FooRef for () {
116         fn foo_ref(&self) {}
117     }
118     impl FooRef for &'_ () {
119         fn foo_ref(&self) {}
120     }
121     (&&()).foo_ref(); // Don't lint. `&()` will call `<() as FooRef>::foo_ref`
122
123     struct S;
124     impl From<S> for u32 {
125         fn from(s: S) -> Self {
126             (&s).into()
127         }
128     }
129     impl From<&S> for u32 {
130         fn from(s: &S) -> Self {
131             0
132         }
133     }
134
135     let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
136     let _ = std::path::Path::new(".").join(&&".");
137     deref_target_is_x(&X);
138     multiple_constraints(&[[""]]);
139     multiple_constraints_normalizes_to_same(&X, X);
140     let _ = Some("").unwrap_or(&"");
141     let _ = std::fs::write("x", &"".to_string());
142
143     only_sized(&""); // Don't lint. `Sized` is only bound
144     let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound
145     let _ = Box::new(&""); // Don't lint. Type parameter appears in return type
146     ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter
147     refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't
148     multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments
149 }
150
151 #[allow(clippy::needless_borrowed_reference)]
152 fn x(y: &i32) -> i32 {
153     *y
154 }
155
156 fn mut_ref(y: &mut i32) {
157     *y = 5;
158 }
159
160 fn f<T: Copy>(y: &T) -> T {
161     *y
162 }
163
164 fn g(y: &[u8]) -> u8 {
165     y[0]
166 }
167
168 trait Trait {}
169
170 impl<'a> Trait for &'a str {}
171
172 fn h(_: &dyn Trait) {}
173
174 fn check_expect_suppression() {
175     let a = 5;
176     #[expect(clippy::needless_borrow)]
177     let _ = x(&&a);
178 }
179
180 mod issue9160 {
181     pub struct S<F> {
182         f: F,
183     }
184
185     impl<T, F> S<F>
186     where
187         F: Fn() -> T,
188     {
189         fn calls_field(&self) -> T {
190             (&self.f)()
191         }
192     }
193
194     impl<T, F> S<F>
195     where
196         F: FnMut() -> T,
197     {
198         fn calls_mut_field(&mut self) -> T {
199             (&mut self.f)()
200         }
201     }
202 }
203
204 #[derive(Clone, Copy)]
205 struct X;
206
207 impl std::ops::Deref for X {
208     type Target = X;
209     fn deref(&self) -> &Self::Target {
210         self
211     }
212 }
213
214 fn deref_target_is_x<T>(_: T)
215 where
216     T: std::ops::Deref<Target = X>,
217 {
218 }
219
220 fn multiple_constraints<T, U, V, X, Y>(_: T)
221 where
222     T: IntoIterator<Item = U> + IntoIterator<Item = X>,
223     U: IntoIterator<Item = V>,
224     V: AsRef<str>,
225     X: IntoIterator<Item = Y>,
226     Y: AsRef<std::ffi::OsStr>,
227 {
228 }
229
230 fn multiple_constraints_normalizes_to_same<T, U, V>(_: T, _: V)
231 where
232     T: std::ops::Deref<Target = U>,
233     U: std::ops::Deref<Target = V>,
234 {
235 }
236
237 fn only_sized<T>(_: T) {}
238
239 fn ref_as_ref_path<T: 'static>(_: &'static T)
240 where
241     &'static T: AsRef<std::path::Path>,
242 {
243 }
244
245 trait RefsOnly {
246     type Referent;
247 }
248
249 impl<T> RefsOnly for &T {
250     type Referent = T;
251 }
252
253 fn refs_only<T, U>(_: T)
254 where
255     T: RefsOnly<Referent = U>,
256 {
257 }
258
259 fn multiple_constraints_normalizes_to_different<T, U, V>(_: T, _: U)
260 where
261     T: IntoIterator<Item = U>,
262     U: IntoIterator<Item = V>,
263     V: AsRef<str>,
264 {
265 }
266
267 // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
268 mod copyable_iterator {
269     #[derive(Clone, Copy)]
270     struct Iter;
271     impl Iterator for Iter {
272         type Item = ();
273         fn next(&mut self) -> Option<Self::Item> {
274             None
275         }
276     }
277     fn takes_iter(_: impl Iterator) {}
278     fn dont_warn(mut x: Iter) {
279         takes_iter(&mut x);
280     }
281     #[allow(unused_mut)]
282     fn warn(mut x: &mut Iter) {
283         takes_iter(&mut x)
284     }
285 }
286
287 #[clippy::msrv = "1.52.0"]
288 mod under_msrv {
289     fn foo() {
290         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
291     }
292 }
293
294 #[clippy::msrv = "1.53.0"]
295 mod meets_msrv {
296     fn foo() {
297         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
298     }
299 }
300
301 fn issue9383() {
302     // Should not lint because unions need explicit deref when accessing field
303     use std::mem::ManuallyDrop;
304
305     union Coral {
306         crab: ManuallyDrop<Vec<i32>>,
307     }
308
309     union Ocean {
310         coral: ManuallyDrop<Coral>,
311     }
312
313     let mut ocean = Ocean {
314         coral: ManuallyDrop::new(Coral {
315             crab: ManuallyDrop::new(vec![1, 2, 3]),
316         }),
317     };
318
319     unsafe {
320         ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
321
322         (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
323         ManuallyDrop::drop(&mut (*ocean.coral).crab);
324
325         ManuallyDrop::drop(&mut ocean.coral);
326     }
327 }
328
329 fn closure_test() {
330     let env = "env".to_owned();
331     let arg = "arg".to_owned();
332     let f = |arg| {
333         let loc = "loc".to_owned();
334         let _ = std::fs::write("x", &env); // Don't lint. In environment
335         let _ = std::fs::write("x", &arg);
336         let _ = std::fs::write("x", &loc);
337     };
338     let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
339     f(arg);
340 }
341
342 mod significant_drop {
343     #[derive(Debug)]
344     struct X;
345
346     #[derive(Debug)]
347     struct Y;
348
349     impl Drop for Y {
350         fn drop(&mut self) {}
351     }
352
353     fn foo(x: X, y: Y) {
354         debug(&x);
355         debug(&y); // Don't lint. Has significant drop
356     }
357
358     fn debug(_: impl std::fmt::Debug) {}
359 }
360
361 mod used_exactly_once {
362     fn foo(x: String) {
363         use_x(&x);
364     }
365     fn use_x(_: impl AsRef<str>) {}
366 }
367
368 mod used_more_than_once {
369     fn foo(x: String) {
370         use_x(&x);
371         use_x_again(&x);
372     }
373     fn use_x(_: impl AsRef<str>) {}
374     fn use_x_again(_: impl AsRef<str>) {}
375 }
376
377 // https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
378 mod issue_9111 {
379     struct A;
380
381     impl Extend<u8> for A {
382         fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
383             unimplemented!()
384         }
385     }
386
387     impl<'a> Extend<&'a u8> for A {
388         fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
389             unimplemented!()
390         }
391     }
392
393     fn main() {
394         let mut a = A;
395         a.extend(&[]); // vs a.extend([]);
396     }
397 }
398
399 mod issue_9710 {
400     fn main() {
401         let string = String::new();
402         for _i in 0..10 {
403             f(&string);
404         }
405     }
406
407     fn f<T: AsRef<str>>(_: T) {}
408 }
409
410 mod issue_9739 {
411     fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
412
413     fn main() {
414         foo(if std::env::var_os("HI").is_some() {
415             &[0]
416         } else {
417             &[] as &[u32]
418         });
419     }
420 }
421
422 mod issue_9739_method_variant {
423     struct S;
424
425     impl S {
426         fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
427     }
428
429     fn main() {
430         S.foo(if std::env::var_os("HI").is_some() {
431             &[0]
432         } else {
433             &[] as &[u32]
434         });
435     }
436 }
437
438 mod issue_9782 {
439     fn foo<T: AsRef<[u8]>>(t: T) {
440         println!("{}", std::mem::size_of::<T>());
441         let _t: &[u8] = t.as_ref();
442     }
443
444     fn main() {
445         let a: [u8; 100] = [0u8; 100];
446
447         // 100
448         foo::<[u8; 100]>(a);
449         foo(a);
450
451         // 16
452         foo::<&[u8]>(&a);
453         foo(a.as_slice());
454
455         // 8
456         foo::<&[u8; 100]>(&a);
457         foo(&a);
458     }
459 }
460
461 mod issue_9782_type_relative_variant {
462     struct S;
463
464     impl S {
465         fn foo<T: AsRef<[u8]>>(t: T) {
466             println!("{}", std::mem::size_of::<T>());
467             let _t: &[u8] = t.as_ref();
468         }
469     }
470
471     fn main() {
472         let a: [u8; 100] = [0u8; 100];
473
474         S::foo::<&[u8; 100]>(&a);
475     }
476 }
477
478 mod issue_9782_method_variant {
479     struct S;
480
481     impl S {
482         fn foo<T: AsRef<[u8]>>(&self, t: T) {
483             println!("{}", std::mem::size_of::<T>());
484             let _t: &[u8] = t.as_ref();
485         }
486     }
487
488     fn main() {
489         let a: [u8; 100] = [0u8; 100];
490
491         S.foo::<&[u8; 100]>(&a);
492     }
493 }