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 { .. } => { MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() && if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].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) { if in_external_macro(cx, expr.span) {
return; 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). /// Return true if expr contains a single break expr without destination label and
fn is_break_expr(expr: &Expr) -> bool { /// passed expression. The expression may be within a block.
fn is_simple_break_expr(expr: &Expr) -> bool {
match expr.node { match expr.node {
ExprBreak(dest, _) if dest.ident.is_none() => true, ExprBreak(dest, ref passed_expr) if dest.ident.is_none() && passed_expr.is_none() => true,
ExprBlock(ref b) => match extract_first_expr(b) { ExprBlock(ref b) => {
Some(subexpr) => is_break_expr(subexpr), match extract_first_expr(b) {
None => false, Some(subexpr) => is_simple_break_expr(subexpr),
None => false,
}
}, },
_ => false, _ => false,
} }

View file

@ -183,4 +183,14 @@ fn refutable() {
while let Some(v) = y.next() { // use a for loop here 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;
}
};
} }