@@ -7,9 +7,10 @@ use clippy_utils::{is_trait_method, path_to_local_id, paths};
77use if_chain:: if_chain;
88use rustc_errors:: Applicability ;
99use rustc_hir:: intravisit:: { walk_block, walk_expr, NestedVisitorMap , Visitor } ;
10- use rustc_hir:: { Block , Expr , ExprKind , GenericArg , HirId , Local , Pat , PatKind , QPath , StmtKind } ;
10+ use rustc_hir:: { Block , Expr , ExprKind , GenericArg , GenericArgs , HirId , Local , Pat , PatKind , QPath , StmtKind , Ty } ;
1111use rustc_lint:: LateContext ;
1212use rustc_middle:: hir:: map:: Map ;
13+
1314use rustc_span:: symbol:: { sym, Ident } ;
1415use rustc_span:: { MultiSpan , Span } ;
1516
@@ -26,7 +27,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
2627 if chain_method. ident. name == sym!( collect) && is_trait_method( cx, & args[ 0 ] , sym:: Iterator ) ;
2728 if let Some ( generic_args) = chain_method. args;
2829 if let Some ( GenericArg :: Type ( ref ty) ) = generic_args. args. get( 0 ) ;
29- let ty = cx. typeck_results( ) . node_type ( ty. hir_id) ;
30+ if let Some ( ty ) = cx. typeck_results( ) . node_type_opt ( ty. hir_id) ;
3031 if is_type_diagnostic_item( cx, ty, sym:: vec_type)
3132 || is_type_diagnostic_item( cx, ty, sym:: vecdeque_type)
3233 || match_type( cx, ty, & paths:: BTREEMAP )
@@ -58,20 +59,33 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
5859}
5960
6061fn check_needless_collect_indirect_usage < ' tcx > ( expr : & ' tcx Expr < ' _ > , cx : & LateContext < ' tcx > ) {
62+ fn get_hir_id < ' tcx > ( ty : Option < & Ty < ' tcx > > , method_args : Option < & GenericArgs < ' tcx > > ) -> Option < HirId > {
63+ if let Some ( ty) = ty {
64+ return Some ( ty. hir_id ) ;
65+ }
66+
67+ if let Some ( generic_args) = method_args {
68+ if let Some ( GenericArg :: Type ( ref ty) ) = generic_args. args . get ( 0 ) {
69+ return Some ( ty. hir_id ) ;
70+ }
71+ }
72+
73+ None
74+ }
6175 if let ExprKind :: Block ( block, _) = expr. kind {
6276 for stmt in block. stmts {
6377 if_chain ! {
6478 if let StmtKind :: Local (
6579 Local { pat: Pat { hir_id: pat_id, kind: PatKind :: Binding ( _, _, ident, .. ) , .. } ,
66- init: Some ( init_expr) , .. }
80+ init: Some ( init_expr) , ty , .. }
6781 ) = stmt. kind;
6882 if let ExprKind :: MethodCall ( method_name, collect_span, & [ ref iter_source] , ..) = init_expr. kind;
6983 if method_name. ident. name == sym!( collect) && is_trait_method( cx, init_expr, sym:: Iterator ) ;
70- if let Some ( generic_args) = method_name. args;
71- if let Some ( GenericArg :: Type ( ref ty) ) = generic_args. args. get( 0 ) ;
72- if let ty = cx. typeck_results( ) . node_type( ty. hir_id) ;
84+ if let Some ( hir_id) = get_hir_id( * ty, method_name. args) ;
85+ if let Some ( ty) = cx. typeck_results( ) . node_type_opt( hir_id) ;
7386 if is_type_diagnostic_item( cx, ty, sym:: vec_type) ||
7487 is_type_diagnostic_item( cx, ty, sym:: vecdeque_type) ||
88+ is_type_diagnostic_item( cx, ty, sym:: BinaryHeap ) ||
7589 match_type( cx, ty, & paths:: LINKED_LIST ) ;
7690 if let Some ( iter_calls) = detect_iter_and_into_iters( block, * ident) ;
7791 if let [ iter_call] = & * iter_calls;
0 commit comments