]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/tests/ui/unnecessary_to_owned.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / tools / clippy / tests / ui / unnecessary_to_owned.rs
1 // run-rustfix
2
3 #![allow(clippy::needless_borrow, 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()); // No longer flagged because of #8759.
82
83 require_x(&Cow::<X>::Owned(x.clone()).into_owned());
84 require_x(&x_ref.to_owned()); // No longer flagged because of #8759.
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 require_slice(&[String::from("x")].to_owned());
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.to_vec() {
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"][..].to_vec().into_iter();
222 }
223
224 fn _msrv_1_36() {
225 #![clippy::msrv = "1.36"]
226 let _ = &["x"][..].to_vec().into_iter();
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.to_string()))
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".to_string())
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 }