about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs17
-rw-r--r--src/test/ui/parser/char/whitespace-character-literal.rs3
-rw-r--r--src/test/ui/parser/char/whitespace-character-literal.stderr13
3 files changed, 24 insertions, 9 deletions
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 0f6594a2a7f..aa7ab4a953c 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -7,6 +7,10 @@ use rustc_errors::{pluralize, Applicability, Handler};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 
+fn printing(ch: char) -> bool {
+    unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) != 0 && !ch.is_whitespace()
+}
+
 pub(crate) fn emit_unescape_error(
     handler: &Handler,
     // interior part of the literal, without quotes
@@ -83,7 +87,11 @@ pub(crate) fn emit_unescape_error(
                     );
                 }
             } else {
-                if lit.chars().filter(|x| x.is_whitespace() || x.is_control()).count() >= 1 {
+                let printable: Vec<char> = lit.chars().filter(|x| printing(*x)).collect();
+
+                if let [ch] = printable.as_slice() {
+                    has_help = true;
+
                     handler.span_note(
                         span,
                         &format!(
@@ -91,6 +99,13 @@ pub(crate) fn emit_unescape_error(
                             lit.escape_default(),
                         ),
                     );
+
+                    handler.span_suggestion(
+                        span,
+                        "consider removing the non-printing characters",
+                        ch.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
 
diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs
index ecb5c3cf49e..de5e09204b4 100644
--- a/src/test/ui/parser/char/whitespace-character-literal.rs
+++ b/src/test/ui/parser/char/whitespace-character-literal.rs
@@ -2,8 +2,9 @@
 // characters in it contains a note about non-printing characters.
 
 fn main() {
-    // <hair space>x<zero width space>
     let _hair_space_around = ' x​';
     //~^ ERROR: character literal may only contain one codepoint
     //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}`
+    //~| HELP: consider removing the non-printing characters
+    //~| SUGGESTION: x
 }
diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr
index a12088ce77d..aa4fe4cf01f 100644
--- a/src/test/ui/parser/char/whitespace-character-literal.stderr
+++ b/src/test/ui/parser/char/whitespace-character-literal.stderr
@@ -1,18 +1,17 @@
+['x']
 error: character literal may only contain one codepoint
-  --> $DIR/whitespace-character-literal.rs:6:30
+  --> $DIR/whitespace-character-literal.rs:5:30
    |
 LL |     let _hair_space_around = ' x​';
-   |                              ^^^^
+   |                              ^--^
+   |                               |
+   |                               help: consider removing the non-printing characters: `x`
    |
 note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}`
-  --> $DIR/whitespace-character-literal.rs:6:31
+  --> $DIR/whitespace-character-literal.rs:5:31
    |
 LL |     let _hair_space_around = ' x​';
    |                               ^^
-help: if you meant to write a `str` literal, use double quotes
-   |
-LL |     let _hair_space_around = " x​";
-   |                              ~~~~
 
 error: aborting due to previous error