Skip to content

Commit 45eea9a

Browse files
committed
Auto merge of #5771 - montrivo:bugfix/single-match-else, r=matthiaskrgr
single_match_else - single expr/stmt else block corner case One approach to fix #3489. See discussion in the issue. changelog: single_match_else - single expr/stmt else block corner case fix
2 parents e12a316 + dac19e3 commit 45eea9a

File tree

3 files changed

+106
-9
lines changed

3 files changed

+106
-9
lines changed

clippy_lints/src/matches.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -530,16 +530,22 @@ fn check_single_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
530530
// the lint noisy in unnecessary situations
531531
return;
532532
}
533-
let els = remove_blocks(&arms[1].body);
534-
let els = if is_unit_expr(els) {
533+
let els = arms[1].body;
534+
let els = if is_unit_expr(remove_blocks(els)) {
535535
None
536-
} else if let ExprKind::Block(_, _) = els.kind {
537-
// matches with blocks that contain statements are prettier as `if let + else`
538-
Some(els)
536+
} else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind {
537+
if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() {
538+
// single statement/expr "else" block, don't lint
539+
return;
540+
} else {
541+
// block with 2+ statements or 1 expr and 1+ statement
542+
Some(els)
543+
}
539544
} else {
540-
// allow match arms with just expressions
541-
return;
545+
// not a block, don't lint
546+
return;
542547
};
548+
543549
let ty = cx.tables().expr_ty(ex);
544550
if ty.kind != ty::Bool || is_allowed(cx, MATCH_BOOL, ex.hir_id) {
545551
check_single_match_single_pattern(cx, ex, arms, expr, els);

tests/ui/single_match_else.rs

+51
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![warn(clippy::single_match_else)]
2+
#![allow(clippy::needless_return)]
3+
#![allow(clippy::no_effect)]
24

35
enum ExprNode {
46
ExprAddrOf,
@@ -30,6 +32,55 @@ macro_rules! unwrap_addr {
3032
};
3133
}
3234

35+
#[rustfmt::skip]
3336
fn main() {
3437
unwrap_addr!(ExprNode::Unicorns);
38+
39+
//
40+
// don't lint single exprs/statements
41+
//
42+
43+
// don't lint here
44+
match Some(1) {
45+
Some(a) => println!("${:?}", a),
46+
None => return,
47+
}
48+
49+
// don't lint here
50+
match Some(1) {
51+
Some(a) => println!("${:?}", a),
52+
None => {
53+
return
54+
},
55+
}
56+
57+
// don't lint here
58+
match Some(1) {
59+
Some(a) => println!("${:?}", a),
60+
None => {
61+
return;
62+
},
63+
}
64+
65+
//
66+
// lint multiple exprs/statements "else" blocks
67+
//
68+
69+
// lint here
70+
match Some(1) {
71+
Some(a) => println!("${:?}", a),
72+
None => {
73+
println!("else block");
74+
return
75+
},
76+
}
77+
78+
// lint here
79+
match Some(1) {
80+
Some(a) => println!("${:?}", a),
81+
None => {
82+
println!("else block");
83+
return;
84+
},
85+
}
3586
}

tests/ui/single_match_else.stderr

+42-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
2-
--> $DIR/single_match_else.rs:12:5
2+
--> $DIR/single_match_else.rs:14:5
33
|
44
LL | / match ExprNode::Butterflies {
55
LL | | ExprNode::ExprAddrOf => Some(&NODE),
@@ -19,5 +19,45 @@ LL | None
1919
LL | }
2020
|
2121

22-
error: aborting due to previous error
22+
error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
23+
--> $DIR/single_match_else.rs:70:5
24+
|
25+
LL | / match Some(1) {
26+
LL | | Some(a) => println!("${:?}", a),
27+
LL | | None => {
28+
LL | | println!("else block");
29+
LL | | return
30+
LL | | },
31+
LL | | }
32+
| |_____^
33+
|
34+
help: try this
35+
|
36+
LL | if let Some(a) = Some(1) { println!("${:?}", a) } else {
37+
LL | println!("else block");
38+
LL | return
39+
LL | }
40+
|
41+
42+
error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
43+
--> $DIR/single_match_else.rs:79:5
44+
|
45+
LL | / match Some(1) {
46+
LL | | Some(a) => println!("${:?}", a),
47+
LL | | None => {
48+
LL | | println!("else block");
49+
LL | | return;
50+
LL | | },
51+
LL | | }
52+
| |_____^
53+
|
54+
help: try this
55+
|
56+
LL | if let Some(a) = Some(1) { println!("${:?}", a) } else {
57+
LL | println!("else block");
58+
LL | return;
59+
LL | }
60+
|
61+
62+
error: aborting due to 3 previous errors
2363

0 commit comments

Comments
 (0)