]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | // run-rustfix |
2 | ||
3 | #![allow(clippy::ptr_arg)] | |
4 | #![warn(clippy::unnecessary_to_owned)] | |
04454e1e | 5 | #![feature(custom_inner_attributes)] |
a2a8927a XL |
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); | |
82 | ||
83 | require_x(&Cow::<X>::Owned(x.clone())); | |
84 | require_x(x_ref); | |
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 | } | |
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) {} | |
5e7ed085 | 216 | |
04454e1e FG |
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"][..].iter().cloned(); | |
221 | } | |
222 | ||
223 | fn _msrv_1_36() { | |
224 | #![clippy::msrv = "1.36"] | |
225 | let _ = &["x"][..].iter().copied(); | |
226 | } | |
227 | ||
5e7ed085 FG |
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 | } |