@@ -73,17 +73,30 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopOverFallibles {
7373 ) ;
7474
7575 cx. struct_span_lint ( FOR_LOOP_OVER_FALLIBLES , arg. span , |diag| {
76- diag. build ( msg)
77- . multipart_suggestion_verbose (
78- "consider using `if let` to clear intent" ,
79- vec ! [
80- // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
81- ( expr. span. with_hi( pat. span. lo( ) ) , format!( "if let {var}(" ) ) ,
82- ( pat. span. between( arg. span) , format!( ") = " ) ) ,
83- ] ,
84- Applicability :: MachineApplicable ,
85- )
86- . emit ( )
76+ let mut warn = diag. build ( msg) ;
77+
78+ if let Some ( recv) = extract_iterator_next_call ( cx, arg)
79+ && let Ok ( recv_snip) = cx. sess ( ) . source_map ( ) . span_to_snippet ( recv. span )
80+ {
81+ warn. span_suggestion (
82+ recv. span . between ( arg. span . shrink_to_hi ( ) ) ,
83+ format ! ( "to iterate over `{recv_snip}` remove the call to `next`" ) ,
84+ "" ,
85+ Applicability :: MaybeIncorrect
86+ ) ;
87+ }
88+
89+ warn. multipart_suggestion_verbose (
90+ "consider using `if let` to clear intent" ,
91+ vec ! [
92+ // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
93+ ( expr. span. with_hi( pat. span. lo( ) ) , format!( "if let {var}(" ) ) ,
94+ ( pat. span. between( arg. span) , format!( ") = " ) ) ,
95+ ] ,
96+ Applicability :: MachineApplicable ,
97+ ) ;
98+
99+ warn. emit ( )
87100 } )
88101 }
89102}
@@ -103,3 +116,17 @@ fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx E
103116 None
104117 }
105118}
119+
120+ fn extract_iterator_next_call < ' tcx > (
121+ cx : & LateContext < ' _ > ,
122+ expr : & Expr < ' tcx > ,
123+ ) -> Option < & ' tcx Expr < ' tcx > > {
124+ // This won't work for `Iterator::next(iter)`, is this an issue?
125+ if let hir:: ExprKind :: MethodCall ( _, [ recv] , _) = expr. kind
126+ && cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) == cx. tcx . lang_items ( ) . next_fn ( )
127+ {
128+ Some ( recv)
129+ } else {
130+ return None
131+ }
132+ }
0 commit comments