Skip to content

Commit 8fee4f4

Browse files
committed
quick fix of issue#8542 for lint [needless_match]
modify `[match_as_ref]` to allow needless_match
1 parent b83c632 commit 8fee4f4

File tree

7 files changed

+223
-82
lines changed

7 files changed

+223
-82
lines changed

clippy_lints/src/matches/needless_match.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
2121
if !eq_expr_value(cx, ex, ret_expr) {
2222
return;
2323
}
24-
} else if !pat_same_as_expr(arm.pat, arm.body) {
24+
} else if !pat_same_as_expr(arm.pat, peel_blocks_with_stmt(arm.body)) {
2525
return;
2626
}
2727
}
@@ -92,6 +92,9 @@ fn check_if_let(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool {
9292

9393
if matches!(if_else.kind, ExprKind::Block(..)) {
9494
let else_expr = peel_blocks_with_stmt(if_else);
95+
if matches!(else_expr.kind, ExprKind::Block(..)) {
96+
return false;
97+
}
9598
let ret = strip_return(else_expr);
9699
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
97100
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
@@ -120,16 +123,10 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
120123
let expr = strip_return(expr);
121124
match (&pat.kind, &expr.kind) {
122125
// Example: `Some(val) => Some(val)`
123-
(
124-
PatKind::TupleStruct(QPath::Resolved(_, path), [first_pat, ..], _),
125-
ExprKind::Call(call_expr, [first_param, ..]),
126-
) => {
126+
(PatKind::TupleStruct(QPath::Resolved(_, path), tuple_params, _), ExprKind::Call(call_expr, call_params)) => {
127127
if let ExprKind::Path(QPath::Resolved(_, call_path)) = call_expr.kind {
128-
if has_identical_segments(path.segments, call_path.segments)
129-
&& has_same_non_ref_symbol(first_pat, first_param)
130-
{
131-
return true;
132-
}
128+
return has_identical_segments(path.segments, call_path.segments)
129+
&& has_same_non_ref_symbols(tuple_params, call_params);
133130
}
134131
},
135132
// Example: `val => val`, or `ref val => *val`
@@ -183,15 +180,16 @@ fn has_identical_segments(left_segs: &[PathSegment<'_>], right_segs: &[PathSegme
183180
true
184181
}
185182

186-
fn has_same_non_ref_symbol(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
187-
if_chain! {
188-
if let PatKind::Binding(annot, _, pat_ident, _) = pat.kind;
189-
if !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
190-
if let ExprKind::Path(QPath::Resolved(_, Path {segments: [first_seg, ..], .. })) = expr.kind;
191-
then {
192-
return pat_ident.name == first_seg.ident.name;
183+
fn has_same_non_ref_symbols(pats: &[Pat<'_>], exprs: &[Expr<'_>]) -> bool {
184+
if pats.len() != exprs.len() {
185+
return false;
186+
}
187+
188+
for i in 0..pats.len() {
189+
if !pat_same_as_expr(&pats[i], &exprs[i]) {
190+
return false;
193191
}
194192
}
195193

196-
false
194+
true
197195
}

tests/ui/match_as_ref.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-rustfix
22

33
#![allow(unused)]
4+
#![allow(clippy::needless_match)]
45
#![warn(clippy::match_as_ref)]
56

67
fn match_as_ref() {

tests/ui/match_as_ref.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-rustfix
22

33
#![allow(unused)]
4+
#![allow(clippy::needless_match)]
45
#![warn(clippy::match_as_ref)]
56

67
fn match_as_ref() {

tests/ui/match_as_ref.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: use `as_ref()` instead
2-
--> $DIR/match_as_ref.rs:8:33
2+
--> $DIR/match_as_ref.rs:9:33
33
|
44
LL | let borrowed: Option<&()> = match owned {
55
| _________________________________^
@@ -11,7 +11,7 @@ LL | | };
1111
= note: `-D clippy::match-as-ref` implied by `-D warnings`
1212

1313
error: use `as_mut()` instead
14-
--> $DIR/match_as_ref.rs:14:39
14+
--> $DIR/match_as_ref.rs:15:39
1515
|
1616
LL | let borrow_mut: Option<&mut ()> = match mut_owned {
1717
| _______________________________________^
@@ -21,7 +21,7 @@ LL | | };
2121
| |_____^ help: try this: `mut_owned.as_mut()`
2222

2323
error: use `as_ref()` instead
24-
--> $DIR/match_as_ref.rs:30:13
24+
--> $DIR/match_as_ref.rs:31:13
2525
|
2626
LL | / match self.source {
2727
LL | | Some(ref s) => Some(s),

tests/ui/needless_match.fixed

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#![allow(dead_code)]
55

66
#[derive(Clone, Copy)]
7-
enum Choice {
7+
enum Simple {
88
A,
99
B,
1010
C,
@@ -22,20 +22,21 @@ fn useless_match() {
2222
let _: &str = s;
2323
}
2424

25-
fn custom_type_match(se: Choice) {
26-
let _: Choice = se;
25+
fn custom_type_match() {
26+
let se = Simple::A;
27+
let _: Simple = se;
2728
// Don't trigger
28-
let _: Choice = match se {
29-
Choice::A => Choice::A,
30-
Choice::B => Choice::B,
31-
_ => Choice::C,
29+
let _: Simple = match se {
30+
Simple::A => Simple::A,
31+
Simple::B => Simple::B,
32+
_ => Simple::C,
3233
};
3334
// Mingled, don't trigger
34-
let _: Choice = match se {
35-
Choice::A => Choice::B,
36-
Choice::B => Choice::C,
37-
Choice::C => Choice::D,
38-
Choice::D => Choice::A,
35+
let _: Simple = match se {
36+
Simple::A => Simple::B,
37+
Simple::B => Simple::C,
38+
Simple::C => Simple::D,
39+
Simple::D => Simple::A,
3940
};
4041
}
4142

@@ -68,16 +69,76 @@ fn if_let_result(x: Result<(), i32>) {
6869
let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x };
6970
}
7071

71-
fn if_let_custom_enum(x: Choice) {
72-
let _: Choice = x;
72+
fn if_let_custom_enum(x: Simple) {
73+
let _: Simple = x;
74+
7375
// Don't trigger
74-
let _: Choice = if let Choice::A = x {
75-
Choice::A
76+
let _: Simple = if let Simple::A = x {
77+
Simple::A
7678
} else if true {
77-
Choice::B
79+
Simple::B
7880
} else {
7981
x
8082
};
8183
}
8284

85+
mod issue8542 {
86+
#[derive(Clone, Copy)]
87+
enum E {
88+
VariantA(u8, u8),
89+
VariantB(u8, bool),
90+
}
91+
92+
enum Complex {
93+
A(u8),
94+
B(u8, bool),
95+
C(u8, i32, f64),
96+
D(E, bool),
97+
}
98+
99+
fn match_test() {
100+
let ce = Complex::B(8, false);
101+
let aa = 0_u8;
102+
let bb = false;
103+
104+
let _: Complex = ce;
105+
106+
// Don't trigger
107+
let _: Complex = match ce {
108+
Complex::A(_) => Complex::A(aa),
109+
Complex::B(_, b) => Complex::B(aa, b),
110+
Complex::C(_, b, _) => Complex::C(aa, b, 64_f64),
111+
Complex::D(e, b) => Complex::D(e, b),
112+
};
113+
114+
// Don't trigger
115+
let _: Complex = match ce {
116+
Complex::A(a) => Complex::A(a),
117+
Complex::B(a, _) => Complex::B(a, bb),
118+
Complex::C(a, _, _) => Complex::C(a, 32_i32, 64_f64),
119+
_ => ce,
120+
};
121+
}
122+
123+
fn if_let_test() {
124+
fn do_something() {}
125+
126+
// Don't trigger
127+
let _ = if let Some(a) = Some(1) {
128+
Some(a)
129+
} else {
130+
do_something();
131+
None
132+
};
133+
134+
// Don't trigger
135+
let _ = if let Some(a) = Some(1) {
136+
do_something();
137+
Some(a)
138+
} else {
139+
None
140+
};
141+
}
142+
}
143+
83144
fn main() {}

tests/ui/needless_match.rs

Lines changed: 93 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#![allow(dead_code)]
55

66
#[derive(Clone, Copy)]
7-
enum Choice {
7+
enum Simple {
88
A,
99
B,
1010
C,
@@ -39,25 +39,26 @@ fn useless_match() {
3939
};
4040
}
4141

42-
fn custom_type_match(se: Choice) {
43-
let _: Choice = match se {
44-
Choice::A => Choice::A,
45-
Choice::B => Choice::B,
46-
Choice::C => Choice::C,
47-
Choice::D => Choice::D,
42+
fn custom_type_match() {
43+
let se = Simple::A;
44+
let _: Simple = match se {
45+
Simple::A => Simple::A,
46+
Simple::B => Simple::B,
47+
Simple::C => Simple::C,
48+
Simple::D => Simple::D,
4849
};
4950
// Don't trigger
50-
let _: Choice = match se {
51-
Choice::A => Choice::A,
52-
Choice::B => Choice::B,
53-
_ => Choice::C,
51+
let _: Simple = match se {
52+
Simple::A => Simple::A,
53+
Simple::B => Simple::B,
54+
_ => Simple::C,
5455
};
5556
// Mingled, don't trigger
56-
let _: Choice = match se {
57-
Choice::A => Choice::B,
58-
Choice::B => Choice::C,
59-
Choice::C => Choice::D,
60-
Choice::D => Choice::A,
57+
let _: Simple = match se {
58+
Simple::A => Simple::B,
59+
Simple::B => Simple::C,
60+
Simple::C => Simple::D,
61+
Simple::D => Simple::A,
6162
};
6263
}
6364

@@ -99,24 +100,90 @@ fn if_let_result(x: Result<(), i32>) {
99100
let _: Result<(), i32> = if let Err(e) = Ok(1) { Err(e) } else { x };
100101
}
101102

102-
fn if_let_custom_enum(x: Choice) {
103-
let _: Choice = if let Choice::A = x {
104-
Choice::A
105-
} else if let Choice::B = x {
106-
Choice::B
107-
} else if let Choice::C = x {
108-
Choice::C
103+
fn if_let_custom_enum(x: Simple) {
104+
let _: Simple = if let Simple::A = x {
105+
Simple::A
106+
} else if let Simple::B = x {
107+
Simple::B
108+
} else if let Simple::C = x {
109+
Simple::C
109110
} else {
110111
x
111112
};
113+
112114
// Don't trigger
113-
let _: Choice = if let Choice::A = x {
114-
Choice::A
115+
let _: Simple = if let Simple::A = x {
116+
Simple::A
115117
} else if true {
116-
Choice::B
118+
Simple::B
117119
} else {
118120
x
119121
};
120122
}
121123

124+
mod issue8542 {
125+
#[derive(Clone, Copy)]
126+
enum E {
127+
VariantA(u8, u8),
128+
VariantB(u8, bool),
129+
}
130+
131+
enum Complex {
132+
A(u8),
133+
B(u8, bool),
134+
C(u8, i32, f64),
135+
D(E, bool),
136+
}
137+
138+
fn match_test() {
139+
let ce = Complex::B(8, false);
140+
let aa = 0_u8;
141+
let bb = false;
142+
143+
let _: Complex = match ce {
144+
Complex::A(a) => Complex::A(a),
145+
Complex::B(a, b) => Complex::B(a, b),
146+
Complex::C(a, b, c) => Complex::C(a, b, c),
147+
Complex::D(E::VariantA(ea, eb), b) => Complex::D(E::VariantA(ea, eb), b),
148+
Complex::D(E::VariantB(ea, eb), b) => Complex::D(E::VariantB(ea, eb), b),
149+
};
150+
151+
// Don't trigger
152+
let _: Complex = match ce {
153+
Complex::A(_) => Complex::A(aa),
154+
Complex::B(_, b) => Complex::B(aa, b),
155+
Complex::C(_, b, _) => Complex::C(aa, b, 64_f64),
156+
Complex::D(e, b) => Complex::D(e, b),
157+
};
158+
159+
// Don't trigger
160+
let _: Complex = match ce {
161+
Complex::A(a) => Complex::A(a),
162+
Complex::B(a, _) => Complex::B(a, bb),
163+
Complex::C(a, _, _) => Complex::C(a, 32_i32, 64_f64),
164+
_ => ce,
165+
};
166+
}
167+
168+
fn if_let_test() {
169+
fn do_something() {}
170+
171+
// Don't trigger
172+
let _ = if let Some(a) = Some(1) {
173+
Some(a)
174+
} else {
175+
do_something();
176+
None
177+
};
178+
179+
// Don't trigger
180+
let _ = if let Some(a) = Some(1) {
181+
do_something();
182+
Some(a)
183+
} else {
184+
None
185+
};
186+
}
187+
}
188+
122189
fn main() {}

0 commit comments

Comments
 (0)