Skip to content

Commit b10d9a4

Browse files
Henri Lunnikivihegza
Henri Lunnikivi
authored andcommitted
Cancel lint for given binding if field assignment references it
1 parent 3e052c9 commit b10d9a4

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

clippy_lints/src/field_reassign_with_default.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{match_def_path, paths, qpath_res, snippet, span_lint_and_note};
1+
use crate::utils::{contains_name, match_def_path, paths, qpath_res, snippet, span_lint_and_note};
22
use if_chain::if_chain;
33
use rustc_data_structures::fx::FxHashMap;
44
use rustc_hir::def::Res;
@@ -55,9 +55,10 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
5555
}
5656

5757
// find all "later statement"'s where the fields of the binding set as
58-
// Default::default() get reassigned
58+
// Default::default() get reassigned, unless the reassignment refers to the original binding
5959
let mut first_assign = None;
6060
let mut assigned_fields = FxHashMap::default();
61+
let mut cancel_lint = false;
6162
for consecutive_statement in &block.stmts[stmt_idx + 1..] {
6263
// interrupt if the statement is a let binding (`Local`) that shadows the original
6364
// binding
@@ -68,6 +69,12 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
6869
else if let Some((field_ident, assign_rhs)) =
6970
field_reassigned_by_stmt(consecutive_statement, binding_name)
7071
{
72+
// interrupt and cancel lint if assign_rhs references the original binding
73+
if contains_name(binding_name, assign_rhs) {
74+
cancel_lint = true;
75+
break;
76+
}
77+
7178
// always re-insert set value, this way the latest value is stored for output snippet
7279
assigned_fields.insert(field_ident.name, assign_rhs);
7380

@@ -84,7 +91,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
8491

8592
// if there are incorrectly assigned fields, do a span_lint_and_note to suggest
8693
// construction using `Ty { fields, ..Default::default() }`
87-
if !assigned_fields.is_empty() {
94+
if !assigned_fields.is_empty() && !cancel_lint {
8895
// take the original assignment as span
8996
let stmt = &block.stmts[stmt_idx];
9097

tests/ui/field_reassign_with_default.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,9 @@ fn main() {
8181
let mut a: A = Default::default();
8282
a.i = Default::default();
8383
a.j = 45;
84+
85+
// right, because an assignment refers to another field
86+
let mut x = A::default();
87+
x.i = 42;
88+
x.j = 21 + x.i as i64;
8489
}

0 commit comments

Comments
 (0)