Skip to content

Commit 5761bb7

Browse files
committed
Add new lint if_then_panic
1 parent b556398 commit 5761bb7

10 files changed

+155
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,6 +2688,7 @@ Released 2018-09-13
26882688
[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result
26892689
[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
26902690
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
2691+
[`if_then_panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
26912692
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
26922693
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
26932694
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone

clippy_lints/src/if_then_panic.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use clippy_utils::diagnostics::span_lint_and_help;
2+
use clippy_utils::is_expn_of;
3+
use rustc_hir::{Block, Expr, ExprKind};
4+
use rustc_lint::{LateContext, LateLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
/// Detects `if`-then-`panic!` that can be replaced with `assert!`.
10+
///
11+
/// ### Why is this bad?
12+
/// `assert!` is simpler than `if`-then-`panic!`.
13+
///
14+
/// ### Example
15+
/// ```rust
16+
/// let sad_people: Vec<&str> = vec![];
17+
/// if !sad_people.is_empty() {
18+
/// panic!("there are sad people: {:?}", sad_people);
19+
/// }
20+
/// ```
21+
/// Use instead:
22+
/// ```rust
23+
/// let sad_people: Vec<&str> = vec![];
24+
/// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
25+
/// ```
26+
pub IF_THEN_PANIC,
27+
style,
28+
"`panic!` and only a `panic!` in `if`-then statement"
29+
}
30+
31+
declare_lint_pass!(IfThenPanic => [IF_THEN_PANIC]);
32+
33+
impl LateLintPass<'_> for IfThenPanic {
34+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
35+
if_chain! {
36+
if let Expr {
37+
kind: ExprKind:: If(cond, Expr {
38+
kind: ExprKind::Block(
39+
Block {
40+
stmts: [stmt],
41+
..
42+
},
43+
_),
44+
..
45+
}, None),
46+
..
47+
} = &expr;
48+
if is_expn_of(stmt.span, "panic").is_some();
49+
if !matches!(cond.kind, ExprKind::Let(_, _, _));
50+
51+
then {
52+
span_lint_and_help(
53+
cx,
54+
IF_THEN_PANIC,
55+
expr.span,
56+
"only a `panic!` in `if`-then statement",
57+
None,
58+
"considering use `assert!` instead"
59+
)
60+
}
61+
}
62+
}
63+
}

clippy_lints/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ mod identity_op;
227227
mod if_let_mutex;
228228
mod if_let_some_result;
229229
mod if_not_else;
230+
mod if_then_panic;
230231
mod if_then_some_else_none;
231232
mod implicit_hasher;
232233
mod implicit_return;
@@ -658,6 +659,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
658659
if_let_mutex::IF_LET_MUTEX,
659660
if_let_some_result::IF_LET_SOME_RESULT,
660661
if_not_else::IF_NOT_ELSE,
662+
if_then_panic::IF_THEN_PANIC,
661663
if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
662664
implicit_hasher::IMPLICIT_HASHER,
663665
implicit_return::IMPLICIT_RETURN,
@@ -1253,6 +1255,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
12531255
LintId::of(identity_op::IDENTITY_OP),
12541256
LintId::of(if_let_mutex::IF_LET_MUTEX),
12551257
LintId::of(if_let_some_result::IF_LET_SOME_RESULT),
1258+
LintId::of(if_then_panic::IF_THEN_PANIC),
12561259
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
12571260
LintId::of(infinite_iter::INFINITE_ITER),
12581261
LintId::of(inherent_to_string::INHERENT_TO_STRING),
@@ -1508,6 +1511,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15081511
LintId::of(functions::MUST_USE_UNIT),
15091512
LintId::of(functions::RESULT_UNIT_ERR),
15101513
LintId::of(if_let_some_result::IF_LET_SOME_RESULT),
1514+
LintId::of(if_then_panic::IF_THEN_PANIC),
15111515
LintId::of(inherent_to_string::INHERENT_TO_STRING),
15121516
LintId::of(len_zero::COMPARISON_TO_EMPTY),
15131517
LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
@@ -2135,6 +2139,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
21352139
store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
21362140
store.register_late_pass(move || Box::new(feature_name::FeatureName));
21372141
store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
2142+
store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
21382143
}
21392144

21402145
#[rustfmt::skip]

clippy_lints/src/utils/internal_lints.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,9 +561,7 @@ declare_lint_pass!(ProduceIce => [PRODUCE_ICE]);
561561

562562
impl EarlyLintPass for ProduceIce {
563563
fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) {
564-
if is_trigger_fn(fn_kind) {
565-
panic!("Would you like some help with that?");
566-
}
564+
assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?");
567565
}
568566
}
569567

tests/compile-test.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,11 @@ fn extern_flags() -> String {
9090
.copied()
9191
.filter(|n| !crates.contains_key(n))
9292
.collect();
93-
if !not_found.is_empty() {
94-
panic!("dependencies not found in depinfo: {:?}", not_found);
95-
}
93+
assert!(
94+
not_found.is_empty(),
95+
"dependencies not found in depinfo: {:?}",
96+
not_found
97+
);
9698
crates
9799
.into_iter()
98100
.map(|(name, path)| format!(" --extern {}={}", name, path))

tests/integration.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,11 @@ fn integration_test() {
7474
panic!("incompatible crate versions");
7575
} else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
7676
panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
77-
} else if stderr.contains("toolchain") && stderr.contains("is not installed") {
78-
panic!("missing required toolchain");
77+
} else {
78+
assert!(
79+
!stderr.contains("toolchain") || !stderr.contains("is not installed"),
80+
"missing required toolchain"
81+
);
7982
}
8083

8184
match output.status.code() {

tests/ui/fallible_impl_from.stderr

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ LL | panic!();
4040
| ^^^^^^^^^
4141
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
4242

43+
error: only a `panic!` in `if`-then statement
44+
--> $DIR/fallible_impl_from.rs:28:9
45+
|
46+
LL | / if i != 42 {
47+
LL | | panic!();
48+
LL | | }
49+
| |_________^
50+
|
51+
= note: `-D clippy::if-then-panic` implied by `-D warnings`
52+
= help: considering use `assert!` instead
53+
4354
error: consider implementing `TryFrom` instead
4455
--> $DIR/fallible_impl_from.rs:35:1
4556
|
@@ -67,6 +78,17 @@ LL | panic!("{:?}", s);
6778
| ^^^^^^^^^^^^^^^^^^
6879
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
6980

81+
error: only a `panic!` in `if`-then statement
82+
--> $DIR/fallible_impl_from.rs:40:16
83+
|
84+
LL | } else if s.parse::<u32>().unwrap() != 42 {
85+
| ________________^
86+
LL | | panic!("{:?}", s);
87+
LL | | }
88+
| |_________^
89+
|
90+
= help: considering use `assert!` instead
91+
7092
error: consider implementing `TryFrom` instead
7193
--> $DIR/fallible_impl_from.rs:53:1
7294
|
@@ -89,5 +111,15 @@ LL | panic!("{:?}", s);
89111
| ^^^^^^^^^^^^^^^^^^
90112
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
91113

92-
error: aborting due to 4 previous errors
114+
error: only a `panic!` in `if`-then statement
115+
--> $DIR/fallible_impl_from.rs:55:9
116+
|
117+
LL | / if s.parse::<u32>().ok().unwrap() != 42 {
118+
LL | | panic!("{:?}", s);
119+
LL | | }
120+
| |_________^
121+
|
122+
= help: considering use `assert!` instead
123+
124+
error: aborting due to 7 previous errors
93125

tests/ui/if_then_panic.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![warn(clippy::if_then_panic)]
2+
3+
fn main() {
4+
let a = vec![1, 2, 3];
5+
let c = Some(2);
6+
if a.len() == 3 {
7+
panic!("qaqaq");
8+
}
9+
if let Some(b) = c {
10+
panic!("orz");
11+
}
12+
if a.len() == 3 {
13+
panic!("qaqaq");
14+
} else {
15+
println!("qwq");
16+
}
17+
}

tests/ui/if_then_panic.stderr

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: only a `panic!` in `if`-then statement
2+
--> $DIR/if_then_panic.rs:6:5
3+
|
4+
LL | / if a.len() == 3 {
5+
LL | | panic!("qaqaq");
6+
LL | | }
7+
| |_____^
8+
|
9+
= note: `-D clippy::if-then-panic` implied by `-D warnings`
10+
= help: considering use `assert!` instead
11+
12+
error: aborting due to previous error
13+

tests/ui/ptr_arg.stderr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ help: change `y.as_str()` to
108108
LL | let c = y;
109109
| ~
110110

111+
error: only a `panic!` in `if`-then statement
112+
--> $DIR/ptr_arg.rs:83:5
113+
|
114+
LL | / if x.capacity() > 1024 {
115+
LL | | panic!("Too large!");
116+
LL | | }
117+
| |_____^
118+
|
119+
= note: `-D clippy::if-then-panic` implied by `-D warnings`
120+
= help: considering use `assert!` instead
121+
111122
error: using a reference to `Cow` is not recommended
112123
--> $DIR/ptr_arg.rs:90:25
113124
|
@@ -171,5 +182,5 @@ help: change `str.clone()` to
171182
LL | let _ = str.to_path_buf().clone();
172183
| ~~~~~~~~~~~~~~~~~
173184

174-
error: aborting due to 12 previous errors
185+
error: aborting due to 13 previous errors
175186

0 commit comments

Comments
 (0)