| #![allow(unused_braces, unused_variables, dead_code)] |
| #![allow( |
| clippy::collapsible_else_if, |
| clippy::let_unit_value, |
| clippy::redundant_at_rest_pattern |
| )] |
| #![warn(clippy::manual_let_else)] |
| // Ensure that we don't conflict with match -> if let lints |
| #![warn(clippy::single_match_else, clippy::single_match)] |
| |
| fn f() -> Result<u32, u32> { |
| Ok(0) |
| } |
| |
| fn g() -> Option<()> { |
| None |
| } |
| |
| fn h() -> (Option<()>, Option<()>) { |
| (None, None) |
| } |
| |
| enum Variant { |
| Foo, |
| Bar(u32), |
| Baz(u32), |
| } |
| |
| fn build_enum() -> Variant { |
| Variant::Foo |
| } |
| |
| fn main() {} |
| |
| fn fire() { |
| let Some(v) = g() else { return }; |
| |
| let Some(v) = g() else { return }; |
| |
| loop { |
| // More complex pattern for the identity arm and diverging arm |
| let ((Some(v), None) | (None, Some(v))) = h() else { continue }; |
| // Custom enums are supported as long as the "else" arm is a simple _ |
| let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue }; |
| } |
| |
| // There is a _ in the diverging arm |
| // TODO also support unused bindings aka _v |
| let Ok(v) = f() else { return }; |
| |
| // Err(()) is an allowed pattern |
| let Ok(v) = f().map_err(|_| ()) else { return }; |
| |
| let f = Variant::Bar(1); |
| |
| let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return }; |
| |
| let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return }; |
| |
| let data = [1_u8, 2, 3, 4, 0, 0, 0, 0]; |
| let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return }; |
| } |
| |
| fn not_fire() { |
| // Multiple diverging arms |
| let v = match h() { |
| _ => panic!(), |
| (None, Some(_v)) => return, |
| (Some(v), None) => v, |
| }; |
| |
| // Multiple identity arms |
| let v = match h() { |
| _ => panic!(), |
| (None, Some(v)) => v, |
| (Some(v), None) => v, |
| }; |
| |
| // No diverging arm at all, only identity arms. |
| // This is no case for let else, but destructuring assignment. |
| let v = match f() { |
| Ok(v) => v, |
| Err(e) => e, |
| }; |
| |
| // The identity arm has a guard |
| let v = match g() { |
| Some(v) if g().is_none() => v, |
| _ => return, |
| }; |
| |
| // The diverging arm has a guard |
| let v = match f() { |
| Err(v) if v > 0 => panic!(), |
| Ok(v) | Err(v) => v, |
| }; |
| |
| // The diverging arm creates a binding |
| let v = match f() { |
| Ok(v) => v, |
| Err(e) => panic!("error: {e}"), |
| }; |
| |
| // Custom enum where the diverging arm |
| // explicitly mentions the variant |
| let v = match build_enum() { |
| Variant::Foo => return, |
| Variant::Bar(v) | Variant::Baz(v) => v, |
| }; |
| |
| // The custom enum is surrounded by an Err() |
| let v = match Err(build_enum()) { |
| Ok(v) | Err(Variant::Bar(v) | Variant::Baz(v)) => v, |
| Err(Variant::Foo) => return, |
| }; |
| |
| // Issue 10241 |
| // The non-divergent arm arrives in second position and |
| // may cover values already matched in the first arm. |
| let v = match h() { |
| (Some(_), Some(_)) | (None, None) => return, |
| (Some(v), _) | (None, Some(v)) => v, |
| }; |
| |
| let v = match build_enum() { |
| _ => return, |
| Variant::Bar(v) | Variant::Baz(v) => v, |
| }; |
| |
| let data = [1_u8, 2, 3, 4, 0, 0, 0, 0]; |
| let data = match data.as_slice() { |
| [] | [0, 0] => return, |
| [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data, |
| }; |
| } |