Merge pull request #1744 from Manishearth/mut_fp

Fix a false positive around mutable references and .cloned() iterators
This commit is contained in:
Oliver Schneider 2017-05-11 16:20:05 +02:00 committed by GitHub
commit 5f94763c69
2 changed files with 16 additions and 4 deletions

View File

@ -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,11 +48,16 @@ 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
{
// 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 {
if clone_call.node == "clone" &&

View File

@ -97,4 +97,9 @@ fn map_clone_deref() {
let _: Option<i32> = 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() { }