diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cd36afba6af4..c3ca1de3a23b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -488,7 +488,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops { }, NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (), } - }; + } // check for `loop { if let {} else break }` that could be `while let` // (also matches an explicit "match" instead of "if let") @@ -587,16 +587,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops { } } - if_chain! { - if let ExprKind::Loop(block, _, LoopSource::While) = &expr.node; - if let Block { expr: Some(expr), .. } = &**block; - if let ExprKind::Match(cond, arms, MatchSource::WhileDesugar) = &expr.node; - if let ExprKind::DropTemps(cond) = &cond.node; - if let [arm, ..] = &arms[..]; - if let Arm { body, .. } = arm; - then { - check_infinite_loop(cx, cond, body); - } + if let Some((cond, body)) = higher::while_loop(&expr) { + check_infinite_loop(cx, cond, body); } check_needless_collect(expr, cx); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index a00eee67166e..f419338097d2 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -702,7 +702,7 @@ fn loop_desugaring_name(des: hir::LoopSource) -> &'static str { match des { hir::LoopSource::ForLoop => "LoopSource::ForLoop", hir::LoopSource::Loop => "LoopSource::Loop", - hir::LoopSource::While => "LoopSource::WhileDesugar", + hir::LoopSource::While => "LoopSource::While", hir::LoopSource::WhileLet => "LoopSource::WhileLet", } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index dda05d3fbc52..6fb2a3622c60 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -199,6 +199,23 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> None } +/// Recover the essential nodes of a desugared while loop: +/// `while cond { body }` becomes `(cond, body)`. +pub fn while_loop(expr: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr)> { + if_chain! { + if let hir::ExprKind::Loop(block, _, hir::LoopSource::While) = &expr.node; + if let hir::Block { expr: Some(expr), .. } = &**block; + if let hir::ExprKind::Match(cond, arms, hir::MatchSource::WhileDesugar) = &expr.node; + if let hir::ExprKind::DropTemps(cond) = &cond.node; + if let [arm, ..] = &arms[..]; + if let hir::Arm { body, .. } = arm; + then { + return Some((cond, body)); + } + } + None +} + /// Recover the essential nodes of a desugared if block /// `if cond { then } else { els }` becomes `(cond, then, Some(els))` pub fn if_block(expr: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr, Option<&hir::Expr>)> {