Rollup merge of #144439 - xizheyin:symbol-rs, r=petrochenkov

Introduce ModernIdent type to unify macro 2.0 hygiene handling

This pr introduce ModernIdent type to unify macro 2.0 hygiene handling

1. Added ModernIdent type. Wraps Ident and automatically calls `normalize_to_macros_2_0()`
2. Unified identifier normalization. Replaced scattered ident.normalize_to_macros_2_0() calls with ModernIdent::new(ident)

r? ````@petrochenkov````
This commit is contained in:
Stuart Cook
2025-08-07 20:49:44 +10:00
committed by GitHub
9 changed files with 97 additions and 44 deletions

View File

@@ -66,7 +66,8 @@ pub use span_encoding::{DUMMY_SP, Span};
pub mod symbol;
pub use symbol::{
ByteSymbol, Ident, MacroRulesNormalizedIdent, STDLIB_STABLE_CRATES, Symbol, kw, sym,
ByteSymbol, Ident, MacroRulesNormalizedIdent, Macros20NormalizedIdent, STDLIB_STABLE_CRATES,
Symbol, kw, sym,
};
mod analyze_source_file;

View File

@@ -3,6 +3,7 @@
//! type, and vice versa.
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::{fmt, str};
use rustc_arena::DroplessArena;
@@ -2563,16 +2564,17 @@ impl fmt::Display for IdentPrinter {
}
/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on
/// construction.
// FIXME(matthewj, petrochenkov) Use this more often, add a similar
// `ModernIdent` struct and use that as well.
/// construction for "local variable hygiene" comparisons.
///
/// Use this type when you need to compare identifiers according to macro_rules hygiene.
/// This ensures compile-time safety and avoids manual normalization calls.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct MacroRulesNormalizedIdent(Ident);
impl MacroRulesNormalizedIdent {
#[inline]
pub fn new(ident: Ident) -> Self {
Self(ident.normalize_to_macro_rules())
MacroRulesNormalizedIdent(ident.normalize_to_macro_rules())
}
}
@@ -2588,6 +2590,48 @@ impl fmt::Display for MacroRulesNormalizedIdent {
}
}
/// An newtype around `Ident` that calls [Ident::normalize_to_macros_2_0] on
/// construction for "item hygiene" comparisons.
///
/// Identifiers with same string value become same if they came from the same macro 2.0 macro
/// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
/// different macro 2.0 macros.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Macros20NormalizedIdent(pub Ident);
impl Macros20NormalizedIdent {
#[inline]
pub fn new(ident: Ident) -> Self {
Macros20NormalizedIdent(ident.normalize_to_macros_2_0())
}
// dummy_span does not need to be normalized, so we can use `Ident` directly
pub fn with_dummy_span(name: Symbol) -> Self {
Macros20NormalizedIdent(Ident::with_dummy_span(name))
}
}
impl fmt::Debug for Macros20NormalizedIdent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl fmt::Display for Macros20NormalizedIdent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
/// By impl Deref, we can access the wrapped Ident as if it were a normal Ident
/// such as `norm_ident.name` instead of `norm_ident.0.name`.
impl Deref for Macros20NormalizedIdent {
type Target = Ident;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// An interned UTF-8 string.
///
/// Internally, a `Symbol` is implemented as an index, and all operations