@@ -1369,6 +1369,38 @@ declare_clippy_lint! {
1369
1369
"using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`"
1370
1370
}
1371
1371
1372
+ declare_clippy_lint ! {
1373
+ /// **What it does:** Checks for `from_iter()` function calls that implements `FromIterator`
1374
+ /// trait.
1375
+ ///
1376
+ /// **Why is this bad?** Makes code less readable especially in method chaining.
1377
+ ///
1378
+ /// **Known problems:** None.
1379
+ ///
1380
+ /// **Example:**
1381
+ ///
1382
+ /// ```rust
1383
+ /// use std::iter::FromIterator;
1384
+ ///
1385
+ /// let five_fives = std::iter::repeat(5).take(5);
1386
+ ///
1387
+ /// let v = Vec::from_iter(five_fives);
1388
+ ///
1389
+ /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
1390
+ /// ```
1391
+ /// Use instead:
1392
+ /// ```rust
1393
+ /// let five_fives = std::iter::repeat(5).take(5);
1394
+ ///
1395
+ /// let v: Vec<i32> = five_fives.collect();
1396
+ ///
1397
+ /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
1398
+ /// ```
1399
+ pub FROM_ITER_INSTEAD_OF_COLLECT ,
1400
+ style,
1401
+ "use `.collect()` instead of `::from_iter()`"
1402
+ }
1403
+
1372
1404
declare_lint_pass ! ( Methods => [
1373
1405
UNWRAP_USED ,
1374
1406
EXPECT_USED ,
@@ -1419,6 +1451,7 @@ declare_lint_pass!(Methods => [
1419
1451
OPTION_AS_REF_DEREF ,
1420
1452
UNNECESSARY_LAZY_EVALUATIONS ,
1421
1453
MAP_COLLECT_RESULT_UNIT ,
1454
+ FROM_ITER_INSTEAD_OF_COLLECT ,
1422
1455
] ) ;
1423
1456
1424
1457
impl < ' tcx > LateLintPass < ' tcx > for Methods {
@@ -1505,6 +1538,14 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1505
1538
}
1506
1539
1507
1540
match expr. kind {
1541
+ hir:: ExprKind :: Call ( ref func, ref args) => {
1542
+ if let hir:: ExprKind :: Path ( path) = & func. kind {
1543
+ let path_segment = last_path_segment ( path) ;
1544
+ if path_segment. ident . name . as_str ( ) == "from_iter" {
1545
+ lint_from_iter ( cx, expr, args) ;
1546
+ }
1547
+ }
1548
+ } ,
1508
1549
hir:: ExprKind :: MethodCall ( ref method_call, ref method_span, ref args, _) => {
1509
1550
lint_or_fun_call ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
1510
1551
lint_expect_fun_call ( cx, expr, * method_span, & method_call. ident . as_str ( ) , args) ;
@@ -3831,6 +3872,24 @@ fn lint_filetype_is_file(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir
3831
3872
span_lint_and_help ( cx, FILETYPE_IS_FILE , span, & lint_msg, None , & help_msg) ;
3832
3873
}
3833
3874
3875
+ fn lint_from_iter ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , args : & [ hir:: Expr < ' _ > ] ) {
3876
+ let ty = cx. typeck_results ( ) . expr_ty ( expr) ;
3877
+ let id = get_trait_def_id ( cx, & paths:: FROM_ITERATOR_TRAIT ) . unwrap ( ) ;
3878
+
3879
+ if implements_trait ( cx, ty, id, & [ ] ) {
3880
+ // `expr` implements `FromIterator` trait
3881
+ let iter_expr = snippet ( cx, args[ 0 ] . span , ".." ) ;
3882
+ span_lint_and_help (
3883
+ cx,
3884
+ FROM_ITER_INSTEAD_OF_COLLECT ,
3885
+ expr. span ,
3886
+ "use `.collect()` instead of `::from_iter()`" ,
3887
+ None ,
3888
+ & format ! ( "consider using `{}.collect()`" , iter_expr) ,
3889
+ ) ;
3890
+ }
3891
+ }
3892
+
3834
3893
fn fn_header_equals ( expected : hir:: FnHeader , actual : hir:: FnHeader ) -> bool {
3835
3894
expected. constness == actual. constness
3836
3895
&& expected. unsafety == actual. unsafety
0 commit comments