Rollup merge of #4730 - yerke:fix-check_infinite_loop, r=flip1995

Fix check_infinite_loop (while_immutable_condition) by checking for break or return inside loop body

changelog: Fix check_infinite_loop (while_immutable_condition) by checking for break or return inside loop body
fixes #4648
This commit is contained in:
Philipp Krones 2019-11-23 18:15:58 +01:00 committed by GitHub
commit 016857db65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 13 deletions

View file

@ -2367,17 +2367,57 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e
return;
};
let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
has_break_or_return: false,
};
has_break_or_return_visitor.visit_expr(expr);
let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
if no_cond_variable_mutated && !mutable_static_in_cond {
span_lint(
span_lint_and_then(
cx,
WHILE_IMMUTABLE_CONDITION,
cond.span,
"Variable in the condition are not mutated in the loop body. \
This either leads to an infinite or to a never running loop.",
"variables in the condition are not mutated in the loop body",
|db| {
db.note("this may lead to an infinite or to a never running loop");
if has_break_or_return {
db.note("this loop contains `return`s or `break`s");
db.help("rewrite it as `if cond { loop { } }`");
}
},
);
}
}
struct HasBreakOrReturnVisitor {
has_break_or_return: bool,
}
impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if self.has_break_or_return {
return;
}
match expr.kind {
ExprKind::Ret(_) | ExprKind::Break(_, _) => {
self.has_break_or_return = true;
return;
},
_ => {},
}
walk_expr(self, expr);
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
}
/// Collects the set of variables in an expression
/// Stops analysis if a function call is found
/// Note: In some cases such as `self`, there are no mutable annotation,