1- use  rustc_hir:: { Expr ,  ExprKind ,  HirId ,   Stmt ,  StmtKind } ; 
2- use  rustc_middle:: ty:: { self ,   Ty } ; 
1+ use  rustc_hir:: { Expr ,  ExprKind ,  Stmt ,  StmtKind } ; 
2+ use  rustc_middle:: ty:: { self } ; 
33use  rustc_session:: { declare_lint,  declare_lint_pass} ; 
4+ use  rustc_span:: sym; 
45
56use  crate :: lints:: MappingToUnit ; 
67use  crate :: { LateContext ,  LateLintPass ,  LintContext } ; 
@@ -39,58 +40,43 @@ declare_lint_pass!(MapUnitFn => [MAP_UNIT_FN]);
3940
4041impl < ' tcx >  LateLintPass < ' tcx >  for  MapUnitFn  { 
4142    fn  check_stmt ( & mut  self ,  cx :  & LateContext < ' tcx > ,  stmt :  & Stmt < ' _ > )  { 
42-         if  stmt . span . from_expansion ( )  { 
43+         let   StmtKind :: Semi ( expr )  = stmt . kind   else  { 
4344            return ; 
44-         } 
45- 
46-         if  let  StmtKind :: Semi ( expr)  = stmt. kind 
47-             && let  ExprKind :: MethodCall ( path,  receiver,  args,  span)  = expr. kind 
45+         } ; 
46+         let  ExprKind :: MethodCall ( path,  receiver,  [ arg] ,  span)  = expr. kind  else  { 
47+             return ; 
48+         } ; 
49+         if  path. ident . name  != sym:: map
50+             || stmt. span . from_expansion ( ) 
51+             || receiver. span . from_expansion ( ) 
52+             || arg. span . from_expansion ( ) 
53+             || !is_impl_slice ( cx,  receiver) 
54+             || !cx
55+                 . typeck_results ( ) 
56+                 . type_dependent_def_id ( expr. hir_id ) 
57+                 . is_some_and ( |id| cx. tcx . is_diagnostic_item ( sym:: IteratorMap ,  id) ) 
4858        { 
49-             if  path. ident . name . as_str ( )  == "map"  { 
50-                 if  receiver. span . from_expansion ( ) 
51-                     || args. iter ( ) . any ( |e| e. span . from_expansion ( ) ) 
52-                     || !is_impl_slice ( cx,  receiver) 
53-                     || !is_diagnostic_name ( cx,  expr. hir_id ,  "IteratorMap" ) 
54-                 { 
55-                     return ; 
56-                 } 
57-                 let  arg_ty = cx. typeck_results ( ) . expr_ty ( & args[ 0 ] ) ; 
58-                 let  default_span = args[ 0 ] . span ; 
59-                 if  let  ty:: FnDef ( id,  _)  = arg_ty. kind ( )  { 
60-                     let  fn_ty = cx. tcx . fn_sig ( id) . skip_binder ( ) ; 
61-                     let  ret_ty = fn_ty. output ( ) . skip_binder ( ) ; 
62-                     if  is_unit_type ( ret_ty)  { 
63-                         cx. emit_span_lint ( 
64-                             MAP_UNIT_FN , 
65-                             span, 
66-                             MappingToUnit  { 
67-                                 function_label :  cx. tcx . span_of_impl ( * id) . unwrap_or ( default_span) , 
68-                                 argument_label :  args[ 0 ] . span , 
69-                                 map_label :  span, 
70-                                 suggestion :  path. ident . span , 
71-                                 replace :  "for_each" . to_string ( ) , 
72-                             } , 
73-                         ) 
74-                     } 
75-                 }  else  if  let  ty:: Closure ( id,  subs)  = arg_ty. kind ( )  { 
76-                     let  cl_ty = subs. as_closure ( ) . sig ( ) ; 
77-                     let  ret_ty = cl_ty. output ( ) . skip_binder ( ) ; 
78-                     if  is_unit_type ( ret_ty)  { 
79-                         cx. emit_span_lint ( 
80-                             MAP_UNIT_FN , 
81-                             span, 
82-                             MappingToUnit  { 
83-                                 function_label :  cx. tcx . span_of_impl ( * id) . unwrap_or ( default_span) , 
84-                                 argument_label :  args[ 0 ] . span , 
85-                                 map_label :  span, 
86-                                 suggestion :  path. ident . span , 
87-                                 replace :  "for_each" . to_string ( ) , 
88-                             } , 
89-                         ) 
90-                     } 
91-                 } 
92-             } 
59+             return ; 
9360        } 
61+         let  ( id,  sig)  = match  * cx. typeck_results ( ) . expr_ty ( arg) . kind ( )  { 
62+             ty:: Closure ( id,  subs)  => ( id,  subs. as_closure ( ) . sig ( ) ) , 
63+             ty:: FnDef ( id,  _)  => ( id,  cx. tcx . fn_sig ( id) . skip_binder ( ) ) , 
64+             _ => return , 
65+         } ; 
66+         let  ret_ty = sig. output ( ) . skip_binder ( ) ; 
67+         if  !( ret_ty. is_unit ( )  || ret_ty. is_never ( ) )  { 
68+             return ; 
69+         } 
70+         cx. emit_span_lint ( 
71+             MAP_UNIT_FN , 
72+             span, 
73+             MappingToUnit  { 
74+                 function_label :  cx. tcx . span_of_impl ( id) . unwrap_or ( arg. span ) , 
75+                 argument_label :  arg. span , 
76+                 map_label :  span, 
77+                 suggestion :  path. ident . span , 
78+             } , 
79+         ) ; 
9480    } 
9581} 
9682
@@ -102,18 +88,3 @@ fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
10288    } 
10389    false 
10490} 
105- 
106- fn  is_unit_type ( ty :  Ty < ' _ > )  -> bool  { 
107-     ty. is_unit ( )  || ty. is_never ( ) 
108- } 
109- 
110- fn  is_diagnostic_name ( cx :  & LateContext < ' _ > ,  id :  HirId ,  name :  & str )  -> bool  { 
111-     if  let  Some ( def_id)  = cx. typeck_results ( ) . type_dependent_def_id ( id) 
112-         && let  Some ( item)  = cx. tcx . get_diagnostic_name ( def_id) 
113-     { 
114-         if  item. as_str ( )  == name { 
115-             return  true ; 
116-         } 
117-     } 
118-     false 
119- } 
0 commit comments