| #![warn(clippy::needless_match)] |
| #![allow(clippy::manual_map)] |
| #![allow(dead_code)] |
| |
| #[derive(Clone, Copy)] |
| enum Simple { |
| A, |
| B, |
| C, |
| D, |
| } |
| |
| fn useless_match() { |
| let i = 10; |
| let _: i32 = i; |
| let s = "test"; |
| let _: &str = s; |
| } |
| |
| fn custom_type_match() { |
| let se = Simple::A; |
| let _: Simple = se; |
| // Don't trigger |
| let _: Simple = match se { |
| Simple::A => Simple::A, |
| Simple::B => Simple::B, |
| _ => Simple::C, |
| }; |
| // Mingled, don't trigger |
| let _: Simple = match se { |
| Simple::A => Simple::B, |
| Simple::B => Simple::C, |
| Simple::C => Simple::D, |
| Simple::D => Simple::A, |
| }; |
| } |
| |
| fn option_match(x: Option<i32>) { |
| let _: Option<i32> = x; |
| // Don't trigger, this is the case for manual_map_option |
| let _: Option<i32> = match x { |
| Some(a) => Some(-a), |
| None => None, |
| }; |
| } |
| |
| fn func_ret_err<T>(err: T) -> Result<i32, T> { |
| Err(err) |
| } |
| |
| fn result_match() { |
| let _: Result<i32, i32> = Ok(1); |
| let _: Result<i32, i32> = func_ret_err(0_i32); |
| // as ref, don't trigger |
| let res = &func_ret_err(0_i32); |
| let _: Result<&i32, &i32> = match *res { |
| Ok(ref x) => Ok(x), |
| Err(ref x) => Err(x), |
| }; |
| } |
| |
| fn if_let_option() { |
| let _ = Some(1); |
| |
| fn do_something() {} |
| |
| // Don't trigger |
| let _ = if let Some(a) = Some(1) { |
| Some(a) |
| } else { |
| do_something(); |
| None |
| }; |
| |
| // Don't trigger |
| let _ = if let Some(a) = Some(1) { |
| do_something(); |
| Some(a) |
| } else { |
| None |
| }; |
| |
| // Don't trigger |
| let _ = if let Some(a) = Some(1) { Some(a) } else { Some(2) }; |
| } |
| |
| fn if_let_option_result() -> Result<(), ()> { |
| fn f(x: i32) -> Result<Option<i32>, ()> { |
| Ok(Some(x)) |
| } |
| // Don't trigger |
| let _ = if let Some(v) = f(1)? { Some(v) } else { f(2)? }; |
| Ok(()) |
| } |
| |
| fn if_let_result() { |
| let x: Result<i32, i32> = Ok(1); |
| let _: Result<i32, i32> = x; |
| let _: Result<i32, i32> = x; |
| // Input type mismatch, don't trigger |
| #[allow(clippy::question_mark)] |
| let _: Result<i32, i32> = if let Err(e) = Ok(1) { Err(e) } else { x }; |
| } |
| |
| fn if_let_custom_enum(x: Simple) { |
| let _: Simple = x; |
| |
| // Don't trigger |
| let _: Simple = if let Simple::A = x { |
| Simple::A |
| } else if true { |
| Simple::B |
| } else { |
| x |
| }; |
| } |
| |
| mod issue8542 { |
| #[derive(Clone, Copy)] |
| enum E { |
| VariantA(u8, u8), |
| VariantB(u8, bool), |
| } |
| |
| enum Complex { |
| A(u8), |
| B(u8, bool), |
| C(u8, i32, f64), |
| D(E, bool), |
| } |
| |
| fn match_test() { |
| let ce = Complex::B(8, false); |
| let aa = 0_u8; |
| let bb = false; |
| |
| let _: Complex = ce; |
| |
| // Don't trigger |
| let _: Complex = match ce { |
| Complex::A(_) => Complex::A(aa), |
| Complex::B(_, b) => Complex::B(aa, b), |
| Complex::C(_, b, _) => Complex::C(aa, b, 64_f64), |
| Complex::D(e, b) => Complex::D(e, b), |
| }; |
| |
| // Don't trigger |
| let _: Complex = match ce { |
| Complex::A(a) => Complex::A(a), |
| Complex::B(a, _) => Complex::B(a, bb), |
| Complex::C(a, _, _) => Complex::C(a, 32_i32, 64_f64), |
| _ => ce, |
| }; |
| } |
| } |
| |
| /// Lint triggered when type coercions happen. |
| /// Do NOT trigger on any of these. |
| mod issue8551 { |
| trait Trait {} |
| struct Struct; |
| impl Trait for Struct {} |
| |
| fn optmap(s: Option<&Struct>) -> Option<&dyn Trait> { |
| match s { |
| Some(s) => Some(s), |
| None => None, |
| } |
| } |
| |
| fn lint_tests() { |
| let option: Option<&Struct> = None; |
| let _: Option<&dyn Trait> = match option { |
| Some(s) => Some(s), |
| None => None, |
| }; |
| |
| let _: Option<&dyn Trait> = if true { |
| match option { |
| Some(s) => Some(s), |
| None => None, |
| } |
| } else { |
| None |
| }; |
| |
| let result: Result<&Struct, i32> = Err(0); |
| let _: Result<&dyn Trait, i32> = match result { |
| Ok(s) => Ok(s), |
| Err(e) => Err(e), |
| }; |
| |
| let _: Option<&dyn Trait> = if let Some(s) = option { Some(s) } else { None }; |
| } |
| } |
| |
| trait Tr { |
| fn as_mut(&mut self) -> Result<&mut i32, &mut i32>; |
| } |
| impl Tr for Result<i32, i32> { |
| fn as_mut(&mut self) -> Result<&mut i32, &mut i32> { |
| match self { |
| Ok(x) => Ok(x), |
| Err(e) => Err(e), |
| } |
| } |
| } |
| |
| mod issue9084 { |
| fn wildcard_if() { |
| let mut some_bool = true; |
| let e = Some(1); |
| |
| // should lint |
| let _ = e; |
| |
| // should lint |
| let _ = e; |
| |
| // should not lint |
| let _ = match e { |
| _ if some_bool => e, |
| _ => Some(2), |
| }; |
| |
| // should not lint |
| let _ = match e { |
| Some(i) => Some(i + 1), |
| _ if some_bool => e, |
| _ => e, |
| }; |
| |
| // should not lint (guard has side effects) |
| let _ = match e { |
| Some(i) => Some(i), |
| _ if { |
| some_bool = false; |
| some_bool |
| } => |
| { |
| e |
| }, |
| _ => e, |
| }; |
| } |
| } |
| |
| fn main() {} |