Skip to content

Commit f3de78e

Browse files
committed
Auto merge of #6945 - ThibsG:BadSuggestionGenericsForReassignDefault, r=Manishearth
Fix suggestion with generics for `field_reassign_with_default` lint Fix bad suggestion where `::` is missing after type if generics are involved Fixes #6944 changelog: none
2 parents 0bdaa77 + 3ddaabc commit f3de78e

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

clippy_lints/src/default.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl LateLintPass<'_> for Default {
104104
}
105105
}
106106

107+
#[allow(clippy::too_many_lines)]
107108
fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
108109
// start from the `let mut _ = _::default();` and look at all the following
109110
// statements, see if they re-assign the fields of the binding
@@ -197,6 +198,24 @@ impl LateLintPass<'_> for Default {
197198
.collect::<Vec<String>>()
198199
.join(", ");
199200

201+
// give correct suggestion if generics are involved (see #6944)
202+
let binding_type = if_chain! {
203+
if let ty::Adt(adt_def, substs) = binding_type.kind();
204+
if !substs.is_empty();
205+
let adt_def_ty_name = cx.tcx.item_name(adt_def.did);
206+
let generic_args = substs.iter().collect::<Vec<_>>();
207+
let tys_str = generic_args
208+
.iter()
209+
.map(ToString::to_string)
210+
.collect::<Vec<_>>()
211+
.join(", ");
212+
then {
213+
format!("{}::<{}>", adt_def_ty_name, &tys_str)
214+
} else {
215+
binding_type.to_string()
216+
}
217+
};
218+
200219
let sugg = if ext_with_default {
201220
if field_list.is_empty() {
202221
format!("{}::default()", binding_type)

tests/ui/field_reassign_with_default.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ fn main() {
136136

137137
// Don't lint in external macros
138138
field_reassign_with_default!();
139+
140+
// be sure suggestion is correct with generics
141+
let mut a: Wrapper<bool> = Default::default();
142+
a.i = true;
143+
144+
let mut a: WrapperMulti<i32, i64> = Default::default();
145+
a.i = 42;
139146
}
140147

141148
mod m {
@@ -145,3 +152,14 @@ mod m {
145152
b: u64,
146153
}
147154
}
155+
156+
#[derive(Default)]
157+
struct Wrapper<T> {
158+
i: T,
159+
}
160+
161+
#[derive(Default)]
162+
struct WrapperMulti<T, U> {
163+
i: T,
164+
j: U,
165+
}

tests/ui/field_reassign_with_default.stderr

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,29 @@ note: consider initializing the variable with `C { i: vec![1], ..Default::defaul
8383
LL | let mut a: C = C::default();
8484
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8585

86-
error: aborting due to 7 previous errors
86+
error: field assignment outside of initializer for an instance created with Default::default()
87+
--> $DIR/field_reassign_with_default.rs:142:5
88+
|
89+
LL | a.i = true;
90+
| ^^^^^^^^^^^
91+
|
92+
note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
93+
--> $DIR/field_reassign_with_default.rs:141:5
94+
|
95+
LL | let mut a: Wrapper<bool> = Default::default();
96+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97+
98+
error: field assignment outside of initializer for an instance created with Default::default()
99+
--> $DIR/field_reassign_with_default.rs:145:5
100+
|
101+
LL | a.i = 42;
102+
| ^^^^^^^^^
103+
|
104+
note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
105+
--> $DIR/field_reassign_with_default.rs:144:5
106+
|
107+
LL | let mut a: WrapperMulti<i32, i64> = Default::default();
108+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
109+
110+
error: aborting due to 9 previous errors
87111

0 commit comments

Comments
 (0)