@@ -1528,6 +1528,9 @@ fn check_arg_type(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
1528
1528
}
1529
1529
}
1530
1530
1531
+ // To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be
1532
+ // incremented exactly once in the loop body, and initialized to zero
1533
+ // at the start of the loop.
1531
1534
fn check_for_loop_explicit_counter < ' tcx > (
1532
1535
cx : & LateContext < ' tcx > ,
1533
1536
pat : & ' tcx Pat < ' _ > ,
@@ -1546,7 +1549,10 @@ fn check_for_loop_explicit_counter<'tcx>(
1546
1549
let mut visitor2 = InitializeVisitor :: new ( cx, expr, id) ;
1547
1550
walk_block ( & mut visitor2, block) ;
1548
1551
1549
- if let Some ( name) = visitor2. get_result ( ) {
1552
+ if_chain ! {
1553
+ if let Some ( ( name, initializer) ) = visitor2. get_result( ) ;
1554
+ if is_integer_const( cx, initializer, 0 ) ;
1555
+ then {
1550
1556
let mut applicability = Applicability :: MachineApplicable ;
1551
1557
1552
1558
// for some reason this is the only way to get the `Span`
@@ -1571,6 +1577,7 @@ fn check_for_loop_explicit_counter<'tcx>(
1571
1577
) ,
1572
1578
applicability,
1573
1579
) ;
1580
+ }
1574
1581
}
1575
1582
}
1576
1583
}
@@ -2198,20 +2205,20 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
2198
2205
}
2199
2206
}
2200
2207
2201
- enum InitializeVisitorState {
2208
+ enum InitializeVisitorState < ' hir > {
2202
2209
Initial , // Not examined yet
2203
2210
Declared ( Symbol ) , // Declared but not (yet) initialized
2204
- Initialized { name : Symbol } ,
2211
+ Initialized { name : Symbol , initializer : & ' hir Expr < ' hir > } ,
2205
2212
DontWarn ,
2206
2213
}
2207
2214
2208
- /// Checks whether a variable is initialized to zero at the start of a loop and not modified
2215
+ /// Checks whether a variable is initialized at the start of a loop and not modified
2209
2216
/// and used after the loop.
2210
2217
struct InitializeVisitor < ' a , ' tcx > {
2211
2218
cx : & ' a LateContext < ' tcx > , // context reference
2212
2219
end_expr : & ' tcx Expr < ' tcx > , // the for loop. Stop scanning here.
2213
2220
var_id : HirId ,
2214
- state : InitializeVisitorState ,
2221
+ state : InitializeVisitorState < ' tcx > ,
2215
2222
depth : u32 , // depth of conditional expressions
2216
2223
past_loop : bool ,
2217
2224
}
@@ -2228,9 +2235,9 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
2228
2235
}
2229
2236
}
2230
2237
2231
- fn get_result ( & self ) -> Option < Name > {
2232
- if let InitializeVisitorState :: Initialized { name } = self . state {
2233
- Some ( name)
2238
+ fn get_result ( & self ) -> Option < ( Name , & ' tcx Expr < ' tcx > ) > {
2239
+ if let InitializeVisitorState :: Initialized { name, initializer } = self . state {
2240
+ Some ( ( name, initializer ) )
2234
2241
} else {
2235
2242
None
2236
2243
}
@@ -2247,19 +2254,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
2247
2254
if local. pat. hir_id == self . var_id;
2248
2255
if let PatKind :: Binding ( .., ident, _) = local. pat. kind;
2249
2256
then {
2250
- self . state = if_chain! {
2251
- if let Some ( ref init) = local. init;
2252
- if is_integer_const( & self . cx, init, 0 ) ;
2253
- then {
2257
+ self . state = if let Some ( ref init) = local. init {
2254
2258
InitializeVisitorState :: Initialized {
2255
- name: ident. name
2259
+ initializer: init,
2260
+ name: ident. name,
2256
2261
}
2257
2262
} else {
2258
2263
InitializeVisitorState :: Declared ( ident. name)
2259
2264
}
2260
2265
}
2261
2266
}
2262
- }
2263
2267
walk_stmt ( self , stmt) ;
2264
2268
}
2265
2269
@@ -2291,11 +2295,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
2291
2295
} ,
2292
2296
ExprKind :: Assign ( ref lhs, ref rhs, _) if lhs. hir_id == expr. hir_id => {
2293
2297
self . state = if_chain ! {
2294
- if is_integer_const ( & self . cx , rhs , 0 ) && self . depth == 0 ;
2298
+ if self . depth == 0 ;
2295
2299
if let InitializeVisitorState :: Declared ( name)
2296
2300
| InitializeVisitorState :: Initialized { name, ..} = self . state;
2297
2301
then {
2298
- InitializeVisitorState :: Initialized { name }
2302
+ InitializeVisitorState :: Initialized { initializer : rhs , name }
2299
2303
} else {
2300
2304
InitializeVisitorState :: DontWarn
2301
2305
}
0 commit comments