diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 521d02db8..1846596fa 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -194,8 +194,11 @@ fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { ControlFlow::Continue(Descend::No) }, ExprKind::Match(match_expr, match_arms, _) => { - let diverges = - expr_diverges(cx, match_expr) || match_arms.iter().all(|arm| expr_diverges(cx, arm.body)); + let diverges = expr_diverges(cx, match_expr) + || match_arms.iter().all(|arm| { + let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(cx, g.body())); + guard_diverges || expr_diverges(cx, arm.body) + }); if diverges { return ControlFlow::Break(()); } diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 9046c0aff..2ef40e591 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -3,6 +3,7 @@ clippy::collapsible_else_if, clippy::unused_unit, clippy::let_unit_value, + clippy::match_single_binding, clippy::never_loop )] #![warn(clippy::manual_let_else)] @@ -55,6 +56,38 @@ fn fire() { if true { return } else { panic!() } }; + // Diverging after an if still makes the block diverge: + let v = if let Some(v_some) = g() { + v_some + } else { + if true {} + panic!(); + }; + + // A match diverges if all branches diverge: + // Note: the corresponding let-else requires a ; at the end of the match + // as otherwise the type checker does not turn it into a ! type. + let v = if let Some(v_some) = g() { + v_some + } else { + match () { + _ if panic!() => {}, + _ => panic!(), + } + }; + + // An if's expression can cause divergence: + let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; + + // An expression of a match can cause divergence: + let v = if let Some(v_some) = g() { + v_some + } else { + match panic!() { + _ => {}, + } + }; + // Top level else if let v = if let Some(v_some) = g() { v_some diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index e073276d2..453b68b8b 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:17:5 + --> $DIR/manual_let_else.rs:18:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };` @@ -7,7 +7,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = note: `-D clippy::manual-let-else` implied by `-D warnings` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:18:5 + --> $DIR/manual_let_else.rs:19:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -24,7 +24,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:24:5 + --> $DIR/manual_let_else.rs:25:5 | LL | / let v = if let Some(v) = g() { LL | | // Blocks around the identity should have no impact @@ -45,25 +45,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:37:9 + --> $DIR/manual_let_else.rs:38:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:38:9 + --> $DIR/manual_let_else.rs:39:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:42:5 + --> $DIR/manual_let_else.rs:43:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:45:5 + --> $DIR/manual_let_else.rs:46:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -80,7 +80,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:52:5 + --> $DIR/manual_let_else.rs:53:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -97,7 +97,75 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:59:5 + --> $DIR/manual_let_else.rs:60:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | v_some +LL | | } else { +LL | | if true {} +LL | | panic!(); +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v_some) = g() else { +LL + if true {} +LL + panic!(); +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:70:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | v_some +LL | | } else { +LL | | match () { +... | +LL | | } +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v_some) = g() else { +LL + match () { +LL + _ if panic!() => {}, +LL + _ => panic!(), +LL + } +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:80:5 + | +LL | let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };` + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:83:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | v_some +LL | | } else { +LL | | match panic!() { +LL | | _ => {}, +LL | | } +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v_some) = g() else { +LL + match panic!() { +LL + _ => {}, +LL + } +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:92:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -118,7 +186,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:68:5 + --> $DIR/manual_let_else.rs:101:5 | LL | / let v = if let Some(v_some) = g() { LL | | v_some @@ -147,7 +215,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:85:5 + --> $DIR/manual_let_else.rs:118:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | v_some @@ -164,7 +232,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:92:5 + --> $DIR/manual_let_else.rs:125:5 | LL | / let v = if let (Some(v_some), w_some) = (g(), 0) { LL | | (w_some, v_some) @@ -181,7 +249,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:101:13 + --> $DIR/manual_let_else.rs:134:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -191,5 +259,5 @@ LL | create_binding_if_some!(w, g()); | = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 13 previous errors +error: aborting due to 17 previous errors