//@aux-build:option_helpers.rs #![warn(clippy::manual_is_variant_and)] #[macro_use] extern crate option_helpers; struct Foo(T); impl Foo { fn map bool>(self, mut f: F) -> Option { Some(f(self.0)) } } fn foo() -> Option { Some(true) } macro_rules! some_true { () => { Some(true) }; } macro_rules! some_false { () => { Some(false) }; } macro_rules! mac { (some $e:expr) => { Some($e) }; (some_map $e:expr) => { Some($e).map(|x| x % 2 == 0) }; (map $e:expr) => { $e.map(|x| x % 2 == 0) }; (eq $a:expr, $b:expr) => { $a == $b }; } #[rustfmt::skip] fn option_methods() { let opt = Some(1); // Check for `option.map(_).unwrap_or_default()` use. // Single line case. let _ = opt.map(|x| x > 1) //~^ manual_is_variant_and // Should lint even though this call is on a separate line. .unwrap_or_default(); // Multi-line cases. let _ = opt.map(|x| { //~^ manual_is_variant_and x > 1 } ).unwrap_or_default(); let _ = opt.map(|x| x > 1).unwrap_or_default(); //~^ manual_is_variant_and let _ = opt .map(|x| x > 1) //~^ manual_is_variant_and .unwrap_or_default(); let _ = Some(2).map(|x| x % 2 == 0) == Some(true); //~^ manual_is_variant_and let _ = Some(2).map(|x| x % 2 == 0) != Some(true); //~^ manual_is_variant_and let _ = Some(2).map(|x| x % 2 == 0) == some_true!(); //~^ manual_is_variant_and let _ = Some(2).map(|x| x % 2 == 0) != some_false!(); //~^ manual_is_variant_and // won't fix because the return type of the closure is not `bool` let _ = opt.map(|x| x + 1).unwrap_or_default(); let opt2 = Some('a'); let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint //~^ manual_is_variant_and let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint // Should not lint. let _ = Foo::(0).map(|x| x.is_multiple_of(2)) == Some(true); let _ = Some(2).map(|x| x % 2 == 0) != foo(); let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true)); let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true); let _ = mac!(some_map 2) == Some(true); let _ = mac!(map Some(2)) == Some(true); } #[rustfmt::skip] fn result_methods() { let res: Result = Ok(1); // multi line cases let _ = res.map(|x| { //~^ manual_is_variant_and x > 1 } ).unwrap_or_default(); let _ = res.map(|x| x > 1) //~^ manual_is_variant_and .unwrap_or_default(); let _ = Ok::(2).map(|x| x.is_multiple_of(2)) == Ok(true); //~^ manual_is_variant_and let _ = Ok::(2).map(|x| x.is_multiple_of(2)) != Ok(true); //~^ manual_is_variant_and let _ = Ok::(2).map(|x| x.is_multiple_of(2)) != Ok(true); //~^ manual_is_variant_and // won't fix because the return type of the closure is not `bool` let _ = res.map(|x| x + 1).unwrap_or_default(); let res2: Result = Ok('a'); let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint //~^ manual_is_variant_and let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint } fn main() { option_methods(); result_methods(); } fn issue15202() { let xs = [None, Some(b'_'), Some(b'1')]; for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) != Some(true); //~^ manual_is_variant_and let a2 = x.is_none_or(|b| !b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) != Some(false); //~^ manual_is_variant_and let a2 = x.is_none_or(|b| b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) == Some(true); //~^ manual_is_variant_and let a2 = x.is_some_and(|b| b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) == Some(false); //~^ manual_is_variant_and let a2 = x.is_some_and(|b| !b.is_ascii_digit()); assert_eq!(a1, a2); } let xs = [Err("foo"), Ok(b'_'), Ok(b'1')]; for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) != Ok(true); //~^ manual_is_variant_and let a2 = !x.is_ok_and(|b| b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) != Ok(false); //~^ manual_is_variant_and let a2 = !x.is_ok_and(|b| !b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) == Ok(true); //~^ manual_is_variant_and let a2 = x.is_ok_and(|b| b.is_ascii_digit()); assert_eq!(a1, a2); } for x in xs { let a1 = x.map(|b| b.is_ascii_digit()) == Ok(false); //~^ manual_is_variant_and let a2 = x.is_ok_and(|b| !b.is_ascii_digit()); assert_eq!(a1, a2); } } mod with_func { fn iad(b: u8) -> bool { b.is_ascii_digit() } fn check_option(b: Option) { let a1 = b.map(iad) == Some(true); //~^ manual_is_variant_and let a2 = b.is_some_and(iad); assert_eq!(a1, a2); let a1 = b.map(iad) == Some(false); //~^ manual_is_variant_and let a2 = b.is_some_and(|x| !iad(x)); assert_eq!(a1, a2); let a1 = b.map(iad) != Some(true); //~^ manual_is_variant_and let a2 = b.is_none_or(|x| !iad(x)); assert_eq!(a1, a2); let a1 = b.map(iad) != Some(false); //~^ manual_is_variant_and let a2 = b.is_none_or(iad); assert_eq!(a1, a2); } fn check_result(b: Result) { let a1 = b.map(iad) == Ok(true); //~^ manual_is_variant_and let a2 = b.is_ok_and(iad); assert_eq!(a1, a2); let a1 = b.map(iad) == Ok(false); //~^ manual_is_variant_and let a2 = b.is_ok_and(|x| !iad(x)); assert_eq!(a1, a2); let a1 = b.map(iad) != Ok(true); //~^ manual_is_variant_and let a2 = !b.is_ok_and(iad); assert_eq!(a1, a2); let a1 = b.map(iad) != Ok(false); //~^ manual_is_variant_and let a2 = !b.is_ok_and(|x| !iad(x)); assert_eq!(a1, a2); } }