]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/unnecessary_to_owned.rs
Rollup merge of #96565 - notriddle:notriddle/impl-box, r=camelid
[rust.git] / src / tools / clippy / tests / ui / unnecessary_to_owned.rs
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).into_owned());
61     require_c_str(&c_str.to_owned());
62
63     require_os_str(&os_str.to_os_string());
64     require_os_str(&Cow::from(os_str).into_owned());
65     require_os_str(&os_str.to_owned());
66
67     require_path(&path.to_path_buf());
68     require_path(&Cow::from(path).into_owned());
69     require_path(&path.to_owned());
70
71     require_str(&s.to_string());
72     require_str(&Cow::from(s).into_owned());
73     require_str(&s.to_owned());
74     require_str(&x_ref.to_string());
75
76     require_slice(&slice.to_vec());
77     require_slice(&Cow::from(slice).into_owned());
78     require_slice(&array.to_owned());
79     require_slice(&array_ref.to_owned());
80     require_slice(&slice.to_owned());
81     require_slice(&x_ref.to_owned());
82
83     require_x(&Cow::<X>::Owned(x.clone()).into_owned());
84     require_x(&x_ref.to_owned());
85
86     require_deref_c_str(c_str.to_owned());
87     require_deref_os_str(os_str.to_owned());
88     require_deref_path(path.to_owned());
89     require_deref_str(s.to_owned());
90     require_deref_slice(slice.to_owned());
91
92     require_impl_deref_c_str(c_str.to_owned());
93     require_impl_deref_os_str(os_str.to_owned());
94     require_impl_deref_path(path.to_owned());
95     require_impl_deref_str(s.to_owned());
96     require_impl_deref_slice(slice.to_owned());
97
98     require_deref_str_slice(s.to_owned(), slice.to_owned());
99     require_deref_slice_str(slice.to_owned(), s.to_owned());
100
101     require_as_ref_c_str(c_str.to_owned());
102     require_as_ref_os_str(os_str.to_owned());
103     require_as_ref_path(path.to_owned());
104     require_as_ref_str(s.to_owned());
105     require_as_ref_str(x.to_owned());
106     require_as_ref_slice(array.to_owned());
107     require_as_ref_slice(array_ref.to_owned());
108     require_as_ref_slice(slice.to_owned());
109
110     require_impl_as_ref_c_str(c_str.to_owned());
111     require_impl_as_ref_os_str(os_str.to_owned());
112     require_impl_as_ref_path(path.to_owned());
113     require_impl_as_ref_str(s.to_owned());
114     require_impl_as_ref_str(x.to_owned());
115     require_impl_as_ref_slice(array.to_owned());
116     require_impl_as_ref_slice(array_ref.to_owned());
117     require_impl_as_ref_slice(slice.to_owned());
118
119     require_as_ref_str_slice(s.to_owned(), array.to_owned());
120     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
121     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
122     require_as_ref_slice_str(array.to_owned(), s.to_owned());
123     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
124     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
125
126     let _ = x.join(&x_ref.to_string());
127
128     let _ = slice.to_vec().into_iter();
129     let _ = slice.to_owned().into_iter();
130     let _ = [std::path::PathBuf::new()][..].to_vec().into_iter();
131     let _ = [std::path::PathBuf::new()][..].to_owned().into_iter();
132
133     let _ = IntoIterator::into_iter(slice.to_vec());
134     let _ = IntoIterator::into_iter(slice.to_owned());
135     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec());
136     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned());
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().to_owned());
152     require_os_str(&OsString::from("x").to_os_string());
153     require_path(&std::path::PathBuf::from("x").to_path_buf());
154     require_str(&String::from("x").to_string());
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.to_vec() {
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 fn _msrv_1_35() {
218     #![clippy::msrv = "1.35"]
219     // `copied` was stabilized in 1.36, so clippy should use `cloned`.
220     let _ = &["x"][..].to_vec().into_iter();
221 }
222
223 fn _msrv_1_36() {
224     #![clippy::msrv = "1.36"]
225     let _ = &["x"][..].to_vec().into_iter();
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.to_string()))
273     }
274 }