Skip to content

Commit 0524773

Browse files
committed
fix: unit_arg suggests wrongly for Default::default
1 parent 1029572 commit 0524773

File tree

6 files changed

+49
-28
lines changed

6 files changed

+49
-28
lines changed

clippy_lints/src/default.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
22
use clippy_utils::source::snippet_with_context;
33
use clippy_utils::ty::{has_drop, is_copy};
4-
use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_from_proc_macro};
4+
use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_expr_default, is_from_proc_macro};
55
use rustc_data_structures::fx::FxHashSet;
66
use rustc_errors::Applicability;
7-
use rustc_hir::def::Res;
87
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind, StructTailExpr};
98
use rustc_lint::{LateContext, LateLintPass};
109
use rustc_middle::ty;
@@ -129,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
129128
// only take bindings to identifiers
130129
&& let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind
131130
// only when assigning `... = Default::default()`
132-
&& is_expr_default(expr, cx)
131+
&& is_expr_default(cx, expr)
133132
&& let binding_type = cx.typeck_results().node_type(binding_id)
134133
&& let ty::Adt(adt, args) = *binding_type.kind()
135134
&& adt.is_struct()
@@ -251,19 +250,6 @@ impl<'tcx> LateLintPass<'tcx> for Default {
251250
}
252251
}
253252

254-
/// Checks if the given expression is the `default` method belonging to the `Default` trait.
255-
fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
256-
if let ExprKind::Call(fn_expr, []) = &expr.kind
257-
&& let ExprKind::Path(qpath) = &fn_expr.kind
258-
&& let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id)
259-
{
260-
// right hand side of assignment is `Default::default`
261-
cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
262-
} else {
263-
false
264-
}
265-
}
266-
267253
/// Returns the reassigned field and the assigning expression (right-hand side of assign).
268254
fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
269255
if let StmtKind::Semi(later_expr) = this.kind

clippy_lints/src/unit_types/unit_arg.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::is_from_proc_macro;
32
use clippy_utils::source::{SourceText, SpanRangeExt, indent_of, reindent_multiline};
3+
use clippy_utils::{is_expr_default, is_from_proc_macro};
44
use rustc_errors::Applicability;
55
use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind};
66
use rustc_lint::LateContext;
@@ -59,7 +59,7 @@ fn is_questionmark_desugar_marked_call(expr: &Expr<'_>) -> bool {
5959
}
6060
}
6161

62-
fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Expr<'_>]) {
62+
fn lint_unit_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, args_to_recover: &[&'tcx Expr<'tcx>]) {
6363
let mut applicability = Applicability::MachineApplicable;
6464
let (singular, plural) = if args_to_recover.len() > 1 {
6565
("", "s")
@@ -102,9 +102,11 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
102102
.iter()
103103
.filter_map(|arg| arg.span.get_source_text(cx))
104104
.collect();
105-
let arg_snippets_without_empty_blocks: Vec<_> = args_to_recover
105+
106+
// If the argument is an empty block or `Default::default()`, we can replace it with `()`.
107+
let arg_snippets_without_redundant_exprs: Vec<_> = args_to_recover
106108
.iter()
107-
.filter(|arg| !is_empty_block(arg))
109+
.filter(|arg| !is_empty_block(arg) && !is_expr_default(cx, arg))
108110
.filter_map(|arg| arg.span.get_source_text(cx))
109111
.collect();
110112

@@ -114,10 +116,10 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
114116
expr,
115117
&call_snippet,
116118
&arg_snippets,
117-
&arg_snippets_without_empty_blocks,
119+
&arg_snippets_without_redundant_exprs,
118120
);
119121

120-
if arg_snippets_without_empty_blocks.is_empty() {
122+
if arg_snippets_without_redundant_exprs.is_empty() {
121123
db.multipart_suggestion(
122124
format!("use {singular}unit literal{plural} instead"),
123125
args_to_recover
@@ -127,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
127129
applicability,
128130
);
129131
} else {
130-
let plural = arg_snippets_without_empty_blocks.len() > 1;
132+
let plural = arg_snippets_without_redundant_exprs.len() > 1;
131133
let empty_or_s = if plural { "s" } else { "" };
132134
let it_or_them = if plural { "them" } else { "it" };
133135
db.span_suggestion(

clippy_utils/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3471,3 +3471,16 @@ pub fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
34713471
None
34723472
}
34733473
}
3474+
3475+
/// Checks if the given expression is the `default` method belonging to the `Default` trait.
3476+
pub fn is_expr_default<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
3477+
if let ExprKind::Call(fn_expr, []) = &expr.kind
3478+
&& let ExprKind::Path(qpath) = &fn_expr.kind
3479+
&& let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id)
3480+
{
3481+
// right hand side of assignment is `Default::default`
3482+
cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
3483+
} else {
3484+
false
3485+
}
3486+
}

tests/ui/unit_arg_empty_blocks.fixed renamed to tests/ui/unit_arg_fixable.fixed

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,9 @@ fn taking_three_units(a: (), b: (), c: ()) {}
3232
fn main() {
3333
bad();
3434
}
35+
36+
fn issue14857() {
37+
let fn_take_unit = |_: ()| {};
38+
fn_take_unit(());
39+
//~^ unit_arg
40+
}

tests/ui/unit_arg_empty_blocks.rs renamed to tests/ui/unit_arg_fixable.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,9 @@ fn taking_three_units(a: (), b: (), c: ()) {}
2929
fn main() {
3030
bad();
3131
}
32+
33+
fn issue14857() {
34+
let fn_take_unit = |_: ()| {};
35+
fn_take_unit(Default::default());
36+
//~^ unit_arg
37+
}

tests/ui/unit_arg_empty_blocks.stderr renamed to tests/ui/unit_arg_fixable.stderr

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: passing a unit value to a function
2-
--> tests/ui/unit_arg_empty_blocks.rs:16:5
2+
--> tests/ui/unit_arg_fixable.rs:16:5
33
|
44
LL | foo({});
55
| ^^^^--^
@@ -10,15 +10,15 @@ LL | foo({});
1010
= help: to override `-D warnings` add `#[allow(clippy::unit_arg)]`
1111

1212
error: passing a unit value to a function
13-
--> tests/ui/unit_arg_empty_blocks.rs:18:5
13+
--> tests/ui/unit_arg_fixable.rs:18:5
1414
|
1515
LL | foo3({}, 2, 2);
1616
| ^^^^^--^^^^^^^
1717
| |
1818
| help: use a unit literal instead: `()`
1919

2020
error: passing unit values to a function
21-
--> tests/ui/unit_arg_empty_blocks.rs:20:5
21+
--> tests/ui/unit_arg_fixable.rs:20:5
2222
|
2323
LL | taking_two_units({}, foo(0));
2424
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL ~ taking_two_units((), ());
3030
|
3131

3232
error: passing unit values to a function
33-
--> tests/ui/unit_arg_empty_blocks.rs:22:5
33+
--> tests/ui/unit_arg_fixable.rs:22:5
3434
|
3535
LL | taking_three_units({}, foo(0), foo(1));
3636
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,5 +42,13 @@ LL + foo(1);
4242
LL ~ taking_three_units((), (), ());
4343
|
4444

45-
error: aborting due to 4 previous errors
45+
error: passing a unit value to a function
46+
--> tests/ui/unit_arg_fixable.rs:35:5
47+
|
48+
LL | fn_take_unit(Default::default());
49+
| ^^^^^^^^^^^^^------------------^
50+
| |
51+
| help: use a unit literal instead: `()`
52+
53+
error: aborting due to 5 previous errors
4654

0 commit comments

Comments
 (0)