@@ -79,7 +79,9 @@ use bind_instead_of_map::BindInsteadOfMap;
79
79
use clippy_utils:: consts:: { constant, Constant } ;
80
80
use clippy_utils:: diagnostics:: { span_lint, span_lint_and_help} ;
81
81
use clippy_utils:: ty:: { contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item} ;
82
- use clippy_utils:: { contains_return, get_trait_def_id, iter_input_pats, meets_msrv, msrvs, paths, return_ty} ;
82
+ use clippy_utils:: {
83
+ contains_return, get_trait_def_id, is_trait_method, iter_input_pats, meets_msrv, msrvs, paths, return_ty,
84
+ } ;
83
85
use if_chain:: if_chain;
84
86
use rustc_hir as hir;
85
87
use rustc_hir:: def:: Res ;
@@ -2314,11 +2316,11 @@ impl_lint_pass!(Methods => [
2314
2316
] ) ;
2315
2317
2316
2318
/// Extracts a method call name, args, and `Span` of the method name.
2317
- fn method_call < ' tcx > ( recv : & ' tcx hir:: Expr < ' tcx > ) -> Option < ( & ' tcx str , & ' tcx [ hir:: Expr < ' tcx > ] , Span ) > {
2318
- if let ExprKind :: MethodCall ( path, args, _ ) = recv. kind {
2319
+ fn method_call < ' tcx > ( recv : & ' tcx hir:: Expr < ' tcx > ) -> Option < ( & ' tcx str , & ' tcx [ hir:: Expr < ' tcx > ] , Span , Span ) > {
2320
+ if let ExprKind :: MethodCall ( path, args, call_span ) = recv. kind {
2319
2321
if !args. iter ( ) . any ( |e| e. span . from_expansion ( ) ) {
2320
2322
let name = path. ident . name . as_str ( ) ;
2321
- return Some ( ( name, args, path. ident . span ) ) ;
2323
+ return Some ( ( name, args, path. ident . span , call_span ) ) ;
2322
2324
}
2323
2325
}
2324
2326
None
@@ -2359,8 +2361,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
2359
2361
} ,
2360
2362
_ => ( ) ,
2361
2363
}
2362
-
2363
- needless_collect:: check ( expr, cx) ;
2364
2364
}
2365
2365
2366
2366
#[ allow( clippy:: too_many_lines) ]
@@ -2533,7 +2533,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
2533
2533
2534
2534
#[ allow( clippy:: too_many_lines) ]
2535
2535
fn check_methods < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , msrv : Option < & RustcVersion > ) {
2536
- if let Some ( ( name, [ recv, args @ ..] , span) ) = method_call ( expr) {
2536
+ if let Some ( ( name, [ recv, args @ ..] , span, call_span ) ) = method_call ( expr) {
2537
2537
match ( name, args) {
2538
2538
( "add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub" , [ _arg] ) => {
2539
2539
zst_offset:: check ( cx, expr, recv) ;
@@ -2552,34 +2552,37 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2552
2552
( "as_ref" , [ ] ) => useless_asref:: check ( cx, expr, "as_ref" , recv) ,
2553
2553
( "assume_init" , [ ] ) => uninit_assumed_init:: check ( cx, expr, recv) ,
2554
2554
( "cloned" , [ ] ) => cloned_instead_of_copied:: check ( cx, expr, recv, span, msrv) ,
2555
- ( "collect" , [ ] ) => match method_call ( recv) {
2556
- Some ( ( name @ ( "cloned" | "copied" ) , [ recv2] , _) ) => {
2557
- iter_cloned_collect:: check ( cx, name, expr, recv2) ;
2558
- } ,
2559
- Some ( ( "map" , [ m_recv, m_arg] , _) ) => {
2560
- map_collect_result_unit:: check ( cx, expr, m_recv, m_arg, recv) ;
2561
- } ,
2562
- Some ( ( "take" , [ take_self_arg, take_arg] , _) ) => {
2563
- if meets_msrv ( msrv, & msrvs:: STR_REPEAT ) {
2564
- manual_str_repeat:: check ( cx, expr, recv, take_self_arg, take_arg) ;
2565
- }
2566
- } ,
2567
- _ => { } ,
2555
+ ( "collect" , [ ] ) if is_trait_method ( cx, expr, sym:: Iterator ) => {
2556
+ needless_collect:: check ( cx, span, expr, recv, call_span) ;
2557
+ match method_call ( recv) {
2558
+ Some ( ( name @ ( "cloned" | "copied" ) , [ recv2] , _, _) ) => {
2559
+ iter_cloned_collect:: check ( cx, name, expr, recv2) ;
2560
+ } ,
2561
+ Some ( ( "map" , [ m_recv, m_arg] , _, _) ) => {
2562
+ map_collect_result_unit:: check ( cx, expr, m_recv, m_arg) ;
2563
+ } ,
2564
+ Some ( ( "take" , [ take_self_arg, take_arg] , _, _) ) => {
2565
+ if meets_msrv ( msrv, & msrvs:: STR_REPEAT ) {
2566
+ manual_str_repeat:: check ( cx, expr, recv, take_self_arg, take_arg) ;
2567
+ }
2568
+ } ,
2569
+ _ => { } ,
2570
+ }
2568
2571
} ,
2569
2572
( name @ "count" , args @ [ ] ) => match method_call ( recv) {
2570
- Some ( ( "cloned" , [ recv2] , _) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2571
- Some ( ( name2 @ ( "into_iter" | "iter" | "iter_mut" ) , [ recv2] , _) ) => {
2573
+ Some ( ( "cloned" , [ recv2] , _, _ ) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2574
+ Some ( ( name2 @ ( "into_iter" | "iter" | "iter_mut" ) , [ recv2] , _, _ ) ) => {
2572
2575
iter_count:: check ( cx, expr, recv2, name2) ;
2573
2576
} ,
2574
- Some ( ( "map" , [ _, arg] , _) ) => suspicious_map:: check ( cx, expr, recv, arg) ,
2577
+ Some ( ( "map" , [ _, arg] , _, _ ) ) => suspicious_map:: check ( cx, expr, recv, arg) ,
2575
2578
_ => { } ,
2576
2579
} ,
2577
2580
( "drain" , [ arg] ) => {
2578
2581
iter_with_drain:: check ( cx, expr, recv, span, arg) ;
2579
2582
} ,
2580
2583
( "expect" , [ _] ) => match method_call ( recv) {
2581
- Some ( ( "ok" , [ recv] , _) ) => ok_expect:: check ( cx, expr, recv) ,
2582
- Some ( ( "err" , [ recv] , err_span) ) => err_expect:: check ( cx, expr, recv, msrv, span, err_span) ,
2584
+ Some ( ( "ok" , [ recv] , _, _ ) ) => ok_expect:: check ( cx, expr, recv) ,
2585
+ Some ( ( "err" , [ recv] , err_span, _ ) ) => err_expect:: check ( cx, expr, recv, msrv, span, err_span) ,
2583
2586
_ => expect_used:: check ( cx, expr, recv) ,
2584
2587
} ,
2585
2588
( "extend" , [ arg] ) => {
@@ -2598,13 +2601,13 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2598
2601
flat_map_option:: check ( cx, expr, arg, span) ;
2599
2602
} ,
2600
2603
( name @ "flatten" , args @ [ ] ) => match method_call ( recv) {
2601
- Some ( ( "map" , [ recv, map_arg] , map_span) ) => map_flatten:: check ( cx, expr, recv, map_arg, map_span) ,
2602
- Some ( ( "cloned" , [ recv2] , _) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2604
+ Some ( ( "map" , [ recv, map_arg] , map_span, _ ) ) => map_flatten:: check ( cx, expr, recv, map_arg, map_span) ,
2605
+ Some ( ( "cloned" , [ recv2] , _, _ ) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2603
2606
_ => { } ,
2604
2607
} ,
2605
2608
( "fold" , [ init, acc] ) => unnecessary_fold:: check ( cx, expr, init, acc, span) ,
2606
2609
( "for_each" , [ _] ) => {
2607
- if let Some ( ( "inspect" , [ _, _] , span2) ) = method_call ( recv) {
2610
+ if let Some ( ( "inspect" , [ _, _] , span2, _ ) ) = method_call ( recv) {
2608
2611
inspect_for_each:: check ( cx, expr, span2) ;
2609
2612
}
2610
2613
} ,
@@ -2614,19 +2617,19 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2614
2617
( "is_none" , [ ] ) => check_is_some_is_none ( cx, expr, recv, false ) ,
2615
2618
( "is_some" , [ ] ) => check_is_some_is_none ( cx, expr, recv, true ) ,
2616
2619
( "join" , [ join_arg] ) => {
2617
- if let Some ( ( "collect" , _, span) ) = method_call ( recv) {
2620
+ if let Some ( ( "collect" , _, span, _ ) ) = method_call ( recv) {
2618
2621
unnecessary_join:: check ( cx, expr, recv, join_arg, span) ;
2619
2622
}
2620
2623
} ,
2621
2624
( "last" , args @ [ ] ) | ( "skip" , args @ [ _] ) => {
2622
- if let Some ( ( name2, [ recv2, args2 @ ..] , _span2) ) = method_call ( recv) {
2625
+ if let Some ( ( name2, [ recv2, args2 @ ..] , _span2, _ ) ) = method_call ( recv) {
2623
2626
if let ( "cloned" , [ ] ) = ( name2, args2) {
2624
2627
iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ;
2625
2628
}
2626
2629
}
2627
2630
} ,
2628
2631
( name @ ( "map" | "map_err" ) , [ m_arg] ) => {
2629
- if let Some ( ( name, [ recv2, args @ ..] , span2) ) = method_call ( recv) {
2632
+ if let Some ( ( name, [ recv2, args @ ..] , span2, _ ) ) = method_call ( recv) {
2630
2633
match ( name, args) {
2631
2634
( "as_mut" , [ ] ) => option_as_ref_deref:: check ( cx, expr, recv2, m_arg, true , msrv) ,
2632
2635
( "as_ref" , [ ] ) => option_as_ref_deref:: check ( cx, expr, recv2, m_arg, false , msrv) ,
@@ -2641,7 +2644,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2641
2644
} ,
2642
2645
( "map_or" , [ def, map] ) => option_map_or_none:: check ( cx, expr, recv, def, map) ,
2643
2646
( name @ "next" , args @ [ ] ) => {
2644
- if let Some ( ( name2, [ recv2, args2 @ ..] , _) ) = method_call ( recv) {
2647
+ if let Some ( ( name2, [ recv2, args2 @ ..] , _, _ ) ) = method_call ( recv) {
2645
2648
match ( name2, args2) {
2646
2649
( "cloned" , [ ] ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2647
2650
( "filter" , [ arg] ) => filter_next:: check ( cx, expr, recv2, arg) ,
@@ -2654,10 +2657,10 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2654
2657
}
2655
2658
} ,
2656
2659
( "nth" , args @ [ n_arg] ) => match method_call ( recv) {
2657
- Some ( ( "bytes" , [ recv2] , _) ) => bytes_nth:: check ( cx, expr, recv2, n_arg) ,
2658
- Some ( ( "cloned" , [ recv2] , _) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2659
- Some ( ( "iter" , [ recv2] , _) ) => iter_nth:: check ( cx, expr, recv2, recv, n_arg, false ) ,
2660
- Some ( ( "iter_mut" , [ recv2] , _) ) => iter_nth:: check ( cx, expr, recv2, recv, n_arg, true ) ,
2660
+ Some ( ( "bytes" , [ recv2] , _, _ ) ) => bytes_nth:: check ( cx, expr, recv2, n_arg) ,
2661
+ Some ( ( "cloned" , [ recv2] , _, _ ) ) => iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ,
2662
+ Some ( ( "iter" , [ recv2] , _, _ ) ) => iter_nth:: check ( cx, expr, recv2, recv, n_arg, false ) ,
2663
+ Some ( ( "iter_mut" , [ recv2] , _, _ ) ) => iter_nth:: check ( cx, expr, recv2, recv, n_arg, true ) ,
2661
2664
_ => iter_nth_zero:: check ( cx, expr, recv, n_arg) ,
2662
2665
} ,
2663
2666
( "ok_or_else" , [ arg] ) => unnecessary_lazy_eval:: check ( cx, expr, recv, arg, "ok_or" ) ,
@@ -2679,7 +2682,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2679
2682
} ,
2680
2683
( "step_by" , [ arg] ) => iterator_step_by_zero:: check ( cx, expr, arg) ,
2681
2684
( "take" , args @ [ _arg] ) => {
2682
- if let Some ( ( name2, [ recv2, args2 @ ..] , _span2) ) = method_call ( recv) {
2685
+ if let Some ( ( name2, [ recv2, args2 @ ..] , _span2, _ ) ) = method_call ( recv) {
2683
2686
if let ( "cloned" , [ ] ) = ( name2, args2) {
2684
2687
iter_overeager_cloned:: check ( cx, expr, recv2, name, args) ;
2685
2688
}
@@ -2691,30 +2694,31 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2691
2694
} ,
2692
2695
( "unwrap" , [ ] ) => {
2693
2696
match method_call ( recv) {
2694
- Some ( ( "get" , [ recv, get_arg] , _) ) => {
2697
+ Some ( ( "get" , [ recv, get_arg] , _, _ ) ) => {
2695
2698
get_unwrap:: check ( cx, expr, recv, get_arg, false ) ;
2696
2699
} ,
2697
- Some ( ( "get_mut" , [ recv, get_arg] , _) ) => {
2700
+ Some ( ( "get_mut" , [ recv, get_arg] , _, _ ) ) => {
2698
2701
get_unwrap:: check ( cx, expr, recv, get_arg, true ) ;
2699
2702
} ,
2700
- Some ( ( "or" , [ recv, or_arg] , or_span) ) => {
2703
+ Some ( ( "or" , [ recv, or_arg] , or_span, _ ) ) => {
2701
2704
or_then_unwrap:: check ( cx, expr, recv, or_arg, or_span) ;
2702
2705
} ,
2703
2706
_ => { } ,
2704
2707
}
2705
2708
unwrap_used:: check ( cx, expr, recv) ;
2706
2709
} ,
2707
2710
( "unwrap_or" , [ u_arg] ) => match method_call ( recv) {
2708
- Some ( ( arith @ ( "checked_add" | "checked_sub" | "checked_mul" ) , [ lhs, rhs] , _) ) => {
2711
+ Some ( ( arith @ ( "checked_add" | "checked_sub" | "checked_mul" ) , [ lhs, rhs] , _, _ ) ) => {
2709
2712
manual_saturating_arithmetic:: check ( cx, expr, lhs, rhs, u_arg, & arith[ "checked_" . len ( ) ..] ) ;
2710
2713
} ,
2711
- Some ( ( "map" , [ m_recv, m_arg] , span) ) => {
2714
+ Some ( ( "map" , [ m_recv, m_arg] , span, _ ) ) => {
2712
2715
option_map_unwrap_or:: check ( cx, expr, m_recv, m_arg, recv, u_arg, span) ;
2713
2716
} ,
2714
2717
_ => { } ,
2715
2718
} ,
2716
2719
( "unwrap_or_else" , [ u_arg] ) => match method_call ( recv) {
2717
- Some ( ( "map" , [ recv, map_arg] , _) ) if map_unwrap_or:: check ( cx, expr, recv, map_arg, u_arg, msrv) => { } ,
2720
+ Some ( ( "map" , [ recv, map_arg] , _, _) ) if map_unwrap_or:: check ( cx, expr, recv, map_arg, u_arg, msrv) => {
2721
+ } ,
2718
2722
_ => {
2719
2723
unwrap_or_else_default:: check ( cx, expr, recv, u_arg) ;
2720
2724
unnecessary_lazy_eval:: check ( cx, expr, recv, u_arg, "unwrap_or" ) ;
@@ -2726,7 +2730,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
2726
2730
}
2727
2731
2728
2732
fn check_is_some_is_none ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , is_some : bool ) {
2729
- if let Some ( ( name @ ( "find" | "position" | "rposition" ) , [ f_recv, arg] , span) ) = method_call ( recv) {
2733
+ if let Some ( ( name @ ( "find" | "position" | "rposition" ) , [ f_recv, arg] , span, _ ) ) = method_call ( recv) {
2730
2734
search_is_some:: check ( cx, expr, name, is_some, f_recv, arg, recv, span) ;
2731
2735
}
2732
2736
}
0 commit comments