diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index f6138a4870e..6b721a970a6 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,5 +1,6 @@ use rustc::lint::*; use rustc::hir::*; +use rustc::ty; use syntax::ast; use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; @@ -33,6 +34,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ExprClosure(_, ref decl, closure_eid, _) => { let body = cx.tcx.hir.body(closure_eid); let closure_expr = remove_blocks(&body.value); + let ty = cx.tables.pat_ty(&body.arguments[0].pat); if_let_chain! {[ // nothing special in the argument, besides reference bindings // (e.g. .map(|&x| x) ) @@ -46,10 +48,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // .cloned() only removes one level of indirection, don't lint on more walk_ptrs_ty_depth(cx.tables.pat_ty(&first_arg.pat)).1 == 1 { - span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( - "you seem to be using .map() to clone the contents of an {}, consider \ - using `.cloned()`", type_name), - &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + // the argument is not an &mut T + if let ty::TyRef(_, tam) = ty.sty { + if tam.mutbl == MutImmutable { + span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( + "you seem to be using .map() to clone the contents of an {}, consider \ + using `.cloned()`", type_name), + &format!("try\n{}.cloned()", snippet(cx, args[0].span, ".."))); + } + } } // explicit clone() calls ( .map(|x| x.clone()) ) else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node { diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index f62d73532dd..a71a3067d25 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -97,4 +97,9 @@ fn map_clone_deref() { let _: Option = x.as_ref().map(|y| **y); } +// stuff that used to be a false positive +fn former_false_positive() { + vec![1].iter_mut().map(|x| *x); // #443 +} + fn main() { }