Skip to content

Commit 6e4dc93

Browse files
committed
Support suggesting panics
1 parent 69af0e1 commit 6e4dc93

File tree

5 files changed

+163
-61
lines changed

5 files changed

+163
-61
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,10 +3664,10 @@ impl Methods {
36643664
Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
36653665
_ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
36663666
}
3667-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3667+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
36683668
},
36693669
("expect_err", [_]) => {
3670-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3670+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
36713671
expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests);
36723672
},
36733673
("extend", [arg]) => {
@@ -3874,12 +3874,12 @@ impl Methods {
38743874
},
38753875
_ => {},
38763876
}
3877-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3877+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
38783878
unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests);
38793879
},
38803880
("unwrap_err", []) => {
3881-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3882-
unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests)
3881+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
3882+
unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests);
38833883
},
38843884
("unwrap_or", [u_arg]) => {
38853885
match method_call(recv) {
@@ -3894,10 +3894,10 @@ impl Methods {
38943894
},
38953895
_ => {},
38963896
}
3897-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3897+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
38983898
},
38993899
("unwrap_or_default", []) => {
3900-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3900+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
39013901
}
39023902
("unwrap_or_else", [u_arg]) => {
39033903
match method_call(recv) {
@@ -3908,7 +3908,7 @@ impl Methods {
39083908
unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
39093909
},
39103910
}
3911-
unnecessary_literal_unwrap::check(cx, expr, recv, name);
3911+
unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
39123912
},
39133913
("zip", [arg]) => {
39143914
if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind

clippy_lints/src/methods/unnecessary_literal_unwrap.rs

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,68 @@ use rustc_lint::LateContext;
55

66
use super::UNNECESSARY_LITERAL_UNWRAP;
77

8-
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, name: &str) {
8+
pub(super) fn check(
9+
cx: &LateContext<'_>,
10+
expr: &hir::Expr<'_>,
11+
recv: &hir::Expr<'_>,
12+
method: &str,
13+
args: &[hir::Expr<'_>],
14+
) {
915
let init = clippy_utils::expr_or_init(cx, recv);
1016

11-
if let hir::ExprKind::Call(call, [arg]) = init.kind {
12-
let constructor = if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) {
13-
"Some"
17+
let (constructor, call_args) = if let hir::ExprKind::Call(call, call_args) = init.kind {
18+
if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::OptionSome) {
19+
("Some", call_args)
1420
} else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultOk) {
15-
"Ok"
21+
("Ok", call_args)
1622
} else if is_res_lang_ctor(cx, path_res(cx, call), hir::LangItem::ResultErr) {
17-
"Err"
23+
("Err", call_args)
1824
} else {
1925
return;
20-
};
26+
}
27+
} else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) {
28+
let call_args: &[hir::Expr<'_>] = &[];
29+
("None", call_args)
30+
} else {
31+
return;
32+
};
2133

22-
if init.span == recv.span {
23-
span_lint_and_then(
24-
cx,
25-
UNNECESSARY_LITERAL_UNWRAP,
26-
expr.span,
27-
&format!("used `{name}()` on `{constructor}` value"),
28-
|diag| {
29-
let suggestions = vec![
30-
(recv.span.with_hi(arg.span.lo()), String::new()),
31-
(expr.span.with_lo(arg.span.hi()), String::new()),
32-
];
34+
let help_message = format!("used `{method}()` on `{constructor}` value");
35+
let suggestion_message = format!("remove the `{constructor}` and `{method}()`");
3336

34-
diag.multipart_suggestion(
35-
format!("remove the `{constructor}` and `{name}()`"),
36-
suggestions,
37-
Applicability::MachineApplicable,
38-
);
39-
},
40-
);
41-
} else {
42-
span_lint_and_then(
43-
cx,
44-
UNNECESSARY_LITERAL_UNWRAP,
45-
expr.span,
46-
&format!("used `{name}()` on `{constructor}` value"),
47-
|diag| {
48-
diag.span_help(init.span, format!("remove the `{constructor}` and `{name}()`"));
49-
},
50-
);
51-
}
37+
if init.span == recv.span {
38+
span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| {
39+
let suggestions = match (constructor, method) {
40+
("None", "unwrap") => vec![(expr.span, "panic!()".to_string())],
41+
("None", "expect") => vec![
42+
(expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()),
43+
(expr.span.with_lo(args[0].span.hi()), ")".to_string()),
44+
],
45+
("Ok", "unwrap_err") | ("Err", "unwrap") => vec![
46+
(
47+
recv.span.with_hi(call_args[0].span.lo()),
48+
"panic!(\"{:?}\", ".to_string(),
49+
),
50+
(expr.span.with_lo(call_args[0].span.hi()), ")".to_string()),
51+
],
52+
("Ok", "expect_err") | ("Err", "expect") => vec![
53+
(
54+
recv.span.with_hi(call_args[0].span.lo()),
55+
"panic!(\"{1}: {:?}\", ".to_string(),
56+
),
57+
(call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()),
58+
],
59+
_ => vec![
60+
(recv.span.with_hi(call_args[0].span.lo()), String::new()),
61+
(expr.span.with_lo(call_args[0].span.hi()), String::new()),
62+
],
63+
};
64+
65+
diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable);
66+
});
67+
} else {
68+
span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| {
69+
diag.span_help(init.span, suggestion_message);
70+
});
5271
}
5372
}

tests/ui/unnecessary_literal_unwrap.fixed

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
//run-rustfix
22
#![warn(clippy::unnecessary_literal_unwrap)]
33
#![allow(clippy::unnecessary_lazy_evaluations)]
4+
#![allow(unreachable_code)]
45

5-
fn unwrap_option() {
6+
fn unwrap_option_some() {
67
let _val = 1;
78
let _val = 1;
89
}
910

11+
fn unwrap_option_none() {
12+
panic!();
13+
panic!("this always happens");
14+
}
15+
1016
fn unwrap_result_ok() {
1117
let _val = 1;
1218
let _val = 1;
19+
panic!("{:?}", 1);
20+
panic!("{1}: {:?}", 1, "this always happens");
1321
}
1422

1523
fn unwrap_result_err() {
1624
let _val = 1;
1725
let _val = 1;
26+
panic!("{:?}", 1);
27+
panic!("{1}: {:?}", 1, "this always happens");
1828
}
1929

2030
fn unwrap_methods_option() {
@@ -30,7 +40,8 @@ fn unwrap_methods_result() {
3040
}
3141

3242
fn main() {
33-
unwrap_option();
43+
unwrap_option_some();
44+
unwrap_option_none();
3445
unwrap_result_ok();
3546
unwrap_result_err();
3647
unwrap_methods_option();

tests/ui/unnecessary_literal_unwrap.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
//run-rustfix
22
#![warn(clippy::unnecessary_literal_unwrap)]
33
#![allow(clippy::unnecessary_lazy_evaluations)]
4+
#![allow(unreachable_code)]
45

5-
fn unwrap_option() {
6+
fn unwrap_option_some() {
67
let _val = Some(1).unwrap();
78
let _val = Some(1).expect("this never happens");
89
}
910

11+
fn unwrap_option_none() {
12+
None::<usize>.unwrap();
13+
None::<usize>.expect("this always happens");
14+
}
15+
1016
fn unwrap_result_ok() {
1117
let _val = Ok::<usize, ()>(1).unwrap();
1218
let _val = Ok::<usize, ()>(1).expect("this never happens");
19+
Ok::<usize, ()>(1).unwrap_err();
20+
Ok::<usize, ()>(1).expect_err("this always happens");
1321
}
1422

1523
fn unwrap_result_err() {
1624
let _val = Err::<(), usize>(1).unwrap_err();
1725
let _val = Err::<(), usize>(1).expect_err("this never happens");
26+
Err::<(), usize>(1).unwrap();
27+
Err::<(), usize>(1).expect("this always happens");
1828
}
1929

2030
fn unwrap_methods_option() {
@@ -30,7 +40,8 @@ fn unwrap_methods_result() {
3040
}
3141

3242
fn main() {
33-
unwrap_option();
43+
unwrap_option_some();
44+
unwrap_option_none();
3445
unwrap_result_ok();
3546
unwrap_result_err();
3647
unwrap_methods_option();

0 commit comments

Comments
 (0)