diff options
| -rw-r--r-- | compiler/rustc_ast/src/util/literal.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/build.rs | 43 |
2 files changed, 44 insertions, 33 deletions
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index a0a925d4700..4cc4b6367b4 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -8,6 +8,26 @@ use rustc_span::Span; use std::ascii; use std::str; +// 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 { + let s = symbol.as_str(); + let escaped = s.escape_default().to_string(); + if s == escaped { symbol } else { Symbol::intern(&escaped) } +} + +// Escapes a char. +pub fn escape_char_symbol(ch: char) -> Symbol { + let s: String = ch.escape_default().map(Into::<char>::into).collect(); + Symbol::intern(&s) +} + +// Escapes a byte string. +pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol { + let s = bytes.escape_ascii().to_string(); + Symbol::intern(&s) +} + #[derive(Debug)] pub enum LitError { LexerError, @@ -149,16 +169,11 @@ impl LitKind { pub fn synthesize_token_lit(&self) -> token::Lit { let (kind, symbol, suffix) = match *self { LitKind::Str(symbol, ast::StrStyle::Cooked) => { - // Don't re-intern unless the escaped string is different. - let s = symbol.as_str(); - let escaped = s.escape_default().to_string(); - let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) }; - (token::Str, symbol, None) + (token::Str, escape_string_symbol(symbol), None) } LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None), LitKind::ByteStr(ref bytes, ast::StrStyle::Cooked) => { - let string = bytes.escape_ascii().to_string(); - (token::ByteStr, Symbol::intern(&string), None) + (token::ByteStr, escape_byte_str_symbol(bytes), None) } LitKind::ByteStr(ref bytes, ast::StrStyle::Raw(n)) => { // Unwrap because raw byte string literals can only contain ASCII. @@ -169,10 +184,7 @@ impl LitKind { let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect(); (token::Byte, Symbol::intern(&string), None) } - LitKind::Char(ch) => { - let string: String = ch.escape_default().map(Into::<char>::into).collect(); - (token::Char, Symbol::intern(&string), None) - } + LitKind::Char(ch) => (token::Char, escape_char_symbol(ch), None), LitKind::Int(n, ty) => { let suffix = match ty { ast::LitIntType::Unsigned(ty) => Some(ty.name()), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index d8245ff613a..2fec24a1aec 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -1,8 +1,7 @@ use crate::base::ExtCtxt; -use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; -use rustc_data_structures::sync::Lrc; +use rustc_ast::{attr, token, util::literal}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -332,36 +331,36 @@ impl<'a> ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> { - let token_lit = lit_kind.synthesize_token_lit(); - self.expr(span, ast::ExprKind::Lit(token_lit)) + pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> { + let suffix = Some(ast::UintTy::Usize.name()); + let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> { - self.expr_lit( - span, - ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), - ) - } - - pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32))) + pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> { + let suffix = Some(ast::UintTy::U32.name()); + let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Bool(value)) + pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> { + let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) + pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> { + let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::Char(ch)) + pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> { + let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> { - self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes), ast::StrStyle::Cooked)) + pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> { + let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None); + self.expr(span, ast::ExprKind::Lit(lit)) } /// `[expr1, expr2, ...]` |
