Improve char escaping in lexer messages
Currently ', " and \ are escaped as \', \" and \\ respectively. This leads to confusing messages such as `error: unknown start of token: \\` when encountering a single backslash. Fix by emitting printable ASCII characters directly. This will still escape \r, \n, \t and Unicode characters. Fixes #47902
This commit is contained in:
@@ -246,14 +246,27 @@ impl<'a> StringReader<'a> {
|
|||||||
self.err_span(self.mk_sp(from_pos, to_pos), m)
|
self.err_span(self.mk_sp(from_pos, to_pos), m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes a character to a message string for error reporting
|
||||||
|
fn push_escaped_char_for_msg(m: &mut String, c: char) {
|
||||||
|
match c {
|
||||||
|
'\u{20}'...'\u{7e}' => {
|
||||||
|
// Don't escape \, ' or " for user-facing messages
|
||||||
|
m.push(c);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
for c in c.escape_default() {
|
||||||
|
m.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
|
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
|
||||||
/// escaped character to the error message
|
/// escaped character to the error message
|
||||||
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
|
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
|
||||||
let mut m = m.to_string();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
for c in c.escape_default() {
|
Self::push_escaped_char_for_msg(&mut m, c);
|
||||||
m.push(c)
|
|
||||||
}
|
|
||||||
self.fatal_span_(from_pos, to_pos, &m[..])
|
self.fatal_span_(from_pos, to_pos, &m[..])
|
||||||
}
|
}
|
||||||
fn struct_fatal_span_char(&self,
|
fn struct_fatal_span_char(&self,
|
||||||
@@ -264,9 +277,7 @@ impl<'a> StringReader<'a> {
|
|||||||
-> DiagnosticBuilder<'a> {
|
-> DiagnosticBuilder<'a> {
|
||||||
let mut m = m.to_string();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
for c in c.escape_default() {
|
Self::push_escaped_char_for_msg(&mut m, c);
|
||||||
m.push(c)
|
|
||||||
}
|
|
||||||
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
|
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,9 +286,7 @@ impl<'a> StringReader<'a> {
|
|||||||
fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
|
fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
|
||||||
let mut m = m.to_string();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
for c in c.escape_default() {
|
Self::push_escaped_char_for_msg(&mut m, c);
|
||||||
m.push(c)
|
|
||||||
}
|
|
||||||
self.err_span_(from_pos, to_pos, &m[..]);
|
self.err_span_(from_pos, to_pos, &m[..]);
|
||||||
}
|
}
|
||||||
fn struct_err_span_char(&self,
|
fn struct_err_span_char(&self,
|
||||||
@@ -288,9 +297,7 @@ impl<'a> StringReader<'a> {
|
|||||||
-> DiagnosticBuilder<'a> {
|
-> DiagnosticBuilder<'a> {
|
||||||
let mut m = m.to_string();
|
let mut m = m.to_string();
|
||||||
m.push_str(": ");
|
m.push_str(": ");
|
||||||
for c in c.escape_default() {
|
Self::push_escaped_char_for_msg(&mut m, c);
|
||||||
m.push(c)
|
|
||||||
}
|
|
||||||
self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
|
self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
// these literals are just silly.
|
// these literals are just silly.
|
||||||
''';
|
''';
|
||||||
//~^ ERROR: character constant must be escaped: \'
|
//~^ ERROR: character constant must be escaped: '
|
||||||
|
|
||||||
// note that this is a literal "\n" byte
|
// note that this is a literal "\n" byte
|
||||||
'
|
'
|
||||||
|
|||||||
13
src/test/parse-fail/lex-stray-backslash.rs
Normal file
13
src/test/parse-fail/lex-stray-backslash.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: -Z parse-only
|
||||||
|
|
||||||
|
\ //~ ERROR: unknown start of token: \
|
||||||
Reference in New Issue
Block a user