diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
commit | 218caa410aa38c29984be31a5229b9fa717560ee (patch) | |
tree | c54bd55eeb6e4c508940a30e94c0032fbd45d677 /compiler/rustc_ast/src/util | |
parent | Releasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ast/src/util')
-rw-r--r-- | compiler/rustc_ast/src/util/comments.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/literal.rs | 146 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/parser.rs | 2 |
3 files changed, 98 insertions, 52 deletions
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 35454c3a6..275ed02c2 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -51,7 +51,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { if i != 0 || j != lines.len() { Some((i, j)) } else { None } } - fn get_horizontal_trim<'a>(lines: &'a [&str], kind: CommentKind) -> Option<String> { + fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<String> { let mut i = usize::MAX; let mut first = true; diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index f6f186b51..74b842ac9 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -1,11 +1,31 @@ //! Code related to parsing literals. -use crate::ast::{self, LitKind, MetaItemLit}; +use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::token::{self, Token}; use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::ascii; +use std::{ascii, fmt, 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 { @@ -14,7 +34,7 @@ pub enum LitError { InvalidIntSuffix, InvalidFloatSuffix, NonDecimalFloat(u32), - IntTooLarge, + IntTooLarge(u32), } impl LitKind { @@ -115,9 +135,9 @@ impl LitKind { } }); error?; - LitKind::ByteStr(buf.into()) + LitKind::ByteStr(buf.into(), StrStyle::Cooked) } - token::ByteStrRaw(_) => { + token::ByteStrRaw(n) => { let s = symbol.as_str(); let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); @@ -136,69 +156,95 @@ impl LitKind { symbol.to_string().into_bytes() }; - LitKind::ByteStr(bytes.into()) + LitKind::ByteStr(bytes.into(), StrStyle::Raw(n)) } token::Err => LitKind::Err, }) } +} - /// Attempts to recover a token from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn to_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) - } - LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None), - LitKind::ByteStr(ref bytes) => { - let string = bytes.escape_ascii().to_string(); - (token::ByteStr, Symbol::intern(&string), None) +impl fmt::Display for LitKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + LitKind::Byte(b) => { + let b: String = ascii::escape_default(b).map(Into::<char>::into).collect(); + write!(f, "b'{b}'")?; } - LitKind::Byte(byte) => { - let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect(); - (token::Byte, Symbol::intern(&string), None) + LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?, + LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?, + LitKind::Str(sym, StrStyle::Raw(n)) => write!( + f, + "r{delim}\"{string}\"{delim}", + delim = "#".repeat(n as usize), + string = sym + )?, + LitKind::ByteStr(ref bytes, StrStyle::Cooked) => { + write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))? } - LitKind::Char(ch) => { - let string: String = ch.escape_default().map(Into::<char>::into).collect(); - (token::Char, Symbol::intern(&string), None) + LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => { + // Unwrap because raw byte string literals can only contain ASCII. + let symbol = str::from_utf8(bytes).unwrap(); + write!( + f, + "br{delim}\"{string}\"{delim}", + delim = "#".repeat(n as usize), + string = symbol + )?; } LitKind::Int(n, ty) => { - let suffix = match ty { - ast::LitIntType::Unsigned(ty) => Some(ty.name()), - ast::LitIntType::Signed(ty) => Some(ty.name()), - ast::LitIntType::Unsuffixed => None, - }; - (token::Integer, sym::integer(n), suffix) + write!(f, "{n}")?; + match ty { + ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?, + ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?, + ast::LitIntType::Unsuffixed => {} + } } LitKind::Float(symbol, ty) => { - let suffix = match ty { - ast::LitFloatType::Suffixed(ty) => Some(ty.name()), - ast::LitFloatType::Unsuffixed => None, - }; - (token::Float, symbol, suffix) + write!(f, "{symbol}")?; + match ty { + ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?, + ast::LitFloatType::Unsuffixed => {} + } } - LitKind::Bool(value) => { - let symbol = if value { kw::True } else { kw::False }; - (token::Bool, symbol, None) + LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?, + LitKind::Err => { + // This only shows up in places like `-Zunpretty=hir` output, so we + // don't bother to produce something useful. + write!(f, "<bad-literal>")?; } - // This only shows up in places like `-Zunpretty=hir` output, so we - // don't bother to produce something useful. - LitKind::Err => (token::Err, Symbol::intern("<bad-literal>"), None), - }; + } - token::Lit::new(kind, symbol, suffix) + Ok(()) } } impl MetaItemLit { - /// Converts token literal into a meta item literal. + /// Converts a token literal into a meta item literal. pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> { - Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) + Ok(MetaItemLit { + symbol: token_lit.symbol, + suffix: token_lit.suffix, + kind: LitKind::from_token_lit(token_lit)?, + span, + }) + } + + /// Cheaply converts a meta item literal into a token literal. + pub fn as_token_lit(&self) -> token::Lit { + let kind = match self.kind { + LitKind::Bool(_) => token::Bool, + LitKind::Str(_, ast::StrStyle::Cooked) => token::Str, + LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n), + LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr, + LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n), + LitKind::Byte(_) => token::Byte, + LitKind::Char(_) => token::Char, + LitKind::Int(..) => token::Integer, + LitKind::Float(..) => token::Float, + LitKind::Err => token::Err, + }; + + token::Lit::new(kind, self.symbol, self.suffix) } /// Converts an arbitrary token into meta item literal. @@ -287,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr // but these kinds of errors are already reported by the lexer. let from_lexer = base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge } + if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } }) } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 819f1884a..4f7099c7b 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -304,7 +304,7 @@ impl ExprPrecedence { | ExprPrecedence::Yeet => PREC_JUMP, // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to - // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence + // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence // ensures that `pprust` will add parentheses in the right places to get the desired // parse. ExprPrecedence::Range => PREC_RANGE, |