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