Skip to content

Commit 52ecd4f

Browse files
committed
emit a suggestion
1 parent f65c481 commit 52ecd4f

File tree

3 files changed

+144
-15
lines changed

3 files changed

+144
-15
lines changed

clippy_lints/src/duplicate_match_guard.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use clippy_utils::diagnostics::span_lint;
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::eq_expr_value;
3+
use clippy_utils::source::snippet_with_applicability;
4+
use rustc_errors::Applicability;
35
use rustc_hir::{Arm, ExprKind};
46
use rustc_lint::{LateContext, LateLintPass};
57
use rustc_session::declare_lint_pass;
@@ -54,10 +56,29 @@ impl<'tcx> LateLintPass<'tcx> for DuplicateMatchGuard {
5456
&& let ExprKind::Block(block, _) = arm.body.kind
5557
&& block.stmts.is_empty()
5658
&& let Some(trailing_expr) = block.expr
57-
&& let ExprKind::If(cond, _, None) = trailing_expr.kind
59+
&& let ExprKind::If(cond, then, None) = trailing_expr.kind
5860
&& eq_expr_value(cx, guard, cond.peel_drop_temps())
5961
{
60-
span_lint(cx, DUPLICATE_MATCH_GUARD, cond.span, "condition duplicates match guard");
62+
let ExprKind::Block(then, _) = then.kind else {
63+
unreachable!("the `then` expr in `ExprKind::If` is always `ExprKind::Block`")
64+
};
65+
66+
// the two expressions may be syntactically different, even if identical
67+
// semantically -- the user might want to replace the condition in the guard
68+
// with the one in the body
69+
let mut applicability = Applicability::MaybeIncorrect;
70+
71+
let sugg = snippet_with_applicability(cx, then.span, "..", &mut applicability);
72+
73+
span_lint_and_sugg(
74+
cx,
75+
DUPLICATE_MATCH_GUARD,
76+
trailing_expr.span,
77+
"condition duplicates match guard",
78+
"remove the condition",
79+
sugg.to_string(),
80+
applicability,
81+
);
6182
}
6283
}
6384
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#![allow(clippy::needless_return, clippy::needless_else)]
2+
#![warn(clippy::duplicate_match_guard)]
3+
4+
fn main() {
5+
let mut a = 5;
6+
let b = 4;
7+
let mut v: Vec<u32> = vec![];
8+
9+
match 0u32 {
10+
0 if true => {
11+
{
12+
//~^ duplicate_match_guard
13+
return;
14+
}
15+
},
16+
0 if a > b => {
17+
{
18+
//~^ duplicate_match_guard
19+
return;
20+
}
21+
},
22+
// not _identical_, but the meaning is the same
23+
0 if a > b => {
24+
{
25+
//~^ duplicate_match_guard
26+
return;
27+
}
28+
},
29+
// a bit more complicated
30+
0 if a > 0 && b > 0 => {
31+
{
32+
//~^ duplicate_match_guard
33+
return;
34+
}
35+
},
36+
37+
// no warnings
38+
0 if true => {
39+
if false {
40+
return;
41+
}
42+
},
43+
// has side effects, so don't lint
44+
0 if v.pop().is_some() => {
45+
if v.pop().is_some() {
46+
return;
47+
}
48+
},
49+
// there's _something_ in the else branch
50+
0 if a > b => {
51+
if a > b {
52+
a += b;
53+
} else {
54+
}
55+
},
56+
// body has statements before the if
57+
0 if a > b => {
58+
a += b;
59+
if a > b {
60+
return;
61+
}
62+
},
63+
_ => todo!(),
64+
};
65+
}
Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,72 @@
11
error: condition duplicates match guard
2-
--> tests/ui/duplicate_match_guard.rs:11:16
2+
--> tests/ui/duplicate_match_guard.rs:11:13
33
|
4-
LL | if true {
5-
| ^^^^
4+
LL | / if true {
5+
LL | |
6+
LL | | return;
7+
LL | | }
8+
| |_____________^
69
|
710
= note: `-D clippy::duplicate-match-guard` implied by `-D warnings`
811
= help: to override `-D warnings` add `#[allow(clippy::duplicate_match_guard)]`
12+
help: remove the condition
13+
|
14+
LL ~ {
15+
LL +
16+
LL + return;
17+
LL + }
18+
|
919

1020
error: condition duplicates match guard
11-
--> tests/ui/duplicate_match_guard.rs:17:16
21+
--> tests/ui/duplicate_match_guard.rs:17:13
22+
|
23+
LL | / if a > b {
24+
LL | |
25+
LL | | return;
26+
LL | | }
27+
| |_____________^
28+
|
29+
help: remove the condition
30+
|
31+
LL ~ {
32+
LL +
33+
LL + return;
34+
LL + }
1235
|
13-
LL | if a > b {
14-
| ^^^^^
1536

1637
error: condition duplicates match guard
17-
--> tests/ui/duplicate_match_guard.rs:24:16
38+
--> tests/ui/duplicate_match_guard.rs:24:13
39+
|
40+
LL | / if b < a {
41+
LL | |
42+
LL | | return;
43+
LL | | }
44+
| |_____________^
45+
|
46+
help: remove the condition
47+
|
48+
LL ~ {
49+
LL +
50+
LL + return;
51+
LL + }
1852
|
19-
LL | if b < a {
20-
| ^^^^^
2153

2254
error: condition duplicates match guard
23-
--> tests/ui/duplicate_match_guard.rs:31:16
55+
--> tests/ui/duplicate_match_guard.rs:31:13
56+
|
57+
LL | / if a > 0 && b > 0 {
58+
LL | |
59+
LL | | return;
60+
LL | | }
61+
| |_____________^
62+
|
63+
help: remove the condition
64+
|
65+
LL ~ {
66+
LL +
67+
LL + return;
68+
LL + }
2469
|
25-
LL | if a > 0 && b > 0 {
26-
| ^^^^^^^^^^^^^^
2770

2871
error: aborting due to 4 previous errors
2972

0 commit comments

Comments
 (0)