Skip to content

Commit a9a086a

Browse files
committed
Improve message for match_single_arms
1 parent 11b1fc7 commit a9a086a

File tree

4 files changed

+249
-236
lines changed

4 files changed

+249
-236
lines changed

clippy_lints/src/matches.rs

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2569,42 +2569,52 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
25692569
};
25702570

25712571
let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
2572-
for (&(_, i), &(_, j)) in search_same(&indexed_arms, hash, eq) {
2573-
span_lint_and_then(
2574-
cx,
2575-
MATCH_SAME_ARMS,
2576-
j.body.span,
2577-
"this `match` has identical arm bodies",
2578-
|diag| {
2579-
diag.span_note(i.body.span, "same as this");
2580-
2581-
// Note: this does not use `span_suggestion` on purpose:
2582-
// there is no clean way
2583-
// to remove the other arm. Building a span and suggest to replace it to ""
2584-
// makes an even more confusing error message. Also in order not to make up a
2585-
// span for the whole pattern, the suggestion is only shown when there is only
2586-
// one pattern. The user should know about `|` if they are already using it…
2587-
2588-
let lhs = snippet(cx, i.pat.span, "<pat1>");
2589-
let rhs = snippet(cx, j.pat.span, "<pat2>");
2590-
2591-
if let PatKind::Wild = j.pat.kind {
2592-
// if the last arm is _, then i could be integrated into _
2593-
// note that i.pat cannot be _, because that would mean that we're
2594-
// hiding all the subsequent arms, and rust won't compile
2595-
diag.span_note(
2596-
i.body.span,
2597-
&format!(
2598-
"`{}` has the same arm body as the `_` wildcard, consider removing it",
2599-
lhs
2600-
),
2601-
);
2602-
} else {
2603-
diag.span_help(i.pat.span, &format!("consider refactoring into `{} | {}`", lhs, rhs,))
2604-
.help("...or consider changing the match arm bodies");
2605-
}
2606-
},
2607-
);
2572+
for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) {
2573+
if matches!(arm2.pat.kind, PatKind::Wild) {
2574+
span_lint_and_then(
2575+
cx,
2576+
MATCH_SAME_ARMS,
2577+
arm1.span,
2578+
"this match arm has an identical body to the `_` wildcard arm",
2579+
|diag| {
2580+
diag.span_suggestion(
2581+
arm1.span,
2582+
"try removing the arm",
2583+
String::new(),
2584+
Applicability::MaybeIncorrect,
2585+
)
2586+
.help("or try changing either arm body")
2587+
.span_note(arm2.span, "`_` wildcard arm here");
2588+
},
2589+
);
2590+
} else {
2591+
let back_block = backwards_blocking_idxs[j];
2592+
let (keep_arm, move_arm) = if back_block < i || (back_block == 0 && forwards_blocking_idxs[i] <= j) {
2593+
(arm1, arm2)
2594+
} else {
2595+
(arm2, arm1)
2596+
};
2597+
2598+
span_lint_and_then(
2599+
cx,
2600+
MATCH_SAME_ARMS,
2601+
keep_arm.span,
2602+
"this match arm has an identical body to another arm",
2603+
|diag| {
2604+
let move_pat_snip = snippet(cx, move_arm.pat.span, "<pat2>");
2605+
let keep_pat_snip = snippet(cx, keep_arm.pat.span, "<pat1>");
2606+
2607+
diag.span_suggestion(
2608+
keep_arm.pat.span,
2609+
"try merging the arm patterns",
2610+
format!("{} | {}", keep_pat_snip, move_pat_snip),
2611+
Applicability::MaybeIncorrect,
2612+
)
2613+
.help("or try changing either arm body")
2614+
.span_note(move_arm.span, "other arm here");
2615+
},
2616+
);
2617+
}
26082618
}
26092619
}
26102620
}

tests/ui/match_same_arms.stderr

Lines changed: 79 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,121 @@
1-
error: this `match` has identical arm bodies
2-
--> $DIR/match_same_arms.rs:13:14
1+
error: this match arm has an identical body to the `_` wildcard arm
2+
--> $DIR/match_same_arms.rs:11:9
33
|
4-
LL | _ => 0, //~ ERROR match arms have same body
5-
| ^
4+
LL | Abc::A => 0,
5+
| ^^^^^^^^^^^ help: try removing the arm
66
|
77
= note: `-D clippy::match-same-arms` implied by `-D warnings`
8-
note: same as this
9-
--> $DIR/match_same_arms.rs:11:19
8+
= help: or try changing either arm body
9+
note: `_` wildcard arm here
10+
--> $DIR/match_same_arms.rs:13:9
1011
|
11-
LL | Abc::A => 0,
12-
| ^
13-
note: `Abc::A` has the same arm body as the `_` wildcard, consider removing it
14-
--> $DIR/match_same_arms.rs:11:19
15-
|
16-
LL | Abc::A => 0,
17-
| ^
12+
LL | _ => 0, //~ ERROR match arms have same body
13+
| ^^^^^^
1814

19-
error: this `match` has identical arm bodies
20-
--> $DIR/match_same_arms.rs:18:20
21-
|
22-
LL | (.., 3) => 42, //~ ERROR match arms have same body
23-
| ^^
24-
|
25-
note: same as this
26-
--> $DIR/match_same_arms.rs:17:23
27-
|
28-
LL | (1, .., 3) => 42,
29-
| ^^
30-
help: consider refactoring into `(1, .., 3) | (.., 3)`
15+
error: this match arm has an identical body to another arm
3116
--> $DIR/match_same_arms.rs:17:9
3217
|
3318
LL | (1, .., 3) => 42,
34-
| ^^^^^^^^^^
35-
= help: ...or consider changing the match arm bodies
19+
| ----------^^^^^^
20+
| |
21+
| help: try merging the arm patterns: `(1, .., 3) | (.., 3)`
22+
|
23+
= help: or try changing either arm body
24+
note: other arm here
25+
--> $DIR/match_same_arms.rs:18:9
26+
|
27+
LL | (.., 3) => 42, //~ ERROR match arms have same body
28+
| ^^^^^^^^^^^^^
3629

37-
error: this `match` has identical arm bodies
38-
--> $DIR/match_same_arms.rs:24:15
30+
error: this match arm has an identical body to another arm
31+
--> $DIR/match_same_arms.rs:24:9
3932
|
4033
LL | 51 => 1, //~ ERROR match arms have same body
41-
| ^
34+
| --^^^^^
35+
| |
36+
| help: try merging the arm patterns: `51 | 42`
4237
|
43-
note: same as this
44-
--> $DIR/match_same_arms.rs:23:15
45-
|
46-
LL | 42 => 1,
47-
| ^
48-
help: consider refactoring into `42 | 51`
38+
= help: or try changing either arm body
39+
note: other arm here
4940
--> $DIR/match_same_arms.rs:23:9
5041
|
5142
LL | 42 => 1,
52-
| ^^
53-
= help: ...or consider changing the match arm bodies
43+
| ^^^^^^^
5444

55-
error: this `match` has identical arm bodies
56-
--> $DIR/match_same_arms.rs:26:15
57-
|
58-
LL | 52 => 2, //~ ERROR match arms have same body
59-
| ^
60-
|
61-
note: same as this
62-
--> $DIR/match_same_arms.rs:25:15
63-
|
64-
LL | 41 => 2,
65-
| ^
66-
help: consider refactoring into `41 | 52`
45+
error: this match arm has an identical body to another arm
6746
--> $DIR/match_same_arms.rs:25:9
6847
|
6948
LL | 41 => 2,
70-
| ^^
71-
= help: ...or consider changing the match arm bodies
49+
| --^^^^^
50+
| |
51+
| help: try merging the arm patterns: `41 | 52`
52+
|
53+
= help: or try changing either arm body
54+
note: other arm here
55+
--> $DIR/match_same_arms.rs:26:9
56+
|
57+
LL | 52 => 2, //~ ERROR match arms have same body
58+
| ^^^^^^^
7259

73-
error: this `match` has identical arm bodies
74-
--> $DIR/match_same_arms.rs:32:14
60+
error: this match arm has an identical body to another arm
61+
--> $DIR/match_same_arms.rs:32:9
7562
|
7663
LL | 2 => 2, //~ ERROR 2nd matched arms have same body
77-
| ^
78-
|
79-
note: same as this
80-
--> $DIR/match_same_arms.rs:31:14
64+
| -^^^^^
65+
| |
66+
| help: try merging the arm patterns: `2 | 1`
8167
|
82-
LL | 1 => 2,
83-
| ^
84-
help: consider refactoring into `1 | 2`
68+
= help: or try changing either arm body
69+
note: other arm here
8570
--> $DIR/match_same_arms.rs:31:9
8671
|
8772
LL | 1 => 2,
88-
| ^
89-
= help: ...or consider changing the match arm bodies
73+
| ^^^^^^
9074

91-
error: this `match` has identical arm bodies
92-
--> $DIR/match_same_arms.rs:33:14
75+
error: this match arm has an identical body to another arm
76+
--> $DIR/match_same_arms.rs:33:9
9377
|
9478
LL | 3 => 2, //~ ERROR 3rd matched arms have same body
95-
| ^
96-
|
97-
note: same as this
98-
--> $DIR/match_same_arms.rs:31:14
79+
| -^^^^^
80+
| |
81+
| help: try merging the arm patterns: `3 | 1`
9982
|
100-
LL | 1 => 2,
101-
| ^
102-
help: consider refactoring into `1 | 3`
83+
= help: or try changing either arm body
84+
note: other arm here
10385
--> $DIR/match_same_arms.rs:31:9
10486
|
10587
LL | 1 => 2,
106-
| ^
107-
= help: ...or consider changing the match arm bodies
88+
| ^^^^^^
10889

109-
error: this `match` has identical arm bodies
110-
--> $DIR/match_same_arms.rs:50:55
90+
error: this match arm has an identical body to another arm
91+
--> $DIR/match_same_arms.rs:32:9
11192
|
112-
LL | CommandInfo::External { name, .. } => name.to_string(),
113-
| ^^^^^^^^^^^^^^^^
93+
LL | 2 => 2, //~ ERROR 2nd matched arms have same body
94+
| -^^^^^
95+
| |
96+
| help: try merging the arm patterns: `2 | 3`
11497
|
115-
note: same as this
116-
--> $DIR/match_same_arms.rs:49:54
98+
= help: or try changing either arm body
99+
note: other arm here
100+
--> $DIR/match_same_arms.rs:33:9
117101
|
118-
LL | CommandInfo::BuiltIn { name, .. } => name.to_string(),
119-
| ^^^^^^^^^^^^^^^^
120-
help: consider refactoring into `CommandInfo::BuiltIn { name, .. } | CommandInfo::External { name, .. }`
102+
LL | 3 => 2, //~ ERROR 3rd matched arms have same body
103+
| ^^^^^^
104+
105+
error: this match arm has an identical body to another arm
106+
--> $DIR/match_same_arms.rs:50:17
107+
|
108+
LL | CommandInfo::External { name, .. } => name.to_string(),
109+
| ----------------------------------^^^^^^^^^^^^^^^^^^^^
110+
| |
111+
| help: try merging the arm patterns: `CommandInfo::External { name, .. } | CommandInfo::BuiltIn { name, .. }`
112+
|
113+
= help: or try changing either arm body
114+
note: other arm here
121115
--> $DIR/match_same_arms.rs:49:17
122116
|
123117
LL | CommandInfo::BuiltIn { name, .. } => name.to_string(),
124-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
125-
= help: ...or consider changing the match arm bodies
118+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
126119

127-
error: aborting due to 7 previous errors
120+
error: aborting due to 8 previous errors
128121

tests/ui/match_same_arms2.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,27 @@ fn main() {
173173
Z(u32),
174174
}
175175

176+
// Don't lint. `Foo::X(0)` and `Foo::Z(_)` overlap with the arm in between.
176177
let _ = match Foo::X(0) {
177178
Foo::X(0) => 1,
178179
Foo::X(_) | Foo::Y(_) | Foo::Z(0) => 2,
179180
Foo::Z(_) => 1,
180181
_ => 0,
181182
};
183+
184+
// Suggest moving `Foo::Z(_)` up.
185+
let _ = match Foo::X(0) {
186+
Foo::X(0) => 1,
187+
Foo::X(_) | Foo::Y(_) => 2,
188+
Foo::Z(_) => 1,
189+
_ => 0,
190+
};
191+
192+
// Suggest moving `Foo::X(0)` down.
193+
let _ = match Foo::X(0) {
194+
Foo::X(0) => 1,
195+
Foo::Y(_) | Foo::Z(0) => 2,
196+
Foo::Z(_) => 1,
197+
_ => 0,
198+
};
182199
}

0 commit comments

Comments
 (0)