1
1
use crate :: { LateContext , LateLintPass , LintContext } ;
2
2
3
3
use hir:: { Expr , Pat } ;
4
- use rustc_errors:: Applicability ;
4
+ use rustc_errors:: { Applicability , DelayDm } ;
5
5
use rustc_hir as hir;
6
6
use rustc_infer:: traits:: TraitEngine ;
7
7
use rustc_infer:: { infer:: TyCtxtInferExt , traits:: ObligationCause } ;
@@ -55,24 +55,24 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
55
55
_ => return ,
56
56
} ;
57
57
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
+ } ) ;
64
63
64
+ cx. struct_span_lint ( FOR_LOOPS_OVER_FALLIBLES , arg. span , msg, |lint| {
65
65
if let Some ( recv) = extract_iterator_next_call ( cx, arg)
66
66
&& let Ok ( recv_snip) = cx. sess ( ) . source_map ( ) . span_to_snippet ( recv. span )
67
67
{
68
- warn . span_suggestion (
68
+ lint . span_suggestion (
69
69
recv. span . between ( arg. span . shrink_to_hi ( ) ) ,
70
70
format ! ( "to iterate over `{recv_snip}` remove the call to `next`" ) ,
71
71
".by_ref()" ,
72
72
Applicability :: MaybeIncorrect
73
73
) ;
74
74
} else {
75
- warn . multipart_suggestion_verbose (
75
+ lint . multipart_suggestion_verbose (
76
76
format ! ( "to check pattern in a loop use `while let`" ) ,
77
77
vec ! [
78
78
// 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 {
84
84
}
85
85
86
86
if suggest_question_mark ( cx, adt, substs, expr. span ) {
87
- warn . span_suggestion (
87
+ lint . span_suggestion (
88
88
arg. span . shrink_to_hi ( ) ,
89
89
"consider unwrapping the `Result` with `?` to iterate over its contents" ,
90
90
"?" ,
91
91
Applicability :: MaybeIncorrect ,
92
92
) ;
93
93
}
94
94
95
- warn . multipart_suggestion_verbose (
95
+ lint . multipart_suggestion_verbose (
96
96
"consider using `if let` to clear intent" ,
97
97
vec ! [
98
98
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
99
99
( expr. span. with_hi( pat. span. lo( ) ) , format!( "if let {var}(" ) ) ,
100
100
( pat. span. between( arg. span) , format!( ") = " ) ) ,
101
101
] ,
102
102
Applicability :: MaybeIncorrect ,
103
- ) ;
104
-
105
- warn. emit ( )
103
+ )
106
104
} )
107
105
}
108
106
}
@@ -128,7 +126,7 @@ fn extract_iterator_next_call<'tcx>(
128
126
expr : & Expr < ' tcx > ,
129
127
) -> Option < & ' tcx Expr < ' tcx > > {
130
128
// 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
132
130
&& cx. typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) == cx. tcx . lang_items ( ) . next_fn ( )
133
131
{
134
132
Some ( recv)
0 commit comments