| //@aux-build:proc_macros.rs |
| #![warn(clippy::manual_assert_eq)] |
| #![allow(clippy::manual_ignore_case_cmp)] // only raised before the fix |
| #![expect(clippy::eq_op, clippy::assertions_on_constants)] |
| |
| fn main() { |
| let a = "a"; |
| assert_eq!(a, "a".to_ascii_lowercase()); |
| //~^ manual_assert_eq |
| assert_ne!(a, "a".to_ascii_uppercase()); |
| //~^ manual_assert_eq |
| debug_assert_eq!(a, "a".to_ascii_lowercase()); |
| //~^ manual_assert_eq |
| debug_assert_ne!(a, "a".to_ascii_uppercase()); |
| //~^ manual_assert_eq |
| |
| // macros |
| let v = vec![]; |
| assert_eq!(v, vec![1, 2, 3]); |
| //~^ manual_assert_eq |
| assert_eq!(vec![1, 2, 3], v); |
| //~^ manual_assert_eq |
| assert_eq!(vec![1], vec![1, 2, 3]); |
| //~^ manual_assert_eq |
| |
| // Don't lint: has assert message |
| assert!(a == "a".to_ascii_lowercase(), "{a}"); |
| assert!(a == "a".to_ascii_lowercase(), "a==a"); |
| assert!(a == "a".to_ascii_lowercase(), "{a}==a"); |
| assert!(a != "a".to_ascii_uppercase(), "a!=A"); |
| debug_assert!(a == "a".to_ascii_lowercase(), "a==a"); |
| debug_assert!(a != "a".to_ascii_uppercase(), "a!=A"); |
| |
| // Don't lint: `!=`, and at least one of the sides is a constant value |
| assert!(a != "A"); |
| assert!("A" != a); |
| assert!("A" != "A"); |
| |
| // Don't lint: comparison of ptrs |
| fn cmp_ptrs(a: *const u8, b: *const u8) { |
| assert!(a == b); |
| } |
| |
| // Don't lint: one of the sides isn't `Debug` |
| { |
| #[derive(PartialEq)] |
| struct NotDebug; |
| |
| #[derive(PartialEq)] |
| struct NotDebug2; |
| |
| impl PartialEq<NotDebug2> for NotDebug { |
| fn eq(&self, other: &NotDebug2) -> bool { |
| unimplemented!() |
| } |
| } |
| impl PartialEq<NotDebug> for NotDebug2 { |
| fn eq(&self, other: &NotDebug) -> bool { |
| unimplemented!() |
| } |
| } |
| |
| #[derive(Debug)] |
| struct IsDebug; |
| |
| impl PartialEq<IsDebug> for NotDebug { |
| fn eq(&self, other: &IsDebug) -> bool { |
| unimplemented!() |
| } |
| } |
| impl PartialEq<NotDebug> for IsDebug { |
| fn eq(&self, other: &NotDebug) -> bool { |
| unimplemented!() |
| } |
| } |
| |
| let nd = NotDebug; |
| assert!(nd == nd); |
| |
| let nd2 = NotDebug2; |
| assert!(nd == nd2); |
| assert!(nd2 == nd); |
| |
| let id = IsDebug; |
| assert!(id == nd); |
| assert!(nd == id); |
| } |
| |
| // Don't lint: in const context |
| const { |
| assert!(5 == 2 + 3); |
| } |
| |
| // Don't lint: in external macro |
| { |
| // NOTE: this only works because `root_macro_call_first_node` returns `external!`, |
| // which then gets rejected by the macro name check |
| proc_macros::external!(assert!('a' == 'b')); |
| proc_macros::external!({ |
| let some_padding_before = 'a'; |
| assert!('a' == 'b'); |
| let some_padding_after = 'b'; |
| }); |
| |
| // .. which also means that the following is _technically_ a FN -- but surely no one would write |
| // code like this (diverging/unit expression as a child expression of a macro call) |
| vec![(), assert!('a' == 'b'), ()]; |
| } |
| } |
| |
| // Don't lint: in const context |
| const _: () = { |
| assert!(8 == (7 + 1)); |
| }; |