1
Fork 0

Merge pull request #440 from Manishearth/map_clone

match .map(Clone::clone)
This commit is contained in:
Manish Goregaokar 2015-11-08 10:13:55 +05:30
commit 764791b83e
3 changed files with 56 additions and 38 deletions

View file

@ -1,8 +1,8 @@
use rustc::lint::*;
use rustc_front::hir::*;
use syntax::ast::Ident;
use utils::OPTION_PATH;
use utils::{is_adjusted, match_trait_method, match_type, snippet, span_help_and_lint};
use utils::{CLONE_PATH, OPTION_PATH};
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
declare_lint!(pub MAP_CLONE, Warn,
@ -14,12 +14,13 @@ pub struct MapClonePass;
impl LateLintPass for MapClonePass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// call to .map()
if let ExprMethodCall(name, _, ref args) = expr.node {
if name.node.as_str() == "map" && args.len() == 2 {
match args[1].node {
ExprClosure(_, ref decl, ref blk) => {
if_let_chain! {
[
// call to .map()
let ExprMethodCall(name, _, ref args) = expr.node,
name.node.as_str() == "map" && args.len() == 2,
let ExprClosure(_, ref decl, ref blk) = args[1].node,
// just one expression in the closure
blk.stmts.is_empty(),
let Some(ref closure_expr) = blk.expr,
@ -54,6 +55,20 @@ impl LateLintPass for MapClonePass {
}
}
}
},
ExprPath(_, ref path) => {
if match_path(path, &CLONE_PATH) {
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
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, "..")));
}
}
_ => (),
}
}
}
}
}

View file

@ -17,6 +17,7 @@ pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
pub const OPEN_OPTIONS_PATH: [&'static str; 3] = ["std", "fs", "OpenOptions"];
pub const MUTEX_PATH: [&'static str; 4] = ["std", "sync", "mutex", "Mutex"];
pub const CLONE_PATH: [&'static str; 2] = ["Clone", "clone"];
/// Produce a nested chain of if-lets and ifs from the patterns:
///

View file

@ -15,6 +15,8 @@ fn map_clone_iter() {
//~^ HELP try
x.iter().map(|y| *y); //~ ERROR you seem to be using .map()
//~^ HELP try
x.iter().map(Clone::clone); //~ ERROR you seem to be using .map()
//~^ HELP try
}
fn map_clone_option() {