#![warn(clippy::collapsible_match)] #![allow( clippy::needless_return, clippy::no_effect, clippy::single_match, clippy::equatable_if_let )] fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) { // match without block match res_opt { Ok(val) => match val { Some(n) => foo(n), _ => return, }, _ => return, } // match with block match res_opt { Ok(val) => match val { Some(n) => foo(n), _ => return, }, _ => return, } // if let, if let if let Ok(val) = res_opt { if let Some(n) = val { take(n); } } // if let else, if let else if let Ok(val) = res_opt { if let Some(n) = val { take(n); } else { return; } } else { return; } // if let, match if let Ok(val) = res_opt { match val { Some(n) => foo(n), _ => (), } } // match, if let match res_opt { Ok(val) => { if let Some(n) = val { take(n); } }, _ => {}, } // if let else, match if let Ok(val) = res_opt { match val { Some(n) => foo(n), _ => return, } } else { return; } // match, if let else match res_opt { Ok(val) => { if let Some(n) = val { take(n); } else { return; } }, _ => return, } // None in inner match same as outer wild branch match res_opt { Ok(val) => match val { Some(n) => foo(n), None => return, }, _ => return, } // None in outer match same as inner wild branch match opt_opt { Some(val) => match val { Some(n) => foo(n), _ => return, }, None => return, } } fn negative_cases(res_opt: Result<Option<u32>, String>, res_res: Result<Result<u32, String>, String>) { while let Some(x) = make() { if let Some(1) = x { todo!(); } } // no wild pattern in outer match match res_opt { Ok(val) => match val { Some(n) => foo(n), _ => return, }, Err(_) => return, } // inner branch is not wild or None match res_res { Ok(val) => match val { Ok(n) => foo(n), Err(_) => return, }, _ => return, } // statement before inner match match res_opt { Ok(val) => { "hi buddy"; match val { Some(n) => foo(n), _ => return, } }, _ => return, } // statement after inner match match res_opt { Ok(val) => { match val { Some(n) => foo(n), _ => return, } "hi buddy"; }, _ => return, } // wild branches do not match match res_opt { Ok(val) => match val { Some(n) => foo(n), _ => { "sup"; return; }, }, _ => return, } // binding used in if guard match res_opt { Ok(val) if val.is_some() => match val { Some(n) => foo(n), _ => return, }, _ => return, } // binding used in inner match body match res_opt { Ok(val) => match val { Some(_) => take(val), _ => return, }, _ => return, } // if guard on inner match { match res_opt { Ok(val) => match val { Some(n) if make() => foo(n), _ => return, }, _ => return, } match res_opt { Ok(val) => match val { _ => make(), _ if make() => return, }, _ => return, } } // differing macro contexts { macro_rules! mac { ($val:ident) => { match $val { Some(n) => foo(n), _ => return, } }; } match res_opt { Ok(val) => mac!(val), _ => return, } } // OR pattern enum E<T> { A(T), B(T), C(T), }; match make::<E<Option<u32>>>() { E::A(val) | E::B(val) => match val { Some(n) => foo(n), _ => return, }, _ => return, } match make::<Option<E<u32>>>() { Some(val) => match val { E::A(val) | E::B(val) => foo(val), _ => return, }, _ => return, } if let Ok(val) = res_opt { if let Some(n) = val { let _ = || { // usage in closure println!("{:?}", val); }; } } let _: &dyn std::any::Any = match &Some(Some(1)) { Some(e) => match e { Some(e) => e, e => e, }, // else branch looks the same but the binding is different e => e, }; } fn make<T>() -> T { unimplemented!() } fn foo<T, U>(t: T) -> U { unimplemented!() } fn take<T>(t: T) {} fn main() {}