about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-17 15:58:02 +0100
committerGitHub <noreply@github.com>2021-11-17 15:58:02 +0100
commitab958a7ab0f65536fb921896a526ce81e4dee32d (patch)
tree1f5db2c39c2e8d6e96ed67cce55a4457d5e9cc03
parent904dba506640f290c182f5f6e717a82c6e5b8dae (diff)
parenteee29b0b95aedd9568df63a49340ca6efbf4bbb0 (diff)
downloadrust-ab958a7ab0f65536fb921896a526ce81e4dee32d.tar.gz
rust-ab958a7ab0f65536fb921896a526ce81e4dee32d.zip
Rollup merge of #90861 - 5225225:nonprinting-char, r=davidtwco
Print escaped string if char literal has multiple characters, but only one printable character

Fixes #90857

I'm not sure about the error message here, it could get rather long and *maybe* using the names of characters would be better? That wouldn't help the length any, though.
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs27
-rw-r--r--src/test/ui/parser/char/whitespace-character-literal.rs10
-rw-r--r--src/test/ui/parser/char/whitespace-character-literal.stderr16
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
4 files changed, 54 insertions, 1 deletions
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 569f186a727..7f68112a427 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -82,6 +82,33 @@ pub(crate) fn emit_unescape_error(
                         Applicability::MachineApplicable,
                     );
                 }
+            } else {
+                let printable: Vec<char> = lit
+                    .chars()
+                    .filter(|&x| {
+                        unicode_width::UnicodeWidthChar::width(x).unwrap_or(0) != 0
+                            && !x.is_whitespace()
+                    })
+                    .collect();
+
+                if let [ch] = printable.as_slice() {
+                    has_help = true;
+
+                    handler.span_note(
+                        span,
+                        &format!(
+                            "there are non-printing characters, the full sequence is `{}`",
+                            lit.escape_default(),
+                        ),
+                    );
+
+                    handler.span_suggestion(
+                        span,
+                        "consider removing the non-printing characters",
+                        ch.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             }
 
             if !has_help {
diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs
new file mode 100644
index 00000000000..de5e09204b4
--- /dev/null
+++ b/src/test/ui/parser/char/whitespace-character-literal.rs
@@ -0,0 +1,10 @@
+// This tests that the error generated when a character literal has multiple
+// characters in it contains a note about non-printing characters.
+
+fn main() {
+    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
new file mode 100644
index 00000000000..d73de41a809
--- /dev/null
+++ b/src/test/ui/parser/char/whitespace-character-literal.stderr
@@ -0,0 +1,16 @@
+error: character literal may only contain one codepoint
+  --> $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:5:31
+   |
+LL |     let _hair_space_around = ' x​';
+   |                               ^^
+
+error: aborting due to previous error
+
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index cc058d538f3..681b2486d07 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -9,7 +9,7 @@ const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 1102;
 const ISSUES_ENTRY_LIMIT: usize = 2310;
-const PARSER_LIMIT: usize = 1004;
+const PARSER_LIMIT: usize = 1005;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))