mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 05:03:21 +00:00
Add a lint for slice.iter().cloned().collect()
If one uses `slice.iter().cloned().collect()` to create a new `Vec`, it should be `slice.to_owned()`. Fix #1292
This commit is contained in:
parent
4b29f9a364
commit
98aa0db0ac
4 changed files with 48 additions and 3 deletions
|
@ -494,13 +494,33 @@ declare_lint! {
|
|||
/// s.push_str(abc);
|
||||
/// s.push_str(&def));
|
||||
/// ```
|
||||
|
||||
declare_lint! {
|
||||
pub STRING_EXTEND_CHARS,
|
||||
Warn,
|
||||
"using `x.extend(s.chars())` where s is a `&str` or `String`"
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for the use of `.cloned().collect()` on slice to create a Vec.
|
||||
///
|
||||
/// **Why is this bad?** `.to_owned()` is clearer
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// let s = [1,2,3,4,5];
|
||||
/// let s2 : Vec<isize> = s.iter().cloned().collect();
|
||||
/// ```
|
||||
/// The correct use would be:
|
||||
/// ```rust
|
||||
/// let s = [1,2,3,4,5];
|
||||
/// let s2 : Vec<isize> = s.to_owned();
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub ITER_CLONED_COLLECT,
|
||||
Warn,
|
||||
"using `.cloned().collect()` on slice to create a `Vec`"
|
||||
}
|
||||
|
||||
impl LintPass for Pass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
|
@ -525,7 +545,8 @@ impl LintPass for Pass {
|
|||
ITER_NTH,
|
||||
ITER_SKIP_NEXT,
|
||||
GET_UNWRAP,
|
||||
STRING_EXTEND_CHARS)
|
||||
STRING_EXTEND_CHARS,
|
||||
ITER_CLONED_COLLECT)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,6 +601,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
lint_iter_nth(cx, expr, arglists[0], true);
|
||||
} else if method_chain_args(expr, &["skip", "next"]).is_some() {
|
||||
lint_iter_skip_next(cx, expr);
|
||||
} else if let Some(arglists) = method_chain_args(expr, &["cloned", "collect"]) {
|
||||
lint_iter_cloned_collect(cx, expr, arglists[0]);
|
||||
}
|
||||
|
||||
lint_or_fun_call(cx, expr, &name.node.as_str(), args);
|
||||
|
@ -879,6 +902,16 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
|
|||
}}
|
||||
}
|
||||
|
||||
fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) {
|
||||
if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC) &&
|
||||
derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() {
|
||||
span_lint(cx,
|
||||
ITER_CLONED_COLLECT,
|
||||
expr.span,
|
||||
"called `cloned().collect()` on a slice to create a `Vec`. This is more succinctly expressed by calling `to_owned(x)`");
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) {
|
||||
let mut_str = if is_mut { "_mut" } else { "" };
|
||||
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// error-pattern:yummy
|
||||
#![feature(box_syntax)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(static_in_const)]
|
||||
|
||||
#![allow(unknown_lints, missing_docs_in_private_items)]
|
||||
|
||||
|
|
|
@ -689,3 +689,8 @@ fn temporary_cstring() {
|
|||
|
||||
|
||||
}
|
||||
|
||||
fn iter_clone_collect() {
|
||||
let v = [1,2,3,4,5];
|
||||
let v2 : Vec<isize> = v.iter().cloned().collect();
|
||||
}
|
||||
|
|
|
@ -950,5 +950,13 @@ help: assign the `CString` to a variable to extend its lifetime
|
|||
687 | CString::new("foo").unwrap().as_ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: called `cloned().collect()` on a slice to create a `Vec`. This is more succinctly expressed by calling `to_owned(x)`
|
||||
--> $DIR/methods.rs:695:27
|
||||
|
|
||||
695 | let v2 : Vec<isize> = v.iter().cloned().collect();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: #[warn(iter_cloned_collect)] on by default
|
||||
|
||||
error: aborting due to 88 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue