Skip to content

Commit 515b2af

Browse files
committed
Merge pull request #473 from fhartwig/loop-index-false-positive
Suppress explicit_counter_loop lint if loop variable is used after the loop
2 parents 5b6c2b7 + 94dc2f5 commit 515b2af

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

src/loops.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ impl LateLintPass for LoopsPass {
150150
for (id, _) in visitor.states.iter().filter( |&(_,v)| *v == VarState::IncrOnce) {
151151
let mut visitor2 = InitializeVisitor { cx: cx, end_expr: expr, var_id: id.clone(),
152152
state: VarState::IncrOnce, name: None,
153-
depth: 0, done: false };
153+
depth: 0,
154+
past_loop: false };
154155
walk_block(&mut visitor2, block);
155156

156157
if visitor2.state == VarState::Warn {
@@ -502,7 +503,7 @@ struct InitializeVisitor<'v, 't: 'v> {
502503
state: VarState,
503504
name: Option<Name>,
504505
depth: u32, // depth of conditional expressions
505-
done: bool
506+
past_loop: bool
506507
}
507508

508509
impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
@@ -530,12 +531,16 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
530531
}
531532

532533
fn visit_expr(&mut self, expr: &'v Expr) {
533-
if self.state == VarState::DontWarn || expr == self.end_expr {
534-
self.done = true;
534+
if self.state == VarState::DontWarn {
535+
return;
536+
}
537+
if expr == self.end_expr {
538+
self.past_loop = true;
539+
return;
535540
}
536541
// No need to visit expressions before the variable is
537-
// declared or after we've rejected it.
538-
if self.state == VarState::IncrOnce || self.done {
542+
// declared
543+
if self.state == VarState::IncrOnce {
539544
return;
540545
}
541546

@@ -556,11 +561,15 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
556561
_ => ()
557562
}
558563
}
564+
565+
if self.past_loop {
566+
self.state = VarState::DontWarn;
567+
return;
568+
}
559569
}
560570
// If there are other loops between the declaration and the target loop, give up
561-
else if is_loop(expr) {
571+
else if !self.past_loop && is_loop(expr) {
562572
self.state = VarState::DontWarn;
563-
self.done = true;
564573
return;
565574
}
566575
// Keep track of whether we're inside a conditional expression

tests/compile-fail/for_loop.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,6 @@ fn main() {
132132
_index = 0;
133133
for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter
134134

135-
let mut _index;
136-
_index = 0;
137-
for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter
138-
for _v in &vec { _index += 1 } // But this does not warn
139-
140135
// Potential false positives
141136
let mut _index = 0;
142137
_index = 1;
@@ -187,4 +182,8 @@ fn main() {
187182
let mut _index = 0;
188183
{ let mut _x = &mut _index; }
189184
for _v in &vec { _index += 1 }
185+
186+
let mut index = 0;
187+
for _v in &vec { index += 1 }
188+
println!("index: {}", index);
190189
}

0 commit comments

Comments
 (0)