Add expect

Co-Authored-By: Philipp Krones <hello@philkrones.com>
This commit is contained in:
Heinz N. Gies 2019-10-15 21:33:07 +02:00
parent 98dc3aabea
commit a7ad78f3eb
3 changed files with 94 additions and 3 deletions

View file

@ -73,7 +73,7 @@ declare_clippy_lint! {
/// **Known problems:** None.
///
/// **Example:**
/// Using unwrap on an `Option`:
/// Using unwrap on an `Result`:
///
/// ```rust
/// let res: Result<usize, ()> = Ok(1);
@ -91,6 +91,63 @@ declare_clippy_lint! {
"using `Result.unwrap()`, which might be better handled"
}
declare_clippy_lint! {
/// **What it does:** Checks for `.expect()` calls on `Option`s.
///
/// **Why is this bad?** Usually it is better to handle the `None` case. Still,
/// for a lot of quick-and-dirty code, `expect` is a good choice, which is why
/// this lint is `Allow` by default.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// Using expect on an `Option`:
///
/// ```rust
/// let opt = Some(1);
/// opt.expect("one");
/// ```
///
/// Better:
///
/// ```rust
/// let opt = Some(1);
/// opt?;
/// ```
pub OPTION_EXPECT_USED,
restriction,
"using `Option.expect()`, which might be better handled"
}
declare_clippy_lint! {
/// **What it does:** Checks for `.expect()` calls on `Result`s.
///
/// **Why is this bad?** `result.expect()` will let the thread panic on `Err`
/// values. Normally, you want to implement more sophisticated error handling,
/// and propagate errors upwards with `try!`.
///
/// **Known problems:** None.
///
/// **Example:**
/// Using expect on an `Result`:
///
/// ```rust
/// let res: Result<usize, ()> = Ok(1);
/// res.expect("one");
/// ```
///
/// Better:
///
/// ```rust
/// let res: Result<usize, ()> = Ok(1);
/// res?;
/// ```
pub RESULT_EXPECT_USED,
restriction,
"using `Result.expect()`, which might be better handled"
}
declare_clippy_lint! {
/// **What it does:** Checks for methods that should live in a trait
/// implementation of a `std` trait (see [llogiq's blog
@ -1037,6 +1094,8 @@ declare_clippy_lint! {
declare_lint_pass!(Methods => [
OPTION_UNWRAP_USED,
RESULT_UNWRAP_USED,
OPTION_EXPECT_USED,
RESULT_EXPECT_USED,
SHOULD_IMPLEMENT_TRAIT,
WRONG_SELF_CONVENTION,
WRONG_PUB_SELF_CONVENTION,
@ -1095,6 +1154,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
["unwrap", "get_mut"] => lint_get_unwrap(cx, expr, arg_lists[1], true),
["unwrap", ..] => lint_unwrap(cx, expr, arg_lists[0]),
["expect", "ok"] => lint_ok_expect(cx, expr, arg_lists[1]),
["expect", ..] => lint_expect(cx, expr, arg_lists[0]),
["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0]),
["unwrap_or_else", "map"] => lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]),
["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
}
}
/// lint use of `expect()` for `Option`s and `Result`s
fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, expect_args: &[hir::Expr]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
Some((OPTION_EXPECT_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) {
Some((RESULT_EXPECT_USED, "a Result", "Err"))
} else {
None
};
if let Some((lint, kind, none_value)) = mess {
span_lint(
cx,
lint,
expr.span,
&format!(
"used expect() on {} value. If this value is an {} it will panic",
kind, none_value
),
);
}
}
/// lint use of `ok().expect()` for `Result`s
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) {
if_chain! {

View file

@ -76,7 +76,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// **What it does:** Checks for usage of `unreachable!`.
///
/// **Why is this bad?** This macro can cause cause code to panics
/// **Why is this bad?** This macro can cause code to panic
///
/// **Known problems:** None.
///

View file

@ -1,7 +1,13 @@
// aux-build:option_helpers.rs
// compile-flags: --edition 2018
#![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)]
#![warn(
clippy::all,
clippy::pedantic,
clippy::option_unwrap_used,
clippy::option_expect_used,
clippy::result_expect_used
)]
#![allow(
clippy::blacklisted_name,
clippy::default_trait_access,