/// **Known problems:** None.
///
/// **Example:**
- /// Using unwrap on an `Option`:
+ /// Using unwrap on an `Result`:
///
/// ```rust
/// let res: Result<usize, ()> = Ok(1);
"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
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,
["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]),
}
}
+/// 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! {