@@ -494,13 +494,33 @@ declare_lint! {
494
494
/// s.push_str(abc);
495
495
/// s.push_str(&def));
496
496
/// ```
497
-
498
497
declare_lint ! {
499
498
pub STRING_EXTEND_CHARS ,
500
499
Warn ,
501
500
"using `x.extend(s.chars())` where s is a `&str` or `String`"
502
501
}
503
502
503
+ /// **What it does:** Checks for the use of `.cloned().collect()` on slice to create a Vec.
504
+ ///
505
+ /// **Why is this bad?** `.to_owned()` is clearer
506
+ ///
507
+ /// **Known problems:** None.
508
+ ///
509
+ /// **Example:**
510
+ /// ```rust
511
+ /// let s = [1,2,3,4,5];
512
+ /// let s2 : Vec<isize> = s.iter().cloned().collect();
513
+ /// ```
514
+ /// The correct use would be:
515
+ /// ```rust
516
+ /// let s = [1,2,3,4,5];
517
+ /// let s2 : Vec<isize> = s.to_owned();
518
+ /// ```
519
+ declare_lint ! {
520
+ pub ITER_CLONED_COLLECT ,
521
+ Warn ,
522
+ "using `.cloned().collect()` on slice to create a `Vec`"
523
+ }
504
524
505
525
impl LintPass for Pass {
506
526
fn get_lints ( & self ) -> LintArray {
@@ -525,7 +545,8 @@ impl LintPass for Pass {
525
545
ITER_NTH ,
526
546
ITER_SKIP_NEXT ,
527
547
GET_UNWRAP ,
528
- STRING_EXTEND_CHARS )
548
+ STRING_EXTEND_CHARS ,
549
+ ITER_CLONED_COLLECT )
529
550
}
530
551
}
531
552
@@ -580,6 +601,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
580
601
lint_iter_nth ( cx, expr, arglists[ 0 ] , true ) ;
581
602
} else if method_chain_args ( expr, & [ "skip" , "next" ] ) . is_some ( ) {
582
603
lint_iter_skip_next ( cx, expr) ;
604
+ } else if let Some ( arglists) = method_chain_args ( expr, & [ "cloned" , "collect" ] ) {
605
+ lint_iter_cloned_collect ( cx, expr, arglists[ 0 ] ) ;
583
606
}
584
607
585
608
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
879
902
} }
880
903
}
881
904
905
+ fn lint_iter_cloned_collect ( cx : & LateContext , expr : & hir:: Expr , iter_args : & [ hir:: Expr ] ) {
906
+ if match_type ( cx, cx. tables . expr_ty ( expr) , & paths:: VEC ) &&
907
+ derefs_to_slice ( cx, & iter_args[ 0 ] , cx. tables . expr_ty ( & iter_args[ 0 ] ) ) . is_some ( ) {
908
+ span_lint ( cx,
909
+ ITER_CLONED_COLLECT ,
910
+ expr. span ,
911
+ "called `cloned().collect()` on a slice to create a `Vec`. This is more succinctly expressed by calling `to_owned(x)`" ) ;
912
+ }
913
+ }
914
+
882
915
fn lint_iter_nth ( cx : & LateContext , expr : & hir:: Expr , iter_args : & [ hir:: Expr ] , is_mut : bool ) {
883
916
let mut_str = if is_mut { "_mut" } else { "" } ;
884
917
let caller_type = if derefs_to_slice ( cx, & iter_args[ 0 ] , cx. tables . expr_ty ( & iter_args[ 0 ] ) ) . is_some ( ) {
0 commit comments