]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/needless_borrow.rs
Rollup merge of #102961 - reitermarkus:const-cstr-from-ptr, r=oli-obk
[rust.git] / src / tools / clippy / tests / ui / needless_borrow.rs
1 // run-rustfix
2 #![feature(custom_inner_attributes, lint_reasons)]
3
4 #[warn(clippy::all, clippy::needless_borrow)]
5 #[allow(unused_variables)]
6 #[allow(
7     clippy::uninlined_format_args,
8     clippy::unnecessary_mut_passed,
9     clippy::unnecessary_to_owned
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 #[allow(dead_code)]
175 fn check_expect_suppression() {
176     let a = 5;
177     #[expect(clippy::needless_borrow)]
178     let _ = x(&&a);
179 }
180
181 #[allow(dead_code)]
182 mod issue9160 {
183     pub struct S<F> {
184         f: F,
185     }
186
187     impl<T, F> S<F>
188     where
189         F: Fn() -> T,
190     {
191         fn calls_field(&self) -> T {
192             (&self.f)()
193         }
194     }
195
196     impl<T, F> S<F>
197     where
198         F: FnMut() -> T,
199     {
200         fn calls_mut_field(&mut self) -> T {
201             (&mut self.f)()
202         }
203     }
204 }
205
206 #[derive(Clone, Copy)]
207 struct X;
208
209 impl std::ops::Deref for X {
210     type Target = X;
211     fn deref(&self) -> &Self::Target {
212         self
213     }
214 }
215
216 fn deref_target_is_x<T>(_: T)
217 where
218     T: std::ops::Deref<Target = X>,
219 {
220 }
221
222 fn multiple_constraints<T, U, V, X, Y>(_: T)
223 where
224     T: IntoIterator<Item = U> + IntoIterator<Item = X>,
225     U: IntoIterator<Item = V>,
226     V: AsRef<str>,
227     X: IntoIterator<Item = Y>,
228     Y: AsRef<std::ffi::OsStr>,
229 {
230 }
231
232 fn multiple_constraints_normalizes_to_same<T, U, V>(_: T, _: V)
233 where
234     T: std::ops::Deref<Target = U>,
235     U: std::ops::Deref<Target = V>,
236 {
237 }
238
239 fn only_sized<T>(_: T) {}
240
241 fn ref_as_ref_path<T: 'static>(_: &'static T)
242 where
243     &'static T: AsRef<std::path::Path>,
244 {
245 }
246
247 trait RefsOnly {
248     type Referent;
249 }
250
251 impl<T> RefsOnly for &T {
252     type Referent = T;
253 }
254
255 fn refs_only<T, U>(_: T)
256 where
257     T: RefsOnly<Referent = U>,
258 {
259 }
260
261 fn multiple_constraints_normalizes_to_different<T, U, V>(_: T, _: U)
262 where
263     T: IntoIterator<Item = U>,
264     U: IntoIterator<Item = V>,
265     V: AsRef<str>,
266 {
267 }
268
269 // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
270 #[allow(dead_code)]
271 mod copyable_iterator {
272     #[derive(Clone, Copy)]
273     struct Iter;
274     impl Iterator for Iter {
275         type Item = ();
276         fn next(&mut self) -> Option<Self::Item> {
277             None
278         }
279     }
280     fn takes_iter(_: impl Iterator) {}
281     fn dont_warn(mut x: Iter) {
282         takes_iter(&mut x);
283     }
284     #[allow(unused_mut)]
285     fn warn(mut x: &mut Iter) {
286         takes_iter(&mut x)
287     }
288 }
289
290 mod under_msrv {
291     #![allow(dead_code)]
292     #![clippy::msrv = "1.52.0"]
293
294     fn foo() {
295         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
296     }
297 }
298
299 mod meets_msrv {
300     #![allow(dead_code)]
301     #![clippy::msrv = "1.53.0"]
302
303     fn foo() {
304         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
305     }
306 }
307
308 #[allow(unused)]
309 fn issue9383() {
310     // Should not lint because unions need explicit deref when accessing field
311     use std::mem::ManuallyDrop;
312
313     union Coral {
314         crab: ManuallyDrop<Vec<i32>>,
315     }
316
317     union Ocean {
318         coral: ManuallyDrop<Coral>,
319     }
320
321     let mut ocean = Ocean {
322         coral: ManuallyDrop::new(Coral {
323             crab: ManuallyDrop::new(vec![1, 2, 3]),
324         }),
325     };
326
327     unsafe {
328         ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
329
330         (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
331         ManuallyDrop::drop(&mut (*ocean.coral).crab);
332
333         ManuallyDrop::drop(&mut ocean.coral);
334     }
335 }
336
337 #[allow(dead_code)]
338 fn closure_test() {
339     let env = "env".to_owned();
340     let arg = "arg".to_owned();
341     let f = |arg| {
342         let loc = "loc".to_owned();
343         let _ = std::fs::write("x", &env); // Don't lint. In environment
344         let _ = std::fs::write("x", &arg);
345         let _ = std::fs::write("x", &loc);
346     };
347     let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
348     f(arg);
349 }
350
351 #[allow(dead_code)]
352 mod significant_drop {
353     #[derive(Debug)]
354     struct X;
355
356     #[derive(Debug)]
357     struct Y;
358
359     impl Drop for Y {
360         fn drop(&mut self) {}
361     }
362
363     fn foo(x: X, y: Y) {
364         debug(&x);
365         debug(&y); // Don't lint. Has significant drop
366     }
367
368     fn debug(_: impl std::fmt::Debug) {}
369 }
370
371 #[allow(dead_code)]
372 mod used_exactly_once {
373     fn foo(x: String) {
374         use_x(&x);
375     }
376     fn use_x(_: impl AsRef<str>) {}
377 }
378
379 #[allow(dead_code)]
380 mod used_more_than_once {
381     fn foo(x: String) {
382         use_x(&x);
383         use_x_again(&x);
384     }
385     fn use_x(_: impl AsRef<str>) {}
386     fn use_x_again(_: impl AsRef<str>) {}
387 }