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