pre-intern single-letter sym::[a-zA-Z]

This commit is contained in:
Pavel Grigorenko
2026-02-21 22:45:42 +03:00
parent 99246f4093
commit abcdef0640
10 changed files with 63 additions and 32 deletions
@@ -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:
+16 -6
View File
@@ -189,7 +189,14 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
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<syn::Error>) {
});
}
// 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<syn::Error>) {
}
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
@@ -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!(
+9 -9
View File
@@ -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();
@@ -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);
+26 -5
View File
@@ -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<N: TryInto<usize> + Copy + itoa::Integer>(n: N) -> Symbol {
let printed = buffer.format(n);
Symbol::intern(printed)
}
pub const fn ascii_letter_digit(c: char) -> Option<Symbol> {
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 {
+1 -1
View File
@@ -55,7 +55,7 @@ pub fn supported_types(
}
pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool {
target_features.contains(&sym::e)
target_features.contains(&sym::character('e'))
}
fn not_e(
@@ -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()
+3 -3
View File
@@ -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()
+1 -1
View File
@@ -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));