]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs
Auto merge of #91284 - t6:freebsd-riscv64, r=Amanieu
[rust.git] / src / tools / clippy / clippy_lints / src / needless_option_as_deref.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::in_macro;
3 use clippy_utils::source::snippet_opt;
4 use clippy_utils::ty::is_type_diagnostic_item;
5 use rustc_errors::Applicability;
6 use rustc_hir::{Expr, ExprKind};
7 use rustc_lint::{LateContext, LateLintPass};
8 use rustc_middle::ty::TyS;
9 use rustc_session::{declare_lint_pass, declare_tool_lint};
10 use rustc_span::symbol::sym;
11
12 declare_clippy_lint! {
13     /// ### What it does
14     /// Checks for no-op uses of Option::{as_deref,as_deref_mut},
15     /// for example, `Option<&T>::as_deref()` returns the same type.
16     ///
17     /// ### Why is this bad?
18     /// Redundant code and improving readability.
19     ///
20     /// ### Example
21     /// ```rust
22     /// let a = Some(&1);
23     /// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32>
24     /// ```
25     /// Could be written as:
26     /// ```rust
27     /// let a = Some(&1);
28     /// let b = a;
29     /// ```
30     pub NEEDLESS_OPTION_AS_DEREF,
31     complexity,
32     "no-op use of `deref` or `deref_mut` method to `Option`."
33 }
34
35 declare_lint_pass!(OptionNeedlessDeref=> [
36     NEEDLESS_OPTION_AS_DEREF,
37 ]);
38
39 impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref {
40     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
41         if expr.span.from_expansion() || in_macro(expr.span) {
42             return;
43         }
44         let typeck = cx.typeck_results();
45         let outer_ty = typeck.expr_ty(expr);
46
47         if_chain! {
48             if is_type_diagnostic_item(cx,outer_ty,sym::Option);
49             if let ExprKind::MethodCall(path, _, [sub_expr], _) = expr.kind;
50             let symbol = path.ident.as_str();
51             if symbol=="as_deref" || symbol=="as_deref_mut";
52             if TyS::same_type( outer_ty, typeck.expr_ty(sub_expr) );
53             then{
54                 span_lint_and_sugg(
55                     cx,
56                     NEEDLESS_OPTION_AS_DEREF,
57                     expr.span,
58                     "derefed type is same as origin",
59                     "try this",
60                     snippet_opt(cx,sub_expr.span).unwrap(),
61                     Applicability::MachineApplicable
62                 );
63             }
64         }
65     }
66 }