Skip to content

Commit

Permalink
Fix macro issues with field_reassign_with_default
Browse files Browse the repository at this point in the history
  • Loading branch information
phansch committed Jan 5, 2021
1 parent a8825e9 commit 92f2bbb
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 20 deletions.
3 changes: 3 additions & 0 deletions clippy_lints/src/default.rs
Expand Up @@ -8,6 +8,7 @@ use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{Ident, Symbol};
Expand Down Expand Up @@ -120,6 +121,8 @@ impl LateLintPass<'_> for Default {
// only take `let ...` statements
if let StmtKind::Local(local) = stmt.kind;
if let Some(expr) = local.init;
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
if !in_external_macro(cx.tcx.sess, expr.span);
// only take bindings to identifiers
if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
// only when assigning `... = Default::default()`
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/auxiliary/macro_rules.rs
Expand Up @@ -94,3 +94,19 @@ macro_rules! large_enum_variant {
}
};
}

#[macro_export]
macro_rules! field_reassign_with_default {
() => {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
};
}
18 changes: 18 additions & 0 deletions tests/ui/auxiliary/proc_macro_derive.rs
Expand Up @@ -4,6 +4,7 @@
#![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_quote)]
#![allow(incomplete_features)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::eq_op)]

extern crate proc_macro;
Expand All @@ -23,3 +24,20 @@ pub fn derive(_: TokenStream) -> TokenStream {
};
output
}

#[proc_macro_derive(FieldReassignWithDefault)]
pub fn derive_foo(_input: TokenStream) -> TokenStream {
quote! {
#[derive(Default)]
struct A {
pub i: i32,
pub j: i64,
}
#[automatically_derived]
fn lint() {
let mut a: A = Default::default();
a.i = 42;
a;
}
}
}
16 changes: 16 additions & 0 deletions tests/ui/field_reassign_with_default.rs
@@ -1,5 +1,18 @@
// aux-build:proc_macro_derive.rs
// aux-build:macro_rules.rs

#![warn(clippy::field_reassign_with_default)]

#[macro_use]
extern crate proc_macro_derive;
#[macro_use]
extern crate macro_rules;

// Don't lint on derives that derive `Default`
// See https://github.com/rust-lang/rust-clippy/issues/6545
#[derive(FieldReassignWithDefault)]
struct DerivedStruct;

#[derive(Default)]
struct A {
i: i32,
Expand Down Expand Up @@ -120,6 +133,9 @@ fn main() {
// don't expand macros in the suggestion (#6522)
let mut a: C = C::default();
a.i = vec![1];

// Don't lint in external macros
field_reassign_with_default!();
}

mod m {
Expand Down
40 changes: 20 additions & 20 deletions tests/ui/field_reassign_with_default.stderr
@@ -1,84 +1,84 @@
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:35:5
--> $DIR/field_reassign_with_default.rs:48:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
= note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:34:5
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:47:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:75:5
--> $DIR/field_reassign_with_default.rs:88:5
|
LL | a.j = 43;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { j: 43, i: 42 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:74:5
note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:87:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:80:5
--> $DIR/field_reassign_with_default.rs:93:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { i: 42, j: 44 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:79:5
note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:92:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:86:5
--> $DIR/field_reassign_with_default.rs:99:5
|
LL | a.i = 42;
| ^^^^^^^^^
|
note: consider initializing the variable with `A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:85:5
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:98:5
|
LL | let mut a = A::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:96:5
--> $DIR/field_reassign_with_default.rs:109:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:95:5
note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:108:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:100:5
--> $DIR/field_reassign_with_default.rs:113:5
|
LL | a.i = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: consider initializing the variable with `A { i: Default::default(), j: 45 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:99:5
note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:112:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:122:5
--> $DIR/field_reassign_with_default.rs:135:5
|
LL | a.i = vec![1];
| ^^^^^^^^^^^^^^
|
note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:121:5
--> $DIR/field_reassign_with_default.rs:134:5
|
LL | let mut a: C = C::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down

0 comments on commit 92f2bbb

Please sign in to comment.