diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 48a2f19261f6..004b13bcc333 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_debug( name: sym::fmt, generics: Bounds::empty(), explicit_self: true, - nonself_args: vec![(fmtr, sym::f)], + nonself_args: vec![(fmtr, sym::character('f'))], ret_ty: Path(path_std!(fmt::Result)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index e3a70372110a..44cd63e57af4 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -189,7 +189,14 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let mut keyword_stream = quote! {}; let mut symbols_stream = quote! {}; let mut prefill_stream = quote! {}; - let mut entries = Entries::with_capacity(input.keywords.len() + input.symbols.len() + 10); + let prefill_ints = 0..=9; + let prefill_letters = ('A'..='Z').chain('a'..='z'); + let mut entries = Entries::with_capacity( + input.keywords.len() + + input.symbols.len() + + prefill_ints.clone().count() + + prefill_letters.clone().count(), + ); // Generate the listed keywords. for keyword in input.keywords.iter() { @@ -234,12 +241,11 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { }); } - // Generate symbols for the strings "0", "1", ..., "9". - for n in 0..10 { - let n = n.to_string(); - entries.insert(Span::call_site(), &n, &mut errors); + // Generate symbols for ascii letters and digits + for s in prefill_ints.map(|n| n.to_string()).chain(prefill_letters.map(|c| c.to_string())) { + entries.insert(Span::call_site(), &s, &mut errors); prefill_stream.extend(quote! { - #n, + #s, }); } @@ -285,9 +291,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { } let symbol_digits_base = entries.map["0"].idx; + let symbol_uppercase_letters_base = entries.map["A"].idx; + let symbol_lowercase_letters_base = entries.map["a"].idx; let predefined_symbols_count = entries.len(); let output = quote! { const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base; + const SYMBOL_UPPERCASE_LETTERS_BASE: u32 = #symbol_uppercase_letters_base; + const SYMBOL_LOWERCASE_LETTERS_BASE: u32 = #symbol_lowercase_letters_base; /// The number of predefined symbols; this is the first index for /// extra pre-interned symbols in an Interner created via diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f40969170a5b..284e651d94ad 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -647,7 +647,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String { // positive for a `cr#` that wasn't intended to start a c-string literal, but identifying // that in the parser requires unbounded lookahead, so we only add a hint to the existing // error rather than replacing it entirely. - if ((self.prev_token == TokenKind::Ident(sym::c, IdentIsRaw::No) + if ((self.prev_token == TokenKind::Ident(sym::character('c'), IdentIsRaw::No) && matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }))) || (self.prev_token == TokenKind::Ident(sym::cr, IdentIsRaw::No) && matches!( diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index f9c338445848..d43034645a6d 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2324,7 +2324,7 @@ fn string_to_tts_1() { let expected = TokenStream::new(vec![ TokenTree::token_alone(token::Ident(kw::Fn, IdentIsRaw::No), sp(0, 2)), TokenTree::token_joint_hidden( - token::Ident(Symbol::intern("a"), IdentIsRaw::No), + token::Ident(sym::character('a'), IdentIsRaw::No), sp(3, 4), ), TokenTree::Delimited( @@ -2335,7 +2335,7 @@ fn string_to_tts_1() { Delimiter::Parenthesis, TokenStream::new(vec![ TokenTree::token_joint( - token::Ident(Symbol::intern("b"), IdentIsRaw::No), + token::Ident(sym::character('b'), IdentIsRaw::No), sp(5, 6), ), TokenTree::token_alone(token::Colon, sp(6, 7)), @@ -2355,7 +2355,7 @@ fn string_to_tts_1() { Delimiter::Brace, TokenStream::new(vec![ TokenTree::token_joint( - token::Ident(Symbol::intern("b"), IdentIsRaw::No), + token::Ident(sym::character('b'), IdentIsRaw::No), sp(15, 16), ), // `Alone` because the `;` is followed by whitespace. @@ -2543,10 +2543,10 @@ fn look(p: &Parser<'_>, dist: usize, kind: rustc_ast::token::TokenKind) { #[test] fn look_ahead() { create_default_session_globals_then(|| { - let sym_f = Symbol::intern("f"); - let sym_x = Symbol::intern("x"); + let sym_f = sym::character('f'); + let sym_x = sym::character('x'); #[allow(non_snake_case)] - let sym_S = Symbol::intern("S"); + let sym_S = sym::character('S'); let raw_no = IdentIsRaw::No; let psess = ParseSess::new(); @@ -2618,10 +2618,10 @@ fn look_ahead() { #[test] fn look_ahead_non_outermost_stream() { create_default_session_globals_then(|| { - let sym_f = Symbol::intern("f"); - let sym_x = Symbol::intern("x"); + let sym_f = sym::character('f'); + let sym_x = sym::character('x'); #[allow(non_snake_case)] - let sym_S = Symbol::intern("S"); + let sym_S = sym::character('S'); let raw_no = IdentIsRaw::No; let psess = ParseSess::new(); diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs index 63177a727449..b54fdf6d8eaf 100644 --- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs +++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs @@ -2,7 +2,7 @@ use rustc_ast::token::{self, IdentIsRaw}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; -use rustc_span::{BytePos, Span, Symbol, create_default_session_globals_then}; +use rustc_span::{BytePos, Span, create_default_session_globals_then, sym}; use crate::parser::tests::string_to_stream; @@ -92,7 +92,7 @@ fn test_is_empty() { create_default_session_globals_then(|| { let test0 = TokenStream::default(); let test1 = - TokenStream::token_alone(token::Ident(Symbol::intern("a"), IdentIsRaw::No), sp(0, 1)); + TokenStream::token_alone(token::Ident(sym::character('a'), IdentIsRaw::No), sp(0, 1)); let test2 = string_to_ts("foo(bar::baz)"); assert_eq!(test0.is_empty(), true); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9e16ee115212..d17976ba9e8e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -189,7 +189,6 @@ BorrowMut, Break, BuildHasher, - C, CStr, CallOnceFuture, CallRefFuture, @@ -547,7 +546,6 @@ built, builtin_syntax, bundle, - c, c_dash_variadic, c_str_literals, c_unwind, @@ -751,7 +749,6 @@ custom_inner_attributes, custom_mir, custom_test_frameworks, - d, d32, dead_code, dealloc, @@ -845,7 +842,6 @@ dyn_star, dyn_trait, dynamic_no_pic: "dynamic-no-pic", - e, edition_panic, effective_target_features, effects, @@ -912,7 +908,6 @@ extern_weak, external, external_doc, - f, f16, f16_nan, f16c_target_feature, @@ -2770,6 +2765,15 @@ pub mod sym { #[doc(inline)] pub use super::sym_generated::*; + // Used quite often in relation to C ABI. + pub const C: Symbol = ascii_letter_digit('C').unwrap(); + + // RISC-V stuff + #[expect(non_upper_case_globals)] + pub const f: Symbol = ascii_letter_digit('f').unwrap(); + #[expect(non_upper_case_globals)] + pub const d: Symbol = ascii_letter_digit('d').unwrap(); + /// Get the symbol for an integer. /// /// The first few non-negative integers each have a static symbol and therefore @@ -2784,6 +2788,23 @@ pub fn integer + Copy + itoa::Integer>(n: N) -> Symbol { let printed = buffer.format(n); Symbol::intern(printed) } + + pub const fn ascii_letter_digit(c: char) -> Option { + let i = c as u32; + Option::Some(Symbol::new(match c { + '0'..='9' => super::SYMBOL_DIGITS_BASE + (i - '0' as u32), + 'A'..='Z' => super::SYMBOL_UPPERCASE_LETTERS_BASE + (i - 'A' as u32), + 'a'..='z' => super::SYMBOL_LOWERCASE_LETTERS_BASE + (i - 'a' as u32), + _ => return Option::None, + })) + } + + pub fn character(c: char) -> Symbol { + ascii_letter_digit(c).unwrap_or_else(|| { + let mut buf: [u8; char::MAX_LEN_UTF8] = Default::default(); + Symbol::intern(c.encode_utf8(&mut buf)) + }) + } } impl Symbol { diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index 97eb93335818..3976d9890256 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -55,7 +55,7 @@ pub fn supported_types( } pub(crate) fn is_e(target_features: &FxIndexSet) -> bool { - target_features.contains(&sym::e) + target_features.contains(&sym::character('e')) } fn not_e( diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 62ddbc344322..9a6cc3130340 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{ self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, }; -use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, kw}; +use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, kw, sym}; use tracing::{debug, instrument}; use super::ObligationCauseAsDiagArg; @@ -1431,9 +1431,9 @@ fn suggest_precise_capturing<'tcx>( }); } else { let mut next_fresh_param = || { - ["T", "U", "V", "W", "X", "Y", "A", "B", "C"] + ['T', 'U', 'V', 'W', 'X', 'Y', 'A', 'B', 'C'] .into_iter() - .map(Symbol::intern) + .map(sym::character) .chain((0..).map(|i| Symbol::intern(&format!("T{i}")))) .find(|s| captured_non_lifetimes.insert(*s)) .unwrap() diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 23234c208069..84000aab8748 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -12,7 +12,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt}; -use rustc_span::{BytePos, Ident, Span, Symbol, kw}; +use rustc_span::{BytePos, Ident, Span, Symbol, kw, sym}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; @@ -2062,9 +2062,9 @@ pub fn impl_trait_overcapture_suggestion<'tcx>( } let mut next_fresh_param = || { - ["T", "U", "V", "W", "X", "Y", "A", "B", "C"] + ['T', 'U', 'V', 'W', 'X', 'Y', 'A', 'B', 'C'] .into_iter() - .map(Symbol::intern) + .map(sym::character) .chain((0..).map(|i| Symbol::intern(&format!("T{i}")))) .find(|s| captured_non_lifetimes.insert(*s)) .unwrap() diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs index 10a3857878c8..a0fc623c20c4 100644 --- a/src/librustdoc/clean/types/tests.rs +++ b/src/librustdoc/clean/types/tests.rs @@ -75,7 +75,7 @@ fn is_same_generic() { use crate::formats::cache::Cache; create_default_session_globals_then(|| { let cache = Cache::new(false, false); - let generic = Type::Generic(Symbol::intern("T")); + let generic = Type::Generic(sym::character('T')); let unit = Type::Primitive(PrimitiveType::Unit); assert!(!generic.is_doc_subtype_of(&unit, &cache)); assert!(unit.is_doc_subtype_of(&generic, &cache));