while_let_loop doesn't take into account break-with-value #1948

This commit is contained in:
Tim Nielens 2017-09-05 22:28:30 +02:00
parent 7e9ba81297
commit 7489a84c6a
2 changed files with 20 additions and 7 deletions

View file

@ -392,7 +392,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() &&
is_break_expr(&arms[1].body)
is_simple_break_expr(&arms[1].body)
{
if in_external_macro(cx, expr.span) {
return;
@ -1500,13 +1500,16 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
}
}
/// Return true if expr contains a single break expr (maybe within a block).
fn is_break_expr(expr: &Expr) -> bool {
/// Return true if expr contains a single break expr without destination label and
/// passed expression. The expression may be within a block.
fn is_simple_break_expr(expr: &Expr) -> bool {
match expr.node {
ExprBreak(dest, _) if dest.ident.is_none() => true,
ExprBlock(ref b) => match extract_first_expr(b) {
Some(subexpr) => is_break_expr(subexpr),
None => false,
ExprBreak(dest, ref passed_expr) if dest.ident.is_none() && passed_expr.is_none() => true,
ExprBlock(ref b) => {
match extract_first_expr(b) {
Some(subexpr) => is_simple_break_expr(subexpr),
None => false,
}
},
_ => false,
}

View file

@ -183,4 +183,14 @@ fn refutable() {
while let Some(v) = y.next() { // use a for loop here
}
}
//should not trigger while_let_loop lint because break passes an expression
let a = Some(10);
let b = loop {
if let Some(c) = a {
break Some(c);
} else {
break None;
}
};
}