Skip to content

Commit 086b045

Browse files
committed
add checking for x -> x and ref x -> x and related test cases.
1 parent ec91164 commit 086b045

File tree

4 files changed

+105
-19
lines changed

4 files changed

+105
-19
lines changed

clippy_lints/src/matches/needless_match.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
55
use clippy_utils::{eq_expr_value, get_parent_expr, higher, is_else_clause, is_lang_ctor, peel_blocks_with_stmt};
66
use rustc_errors::Applicability;
77
use rustc_hir::LangItem::OptionNone;
8-
use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, Pat, PatKind, Path, PathSegment, QPath};
8+
use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, Pat, PatKind, Path, PathSegment, QPath, UnOp};
99
use rustc_lint::LateContext;
1010
use rustc_span::sym;
1111

@@ -107,6 +107,7 @@ fn check_if_let(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool {
107107
false
108108
}
109109

110+
/// Strip `return` keyword if the expression type is `ExprKind::Ret`.
110111
fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
111112
if let ExprKind::Ret(Some(ret)) = expr.kind {
112113
ret
@@ -118,6 +119,7 @@ fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
118119
fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
119120
let expr = strip_return(expr);
120121
match (&pat.kind, &expr.kind) {
122+
// Example: `Some(val) => Some(val)`
121123
(
122124
PatKind::TupleStruct(QPath::Resolved(_, path), [first_pat, ..], _),
123125
ExprKind::Call(call_expr, [first_param, ..]),
@@ -130,9 +132,34 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
130132
}
131133
}
132134
},
135+
// Example: `val => val`, or `ref val => *val`
136+
(PatKind::Binding(annot, _, pat_ident, _), _) => {
137+
let new_expr = if let (
138+
BindingAnnotation::Ref | BindingAnnotation::RefMut,
139+
ExprKind::Unary(UnOp::Deref, operand_expr),
140+
) = (annot, &expr.kind)
141+
{
142+
operand_expr
143+
} else {
144+
expr
145+
};
146+
147+
if let ExprKind::Path(QPath::Resolved(
148+
_,
149+
Path {
150+
segments: [first_seg, ..],
151+
..
152+
},
153+
)) = new_expr.kind
154+
{
155+
return pat_ident.name == first_seg.ident.name;
156+
}
157+
},
158+
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
133159
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {
134160
return has_identical_segments(p_path.segments, e_path.segments);
135161
},
162+
// Example: `5 => 5`
136163
(PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => {
137164
if let ExprKind::Lit(pat_spanned) = &pat_lit_expr.kind {
138165
return pat_spanned.node == expr_spanned.node;

tests/ui/needless_match.fixed

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,15 @@ enum Choice {
1111
D,
1212
}
1313

14-
fn useless_match(x: i32) {
15-
let _: i32 = x;
14+
#[allow(unused_mut)]
15+
fn useless_match() {
16+
let mut i = 10;
17+
let _: i32 = i;
18+
let _: i32 = i;
19+
let mut _i_mut = i;
20+
21+
let s = "test";
22+
let _: &str = s;
1623
}
1724

1825
fn custom_type_match(se: Choice) {

tests/ui/needless_match.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,31 @@ enum Choice {
1111
D,
1212
}
1313

14-
fn useless_match(x: i32) {
15-
let _: i32 = match x {
14+
#[allow(unused_mut)]
15+
fn useless_match() {
16+
let mut i = 10;
17+
let _: i32 = match i {
1618
0 => 0,
1719
1 => 1,
1820
2 => 2,
19-
_ => x,
21+
_ => i,
22+
};
23+
let _: i32 = match i {
24+
0 => 0,
25+
1 => 1,
26+
ref i => *i,
27+
};
28+
let mut _i_mut = match i {
29+
0 => 0,
30+
1 => 1,
31+
ref mut i => *i,
32+
};
33+
34+
let s = "test";
35+
let _: &str = match s {
36+
"a" => "a",
37+
"b" => "b",
38+
s => s,
2039
};
2140
}
2241

tests/ui/needless_match.stderr

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
11
error: this match expression is unnecessary
2-
--> $DIR/needless_match.rs:15:18
2+
--> $DIR/needless_match.rs:17:18
33
|
4-
LL | let _: i32 = match x {
4+
LL | let _: i32 = match i {
55
| __________________^
66
LL | | 0 => 0,
77
LL | | 1 => 1,
88
LL | | 2 => 2,
9-
LL | | _ => x,
9+
LL | | _ => i,
1010
LL | | };
11-
| |_____^ help: replace it with: `x`
11+
| |_____^ help: replace it with: `i`
1212
|
1313
= note: `-D clippy::needless-match` implied by `-D warnings`
1414

1515
error: this match expression is unnecessary
16-
--> $DIR/needless_match.rs:24:21
16+
--> $DIR/needless_match.rs:23:18
17+
|
18+
LL | let _: i32 = match i {
19+
| __________________^
20+
LL | | 0 => 0,
21+
LL | | 1 => 1,
22+
LL | | ref i => *i,
23+
LL | | };
24+
| |_____^ help: replace it with: `i`
25+
26+
error: this match expression is unnecessary
27+
--> $DIR/needless_match.rs:28:22
28+
|
29+
LL | let mut _i_mut = match i {
30+
| ______________________^
31+
LL | | 0 => 0,
32+
LL | | 1 => 1,
33+
LL | | ref mut i => *i,
34+
LL | | };
35+
| |_____^ help: replace it with: `i`
36+
37+
error: this match expression is unnecessary
38+
--> $DIR/needless_match.rs:35:19
39+
|
40+
LL | let _: &str = match s {
41+
| ___________________^
42+
LL | | "a" => "a",
43+
LL | | "b" => "b",
44+
LL | | s => s,
45+
LL | | };
46+
| |_____^ help: replace it with: `s`
47+
48+
error: this match expression is unnecessary
49+
--> $DIR/needless_match.rs:43:21
1750
|
1851
LL | let _: Choice = match se {
1952
| _____________________^
@@ -25,7 +58,7 @@ LL | | };
2558
| |_____^ help: replace it with: `se`
2659

2760
error: this match expression is unnecessary
28-
--> $DIR/needless_match.rs:46:26
61+
--> $DIR/needless_match.rs:65:26
2962
|
3063
LL | let _: Option<i32> = match x {
3164
| __________________________^
@@ -35,7 +68,7 @@ LL | | };
3568
| |_____^ help: replace it with: `x`
3669

3770
error: this match expression is unnecessary
38-
--> $DIR/needless_match.rs:62:31
71+
--> $DIR/needless_match.rs:81:31
3972
|
4073
LL | let _: Result<i32, i32> = match Ok(1) {
4174
| _______________________________^
@@ -45,7 +78,7 @@ LL | | };
4578
| |_____^ help: replace it with: `Ok(1)`
4679

4780
error: this match expression is unnecessary
48-
--> $DIR/needless_match.rs:66:31
81+
--> $DIR/needless_match.rs:85:31
4982
|
5083
LL | let _: Result<i32, i32> = match func_ret_err(0_i32) {
5184
| _______________________________^
@@ -55,25 +88,25 @@ LL | | };
5588
| |_____^ help: replace it with: `func_ret_err(0_i32)`
5689

5790
error: this if-let expression is unnecessary
58-
--> $DIR/needless_match.rs:73:5
91+
--> $DIR/needless_match.rs:92:5
5992
|
6093
LL | if let Some(a) = Some(1) { Some(a) } else { None }
6194
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(1)`
6295

6396
error: this if-let expression is unnecessary
64-
--> $DIR/needless_match.rs:77:30
97+
--> $DIR/needless_match.rs:96:30
6598
|
6699
LL | let _: Result<(), i32> = if let Err(e) = x { Err(e) } else { x };
67100
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x`
68101

69102
error: this if-let expression is unnecessary
70-
--> $DIR/needless_match.rs:78:30
103+
--> $DIR/needless_match.rs:97:30
71104
|
72105
LL | let _: Result<(), i32> = if let Ok(val) = x { Ok(val) } else { x };
73106
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x`
74107

75108
error: this if-let expression is unnecessary
76-
--> $DIR/needless_match.rs:84:21
109+
--> $DIR/needless_match.rs:103:21
77110
|
78111
LL | let _: Choice = if let Choice::A = x {
79112
| _____________________^
@@ -85,5 +118,5 @@ LL | | x
85118
LL | | };
86119
| |_____^ help: replace it with: `x`
87120

88-
error: aborting due to 9 previous errors
121+
error: aborting due to 12 previous errors
89122

0 commit comments

Comments
 (0)