From a26b0b9ccce01ff29c295e3d6b2d656395f3d88f Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Sun, 14 Sep 2025 14:47:51 -0400 Subject: [PATCH] add trait impls to proc_macro::Ident --- library/proc_macro/src/bridge/mod.rs | 33 +++++++++++++++-- library/proc_macro/src/bridge/symbol.rs | 35 ++++++++++++++++++- library/proc_macro/src/lib.rs | 14 +++++--- .../clippy/tests/ui/auxiliary/proc_macros.rs | 2 +- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index b0ee9c0cc3027..4789fcd33f456 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -8,7 +8,7 @@ #![deny(unsafe_code)] -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::ops::{Bound, Range}; use std::sync::Once; use std::{fmt, marker, mem, panic, thread}; @@ -449,13 +449,42 @@ pub struct Punct { compound_traits!(struct Punct { ch, joint, span }); -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone)] pub struct Ident { pub sym: Symbol, pub is_raw: bool, pub span: Span, } +impl PartialEq for Ident +where + Symbol: PartialEq, + T: AsRef + ?Sized, +{ + fn eq(&self, other: &T) -> bool { + self.to_string() == other.as_ref() + } +} + +impl Hash for Ident { + fn hash(&self, state: &mut H) { + self.sym.hash(state); + self.is_raw.hash(state); + } +} + +/// Prints the identifier as a string that should be losslessly convertible back +/// into the same identifier. +#[stable(feature = "proc_macro_lib2", since = "1.29.0")] +impl fmt::Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.is_raw { + f.write_str("r#")?; + } + fmt::Display::fmt(&self.sym, f) + } +} + compound_traits!(struct Ident { sym, is_raw, span }); #[derive(Clone, Eq, PartialEq)] diff --git a/library/proc_macro/src/bridge/symbol.rs b/library/proc_macro/src/bridge/symbol.rs index 0d6a725fddd98..4e09bff744930 100644 --- a/library/proc_macro/src/bridge/symbol.rs +++ b/library/proc_macro/src/bridge/symbol.rs @@ -11,11 +11,12 @@ use std::cell::RefCell; use std::num::NonZero; +use std::{cmp, str}; use super::*; /// Handle for a symbol string stored within the Interner. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone)] pub struct Symbol(NonZero); impl !Send for Symbol {} @@ -96,6 +97,38 @@ impl fmt::Display for Symbol { } } +impl PartialEq for Symbol { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl PartialEq for Symbol { + fn eq(&self, other: &str) -> bool { + self.with(|s| s == other) + } +} + +impl Eq for Symbol {} + +impl Hash for Symbol { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl PartialOrd for Symbol { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Symbol { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.with(|s| other.with(|o| s.cmp(o))) + } +} + impl Encode for Symbol { fn encode(self, w: &mut Writer, s: &mut S) { self.with(|sym| sym.encode(w, s)) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 1aa6064633c3b..5ed8d87cabe4b 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1032,7 +1032,7 @@ impl PartialEq for char { } /// An identifier (`ident`). -#[derive(Clone)] +#[derive(Clone, Hash)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub struct Ident(bridge::Ident); @@ -1097,10 +1097,7 @@ impl Ident { #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0.is_raw { - f.write_str("r#")?; - } - fmt::Display::fmt(&self.0.sym, f) + self.0.fmt(f) } } @@ -1114,6 +1111,13 @@ impl fmt::Debug for Ident { } } +#[stable(feature = "proc_macro_ident_impls", since = "CURRENT_RUSTC_VERSION")] +impl + ?Sized> PartialEq for Ident { + fn eq(&self, other: &T) -> bool { + self.0 == other + } +} + /// A literal string (`"hello"`), byte string (`b"hello"`), C string (`c"hello"`), /// character (`'a'`), byte character (`b'a'`), an integer or floating point number /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`). diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs index bb55539617fc5..34a9162055671 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs @@ -465,7 +465,7 @@ impl Expander { } else if let TT::Punct(p) = &input.tt && p.as_char() == '!' && let TT::Ident(name) = &tt - && name.to_string() == "inline" + && *name == "inline" { let g = expect_tt( input.iter.next(),