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