1 //! Utilities for rendering escape sequence errors as diagnostics.
6 use rustc_errors
::{Applicability, Handler}
;
7 use rustc_lexer
::unescape
::{EscapeError, Mode}
;
8 use rustc_span
::{BytePos, Span}
;
10 pub(crate) fn emit_unescape_error(
12 // interior part of the literal, without quotes
14 // full span of the literal, including quotes
15 span_with_quotes
: Span
,
17 // range of the error inside `lit`
22 "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}",
30 let Range { start, end }
= range
;
31 let (start
, end
) = (start
as u32, end
as u32);
32 let lo
= span_with_quotes
.lo() + BytePos(start
+ 1);
33 let hi
= lo
+ BytePos(end
- start
);
34 span_with_quotes
.with_lo(lo
).with_hi(hi
)
37 let c
= lit
[range
.clone()].chars().rev().next().unwrap();
38 let span
= span
.with_lo(span
.hi() - BytePos(c
.len_utf8() as u32));
42 EscapeError
::LoneSurrogateUnicodeEscape
=> {
44 .struct_span_err(span
, "invalid unicode character escape")
45 .help("unicode escape must not be a surrogate")
48 EscapeError
::OutOfRangeUnicodeEscape
=> {
50 .struct_span_err(span
, "invalid unicode character escape")
51 .help("unicode escape must be at most 10FFFF")
54 EscapeError
::MoreThanOneChar
=> {
55 let msg
= if mode
.is_bytes() {
56 "if you meant to write a byte string literal, use double quotes"
58 "if you meant to write a `str` literal, use double quotes"
64 "character literal may only contain one codepoint",
69 format
!("\"{}\"", lit
),
70 Applicability
::MachineApplicable
,
74 EscapeError
::EscapeOnlyChar
=> {
75 let (c
, _span
) = last_char();
77 let mut msg
= if mode
.is_bytes() {
78 "byte constant must be escaped: "
80 "character constant must be escaped: "
83 push_escaped_char(&mut msg
, c
);
85 handler
.span_err(span
, msg
.as_str())
87 EscapeError
::BareCarriageReturn
=> {
88 let msg
= if mode
.in_double_quotes() {
89 "bare CR not allowed in string, use \\r instead"
91 "character constant must be escaped: \\r"
93 handler
.span_err(span
, msg
);
95 EscapeError
::BareCarriageReturnInRawString
=> {
96 assert
!(mode
.in_double_quotes());
97 let msg
= "bare CR not allowed in raw string";
98 handler
.span_err(span
, msg
);
100 EscapeError
::InvalidEscape
=> {
101 let (c
, span
) = last_char();
104 if mode
.is_bytes() { "unknown byte escape" }
else { "unknown character escape" }
;
105 let mut msg
= label
.to_string();
107 push_escaped_char(&mut msg
, c
);
109 let mut diag
= handler
.struct_span_err(span
, msg
.as_str());
110 diag
.span_label(span
, label
);
111 if c
== '{' || c == '}'
&& !mode
.is_bytes() {
113 "if used in a formatting string, \
114 curly braces are escaped with `{{` and `}}`",
116 } else if c
== '
\r'
{
118 "this is an isolated carriage return; \
119 consider checking your editor and version control settings",
124 EscapeError
::TooShortHexEscape
=> {
125 handler
.span_err(span
, "numeric character escape is too short")
127 EscapeError
::InvalidCharInHexEscape
| EscapeError
::InvalidCharInUnicodeEscape
=> {
128 let (c
, span
) = last_char();
130 let mut msg
= if error
== EscapeError
::InvalidCharInHexEscape
{
131 "invalid character in numeric character escape: "
133 "invalid character in unicode escape: "
136 push_escaped_char(&mut msg
, c
);
138 handler
.span_err(span
, msg
.as_str())
140 EscapeError
::NonAsciiCharInByte
=> {
141 assert
!(mode
.is_bytes());
142 let (_c
, span
) = last_char();
145 "byte constant must be ASCII. \
146 Use a \\xHH escape for a non-ASCII byte",
149 EscapeError
::NonAsciiCharInByteString
=> {
150 assert
!(mode
.is_bytes());
151 let (_c
, span
) = last_char();
152 handler
.span_err(span
, "raw byte string must be ASCII")
154 EscapeError
::OutOfRangeHexEscape
=> handler
.span_err(
156 "this form of character escape may only be used \
157 with characters in the range [\\x00-\\x7f]",
159 EscapeError
::LeadingUnderscoreUnicodeEscape
=> {
160 let (_c
, span
) = last_char();
161 handler
.span_err(span
, "invalid start of unicode escape")
163 EscapeError
::OverlongUnicodeEscape
=> {
164 handler
.span_err(span
, "overlong unicode escape (must have at most 6 hex digits)")
166 EscapeError
::UnclosedUnicodeEscape
=> {
167 handler
.span_err(span
, "unterminated unicode escape (needed a `}`)")
169 EscapeError
::NoBraceInUnicodeEscape
=> {
170 let msg
= "incorrect unicode escape sequence";
171 let mut diag
= handler
.struct_span_err(span
, msg
);
173 let mut suggestion
= "\\u{".to_owned();
174 let mut suggestion_len
= 0;
175 let (c
, char_span
) = last_char();
176 let chars
= once(c
).chain(lit
[range
.end
..].chars());
177 for c
in chars
.take(6).take_while(|c
| c
.is_digit(16)) {
179 suggestion_len
+= c
.len_utf8();
182 if suggestion_len
> 0 {
183 suggestion
.push('
}'
);
184 let lo
= char_span
.lo();
185 let hi
= lo
+ BytePos(suggestion_len
as u32);
186 diag
.span_suggestion(
187 span
.with_lo(lo
).with_hi(hi
),
188 "format of unicode escape sequences uses braces",
190 Applicability
::MaybeIncorrect
,
193 diag
.span_label(span
, msg
);
194 diag
.help("format of unicode escape sequences is `\\u{...}`");
199 EscapeError
::UnicodeEscapeInByte
=> handler
.span_err(
201 "unicode escape sequences cannot be used \
202 as a byte or in a byte string",
204 EscapeError
::EmptyUnicodeEscape
=> {
205 handler
.span_err(span
, "empty unicode escape (must have at least 1 hex digit)")
207 EscapeError
::ZeroChars
=> handler
.span_err(span
, "empty character literal"),
208 EscapeError
::LoneSlash
=> handler
.span_err(span
, "invalid trailing slash in literal"),
212 /// Pushes a character to a message string for error reporting
213 pub(crate) fn push_escaped_char(msg
: &mut String
, c
: char) {
215 '
\u{20}'
..='
\u{7e}'
=> {
216 // Don't escape \, ' or " for user-facing messages
220 msg
.extend(c
.escape_default());