X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Fmethods%2Foption_map_unwrap_or.rs;h=6c641af59f92b9c6a3f1b6941c01305f8b8bd464;hb=611d0398143acef24bc6029810828791a2475b9e;hp=4df963a4f7960632bb60c720e115ff7150142073;hpb=8472ecda0f18a2b1045d4b8736e06e774ab1c73a;p=rust.git diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 4df963a4f79..6c641af59f9 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -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::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 { "" }; let unwrap_snippet_none = unwrap_snippet == "None"; let suggest = if unwrap_snippet_none { - "and_then(f)" + "and_then()" } else { - "map_or(a, f)" + "map_or(, )" }; let msg = &format!( - "called `map(f).unwrap_or({})` on an `Option` value. \ - This can be done more directly by calling `{}` instead", + "called `map().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, } 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, 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() } }