2022-11-21 13:34:47 -06:00
|
|
|
#![allow(unused_braces, unused_variables, dead_code)]
|
2023-07-02 07:35:19 -05:00
|
|
|
#![allow(
|
|
|
|
clippy::collapsible_else_if,
|
|
|
|
clippy::let_unit_value,
|
|
|
|
clippy::redundant_at_rest_pattern
|
|
|
|
)]
|
2022-11-21 13:34:47 -06:00
|
|
|
#![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 v = match g() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
|
|
|
//~| NOTE: `-D clippy::manual-let-else` implied by `-D warnings`
|
2022-11-21 13:34:47 -06:00
|
|
|
Some(v_some) => v_some,
|
|
|
|
None => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
let v = match g() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2022-11-21 13:34:47 -06:00
|
|
|
Some(v_some) => v_some,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
loop {
|
|
|
|
// More complex pattern for the identity arm and diverging arm
|
|
|
|
let v = match h() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2022-11-21 13:34:47 -06:00
|
|
|
(Some(v), None) | (None, Some(v)) => v,
|
2023-02-25 18:08:29 -06:00
|
|
|
(Some(_), Some(_)) | (None, None) => continue,
|
2022-11-21 13:34:47 -06:00
|
|
|
};
|
|
|
|
// Custom enums are supported as long as the "else" arm is a simple _
|
|
|
|
let v = match build_enum() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2022-11-21 13:34:47 -06:00
|
|
|
Variant::Bar(v) | Variant::Baz(v) => v,
|
2023-02-25 18:08:29 -06:00
|
|
|
_ => continue,
|
2022-11-21 13:34:47 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// There is a _ in the diverging arm
|
|
|
|
// TODO also support unused bindings aka _v
|
|
|
|
let v = match f() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2022-11-21 13:34:47 -06:00
|
|
|
Ok(v) => v,
|
|
|
|
Err(_) => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Err(()) is an allowed pattern
|
|
|
|
let v = match f().map_err(|_| ()) {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2022-11-21 13:34:47 -06:00
|
|
|
Ok(v) => v,
|
|
|
|
Err(()) => return,
|
|
|
|
};
|
2022-12-17 07:12:54 -06:00
|
|
|
|
|
|
|
let f = Variant::Bar(1);
|
|
|
|
|
|
|
|
let _value = match f {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2023-06-02 04:41:57 -05:00
|
|
|
Variant::Bar(v) | Variant::Baz(v) => v,
|
2022-12-17 07:12:54 -06:00
|
|
|
_ => return,
|
|
|
|
};
|
2023-02-25 18:08:29 -06:00
|
|
|
|
2023-07-02 07:35:19 -05:00
|
|
|
let _value = match Some(build_enum()) {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2023-07-02 07:35:19 -05:00
|
|
|
Some(Variant::Bar(v) | Variant::Baz(v)) => v,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
2023-02-25 18:08:29 -06:00
|
|
|
let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
|
|
|
|
let data = match data.as_slice() {
|
2023-08-24 14:32:12 -05:00
|
|
|
//~^ ERROR: this could be rewritten as `let...else`
|
2023-02-25 18:08:29 -06:00
|
|
|
[data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
|
|
|
|
_ => return,
|
|
|
|
};
|
2022-11-21 13:34:47 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
};
|
2023-02-25 18:08:29 -06:00
|
|
|
|
|
|
|
// 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,
|
|
|
|
};
|
2022-11-21 13:34:47 -06:00
|
|
|
}
|