From bfe8ccb68d88b5cc2007d8cfbc3f365abfae4fd0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 20 Jul 2026 17:07:45 +0200 Subject: [PATCH] Optimize escape_string_symbol() --- compiler/rustc_ast/src/util/literal.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index e9cf3cf07372e..0984702aa7c39 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -1,5 +1,6 @@ //! Code related to parsing literals. +use std::fmt::Write as _; use std::{ascii, fmt, str}; use rustc_literal_escaper::{ @@ -14,8 +15,22 @@ use crate::token::{self, Token}; // Escapes a string, represented as a symbol. Reuses the original symbol, // avoiding interning, if no changes are required. pub fn escape_string_symbol(symbol: Symbol) -> Symbol { + // Don't use escape_default() here, because using it in conjunction with to_string() + // is slow. let s = symbol.as_str(); - let escaped = s.escape_default().to_string(); + let mut escaped = String::with_capacity(s.len()); + for c in s.chars() { + match c { + '\t' => escaped.push_str("\\t"), + '\r' => escaped.push_str("\\r"), + '\n' => escaped.push_str("\\n"), + '\\' => escaped.push_str("\\\\"), + '\'' => escaped.push_str("\\'"), + '\"' => escaped.push_str("\\\""), + '\x20'..='\x7e' => escaped.push(c), + c => write!(escaped, "\\u{{{:x}}}", c as u32).unwrap(), + } + } if s == escaped { symbol } else { Symbol::intern(&escaped) } }