Skip to content

Commit a7ad78f

Browse files
Licenserflip1995
andcommitted
Add expect
Co-Authored-By: Philipp Krones <[email protected]>
1 parent 98dc3aa commit a7ad78f

File tree

3 files changed

+94
-3
lines changed

3 files changed

+94
-3
lines changed

clippy_lints/src/methods/mod.rs

+86-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ declare_clippy_lint! {
7373
/// **Known problems:** None.
7474
///
7575
/// **Example:**
76-
/// Using unwrap on an `Option`:
76+
/// Using unwrap on an `Result`:
7777
///
7878
/// ```rust
7979
/// let res: Result<usize, ()> = Ok(1);
@@ -91,6 +91,63 @@ declare_clippy_lint! {
9191
"using `Result.unwrap()`, which might be better handled"
9292
}
9393

94+
declare_clippy_lint! {
95+
/// **What it does:** Checks for `.expect()` calls on `Option`s.
96+
///
97+
/// **Why is this bad?** Usually it is better to handle the `None` case. Still,
98+
/// for a lot of quick-and-dirty code, `expect` is a good choice, which is why
99+
/// this lint is `Allow` by default.
100+
///
101+
/// **Known problems:** None.
102+
///
103+
/// **Example:**
104+
///
105+
/// Using expect on an `Option`:
106+
///
107+
/// ```rust
108+
/// let opt = Some(1);
109+
/// opt.expect("one");
110+
/// ```
111+
///
112+
/// Better:
113+
///
114+
/// ```rust
115+
/// let opt = Some(1);
116+
/// opt?;
117+
/// ```
118+
pub OPTION_EXPECT_USED,
119+
restriction,
120+
"using `Option.expect()`, which might be better handled"
121+
}
122+
123+
declare_clippy_lint! {
124+
/// **What it does:** Checks for `.expect()` calls on `Result`s.
125+
///
126+
/// **Why is this bad?** `result.expect()` will let the thread panic on `Err`
127+
/// values. Normally, you want to implement more sophisticated error handling,
128+
/// and propagate errors upwards with `try!`.
129+
///
130+
/// **Known problems:** None.
131+
///
132+
/// **Example:**
133+
/// Using expect on an `Result`:
134+
///
135+
/// ```rust
136+
/// let res: Result<usize, ()> = Ok(1);
137+
/// res.expect("one");
138+
/// ```
139+
///
140+
/// Better:
141+
///
142+
/// ```rust
143+
/// let res: Result<usize, ()> = Ok(1);
144+
/// res?;
145+
/// ```
146+
pub RESULT_EXPECT_USED,
147+
restriction,
148+
"using `Result.expect()`, which might be better handled"
149+
}
150+
94151
declare_clippy_lint! {
95152
/// **What it does:** Checks for methods that should live in a trait
96153
/// implementation of a `std` trait (see [llogiq's blog
@@ -1037,6 +1094,8 @@ declare_clippy_lint! {
10371094
declare_lint_pass!(Methods => [
10381095
OPTION_UNWRAP_USED,
10391096
RESULT_UNWRAP_USED,
1097+
OPTION_EXPECT_USED,
1098+
RESULT_EXPECT_USED,
10401099
SHOULD_IMPLEMENT_TRAIT,
10411100
WRONG_SELF_CONVENTION,
10421101
WRONG_PUB_SELF_CONVENTION,
@@ -1095,6 +1154,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
10951154
["unwrap", "get_mut"] => lint_get_unwrap(cx, expr, arg_lists[1], true),
10961155
["unwrap", ..] => lint_unwrap(cx, expr, arg_lists[0]),
10971156
["expect", "ok"] => lint_ok_expect(cx, expr, arg_lists[1]),
1157+
["expect", ..] => lint_expect(cx, expr, arg_lists[0]),
10981158
["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0]),
10991159
["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]),
11001160
["map_or", ..] => lint_map_or_none(cx, expr, arg_lists[0]),
@@ -2063,6 +2123,31 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::E
20632123
}
20642124
}
20652125

2126+
/// lint use of `expect()` for `Option`s and `Result`s
2127+
fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, expect_args: &[hir::Expr]) {
2128+
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0]));
2129+
2130+
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
2131+
Some((OPTION_EXPECT_USED, "an Option", "None"))
2132+
} else if match_type(cx, obj_ty, &paths::RESULT) {
2133+
Some((RESULT_EXPECT_USED, "a Result", "Err"))
2134+
} else {
2135+
None
2136+
};
2137+
2138+
if let Some((lint, kind, none_value)) = mess {
2139+
span_lint(
2140+
cx,
2141+
lint,
2142+
expr.span,
2143+
&format!(
2144+
"used expect() on {} value. If this value is an {} it will panic",
2145+
kind, none_value
2146+
),
2147+
);
2148+
}
2149+
}
2150+
20662151
/// lint use of `ok().expect()` for `Result`s
20672152
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) {
20682153
if_chain! {

clippy_lints/src/panic_unimplemented.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ declare_clippy_lint! {
7676
declare_clippy_lint! {
7777
/// **What it does:** Checks for usage of `unreachable!`.
7878
///
79-
/// **Why is this bad?** This macro can cause cause code to panics
79+
/// **Why is this bad?** This macro can cause code to panic
8080
///
8181
/// **Known problems:** None.
8282
///

tests/ui/methods.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// aux-build:option_helpers.rs
22
// compile-flags: --edition 2018
33

4-
#![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)]
4+
#![warn(
5+
clippy::all,
6+
clippy::pedantic,
7+
clippy::option_unwrap_used,
8+
clippy::option_expect_used,
9+
clippy::result_expect_used
10+
)]
511
#![allow(
612
clippy::blacklisted_name,
713
clippy::default_trait_access,

0 commit comments

Comments
 (0)