]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/recursive_format_impl.rs
Rollup merge of #102764 - compiler-errors:issue-102762, r=jackh726
[rust.git] / src / tools / clippy / tests / ui / recursive_format_impl.rs
1 #![warn(clippy::recursive_format_impl)]
2 #![allow(
3     clippy::borrow_deref_ref,
4     clippy::deref_addrof,
5     clippy::inherent_to_string_shadow_display,
6     clippy::to_string_in_format_args,
7     clippy::uninlined_format_args
8 )]
9
10 use std::fmt;
11
12 struct A;
13 impl A {
14     fn fmt(&self) {
15         self.to_string();
16     }
17 }
18
19 trait B {
20     fn fmt(&self) {}
21 }
22
23 impl B for A {
24     fn fmt(&self) {
25         self.to_string();
26     }
27 }
28
29 impl fmt::Display for A {
30     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31         write!(f, "{}", self.to_string())
32     }
33 }
34
35 fn fmt(a: A) {
36     a.to_string();
37 }
38
39 struct C;
40
41 impl C {
42     // Doesn't trigger if to_string defined separately
43     // i.e. not using ToString trait (from Display)
44     fn to_string(&self) -> String {
45         String::from("I am C")
46     }
47 }
48
49 impl fmt::Display for C {
50     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51         write!(f, "{}", self.to_string())
52     }
53 }
54
55 enum D {
56     E(String),
57     F,
58 }
59
60 impl std::fmt::Display for D {
61     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62         match &self {
63             Self::E(string) => write!(f, "E {}", string.to_string()),
64             Self::F => write!(f, "F"),
65         }
66     }
67 }
68
69 // Check for use of self as Display, in Display impl
70 // Triggers on direct use of self
71 struct G;
72
73 impl std::fmt::Display for G {
74     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75         write!(f, "{}", self)
76     }
77 }
78
79 // Triggers on reference to self
80 struct H;
81
82 impl std::fmt::Display for H {
83     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84         write!(f, "{}", &self)
85     }
86 }
87
88 impl std::fmt::Debug for H {
89     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90         write!(f, "{:?}", &self)
91     }
92 }
93
94 // Triggers on multiple reference to self
95 struct H2;
96
97 impl std::fmt::Display for H2 {
98     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99         write!(f, "{}", &&&self)
100     }
101 }
102
103 // Doesn't trigger on correct deref
104 struct I;
105
106 impl std::ops::Deref for I {
107     type Target = str;
108
109     fn deref(&self) -> &Self::Target {
110         "test"
111     }
112 }
113
114 impl std::fmt::Display for I {
115     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
116         write!(f, "{}", &**self)
117     }
118 }
119
120 impl std::fmt::Debug for I {
121     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
122         write!(f, "{:?}", &**self)
123     }
124 }
125
126 // Doesn't trigger on multiple correct deref
127 struct I2;
128
129 impl std::ops::Deref for I2 {
130     type Target = str;
131
132     fn deref(&self) -> &Self::Target {
133         "test"
134     }
135 }
136
137 impl std::fmt::Display for I2 {
138     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
139         write!(f, "{}", **&&&**self)
140     }
141 }
142
143 // Doesn't trigger on multiple correct deref
144 struct I3;
145
146 impl std::ops::Deref for I3 {
147     type Target = str;
148
149     fn deref(&self) -> &Self::Target {
150         "test"
151     }
152 }
153
154 impl std::fmt::Display for I3 {
155     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
156         write!(f, "{}", &&**&&&**self)
157     }
158 }
159
160 // Does trigger when deref resolves to self
161 struct J;
162
163 impl std::ops::Deref for J {
164     type Target = str;
165
166     fn deref(&self) -> &Self::Target {
167         "test"
168     }
169 }
170
171 impl std::fmt::Display for J {
172     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
173         write!(f, "{}", &*self)
174     }
175 }
176
177 impl std::fmt::Debug for J {
178     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
179         write!(f, "{:?}", &*self)
180     }
181 }
182
183 struct J2;
184
185 impl std::ops::Deref for J2 {
186     type Target = str;
187
188     fn deref(&self) -> &Self::Target {
189         "test"
190     }
191 }
192
193 impl std::fmt::Display for J2 {
194     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
195         write!(f, "{}", *self)
196     }
197 }
198
199 struct J3;
200
201 impl std::ops::Deref for J3 {
202     type Target = str;
203
204     fn deref(&self) -> &Self::Target {
205         "test"
206     }
207 }
208
209 impl std::fmt::Display for J3 {
210     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
211         write!(f, "{}", **&&*self)
212     }
213 }
214
215 struct J4;
216
217 impl std::ops::Deref for J4 {
218     type Target = str;
219
220     fn deref(&self) -> &Self::Target {
221         "test"
222     }
223 }
224
225 impl std::fmt::Display for J4 {
226     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
227         write!(f, "{}", &&**&&*self)
228     }
229 }
230
231 // Doesn't trigger on Debug from Display
232 struct K;
233
234 impl std::fmt::Debug for K {
235     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
236         write!(f, "test")
237     }
238 }
239
240 impl std::fmt::Display for K {
241     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
242         write!(f, "{:?}", self)
243     }
244 }
245
246 // Doesn't trigger on Display from Debug
247 struct K2;
248
249 impl std::fmt::Debug for K2 {
250     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
251         write!(f, "{}", self)
252     }
253 }
254
255 impl std::fmt::Display for K2 {
256     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
257         write!(f, "test")
258     }
259 }
260
261 // Doesn't trigger on struct fields
262 struct L {
263     field1: u32,
264     field2: i32,
265 }
266
267 impl std::fmt::Display for L {
268     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
269         write!(f, "{},{}", self.field1, self.field2)
270     }
271 }
272
273 impl std::fmt::Debug for L {
274     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
275         write!(f, "{:?},{:?}", self.field1, self.field2)
276     }
277 }
278
279 // Doesn't trigger on nested enum matching
280 enum Tree {
281     Leaf,
282     Node(Vec<Tree>),
283 }
284
285 impl std::fmt::Display for Tree {
286     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287         match self {
288             Tree::Leaf => write!(f, "*"),
289             Tree::Node(children) => {
290                 write!(f, "(")?;
291                 for child in children.iter() {
292                     write!(f, "{},", child)?;
293                 }
294                 write!(f, ")")
295             },
296         }
297     }
298 }
299
300 impl std::fmt::Debug for Tree {
301     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302         match self {
303             Tree::Leaf => write!(f, "*"),
304             Tree::Node(children) => {
305                 write!(f, "(")?;
306                 for child in children.iter() {
307                     write!(f, "{:?},", child)?;
308                 }
309                 write!(f, ")")
310             },
311         }
312     }
313 }
314
315 fn main() {
316     let a = A;
317     a.to_string();
318     a.fmt();
319     fmt(a);
320
321     let c = C;
322     c.to_string();
323 }