Skip to content

Commit 001d071

Browse files
committed
Fix if_then_panic for #![no_std] and Rust 2021
1 parent 300b821 commit 001d071

File tree

8 files changed

+286
-17
lines changed

8 files changed

+286
-17
lines changed

clippy_lints/src/if_then_panic.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,23 @@ impl LateLintPass<'_> for IfThenPanic {
5454
if !cx.tcx.sess.source_map().is_multiline(cond.span);
5555

5656
then {
57-
let span = if let Some(panic_expn) = PanicExpn::parse(semi) {
57+
let call = if_chain! {
58+
if let ExprKind::Block(block, _) = semi.kind;
59+
if let Some(init) = block.expr;
60+
then {
61+
init
62+
} else {
63+
semi
64+
}
65+
};
66+
let span = if let Some(panic_expn) = PanicExpn::parse(call) {
5867
match *panic_expn.format_args.value_args {
5968
[] => panic_expn.format_args.format_string_span,
6069
[.., last] => panic_expn.format_args.format_string_span.to(last.span),
6170
}
6271
} else {
6372
if_chain! {
64-
if let ExprKind::Block(block, _) = semi.kind;
65-
if let Some(init) = block.expr;
66-
if let ExprKind::Call(_, [format_args]) = init.kind;
73+
if let ExprKind::Call(_, [format_args]) = call.kind;
6774

6875
then {
6976
format_args.span

clippy_lints/src/matches.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
968968
}
969969
if_chain! {
970970
if matching_wild;
971-
if let ExprKind::Block(block, _) = arm.body.kind;
972-
if is_panic_block(block);
971+
if is_panic_call(arm.body);
973972
then {
974973
// `Err(_)` or `Err(_e)` arm with `panic!` found
975974
span_lint_and_note(cx,
@@ -1172,14 +1171,19 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
11721171
}
11731172

11741173
// If the block contains only a `panic!` macro (as expression or statement)
1175-
fn is_panic_block(block: &Block<'_>) -> bool {
1176-
match (&block.expr, block.stmts.len(), block.stmts.first()) {
1177-
(&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(),
1178-
(&None, 1, Some(stmt)) => {
1179-
is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
1180-
},
1181-
_ => false,
1182-
}
1174+
fn is_panic_call(expr: &Expr<'_>) -> bool {
1175+
// Unwrap any wrapping blocks
1176+
let span = if let ExprKind::Block(block, _) = expr.kind {
1177+
match (&block.expr, block.stmts.len(), block.stmts.first()) {
1178+
(&Some(exp), 0, _) => exp.span,
1179+
(&None, 1, Some(stmt)) => stmt.span,
1180+
_ => return false,
1181+
}
1182+
} else {
1183+
expr.span
1184+
};
1185+
1186+
is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none()
11831187
}
11841188

11851189
fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)

clippy_utils/src/higher.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,7 @@ impl PanicExpn<'tcx> {
718718
/// Parses an expanded `panic!` invocation
719719
pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
720720
if_chain! {
721-
if let ExprKind::Block(block, _) = expr.kind;
722-
if let Some(init) = block.expr;
723-
if let ExprKind::Call(_, [format_args]) = init.kind;
721+
if let ExprKind::Call(_, [format_args]) = expr.kind;
724722
let expn_data = expr.span.ctxt().outer_expn_data();
725723
if let ExprKind::AddrOf(_, _, format_args) = format_args.kind;
726724
if let Some(format_args) = FormatArgsExpn::parse(format_args);

tests/ui/if_then_panic_core.fixed

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// run-rustfix
2+
#![crate_type = "lib"]
3+
#![no_std]
4+
#![warn(clippy::if_then_panic)]
5+
6+
pub fn main() {
7+
let a = &[1, 2, 3];
8+
let c = Some(2);
9+
if !a.is_empty()
10+
&& a.len() == 3
11+
&& c != None
12+
&& !a.is_empty()
13+
&& a.len() == 3
14+
&& !a.is_empty()
15+
&& a.len() == 3
16+
&& !a.is_empty()
17+
&& a.len() == 3
18+
{
19+
panic!("qaqaq{:?}", a);
20+
}
21+
assert!(a.is_empty(), "qaqaq{:?}", a);
22+
assert!(a.is_empty(), "qwqwq");
23+
if a.len() == 3 {
24+
format_args!("qwq");
25+
format_args!("qwq");
26+
format_args!("qwq");
27+
}
28+
if let Some(b) = c {
29+
panic!("orz {}", b);
30+
}
31+
if a.len() == 3 {
32+
panic!("qaqaq");
33+
} else {
34+
format_args!("qwq");
35+
}
36+
let b = &[1, 2, 3];
37+
assert!(!b.is_empty(), "panic1");
38+
assert!(!(b.is_empty() && a.is_empty()), "panic2");
39+
assert!(!(a.is_empty() && !b.is_empty()), "panic3");
40+
assert!(!(b.is_empty() || a.is_empty()), "panic4");
41+
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
42+
}

tests/ui/if_then_panic_core.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// run-rustfix
2+
#![crate_type = "lib"]
3+
#![no_std]
4+
#![warn(clippy::if_then_panic)]
5+
6+
pub fn main() {
7+
let a = &[1, 2, 3];
8+
let c = Some(2);
9+
if !a.is_empty()
10+
&& a.len() == 3
11+
&& c != None
12+
&& !a.is_empty()
13+
&& a.len() == 3
14+
&& !a.is_empty()
15+
&& a.len() == 3
16+
&& !a.is_empty()
17+
&& a.len() == 3
18+
{
19+
panic!("qaqaq{:?}", a);
20+
}
21+
if !a.is_empty() {
22+
panic!("qaqaq{:?}", a);
23+
}
24+
if !a.is_empty() {
25+
panic!("qwqwq");
26+
}
27+
if a.len() == 3 {
28+
format_args!("qwq");
29+
format_args!("qwq");
30+
format_args!("qwq");
31+
}
32+
if let Some(b) = c {
33+
panic!("orz {}", b);
34+
}
35+
if a.len() == 3 {
36+
panic!("qaqaq");
37+
} else {
38+
format_args!("qwq");
39+
}
40+
let b = &[1, 2, 3];
41+
if b.is_empty() {
42+
panic!("panic1");
43+
}
44+
if b.is_empty() && a.is_empty() {
45+
panic!("panic2");
46+
}
47+
if a.is_empty() && !b.is_empty() {
48+
panic!("panic3");
49+
}
50+
if b.is_empty() || a.is_empty() {
51+
panic!("panic4");
52+
}
53+
if a.is_empty() || !b.is_empty() {
54+
panic!("panic5");
55+
}
56+
}

tests/ui/if_then_panic_core.stderr

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
error: only a `panic!` in `if`-then statement
2+
--> $DIR/if_then_panic_core.rs:21:5
3+
|
4+
LL | / if !a.is_empty() {
5+
LL | | panic!("qaqaq{:?}", a);
6+
LL | | }
7+
| |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
8+
|
9+
= note: `-D clippy::if-then-panic` implied by `-D warnings`
10+
11+
error: only a `panic!` in `if`-then statement
12+
--> $DIR/if_then_panic_core.rs:24:5
13+
|
14+
LL | / if !a.is_empty() {
15+
LL | | panic!("qwqwq");
16+
LL | | }
17+
| |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
18+
19+
error: only a `panic!` in `if`-then statement
20+
--> $DIR/if_then_panic_core.rs:41:5
21+
|
22+
LL | / if b.is_empty() {
23+
LL | | panic!("panic1");
24+
LL | | }
25+
| |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
26+
27+
error: only a `panic!` in `if`-then statement
28+
--> $DIR/if_then_panic_core.rs:44:5
29+
|
30+
LL | / if b.is_empty() && a.is_empty() {
31+
LL | | panic!("panic2");
32+
LL | | }
33+
| |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
34+
35+
error: only a `panic!` in `if`-then statement
36+
--> $DIR/if_then_panic_core.rs:47:5
37+
|
38+
LL | / if a.is_empty() && !b.is_empty() {
39+
LL | | panic!("panic3");
40+
LL | | }
41+
| |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
42+
43+
error: only a `panic!` in `if`-then statement
44+
--> $DIR/if_then_panic_core.rs:50:5
45+
|
46+
LL | / if b.is_empty() || a.is_empty() {
47+
LL | | panic!("panic4");
48+
LL | | }
49+
| |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
50+
51+
error: only a `panic!` in `if`-then statement
52+
--> $DIR/if_then_panic_core.rs:53:5
53+
|
54+
LL | / if a.is_empty() || !b.is_empty() {
55+
LL | | panic!("panic5");
56+
LL | | }
57+
| |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
58+
59+
error: aborting due to 7 previous errors
60+

tests/ui/match_wild_err_arm_core.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#![crate_type = "lib"]
2+
#![no_std]
3+
#![feature(exclusive_range_pattern)]
4+
#![allow(clippy::match_same_arms)]
5+
#![warn(clippy::match_wild_err_arm)]
6+
7+
fn foo() {}
8+
9+
fn match_wild_err_arm() {
10+
let x: Result<i32, &str> = Ok(3);
11+
12+
match x {
13+
Ok(3) => (),
14+
Ok(_) => (),
15+
Err(_) => panic!("err"),
16+
}
17+
18+
match x {
19+
Ok(3) => (),
20+
Ok(_) => (),
21+
Err(_) => panic!(),
22+
}
23+
24+
match x {
25+
Ok(3) => (),
26+
Ok(_) => (),
27+
Err(_) => {
28+
panic!();
29+
},
30+
}
31+
32+
match x {
33+
Ok(3) => (),
34+
Ok(_) => (),
35+
Err(_e) => panic!(),
36+
}
37+
38+
// Allowed when used in `panic!`.
39+
match x {
40+
Ok(3) => (),
41+
Ok(_) => (),
42+
Err(_e) => panic!("{}", _e),
43+
}
44+
45+
// Allowed when not with `panic!` block.
46+
match x {
47+
Ok(3) => (),
48+
Ok(_) => (),
49+
Err(_) => foo(),
50+
}
51+
52+
// Allowed when used with `unreachable!`.
53+
match x {
54+
Ok(3) => (),
55+
Ok(_) => (),
56+
Err(_) => unreachable!(),
57+
}
58+
59+
// Allowed when used with `unreachable!`.
60+
match x {
61+
Ok(3) => (),
62+
Ok(_) => (),
63+
Err(_) => {
64+
unreachable!();
65+
},
66+
}
67+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: `Err(_)` matches all errors
2+
--> $DIR/match_wild_err_arm_core.rs:15:9
3+
|
4+
LL | Err(_) => panic!("err"),
5+
| ^^^^^^
6+
|
7+
= note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
8+
= note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
9+
10+
error: `Err(_)` matches all errors
11+
--> $DIR/match_wild_err_arm_core.rs:21:9
12+
|
13+
LL | Err(_) => panic!(),
14+
| ^^^^^^
15+
|
16+
= note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
17+
18+
error: `Err(_)` matches all errors
19+
--> $DIR/match_wild_err_arm_core.rs:27:9
20+
|
21+
LL | Err(_) => {
22+
| ^^^^^^
23+
|
24+
= note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
25+
26+
error: `Err(_e)` matches all errors
27+
--> $DIR/match_wild_err_arm_core.rs:35:9
28+
|
29+
LL | Err(_e) => panic!(),
30+
| ^^^^^^^
31+
|
32+
= note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
33+
34+
error: aborting due to 4 previous errors
35+

0 commit comments

Comments
 (0)