| //@aux-build:proc_macros.rs | |
| #![warn(clippy::manual_assert_eq)] | |
| #![expect(clippy::assertions_on_constants, clippy::eq_op)] | |
| fn main() { | |
| let a = "a"; | |
| assert!(a == "a".to_ascii_lowercase()); | |
| //~^ manual_assert_eq | |
| assert!(a != "a".to_ascii_uppercase()); | |
| //~^ manual_assert_eq | |
| debug_assert!(a == "a".to_ascii_lowercase()); | |
| //~^ manual_assert_eq | |
| debug_assert!(a != "a".to_ascii_uppercase()); | |
| //~^ manual_assert_eq | |
| // macros | |
| let v = vec![]; | |
| assert!(v == vec![1, 2, 3]); | |
| //~^ manual_assert_eq | |
| assert!(vec![1, 2, 3] == v); | |
| //~^ manual_assert_eq | |
| assert!(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)); | |
| }; |