2 use clippy_utils
::diagnostics
::span_lint_and_sugg
;
3 use clippy_utils
::ty
::implements_trait
;
4 use clippy_utils
::{meets_msrv, msrvs, ty::is_type_diagnostic_item}
;
5 use rustc_errors
::Applicability
;
6 use rustc_lint
::LateContext
;
8 use rustc_middle
::ty
::Ty
;
9 use rustc_semver
::RustcVersion
;
10 use rustc_span
::{sym, Span}
;
14 _expr
: &rustc_hir
::Expr
<'_
>,
15 recv
: &rustc_hir
::Expr
<'_
>,
16 msrv
: Option
<RustcVersion
>,
21 if is_type_diagnostic_item(cx
, cx
.typeck_results().expr_ty(recv
), sym
::Result
);
22 // Test the version to make sure the lint can be showed (expect_err has been
23 // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982)
24 if meets_msrv(msrv
, msrvs
::EXPECT_ERR
);
26 // Grabs the `Result<T, E>` type
27 let result_type
= cx
.typeck_results().expr_ty(recv
);
28 // Tests if the T type in a `Result<T, E>` is not None
29 if let Some(data_type
) = get_data_type(cx
, result_type
);
30 // Tests if the T type in a `Result<T, E>` implements debug
31 if has_debug_impl(data_type
, cx
);
37 err_span
.to(expect_span
),
38 "called `.err().expect()` on a `Result` value",
40 "expect_err".to_string(),
41 Applicability
::MachineApplicable
47 /// Given a `Result<T, E>` type, return its data (`T`).
48 fn get_data_type
<'a
>(cx
: &LateContext
<'_
>, ty
: Ty
<'a
>) -> Option
<Ty
<'a
>> {
50 ty
::Adt(_
, substs
) if is_type_diagnostic_item(cx
, ty
, sym
::Result
) => substs
.types().next(),
55 /// Given a type, very if the Debug trait has been impl'd
56 fn has_debug_impl
<'tcx
>(ty
: Ty
<'tcx
>, cx
: &LateContext
<'tcx
>) -> bool
{
58 .get_diagnostic_item(sym
::Debug
)
59 .map_or(false, |debug
| implements_trait(cx
, ty
, debug
, &[]))