@@ -73,17 +73,30 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopOverFallibles {
73
73
) ;
74
74
75
75
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 ( )
87
100
} )
88
101
}
89
102
}
@@ -103,3 +116,17 @@ fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx E
103
116
None
104
117
}
105
118
}
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