]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/methods/option_map_unwrap_or.rs
Merge commit '57b3c4b90f4346b3990c1be387c3b3ca7b78412c' into clippyup
[rust.git] / clippy_lints / src / methods / option_map_unwrap_or.rs
index 80a937aadb06a9dc7be05df15f22ed5c06fd45bb..6c641af59f92b9c6a3f1b6941c01305f8b8bd464 100644 (file)
@@ -1,27 +1,31 @@
-use crate::utils::{differing_macro_contexts, paths, snippet_with_applicability, span_lint_and_then};
-use crate::utils::{is_copy, match_type};
-use rustc::hir::map::Map;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::is_copy;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
-use rustc_hir::{self, *};
+use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::{self, HirId, Path};
 use rustc_lint::LateContext;
+use rustc_middle::hir::nested_filter;
 use rustc_span::source_map::Span;
-use rustc_span::symbol::Symbol;
+use rustc_span::{sym, Symbol};
 
-use super::OPTION_MAP_UNWRAP_OR;
+use super::MAP_UNWRAP_OR;
 
 /// lint use of `map().unwrap_or()` for `Option`s
-pub(super) fn lint<'a, 'tcx>(
-    cx: &LateContext<'a, 'tcx>,
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
     expr: &rustc_hir::Expr<'_>,
-    map_args: &'tcx [rustc_hir::Expr<'_>],
-    unwrap_args: &'tcx [rustc_hir::Expr<'_>],
+    recv: &rustc_hir::Expr<'_>,
+    map_arg: &'tcx rustc_hir::Expr<'_>,
+    unwrap_recv: &rustc_hir::Expr<'_>,
+    unwrap_arg: &'tcx rustc_hir::Expr<'_>,
     map_span: Span,
 ) {
     // lint if the caller of `map()` is an `Option`
-    if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
-        if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) {
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) {
+        if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) {
             // Do not lint if the `map` argument uses identifiers in the `map`
             // argument that are also used in the `unwrap_or` argument
 
@@ -29,89 +33,89 @@ pub(super) fn lint<'a, 'tcx>(
                 cx,
                 identifiers: FxHashSet::default(),
             };
-            unwrap_visitor.visit_expr(&unwrap_args[1]);
+            unwrap_visitor.visit_expr(unwrap_arg);
 
             let mut map_expr_visitor = MapExprVisitor {
                 cx,
                 identifiers: unwrap_visitor.identifiers,
                 found_identifier: false,
             };
-            map_expr_visitor.visit_expr(&map_args[1]);
+            map_expr_visitor.visit_expr(map_arg);
 
             if map_expr_visitor.found_identifier {
                 return;
             }
         }
 
-        if differing_macro_contexts(unwrap_args[1].span, map_span) {
+        if unwrap_arg.span.ctxt() != map_span.ctxt() {
             return;
         }
 
         let mut applicability = Applicability::MachineApplicable;
         // get snippet for unwrap_or()
-        let unwrap_snippet = snippet_with_applicability(cx, unwrap_args[1].span, "..", &mut applicability);
+        let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability);
         // lint message
         // comparing the snippet from source to raw text ("None") below is safe
         // because we already have checked the type.
-        let arg = if unwrap_snippet == "None" { "None" } else { "a" };
+        let arg = if unwrap_snippet == "None" { "None" } else { "<a>" };
         let unwrap_snippet_none = unwrap_snippet == "None";
         let suggest = if unwrap_snippet_none {
-            "and_then(f)"
+            "and_then(<f>)"
         } else {
-            "map_or(a, f)"
+            "map_or(<a>, <f>)"
         };
         let msg = &format!(
-            "called `map(f).unwrap_or({})` on an `Option` value. \
-             This can be done more directly by calling `{}` instead",
+            "called `map(<f>).unwrap_or({})` on an `Option` value. \
+            This can be done more directly by calling `{}` instead",
             arg, suggest
         );
 
-        span_lint_and_then(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, |db| {
-            let map_arg_span = map_args[1].span;
+        span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| {
+            let map_arg_span = map_arg.span;
 
             let mut suggestion = vec![
                 (
                     map_span,
                     String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }),
                 ),
-                (expr.span.with_lo(unwrap_args[0].span.hi()), String::from("")),
+                (expr.span.with_lo(unwrap_recv.span.hi()), String::from("")),
             ];
 
             if !unwrap_snippet_none {
                 suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{}, ", unwrap_snippet)));
             }
 
-            db.multipart_suggestion(&format!("use `{}` instead", suggest), suggestion, applicability);
+            diag.multipart_suggestion(&format!("use `{}` instead", suggest), suggestion, applicability);
         });
     }
 }
 
 struct UnwrapVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'a, 'tcx>,
+    cx: &'a LateContext<'tcx>,
     identifiers: FxHashSet<Symbol>,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
         self.identifiers.insert(ident(path));
         walk_path(self, path);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }
 
 struct MapExprVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'a, 'tcx>,
+    cx: &'a LateContext<'tcx>,
     identifiers: FxHashSet<Symbol>,
     found_identifier: bool,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
+    type NestedFilter = nested_filter::All;
 
     fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
         if self.identifiers.contains(&ident(path)) {
@@ -121,8 +125,8 @@ fn visit_path(&mut self, path: &'tcx Path<'_>, _id: HirId) {
         walk_path(self, path);
     }
 
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
-        NestedVisitorMap::All(&self.cx.tcx.hir())
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
     }
 }