Skip to content

Commit b8ec12b

Browse files
committed
Avoid triggering default_trait_access
Do not trigger `default_trait_access` on a span already linted by `field_reassigned_with_default`.
1 parent a3ec772 commit b8ec12b

File tree

3 files changed

+79
-79
lines changed

3 files changed

+79
-79
lines changed

clippy_lints/src/field_reassign_with_default.rs renamed to clippy_lints/src/default.rs

+72-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1-
use crate::utils::{contains_name, match_def_path, paths, qpath_res, snippet, span_lint_and_note};
1+
use crate::utils::{any_parent_is_automatically_derived, contains_name, match_def_path, paths, qpath_res, snippet};
2+
use crate::utils::{span_lint_and_note, span_lint_and_sugg};
23
use if_chain::if_chain;
4+
use rustc_data_structures::fx::FxHashSet;
5+
use rustc_errors::Applicability;
36
use rustc_hir::def::Res;
47
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
8+
use rustc_lint::{LateContext, LateLintPass};
59
use rustc_middle::ty::{self, Adt, Ty};
10+
use rustc_session::{declare_tool_lint, impl_lint_pass};
611
use rustc_span::symbol::{Ident, Symbol};
12+
use rustc_span::Span;
713

8-
use rustc_lint::{LateContext, LateLintPass};
9-
use rustc_session::{declare_lint_pass, declare_tool_lint};
14+
declare_clippy_lint! {
15+
/// **What it does:** Checks for literal calls to `Default::default()`.
16+
///
17+
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
18+
/// being gotten than the generic `Default`.
19+
///
20+
/// **Known problems:** None.
21+
///
22+
/// **Example:**
23+
/// ```rust
24+
/// // Bad
25+
/// let s: String = Default::default();
26+
///
27+
/// // Good
28+
/// let s = String::default();
29+
/// ```
30+
pub DEFAULT_TRAIT_ACCESS,
31+
pedantic,
32+
"checks for literal calls to `Default::default()`"
33+
}
1034

1135
declare_clippy_lint! {
1236
/// **What it does:** Checks for immediate reassignment of fields initialized
@@ -19,12 +43,14 @@ declare_clippy_lint! {
1943
/// **Example:**
2044
/// Bad:
2145
/// ```
46+
/// # #[derive(Default)]
2247
/// # struct A { i: i32 }
2348
/// let mut a: A = Default::default();
2449
/// a.i = 42;
2550
/// ```
2651
/// Use instead:
2752
/// ```
53+
/// # #[derive(Default)]
2854
/// # struct A { i: i32 }
2955
/// let a = A {
3056
/// i: 42,
@@ -36,9 +62,46 @@ declare_clippy_lint! {
3662
"binding initialized with Default should have its fields set in the initializer"
3763
}
3864

39-
declare_lint_pass!(FieldReassignWithDefault => [FIELD_REASSIGN_WITH_DEFAULT]);
65+
#[derive(Default)]
66+
pub struct DefaultPass {
67+
// Spans linted by `field_reassign_with_default`.
68+
reassigned_linted: FxHashSet<Span>,
69+
}
70+
71+
impl_lint_pass!(DefaultPass => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);
72+
73+
impl LateLintPass<'_> for DefaultPass {
74+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
75+
if_chain! {
76+
// Avoid cases already linted by `field_reassign_with_default`
77+
if !self.reassigned_linted.contains(&expr.span);
78+
if let ExprKind::Call(ref path, ..) = expr.kind;
79+
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
80+
if let ExprKind::Path(ref qpath) = path.kind;
81+
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
82+
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
83+
// Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
84+
if let QPath::Resolved(None, _path) = qpath;
85+
then {
86+
let expr_ty = cx.typeck_results().expr_ty(expr);
87+
if let ty::Adt(def, ..) = expr_ty.kind() {
88+
// TODO: Work out a way to put "whatever the imported way of referencing
89+
// this type in this file" rather than a fully-qualified type.
90+
let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
91+
span_lint_and_sugg(
92+
cx,
93+
DEFAULT_TRAIT_ACCESS,
94+
expr.span,
95+
&format!("calling `{}` is more clear than this expression", replacement),
96+
"try",
97+
replacement,
98+
Applicability::Unspecified, // First resolve the TODO above
99+
);
100+
}
101+
}
102+
}
103+
}
40104

41-
impl LateLintPass<'_> for FieldReassignWithDefault {
42105
fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
43106
// find all binding statements like `let mut _ = T::default()` where `T::default()` is the
44107
// `default` method of the `Default` trait, and store statement index in current block being
@@ -47,7 +110,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
47110

48111
// start from the `let mut _ = _::default();` and look at all the following
49112
// statements, see if they re-assign the fields of the binding
50-
for (stmt_idx, binding_name, binding_type) in binding_statements_using_default {
113+
for (stmt_idx, binding_name, binding_type, span) in binding_statements_using_default {
51114
// the last statement of a block cannot trigger the lint
52115
if stmt_idx == block.stmts.len() - 1 {
53116
break;
@@ -145,6 +208,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
145208
sugg
146209
),
147210
);
211+
self.reassigned_linted.insert(span);
148212
}
149213
}
150214
}
@@ -171,7 +235,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
171235
fn enumerate_bindings_using_default<'tcx>(
172236
cx: &LateContext<'tcx>,
173237
block: &Block<'tcx>,
174-
) -> Vec<(usize, Symbol, Ty<'tcx>)> {
238+
) -> Vec<(usize, Symbol, Ty<'tcx>, Span)> {
175239
block
176240
.stmts
177241
.iter()
@@ -189,7 +253,7 @@ fn enumerate_bindings_using_default<'tcx>(
189253
if let Some(ref expr) = local.init;
190254
if is_expr_default(expr, cx);
191255
then {
192-
Some((idx, ident.name, ty))
256+
Some((idx, ident.name, ty, expr.span))
193257
} else {
194258
None
195259
}

clippy_lints/src/default_trait_access.rs

-62
This file was deleted.

clippy_lints/src/lib.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ mod copies;
175175
mod copy_iterator;
176176
mod create_dir;
177177
mod dbg_macro;
178-
mod default_trait_access;
178+
mod default;
179179
mod dereference;
180180
mod derive;
181181
mod disallowed_method;
@@ -198,7 +198,6 @@ mod excessive_bools;
198198
mod exit;
199199
mod explicit_write;
200200
mod fallible_impl_from;
201-
mod field_reassign_with_default;
202201
mod float_equality_without_abs;
203202
mod float_literal;
204203
mod floating_point_arithmetic;
@@ -531,7 +530,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
531530
&copy_iterator::COPY_ITERATOR,
532531
&create_dir::CREATE_DIR,
533532
&dbg_macro::DBG_MACRO,
534-
&default_trait_access::DEFAULT_TRAIT_ACCESS,
533+
&default::DEFAULT_TRAIT_ACCESS,
535534
&dereference::EXPLICIT_DEREF_METHODS,
536535
&derive::DERIVE_HASH_XOR_EQ,
537536
&derive::DERIVE_ORD_XOR_PARTIAL_ORD,
@@ -570,7 +569,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
570569
&exit::EXIT,
571570
&explicit_write::EXPLICIT_WRITE,
572571
&fallible_impl_from::FALLIBLE_IMPL_FROM,
573-
&field_reassign_with_default::FIELD_REASSIGN_WITH_DEFAULT,
572+
&default::FIELD_REASSIGN_WITH_DEFAULT,
574573
&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS,
575574
&float_literal::EXCESSIVE_PRECISION,
576575
&float_literal::LOSSY_FLOAT_LITERAL,
@@ -1033,7 +1032,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10331032
store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
10341033
store.register_late_pass(|| box unwrap::Unwrap);
10351034
store.register_late_pass(|| box duration_subsec::DurationSubsec);
1036-
store.register_late_pass(|| box default_trait_access::DefaultTraitAccess);
10371035
store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
10381036
store.register_late_pass(|| box non_copy_const::NonCopyConst);
10391037
store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
@@ -1084,7 +1082,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10841082
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
10851083
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
10861084
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
1087-
store.register_late_pass(|| box field_reassign_with_default::FieldReassignWithDefault);
1085+
store.register_late_pass(|| box default::DefaultPass::default());
10881086
store.register_late_pass(|| box unused_self::UnusedSelf);
10891087
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
10901088
store.register_late_pass(|| box exit::Exit);
@@ -1197,7 +1195,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11971195
LintId::of(&copies::MATCH_SAME_ARMS),
11981196
LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION),
11991197
LintId::of(&copy_iterator::COPY_ITERATOR),
1200-
LintId::of(&default_trait_access::DEFAULT_TRAIT_ACCESS),
1198+
LintId::of(&default::DEFAULT_TRAIT_ACCESS),
12011199
LintId::of(&dereference::EXPLICIT_DEREF_METHODS),
12021200
LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY),
12031201
LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE),
@@ -1324,7 +1322,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
13241322
LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
13251323
LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
13261324
LintId::of(&explicit_write::EXPLICIT_WRITE),
1327-
LintId::of(&field_reassign_with_default::FIELD_REASSIGN_WITH_DEFAULT),
1325+
LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT),
13281326
LintId::of(&float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
13291327
LintId::of(&float_literal::EXCESSIVE_PRECISION),
13301328
LintId::of(&format::USELESS_FORMAT),
@@ -1562,7 +1560,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15621560
LintId::of(&enum_variants::MODULE_INCEPTION),
15631561
LintId::of(&eq_op::OP_REF),
15641562
LintId::of(&eta_reduction::REDUNDANT_CLOSURE),
1565-
LintId::of(&field_reassign_with_default::FIELD_REASSIGN_WITH_DEFAULT),
1563+
LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT),
15661564
LintId::of(&float_literal::EXCESSIVE_PRECISION),
15671565
LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
15681566
LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),

0 commit comments

Comments
 (0)