]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/ui/field_reassign_with_default.rs
Merge commit '35d9c6bf256968e1b40e0d554607928bdf9cebea' into sync_cg_clif-2022-02-23
[rust.git] / src / tools / clippy / tests / ui / field_reassign_with_default.rs
1 // aux-build:proc_macro_derive.rs
2 // aux-build:macro_rules.rs
3
4 #![warn(clippy::field_reassign_with_default)]
5
6 #[macro_use]
7 extern crate proc_macro_derive;
8 #[macro_use]
9 extern crate macro_rules;
10
11 // Don't lint on derives that derive `Default`
12 // See https://github.com/rust-lang/rust-clippy/issues/6545
13 #[derive(FieldReassignWithDefault)]
14 struct DerivedStruct;
15
16 #[derive(Default)]
17 struct A {
18     i: i32,
19     j: i64,
20 }
21
22 struct B {
23     i: i32,
24     j: i64,
25 }
26
27 #[derive(Default)]
28 struct C {
29     i: Vec<i32>,
30     j: i64,
31 }
32
33 #[derive(Default)]
34 struct D {
35     a: Option<i32>,
36     b: Option<i32>,
37 }
38
39 macro_rules! m {
40     ($key:ident: $value:tt) => {{
41         let mut data = $crate::D::default();
42         data.$key = Some($value);
43         data
44     }};
45 }
46
47 /// Implements .next() that returns a different number each time.
48 struct SideEffect(i32);
49
50 impl SideEffect {
51     fn new() -> SideEffect {
52         SideEffect(0)
53     }
54     fn next(&mut self) -> i32 {
55         self.0 += 1;
56         self.0
57     }
58 }
59
60 fn main() {
61     // wrong, produces first error in stderr
62     let mut a: A = Default::default();
63     a.i = 42;
64
65     // right
66     let mut a: A = Default::default();
67
68     // right
69     let a = A {
70         i: 42,
71         ..Default::default()
72     };
73
74     // right
75     let mut a: A = Default::default();
76     if a.i == 0 {
77         a.j = 12;
78     }
79
80     // right
81     let mut a: A = Default::default();
82     let b = 5;
83
84     // right
85     let mut b = 32;
86     let mut a: A = Default::default();
87     b = 2;
88
89     // right
90     let b: B = B { i: 42, j: 24 };
91
92     // right
93     let mut b: B = B { i: 42, j: 24 };
94     b.i = 52;
95
96     // right
97     let mut b = B { i: 15, j: 16 };
98     let mut a: A = Default::default();
99     b.i = 2;
100
101     // wrong, produces second error in stderr
102     let mut a: A = Default::default();
103     a.j = 43;
104     a.i = 42;
105
106     // wrong, produces third error in stderr
107     let mut a: A = Default::default();
108     a.i = 42;
109     a.j = 43;
110     a.j = 44;
111
112     // wrong, produces fourth error in stderr
113     let mut a = A::default();
114     a.i = 42;
115
116     // wrong, but does not produce an error in stderr, because we can't produce a correct kind of
117     // suggestion with current implementation
118     let mut c: (i32, i32) = Default::default();
119     c.0 = 42;
120     c.1 = 21;
121
122     // wrong, produces the fifth error in stderr
123     let mut a: A = Default::default();
124     a.i = Default::default();
125
126     // wrong, produces the sixth error in stderr
127     let mut a: A = Default::default();
128     a.i = Default::default();
129     a.j = 45;
130
131     // right, because an assignment refers to another field
132     let mut x = A::default();
133     x.i = 42;
134     x.j = 21 + x.i as i64;
135
136     // right, we bail out if there's a reassignment to the same variable, since there is a risk of
137     // side-effects affecting the outcome
138     let mut x = A::default();
139     let mut side_effect = SideEffect::new();
140     x.i = side_effect.next();
141     x.j = 2;
142     x.i = side_effect.next();
143
144     // don't lint - some private fields
145     let mut x = m::F::default();
146     x.a = 1;
147
148     // don't expand macros in the suggestion (#6522)
149     let mut a: C = C::default();
150     a.i = vec![1];
151
152     // Don't lint in external macros
153     field_reassign_with_default!();
154
155     // be sure suggestion is correct with generics
156     let mut a: Wrapper<bool> = Default::default();
157     a.i = true;
158
159     let mut a: WrapperMulti<i32, i64> = Default::default();
160     a.i = 42;
161
162     // Don't lint in macros
163     m! {
164         a: 42
165     };
166 }
167
168 mod m {
169     #[derive(Default)]
170     pub struct F {
171         pub a: u64,
172         b: u64,
173     }
174 }
175
176 #[derive(Default)]
177 struct Wrapper<T> {
178     i: T,
179 }
180
181 #[derive(Default)]
182 struct WrapperMulti<T, U> {
183     i: T,
184     j: U,
185 }
186
187 mod issue6312 {
188     use std::sync::atomic::AtomicBool;
189     use std::sync::Arc;
190
191     // do not lint: type implements `Drop` but not all fields are `Copy`
192     #[derive(Clone, Default)]
193     pub struct ImplDropNotAllCopy {
194         name: String,
195         delay_data_sync: Arc<AtomicBool>,
196     }
197
198     impl Drop for ImplDropNotAllCopy {
199         fn drop(&mut self) {
200             self.close()
201         }
202     }
203
204     impl ImplDropNotAllCopy {
205         fn new(name: &str) -> Self {
206             let mut f = ImplDropNotAllCopy::default();
207             f.name = name.to_owned();
208             f
209         }
210         fn close(&self) {}
211     }
212
213     // lint: type implements `Drop` and all fields are `Copy`
214     #[derive(Clone, Default)]
215     pub struct ImplDropAllCopy {
216         name: usize,
217         delay_data_sync: bool,
218     }
219
220     impl Drop for ImplDropAllCopy {
221         fn drop(&mut self) {
222             self.close()
223         }
224     }
225
226     impl ImplDropAllCopy {
227         fn new(name: &str) -> Self {
228             let mut f = ImplDropAllCopy::default();
229             f.name = name.len();
230             f
231         }
232         fn close(&self) {}
233     }
234
235     // lint: type does not implement `Drop` though all fields are `Copy`
236     #[derive(Clone, Default)]
237     pub struct NoDropAllCopy {
238         name: usize,
239         delay_data_sync: bool,
240     }
241
242     impl NoDropAllCopy {
243         fn new(name: &str) -> Self {
244             let mut f = NoDropAllCopy::default();
245             f.name = name.len();
246             f
247         }
248     }
249 }