Skip to content

Commit 1ed3582

Browse files
committed
single_match_else - single expr/stmt else block corner case
1 parent 57cdf2d commit 1ed3582

File tree

3 files changed

+103
-9
lines changed

3 files changed

+103
-9
lines changed

clippy_lints/src/matches.rs

Lines changed: 13 additions & 7 deletions
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

Lines changed: 48 additions & 0 deletions
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,
@@ -32,4 +34,50 @@ macro_rules! unwrap_addr {
3234

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

tests/ui/single_match_else.stderr

Lines changed: 42 additions & 2 deletions
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:67: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:76: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)