@@ -5,6 +5,7 @@ mod expect_used;
5
5
mod filetype_is_file;
6
6
mod filter_map_identity;
7
7
mod filter_next;
8
+ mod from_iter_instead_of_collect;
8
9
mod get_unwrap;
9
10
mod implicit_clone;
10
11
mod inefficient_to_string;
@@ -1761,7 +1762,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1761
1762
hir:: ExprKind :: Call ( ref func, ref args) => {
1762
1763
if let hir:: ExprKind :: Path ( path) = & func. kind {
1763
1764
if match_qpath ( path, & [ "from_iter" ] ) {
1764
- lint_from_iter ( cx, expr, args) ;
1765
+ from_iter_instead_of_collect :: check ( cx, expr, args) ;
1765
1766
}
1766
1767
}
1767
1768
} ,
@@ -3440,65 +3441,6 @@ fn is_bool(ty: &hir::Ty<'_>) -> bool {
3440
3441
}
3441
3442
}
3442
3443
3443
- fn lint_from_iter ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , args : & [ hir:: Expr < ' _ > ] ) {
3444
- let ty = cx. typeck_results ( ) . expr_ty ( expr) ;
3445
- let arg_ty = cx. typeck_results ( ) . expr_ty ( & args[ 0 ] ) ;
3446
-
3447
- if_chain ! {
3448
- if let Some ( from_iter_id) = get_trait_def_id( cx, & paths:: FROM_ITERATOR ) ;
3449
- if let Some ( iter_id) = get_trait_def_id( cx, & paths:: ITERATOR ) ;
3450
-
3451
- if implements_trait( cx, ty, from_iter_id, & [ ] ) && implements_trait( cx, arg_ty, iter_id, & [ ] ) ;
3452
- then {
3453
- // `expr` implements `FromIterator` trait
3454
- let iter_expr = sugg:: Sugg :: hir( cx, & args[ 0 ] , ".." ) . maybe_par( ) ;
3455
- let turbofish = extract_turbofish( cx, expr, ty) ;
3456
- let sugg = format!( "{}.collect::<{}>()" , iter_expr, turbofish) ;
3457
- span_lint_and_sugg(
3458
- cx,
3459
- FROM_ITER_INSTEAD_OF_COLLECT ,
3460
- expr. span,
3461
- "usage of `FromIterator::from_iter`" ,
3462
- "use `.collect()` instead of `::from_iter()`" ,
3463
- sugg,
3464
- Applicability :: MaybeIncorrect ,
3465
- ) ;
3466
- }
3467
- }
3468
- }
3469
-
3470
- fn extract_turbofish ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , ty : Ty < ' tcx > ) -> String {
3471
- if_chain ! {
3472
- let call_site = expr. span. source_callsite( ) ;
3473
- if let Ok ( snippet) = cx. sess( ) . source_map( ) . span_to_snippet( call_site) ;
3474
- let snippet_split = snippet. split( "::" ) . collect:: <Vec <_>>( ) ;
3475
- if let Some ( ( _, elements) ) = snippet_split. split_last( ) ;
3476
-
3477
- then {
3478
- // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
3479
- if let Some ( type_specifier) = snippet_split. iter( ) . find( |e| e. starts_with( '<' ) && e. ends_with( '>' ) ) {
3480
- // remove the type specifier from the path elements
3481
- let without_ts = elements. iter( ) . filter_map( |e| {
3482
- if e == type_specifier { None } else { Some ( ( * e) . to_string( ) ) }
3483
- } ) . collect:: <Vec <_>>( ) ;
3484
- // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
3485
- format!( "{}{}" , without_ts. join( "::" ) , type_specifier)
3486
- } else {
3487
- // type is not explicitly specified so wildcards are needed
3488
- // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
3489
- let ty_str = ty. to_string( ) ;
3490
- let start = ty_str. find( '<' ) . unwrap_or( 0 ) ;
3491
- let end = ty_str. find( '>' ) . unwrap_or_else( || ty_str. len( ) ) ;
3492
- let nb_wildcard = ty_str[ start..end] . split( ',' ) . count( ) ;
3493
- let wildcards = format!( "_{}" , ", _" . repeat( nb_wildcard - 1 ) ) ;
3494
- format!( "{}<{}>" , elements. join( "::" ) , wildcards)
3495
- }
3496
- } else {
3497
- ty. to_string( )
3498
- }
3499
- }
3500
- }
3501
-
3502
3444
fn fn_header_equals ( expected : hir:: FnHeader , actual : hir:: FnHeader ) -> bool {
3503
3445
expected. constness == actual. constness
3504
3446
&& expected. unsafety == actual. unsafety
0 commit comments