1 #![allow(unused_braces, unused_variables, dead_code)]
3 clippy::collapsible_else_if,
5 clippy::let_unit_value,
6 clippy::match_single_binding,
9 #![warn(clippy::manual_let_else)]
11 fn g() -> Option<()> {
18 let v = if let Some(v_some) = g() { v_some } else { return };
19 let v = if let Some(v_some) = g() {
25 let v = if let Some(v) = g() {
26 // Blocks around the identity should have no impact
31 // Some computation should still make it fire
36 // continue and break diverge
38 let v = if let Some(v_some) = g() { v_some } else { continue };
39 let v = if let Some(v_some) = g() { v_some } else { break };
42 // panic also diverges
43 let v = if let Some(v_some) = g() { v_some } else { panic!() };
45 // abort also diverges
46 let v = if let Some(v_some) = g() {
52 // If whose two branches diverge also diverges
53 let v = if let Some(v_some) = g() {
56 if true { return } else { panic!() }
59 // Diverging after an if still makes the block diverge:
60 let v = if let Some(v_some) = g() {
67 // A match diverges if all branches diverge:
68 // Note: the corresponding let-else requires a ; at the end of the match
69 // as otherwise the type checker does not turn it into a ! type.
70 let v = if let Some(v_some) = g() {
79 // An if's expression can cause divergence:
80 let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
82 // An expression of a match can cause divergence:
83 let v = if let Some(v_some) = g() {
92 let v = if let Some(v_some) = g() {
100 // All match arms diverge
101 let v = if let Some(v_some) = g() {
105 (Some(_), None) => return,
117 // Tuples supported for the declared variables
118 let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
124 // Tuples supported for the identity block and pattern
125 let v = if let (Some(v_some), w_some) = (g(), 0) {
131 // entirely inside macro lints
132 macro_rules! create_binding_if_some {
133 ($n:ident, $e:expr) => {
134 let $n = if let Some(v) = $e { v } else { return };
137 create_binding_if_some!(w, g());
141 let v = if let Some(v_some) = g() {
142 // Nothing returned. Should not fire.
148 let v = if let Some(v_some) = g() {
149 // Different variable than v_some. Should not fire.
155 let v = if let Some(v_some) = g() {
156 // Computation in then clause. Should not fire.
163 let v = if let Some(v_some) = g() {
169 // This doesn't diverge. Should not fire.
173 let v = if let Some(v_some) = g() {
176 // There is one match arm that doesn't diverge. Should not fire.
178 (Some(_), None) => return,
179 (None, Some(_)) => return,
180 (Some(_), Some(_)) => (),
185 let v = if let Some(v_some) = g() {
188 // loop with a break statement inside does not diverge.
195 fn un() -> Uninhabited {
198 let v = if let Some(v_some) = None {
201 // Don't lint if the type is uninhabited but not !
205 fn question_mark() -> Option<()> {
206 let v = if let Some(v) = g() {
209 // Question mark does not diverge
215 // Macro boundary inside let
216 macro_rules! some_or_return {
218 if let Some(v) = $e { v } else { return }
221 let v = some_or_return!(g());
223 // Also macro boundary inside let, but inside a macro
224 macro_rules! create_binding_if_some_nf {
225 ($n:ident, $e:expr) => {
226 let $n = some_or_return!($e);
229 create_binding_if_some_nf!(v, g());
231 // Already a let-else
232 let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else { panic!() };
234 // If a type annotation is present, don't lint as
235 // expressing the type might be too hard
236 let v: () = if let Some(v_some) = g() { v_some } else { panic!() };