Skip to content

Commit 13c207d

Browse files
committed
Generalise InitializeVisitor
1 parent c599e2f commit 13c207d

File tree

2 files changed

+21
-17
lines changed

2 files changed

+21
-17
lines changed

clippy_lints/src/loops.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,9 @@ fn check_arg_type(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
15281528
}
15291529
}
15301530

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.
15311534
fn check_for_loop_explicit_counter<'tcx>(
15321535
cx: &LateContext<'tcx>,
15331536
pat: &'tcx Pat<'_>,
@@ -1546,7 +1549,10 @@ fn check_for_loop_explicit_counter<'tcx>(
15461549
let mut visitor2 = InitializeVisitor::new(cx, expr, id);
15471550
walk_block(&mut visitor2, block);
15481551

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 {
15501556
let mut applicability = Applicability::MachineApplicable;
15511557

15521558
// for some reason this is the only way to get the `Span`
@@ -1571,6 +1577,7 @@ fn check_for_loop_explicit_counter<'tcx>(
15711577
),
15721578
applicability,
15731579
);
1580+
}
15741581
}
15751582
}
15761583
}
@@ -2198,20 +2205,20 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
21982205
}
21992206
}
22002207

2201-
enum InitializeVisitorState {
2208+
enum InitializeVisitorState<'hir> {
22022209
Initial, // Not examined yet
22032210
Declared(Symbol), // Declared but not (yet) initialized
2204-
Initialized { name: Symbol },
2211+
Initialized { name: Symbol, initializer: &'hir Expr<'hir> },
22052212
DontWarn,
22062213
}
22072214

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
22092216
/// and used after the loop.
22102217
struct InitializeVisitor<'a, 'tcx> {
22112218
cx: &'a LateContext<'tcx>, // context reference
22122219
end_expr: &'tcx Expr<'tcx>, // the for loop. Stop scanning here.
22132220
var_id: HirId,
2214-
state: InitializeVisitorState,
2221+
state: InitializeVisitorState<'tcx>,
22152222
depth: u32, // depth of conditional expressions
22162223
past_loop: bool,
22172224
}
@@ -2228,9 +2235,9 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
22282235
}
22292236
}
22302237

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))
22342241
} else {
22352242
None
22362243
}
@@ -2247,19 +2254,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
22472254
if local.pat.hir_id == self.var_id;
22482255
if let PatKind::Binding(.., ident, _) = local.pat.kind;
22492256
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 {
22542258
InitializeVisitorState::Initialized {
2255-
name: ident.name
2259+
initializer: init,
2260+
name: ident.name,
22562261
}
22572262
} else {
22582263
InitializeVisitorState::Declared(ident.name)
22592264
}
22602265
}
22612266
}
2262-
}
22632267
walk_stmt(self, stmt);
22642268
}
22652269

@@ -2291,11 +2295,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
22912295
},
22922296
ExprKind::Assign(ref lhs, ref rhs, _) if lhs.hir_id == expr.hir_id => {
22932297
self.state = if_chain! {
2294-
if is_integer_const(&self.cx, rhs, 0) && self.depth == 0;
2298+
if self.depth == 0;
22952299
if let InitializeVisitorState::Declared(name)
22962300
| InitializeVisitorState::Initialized { name, ..} = self.state;
22972301
then {
2298-
InitializeVisitorState::Initialized { name }
2302+
InitializeVisitorState::Initialized { initializer: rhs, name }
22992303
} else {
23002304
InitializeVisitorState::DontWarn
23012305
}

clippy_lints/src/utils/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
707707
}
708708

709709
/// Gets the parent expression, if any –- this is useful to constrain a lint.
710-
pub fn get_parent_expr<'c>(cx: &'c LateContext<'_>, e: &Expr<'_>) -> Option<&'c Expr<'c>> {
710+
pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
711711
let map = &cx.tcx.hir();
712712
let hir_id = e.hir_id;
713713
let parent_id = map.get_parent_node(hir_id);

0 commit comments

Comments
 (0)