]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / src / tools / clippy / tests / ui / unnecessary_to_owned.fixed
1 // run-rustfix
2
3 #![allow(clippy::needless_borrow, clippy::ptr_arg)]
4 #![warn(clippy::unnecessary_to_owned)]
5
6 use std::borrow::Cow;
7 use std::ffi::{CStr, CString, OsStr, OsString};
8 use std::ops::Deref;
9
10 #[derive(Clone)]
11 struct X(String);
12
13 impl Deref for X {
14     type Target = [u8];
15     fn deref(&self) -> &[u8] {
16         self.0.as_bytes()
17     }
18 }
19
20 impl AsRef<str> for X {
21     fn as_ref(&self) -> &str {
22         self.0.as_str()
23     }
24 }
25
26 impl ToString for X {
27     fn to_string(&self) -> String {
28         self.0.to_string()
29     }
30 }
31
32 impl X {
33     fn join(&self, other: impl AsRef<str>) -> Self {
34         let mut s = self.0.clone();
35         s.push_str(other.as_ref());
36         Self(s)
37     }
38 }
39
40 #[allow(dead_code)]
41 #[derive(Clone)]
42 enum FileType {
43     Account,
44     PrivateKey,
45     Certificate,
46 }
47
48 fn main() {
49     let c_str = CStr::from_bytes_with_nul(&[0]).unwrap();
50     let os_str = OsStr::new("x");
51     let path = std::path::Path::new("x");
52     let s = "x";
53     let array = ["x"];
54     let array_ref = &["x"];
55     let slice = &["x"][..];
56     let x = X(String::from("x"));
57     let x_ref = &x;
58
59     require_c_str(&Cow::from(c_str));
60     require_c_str(c_str);
61
62     require_os_str(os_str);
63     require_os_str(&Cow::from(os_str));
64     require_os_str(os_str);
65
66     require_path(path);
67     require_path(&Cow::from(path));
68     require_path(path);
69
70     require_str(s);
71     require_str(&Cow::from(s));
72     require_str(s);
73     require_str(x_ref.as_ref());
74
75     require_slice(slice);
76     require_slice(&Cow::from(slice));
77     require_slice(array.as_ref());
78     require_slice(array_ref.as_ref());
79     require_slice(slice);
80     require_slice(&x_ref.to_owned()); // No longer flagged because of #8759.
81
82     require_x(&Cow::<X>::Owned(x.clone()));
83     require_x(&x_ref.to_owned()); // No longer flagged because of #8759.
84
85     require_deref_c_str(c_str);
86     require_deref_os_str(os_str);
87     require_deref_path(path);
88     require_deref_str(s);
89     require_deref_slice(slice);
90
91     require_impl_deref_c_str(c_str);
92     require_impl_deref_os_str(os_str);
93     require_impl_deref_path(path);
94     require_impl_deref_str(s);
95     require_impl_deref_slice(slice);
96
97     require_deref_str_slice(s, slice);
98     require_deref_slice_str(slice, s);
99
100     require_as_ref_c_str(c_str);
101     require_as_ref_os_str(os_str);
102     require_as_ref_path(path);
103     require_as_ref_str(s);
104     require_as_ref_str(&x);
105     require_as_ref_slice(array);
106     require_as_ref_slice(array_ref);
107     require_as_ref_slice(slice);
108
109     require_impl_as_ref_c_str(c_str);
110     require_impl_as_ref_os_str(os_str);
111     require_impl_as_ref_path(path);
112     require_impl_as_ref_str(s);
113     require_impl_as_ref_str(&x);
114     require_impl_as_ref_slice(array);
115     require_impl_as_ref_slice(array_ref);
116     require_impl_as_ref_slice(slice);
117
118     require_as_ref_str_slice(s, array);
119     require_as_ref_str_slice(s, array_ref);
120     require_as_ref_str_slice(s, slice);
121     require_as_ref_slice_str(array, s);
122     require_as_ref_slice_str(array_ref, s);
123     require_as_ref_slice_str(slice, s);
124
125     let _ = x.join(x_ref);
126
127     let _ = slice.iter().copied();
128     let _ = slice.iter().copied();
129     let _ = [std::path::PathBuf::new()][..].iter().cloned();
130     let _ = [std::path::PathBuf::new()][..].iter().cloned();
131
132     let _ = slice.iter().copied();
133     let _ = slice.iter().copied();
134     let _ = [std::path::PathBuf::new()][..].iter().cloned();
135     let _ = [std::path::PathBuf::new()][..].iter().cloned();
136
137     let _ = check_files(&[FileType::Account]);
138
139     // negative tests
140     require_string(&s.to_string());
141     require_string(&Cow::from(s).into_owned());
142     require_string(&s.to_owned());
143     require_string(&x_ref.to_string());
144
145     // `X` isn't copy.
146     require_slice(&x.to_owned());
147     require_deref_slice(x.to_owned());
148
149     // The following should be flagged by `redundant_clone`, but not by this lint.
150     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap());
151     require_os_str(&OsString::from("x"));
152     require_path(&std::path::PathBuf::from("x"));
153     require_str(&String::from("x"));
154     require_slice(&[String::from("x")]);
155 }
156
157 fn require_c_str(_: &CStr) {}
158 fn require_os_str(_: &OsStr) {}
159 fn require_path(_: &std::path::Path) {}
160 fn require_str(_: &str) {}
161 fn require_slice<T>(_: &[T]) {}
162 fn require_x(_: &X) {}
163
164 fn require_deref_c_str<T: Deref<Target = CStr>>(_: T) {}
165 fn require_deref_os_str<T: Deref<Target = OsStr>>(_: T) {}
166 fn require_deref_path<T: Deref<Target = std::path::Path>>(_: T) {}
167 fn require_deref_str<T: Deref<Target = str>>(_: T) {}
168 fn require_deref_slice<T, U: Deref<Target = [T]>>(_: U) {}
169
170 fn require_impl_deref_c_str(_: impl Deref<Target = CStr>) {}
171 fn require_impl_deref_os_str(_: impl Deref<Target = OsStr>) {}
172 fn require_impl_deref_path(_: impl Deref<Target = std::path::Path>) {}
173 fn require_impl_deref_str(_: impl Deref<Target = str>) {}
174 fn require_impl_deref_slice<T>(_: impl Deref<Target = [T]>) {}
175
176 fn require_deref_str_slice<T: Deref<Target = str>, U, V: Deref<Target = [U]>>(_: T, _: V) {}
177 fn require_deref_slice_str<T, U: Deref<Target = [T]>, V: Deref<Target = str>>(_: U, _: V) {}
178
179 fn require_as_ref_c_str<T: AsRef<CStr>>(_: T) {}
180 fn require_as_ref_os_str<T: AsRef<OsStr>>(_: T) {}
181 fn require_as_ref_path<T: AsRef<std::path::Path>>(_: T) {}
182 fn require_as_ref_str<T: AsRef<str>>(_: T) {}
183 fn require_as_ref_slice<T, U: AsRef<[T]>>(_: U) {}
184
185 fn require_impl_as_ref_c_str(_: impl AsRef<CStr>) {}
186 fn require_impl_as_ref_os_str(_: impl AsRef<OsStr>) {}
187 fn require_impl_as_ref_path(_: impl AsRef<std::path::Path>) {}
188 fn require_impl_as_ref_str(_: impl AsRef<str>) {}
189 fn require_impl_as_ref_slice<T>(_: impl AsRef<[T]>) {}
190
191 fn require_as_ref_str_slice<T: AsRef<str>, U, V: AsRef<[U]>>(_: T, _: V) {}
192 fn require_as_ref_slice_str<T, U: AsRef<[T]>, V: AsRef<str>>(_: U, _: V) {}
193
194 // `check_files` is based on:
195 // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
196 fn check_files(file_types: &[FileType]) -> bool {
197     for t in file_types {
198         let path = match get_file_path(t) {
199             Ok(p) => p,
200             Err(_) => {
201                 return false;
202             },
203         };
204         if !path.is_file() {
205             return false;
206         }
207     }
208     true
209 }
210
211 fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
212     Ok(std::path::PathBuf::new())
213 }
214
215 fn require_string(_: &String) {}
216
217 #[clippy::msrv = "1.35"]
218 fn _msrv_1_35() {
219     // `copied` was stabilized in 1.36, so clippy should use `cloned`.
220     let _ = &["x"][..].iter().cloned();
221 }
222
223 #[clippy::msrv = "1.36"]
224 fn _msrv_1_36() {
225     let _ = &["x"][..].iter().copied();
226 }
227
228 // https://github.com/rust-lang/rust-clippy/issues/8507
229 mod issue_8507 {
230     #![allow(dead_code)]
231
232     struct Opaque<P>(P);
233
234     pub trait Abstracted {}
235
236     impl<P> Abstracted for Opaque<P> {}
237
238     fn build<P>(p: P) -> Opaque<P>
239     where
240         P: AsRef<str>,
241     {
242         Opaque(p)
243     }
244
245     // Should not lint.
246     fn test_str(s: &str) -> Box<dyn Abstracted> {
247         Box::new(build(s.to_string()))
248     }
249
250     // Should not lint.
251     fn test_x(x: super::X) -> Box<dyn Abstracted> {
252         Box::new(build(x))
253     }
254
255     #[derive(Clone, Copy)]
256     struct Y(&'static str);
257
258     impl AsRef<str> for Y {
259         fn as_ref(&self) -> &str {
260             self.0
261         }
262     }
263
264     impl ToString for Y {
265         fn to_string(&self) -> String {
266             self.0.to_string()
267         }
268     }
269
270     // Should lint because Y is copy.
271     fn test_y(y: Y) -> Box<dyn Abstracted> {
272         Box::new(build(y))
273     }
274 }
275
276 // https://github.com/rust-lang/rust-clippy/issues/8759
277 mod issue_8759 {
278     #![allow(dead_code)]
279
280     #[derive(Default)]
281     struct View {}
282
283     impl std::borrow::ToOwned for View {
284         type Owned = View;
285         fn to_owned(&self) -> Self::Owned {
286             View {}
287         }
288     }
289
290     #[derive(Default)]
291     struct RenderWindow {
292         default_view: View,
293     }
294
295     impl RenderWindow {
296         fn default_view(&self) -> &View {
297             &self.default_view
298         }
299         fn set_view(&mut self, _view: &View) {}
300     }
301
302     fn main() {
303         let mut rw = RenderWindow::default();
304         rw.set_view(&rw.default_view().to_owned());
305     }
306 }
307
308 mod issue_8759_variant {
309     #![allow(dead_code)]
310
311     #[derive(Clone, Default)]
312     struct View {}
313
314     #[derive(Default)]
315     struct RenderWindow {
316         default_view: View,
317     }
318
319     impl RenderWindow {
320         fn default_view(&self) -> &View {
321             &self.default_view
322         }
323         fn set_view(&mut self, _view: &View) {}
324     }
325
326     fn main() {
327         let mut rw = RenderWindow::default();
328         rw.set_view(&rw.default_view().to_owned());
329     }
330 }
331
332 mod issue_9317 {
333     #![allow(dead_code)]
334
335     struct Bytes {}
336
337     impl ToString for Bytes {
338         fn to_string(&self) -> String {
339             "123".to_string()
340         }
341     }
342
343     impl AsRef<[u8]> for Bytes {
344         fn as_ref(&self) -> &[u8] {
345             &[1, 2, 3]
346         }
347     }
348
349     fn consume<C: AsRef<[u8]>>(c: C) {
350         let _ = c;
351     }
352
353     pub fn main() {
354         let b = Bytes {};
355         // Should not lint.
356         consume(b.to_string());
357     }
358 }
359
360 mod issue_9351 {
361     #![allow(dead_code)]
362
363     use std::ops::Deref;
364     use std::path::{Path, PathBuf};
365
366     fn require_deref_path<T: Deref<Target = std::path::Path>>(x: T) -> T {
367         x
368     }
369
370     fn generic_arg_used_elsewhere<T: AsRef<Path>>(_x: T, _y: T) {}
371
372     fn id<T: AsRef<str>>(x: T) -> T {
373         x
374     }
375
376     fn predicates_are_satisfied(_x: impl std::fmt::Write) {}
377
378     // Should lint
379     fn single_return() -> impl AsRef<str> {
380         id("abc")
381     }
382
383     // Should not lint
384     fn multiple_returns(b: bool) -> impl AsRef<str> {
385         if b {
386             return String::new();
387         }
388
389         id("abc".to_string())
390     }
391
392     struct S1(String);
393
394     // Should not lint
395     fn fields1() -> S1 {
396         S1(id("abc".to_string()))
397     }
398
399     struct S2 {
400         s: String,
401     }
402
403     // Should not lint
404     fn fields2() {
405         let mut s = S2 { s: "abc".into() };
406         s.s = id("abc".to_string());
407     }
408
409     pub fn main() {
410         let path = std::path::Path::new("x");
411         let path_buf = path.to_owned();
412
413         // Should not lint.
414         let _x: PathBuf = require_deref_path(path.to_owned());
415         generic_arg_used_elsewhere(path.to_owned(), path_buf);
416         predicates_are_satisfied(id("abc".to_string()));
417     }
418 }
419
420 mod issue_9504 {
421     #![allow(dead_code)]
422
423     async fn foo<S: AsRef<str>>(_: S) {}
424     async fn bar() {
425         foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
426     }
427 }
428
429 mod issue_9771a {
430     #![allow(dead_code)]
431
432     use std::marker::PhantomData;
433
434     pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>);
435
436     impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> {
437         pub fn new(key: K) -> Key<K, V> {
438             Key(key, PhantomData)
439         }
440     }
441
442     pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> {
443         Key::new([b"pkh-", pkh].concat().to_vec())
444     }
445 }
446
447 mod issue_9771b {
448     #![allow(dead_code)]
449
450     pub struct Key<K: AsRef<[u8]>>(K);
451
452     pub fn from(c: &[u8]) -> Key<Vec<u8>> {
453         let v = [c].concat();
454         Key(v.to_vec())
455     }
456 }
457
458 // This is a watered down version of the code in: https://github.com/oxigraph/rio
459 // The ICE is triggered by the call to `to_owned` on this line:
460 // https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
461 mod issue_10021 {
462     #![allow(unused)]
463
464     pub struct Iri<T>(T);
465
466     impl<T: AsRef<str>> Iri<T> {
467         pub fn parse(iri: T) -> Result<Self, ()> {
468             unimplemented!()
469         }
470     }
471
472     pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
473         let base_iri = Iri::parse(url.to_owned())?;
474         Ok(())
475     }
476 }