11use crate :: { LateContext , LateLintPass , LintContext } ;
22
33use hir:: { Expr , Pat } ;
4- use rustc_errors:: Applicability ;
4+ use rustc_errors:: { Applicability , DelayDm } ;
55use rustc_hir as hir;
66use rustc_infer:: traits:: TraitEngine ;
77use rustc_infer:: { infer:: TyCtxtInferExt , traits:: ObligationCause } ;
@@ -55,24 +55,24 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
5555 _ => return ,
5656 } ;
5757
58- let msg = format ! (
59- "for loop over {article} `{ty}`. This is more readably written as an `if let` statement" ,
60- ) ;
61-
62- cx. struct_span_lint ( FOR_LOOPS_OVER_FALLIBLES , arg. span , |diag| {
63- let mut warn = diag. build ( msg) ;
58+ let msg = DelayDm ( || {
59+ format ! (
60+ "for loop over {article} `{ty}`. This is more readably written as an `if let` statement" ,
61+ )
62+ } ) ;
6463
64+ cx. struct_span_lint ( FOR_LOOPS_OVER_FALLIBLES , arg. span , msg, |lint| {
6565 if let Some ( recv) = extract_iterator_next_call ( cx, arg)
6666 && let Ok ( recv_snip) = cx. sess ( ) . source_map ( ) . span_to_snippet ( recv. span )
6767 {
68- warn . span_suggestion (
68+ lint . span_suggestion (
6969 recv. span . between ( arg. span . shrink_to_hi ( ) ) ,
7070 format ! ( "to iterate over `{recv_snip}` remove the call to `next`" ) ,
7171 ".by_ref()" ,
7272 Applicability :: MaybeIncorrect
7373 ) ;
7474 } else {
75- warn . multipart_suggestion_verbose (
75+ lint . multipart_suggestion_verbose (
7676 format ! ( "to check pattern in a loop use `while let`" ) ,
7777 vec ! [
7878 // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
@@ -84,25 +84,23 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
8484 }
8585
8686 if suggest_question_mark ( cx, adt, substs, expr. span ) {
87- warn . span_suggestion (
87+ lint . span_suggestion (
8888 arg. span . shrink_to_hi ( ) ,
8989 "consider unwrapping the `Result` with `?` to iterate over its contents" ,
9090 "?" ,
9191 Applicability :: MaybeIncorrect ,
9292 ) ;
9393 }
9494
95- warn . multipart_suggestion_verbose (
95+ lint . multipart_suggestion_verbose (
9696 "consider using `if let` to clear intent" ,
9797 vec ! [
9898 // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
9999 ( expr. span. with_hi( pat. span. lo( ) ) , format!( "if let {var}(" ) ) ,
100100 ( pat. span. between( arg. span) , format!( ") = " ) ) ,
101101 ] ,
102102 Applicability :: MaybeIncorrect ,
103- ) ;
104-
105- warn. emit ( )
103+ )
106104 } )
107105 }
108106}
@@ -128,7 +126,7 @@ fn extract_iterator_next_call<'tcx>(
128126 expr : & Expr < ' tcx > ,
129127) -> Option < & ' tcx Expr < ' tcx > > {
130128 // This won't work for `Iterator::next(iter)`, is this an issue?
131- if let hir:: ExprKind :: MethodCall ( _, [ recv] , _) = expr. kind
129+ if let hir:: ExprKind :: MethodCall ( _, recv, _ , _) = expr. kind
132130 && cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) == cx. tcx . lang_items ( ) . next_fn ( )
133131 {
134132 Some ( recv)
0 commit comments