1
Fork 0

Rename the unescaping functions.

`unescape_literal` becomes `unescape_unicode`, and `unescape_c_string`
becomes `unescape_mixed`. Because rfc3349 will mean that C string
literals will no longer be the only mixed utf8 literals.
This commit is contained in:
Nicholas Nethercote 2024-01-24 15:24:58 +11:00
parent 5e5aa6d556
commit 86f371ed59
9 changed files with 45 additions and 42 deletions

View file

@ -3,8 +3,7 @@
use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
use crate::token::{self, Token}; use crate::token::{self, Token};
use rustc_lexer::unescape::{ use rustc_lexer::unescape::{
byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
Mode,
}; };
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span; use rustc_span::Span;
@ -85,7 +84,7 @@ impl LitKind {
// Force-inlining here is aggressive but the closure is // Force-inlining here is aggressive but the closure is
// called on every char in the string, so it can be hot in // called on every char in the string, so it can be hot in
// programs with many long strings containing escapes. // programs with many long strings containing escapes.
unescape_literal( unescape_unicode(
s, s,
Mode::Str, Mode::Str,
&mut #[inline(always)] &mut #[inline(always)]
@ -109,7 +108,7 @@ impl LitKind {
token::ByteStr => { token::ByteStr => {
let s = symbol.as_str(); let s = symbol.as_str();
let mut buf = Vec::with_capacity(s.len()); let mut buf = Vec::with_capacity(s.len());
unescape_literal(s, Mode::ByteStr, &mut |_, c| match c { unescape_unicode(s, Mode::ByteStr, &mut |_, c| match c {
Ok(c) => buf.push(byte_from_char(c)), Ok(c) => buf.push(byte_from_char(c)),
Err(err) => { Err(err) => {
assert!(!err.is_fatal(), "failed to unescape string literal") assert!(!err.is_fatal(), "failed to unescape string literal")
@ -126,7 +125,7 @@ impl LitKind {
token::CStr => { token::CStr => {
let s = symbol.as_str(); let s = symbol.as_str();
let mut buf = Vec::with_capacity(s.len()); let mut buf = Vec::with_capacity(s.len());
unescape_c_string(s, Mode::CStr, &mut |_span, c| match c { unescape_mixed(s, Mode::CStr, &mut |_span, c| match c {
Ok(MixedUnit::Char(c)) => { Ok(MixedUnit::Char(c)) => {
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
} }

View file

@ -80,12 +80,12 @@ impl EscapeError {
} }
} }
/// Takes a contents of a literal (without quotes) and produces a sequence of /// Takes the contents of a unicode-only (non-mixed-utf8) literal (without
/// escaped characters or errors. /// quotes) and produces a sequence of escaped characters or errors.
/// ///
/// Values are returned by invoking `callback`. For `Char` and `Byte` modes, /// Values are returned by invoking `callback`. For `Char` and `Byte` modes,
/// the callback will be called exactly once. /// the callback will be called exactly once.
pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F) pub fn unescape_unicode<F>(src: &str, mode: Mode, callback: &mut F)
where where
F: FnMut(Range<usize>, Result<char, EscapeError>), F: FnMut(Range<usize>, Result<char, EscapeError>),
{ {
@ -132,7 +132,11 @@ impl From<u8> for MixedUnit {
} }
} }
pub fn unescape_c_string<F>(src: &str, mode: Mode, callback: &mut F) /// Takes the contents of a mixed-utf8 literal (without quotes) and produces
/// a sequence of escaped characters or errors.
///
/// Values are returned by invoking `callback`.
pub fn unescape_mixed<F>(src: &str, mode: Mode, callback: &mut F)
where where
F: FnMut(Range<usize>, Result<MixedUnit, EscapeError>), F: FnMut(Range<usize>, Result<MixedUnit, EscapeError>),
{ {

View file

@ -100,7 +100,7 @@ fn test_unescape_char_good() {
fn test_unescape_str_warn() { fn test_unescape_str_warn() {
fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) { fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
let mut unescaped = Vec::with_capacity(literal.len()); let mut unescaped = Vec::with_capacity(literal.len());
unescape_literal(literal, Mode::Str, &mut |range, res| unescaped.push((range, res))); unescape_unicode(literal, Mode::Str, &mut |range, res| unescaped.push((range, res)));
assert_eq!(unescaped, expected); assert_eq!(unescaped, expected);
} }
@ -124,7 +124,7 @@ fn test_unescape_str_warn() {
fn test_unescape_str_good() { fn test_unescape_str_good() {
fn check(literal_text: &str, expected: &str) { fn check(literal_text: &str, expected: &str) {
let mut buf = Ok(String::with_capacity(literal_text.len())); let mut buf = Ok(String::with_capacity(literal_text.len()));
unescape_literal(literal_text, Mode::Str, &mut |range, c| { unescape_unicode(literal_text, Mode::Str, &mut |range, c| {
if let Ok(b) = &mut buf { if let Ok(b) = &mut buf {
match c { match c {
Ok(c) => b.push(c), Ok(c) => b.push(c),
@ -241,7 +241,7 @@ fn test_unescape_byte_good() {
fn test_unescape_byte_str_good() { fn test_unescape_byte_str_good() {
fn check(literal_text: &str, expected: &[u8]) { fn check(literal_text: &str, expected: &[u8]) {
let mut buf = Ok(Vec::with_capacity(literal_text.len())); let mut buf = Ok(Vec::with_capacity(literal_text.len()));
unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| { unescape_unicode(literal_text, Mode::ByteStr, &mut |range, c| {
if let Ok(b) = &mut buf { if let Ok(b) = &mut buf {
match c { match c {
Ok(c) => b.push(byte_from_char(c)), Ok(c) => b.push(byte_from_char(c)),
@ -264,7 +264,7 @@ fn test_unescape_byte_str_good() {
fn test_unescape_raw_str() { fn test_unescape_raw_str() {
fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) { fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
let mut unescaped = Vec::with_capacity(literal.len()); let mut unescaped = Vec::with_capacity(literal.len());
unescape_literal(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res))); unescape_unicode(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res)));
assert_eq!(unescaped, expected); assert_eq!(unescaped, expected);
} }
@ -276,7 +276,7 @@ fn test_unescape_raw_str() {
fn test_unescape_raw_byte_str() { fn test_unescape_raw_byte_str() {
fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) { fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
let mut unescaped = Vec::with_capacity(literal.len()); let mut unescaped = Vec::with_capacity(literal.len());
unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res))); unescape_unicode(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
assert_eq!(unescaped, expected); assert_eq!(unescaped, expected);
} }

View file

@ -400,7 +400,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
.with_code(error_code!(E0762)) .with_code(error_code!(E0762))
.emit() .emit()
} }
self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' ' self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' '
} }
rustc_lexer::LiteralKind::Byte { terminated } => { rustc_lexer::LiteralKind::Byte { terminated } => {
if !terminated { if !terminated {
@ -412,7 +412,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
.with_code(error_code!(E0763)) .with_code(error_code!(E0763))
.emit() .emit()
} }
self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' self.cook_unicode(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
} }
rustc_lexer::LiteralKind::Str { terminated } => { rustc_lexer::LiteralKind::Str { terminated } => {
if !terminated { if !terminated {
@ -424,7 +424,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
.with_code(error_code!(E0765)) .with_code(error_code!(E0765))
.emit() .emit()
} }
self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " " self.cook_unicode(token::Str, Mode::Str, start, end, 1, 1) // " "
} }
rustc_lexer::LiteralKind::ByteStr { terminated } => { rustc_lexer::LiteralKind::ByteStr { terminated } => {
if !terminated { if !terminated {
@ -436,7 +436,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
.with_code(error_code!(E0766)) .with_code(error_code!(E0766))
.emit() .emit()
} }
self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " self.cook_unicode(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
} }
rustc_lexer::LiteralKind::CStr { terminated } => { rustc_lexer::LiteralKind::CStr { terminated } => {
if !terminated { if !terminated {
@ -448,13 +448,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
.with_code(error_code!(E0767)) .with_code(error_code!(E0767))
.emit() .emit()
} }
self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" " self.cook_mixed(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
} }
rustc_lexer::LiteralKind::RawStr { n_hashes } => { rustc_lexer::LiteralKind::RawStr { n_hashes } => {
if let Some(n_hashes) = n_hashes { if let Some(n_hashes) = n_hashes {
let n = u32::from(n_hashes); let n = u32::from(n_hashes);
let kind = token::StrRaw(n_hashes); let kind = token::StrRaw(n_hashes);
self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "## self.cook_unicode(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "##
} else { } else {
self.report_raw_str_error(start, 1); self.report_raw_str_error(start, 1);
} }
@ -463,7 +463,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
if let Some(n_hashes) = n_hashes { if let Some(n_hashes) = n_hashes {
let n = u32::from(n_hashes); let n = u32::from(n_hashes);
let kind = token::ByteStrRaw(n_hashes); let kind = token::ByteStrRaw(n_hashes);
self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "## self.cook_unicode(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "##
} else { } else {
self.report_raw_str_error(start, 2); self.report_raw_str_error(start, 2);
} }
@ -472,7 +472,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
if let Some(n_hashes) = n_hashes { if let Some(n_hashes) = n_hashes {
let n = u32::from(n_hashes); let n = u32::from(n_hashes);
let kind = token::CStrRaw(n_hashes); let kind = token::CStrRaw(n_hashes);
self.cook_c_string(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "## self.cook_mixed(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "##
} else { } else {
self.report_raw_str_error(start, 2); self.report_raw_str_error(start, 2);
} }
@ -735,7 +735,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
} }
} }
fn cook_quoted( fn cook_unicode(
&self, &self,
kind: token::LitKind, kind: token::LitKind,
mode: Mode, mode: Mode,
@ -745,13 +745,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
postfix_len: u32, postfix_len: u32,
) -> (token::LitKind, Symbol) { ) -> (token::LitKind, Symbol) {
self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
unescape::unescape_literal(src, mode, &mut |span, result| { unescape::unescape_unicode(src, mode, &mut |span, result| {
callback(span, result.map(drop)) callback(span, result.map(drop))
}) })
}) })
} }
fn cook_c_string( fn cook_mixed(
&self, &self,
kind: token::LitKind, kind: token::LitKind,
mode: Mode, mode: Mode,
@ -761,7 +761,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
postfix_len: u32, postfix_len: u32,
) -> (token::LitKind, Symbol) { ) -> (token::LitKind, Symbol) {
self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| { self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
unescape::unescape_c_string(src, mode, &mut |span, result| { unescape::unescape_mixed(src, mode, &mut |span, result| {
callback(span, result.map(drop)) callback(span, result.map(drop))
}) })
}) })

View file

@ -1056,7 +1056,7 @@ fn find_width_map_from_snippet(
fn unescape_string(string: &str) -> Option<string::String> { fn unescape_string(string: &str) -> Option<string::String> {
let mut buf = string::String::new(); let mut buf = string::String::new();
let mut ok = true; let mut ok = true;
unescape::unescape_literal(string, unescape::Mode::Str, &mut |_, unescaped_char| { unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| {
match unescaped_char { match unescaped_char {
Ok(c) => buf.push(c), Ok(c) => buf.push(c),
Err(_) => ok = false, Err(_) => ok = false,

View file

@ -928,7 +928,7 @@ fn remove_line_splices(s: &str) -> String {
.and_then(|s| s.strip_suffix('"')) .and_then(|s| s.strip_suffix('"'))
.unwrap_or_else(|| panic!("expected quoted string, found `{s}`")); .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
let mut res = String::with_capacity(s.len()); let mut res = String::with_capacity(s.len());
unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| { unescape::unescape_unicode(s, unescape::Mode::Str, &mut |range, ch| {
if ch.is_ok() { if ch.is_ok() {
res.push_str(&s[range]); res.push_str(&s[range]);
} }

View file

@ -379,14 +379,14 @@ fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str {
let mut error_message = ""; let mut error_message = "";
match mode { match mode {
Mode::CStr => { Mode::CStr => {
rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { rustc_lexer::unescape::unescape_mixed(text, mode, &mut |_, res| {
if let Err(e) = res { if let Err(e) = res {
error_message = error_to_diagnostic_message(e, mode); error_message = error_to_diagnostic_message(e, mode);
} }
}); });
} }
Mode::ByteStr | Mode::Str => { Mode::ByteStr | Mode::Str => {
rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| { rustc_lexer::unescape::unescape_unicode(text, mode, &mut |_, res| {
if let Err(e) = res { if let Err(e) = res {
error_message = error_to_diagnostic_message(e, mode); error_message = error_to_diagnostic_message(e, mode);
} }

View file

@ -6,7 +6,7 @@ use std::{
}; };
use rustc_lexer::unescape::{ use rustc_lexer::unescape::{
unescape_byte, unescape_c_string, unescape_char, unescape_literal, MixedUnit, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
}; };
use crate::{ use crate::{
@ -193,7 +193,7 @@ pub trait IsString: AstToken {
let text = &self.text()[text_range_no_quotes - start]; let text = &self.text()[text_range_no_quotes - start];
let offset = text_range_no_quotes.start() - start; let offset = text_range_no_quotes.start() - start;
unescape_literal(text, Self::MODE, &mut |range, unescaped_char| { unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| {
let text_range = let text_range =
TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
cb(text_range + offset, unescaped_char); cb(text_range + offset, unescaped_char);
@ -226,7 +226,7 @@ impl ast::String {
let mut buf = String::new(); let mut buf = String::new();
let mut prev_end = 0; let mut prev_end = 0;
let mut has_error = false; let mut has_error = false;
unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
unescaped_char, unescaped_char,
buf.capacity() == 0, buf.capacity() == 0,
) { ) {
@ -270,7 +270,7 @@ impl ast::ByteString {
let mut buf: Vec<u8> = Vec::new(); let mut buf: Vec<u8> = Vec::new();
let mut prev_end = 0; let mut prev_end = 0;
let mut has_error = false; let mut has_error = false;
unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match ( unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
unescaped_char, unescaped_char,
buf.capacity() == 0, buf.capacity() == 0,
) { ) {
@ -311,7 +311,7 @@ impl IsString for ast::CString {
let text = &self.text()[text_range_no_quotes - start]; let text = &self.text()[text_range_no_quotes - start];
let offset = text_range_no_quotes.start() - start; let offset = text_range_no_quotes.start() - start;
unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| { unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| {
let text_range = let text_range =
TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap()); TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
// XXX: This method should only be used for highlighting ranges. The unescaped // XXX: This method should only be used for highlighting ranges. The unescaped
@ -340,7 +340,7 @@ impl ast::CString {
MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()), MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()),
MixedUnit::HighByte(b) => buf.push(b), MixedUnit::HighByte(b) => buf.push(b),
}; };
unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match ( unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match (
unescaped, unescaped,
buf.capacity() == 0, buf.capacity() == 0,
) { ) {

View file

@ -5,7 +5,7 @@
mod block; mod block;
use rowan::Direction; use rowan::Direction;
use rustc_lexer::unescape::{self, unescape_c_string, unescape_literal, Mode}; use rustc_lexer::unescape::{self, unescape_mixed, unescape_unicode, Mode};
use crate::{ use crate::{
algo, algo,
@ -140,7 +140,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
ast::LiteralKind::String(s) => { ast::LiteralKind::String(s) => {
if !s.is_raw() { if !s.is_raw() {
if let Some(without_quotes) = unquote(text, 1, '"') { if let Some(without_quotes) = unquote(text, 1, '"') {
unescape_literal(without_quotes, Mode::Str, &mut |range, char| { unescape_unicode(without_quotes, Mode::Str, &mut |range, char| {
if let Err(err) = char { if let Err(err) = char {
push_err(1, range.start, err); push_err(1, range.start, err);
} }
@ -151,7 +151,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
ast::LiteralKind::ByteString(s) => { ast::LiteralKind::ByteString(s) => {
if !s.is_raw() { if !s.is_raw() {
if let Some(without_quotes) = unquote(text, 2, '"') { if let Some(without_quotes) = unquote(text, 2, '"') {
unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| {
if let Err(err) = char { if let Err(err) = char {
push_err(1, range.start, err); push_err(1, range.start, err);
} }
@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
ast::LiteralKind::CString(s) => { ast::LiteralKind::CString(s) => {
if !s.is_raw() { if !s.is_raw() {
if let Some(without_quotes) = unquote(text, 2, '"') { if let Some(without_quotes) = unquote(text, 2, '"') {
unescape_c_string(without_quotes, Mode::CStr, &mut |range, char| { unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| {
if let Err(err) = char { if let Err(err) = char {
push_err(1, range.start, err); push_err(1, range.start, err);
} }
@ -172,7 +172,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
} }
ast::LiteralKind::Char(_) => { ast::LiteralKind::Char(_) => {
if let Some(without_quotes) = unquote(text, 1, '\'') { if let Some(without_quotes) = unquote(text, 1, '\'') {
unescape_literal(without_quotes, Mode::Char, &mut |range, char| { unescape_unicode(without_quotes, Mode::Char, &mut |range, char| {
if let Err(err) = char { if let Err(err) = char {
push_err(1, range.start, err); push_err(1, range.start, err);
} }
@ -181,7 +181,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
} }
ast::LiteralKind::Byte(_) => { ast::LiteralKind::Byte(_) => {
if let Some(without_quotes) = unquote(text, 2, '\'') { if let Some(without_quotes) = unquote(text, 2, '\'') {
unescape_literal(without_quotes, Mode::Byte, &mut |range, char| { unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| {
if let Err(err) = char { if let Err(err) = char {
push_err(2, range.start, err); push_err(2, range.start, err);
} }