]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/methods/err_expect.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / methods / err_expect.rs
1 use super::ERR_EXPECT;
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;
7 use rustc_middle::ty;
8 use rustc_middle::ty::Ty;
9 use rustc_semver::RustcVersion;
10 use rustc_span::{sym, Span};
11
12 pub(super) fn check(
13 cx: &LateContext<'_>,
14 _expr: &rustc_hir::Expr<'_>,
15 recv: &rustc_hir::Expr<'_>,
16 msrv: Option<RustcVersion>,
17 expect_span: Span,
18 err_span: Span,
19 ) {
20 if_chain! {
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);
25
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);
32
33 then {
34 span_lint_and_sugg(
35 cx,
36 ERR_EXPECT,
37 err_span.to(expect_span),
38 "called `.err().expect()` on a `Result` value",
39 "try",
40 "expect_err".to_string(),
41 Applicability::MachineApplicable
42 );
43 }
44 };
45 }
46
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>> {
49 match ty.kind() {
50 ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym::Result) => substs.types().next(),
51 _ => None,
52 }
53 }
54
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 {
57 cx.tcx
58 .get_diagnostic_item(sym::Debug)
59 .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
60 }