about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-12-27 10:40:06 -0800
committerEsteban Küber <esteban@kuber.com.ar>2018-12-31 09:44:58 -0800
commit7edc434b72e6e1b46b625c3019e8227dc7a8e2e8 (patch)
tree8b0f0c980ee8b58b8f79bf3ca684030ac47d2c8b
parent433ef826f001652f13ecff3697c2233fbe1ce4e2 (diff)
downloadrust-7edc434b72e6e1b46b625c3019e8227dc7a8e2e8.tar.gz
rust-7edc434b72e6e1b46b625c3019e8227dc7a8e2e8.zip
Account for `\xFF` and `\u{FF}` sequences in string format errors
-rw-r--r--src/libsyntax_ext/format.rs45
-rw-r--r--src/test/ui/fmt/format-string-error-2.rs15
-rw-r--r--src/test/ui/fmt/format-string-error-2.stderr48
3 files changed, 107 insertions, 1 deletions
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index ac1402a0faa..3a5f0ec07e7 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -808,12 +808,57 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
                 }
                 ('\\', Some((next_pos, 'n'))) |
                 ('\\', Some((next_pos, 't'))) |
+                ('\\', Some((next_pos, '0'))) |
                 ('\\', Some((next_pos, '\\'))) |
                 ('\\', Some((next_pos, '\''))) |
                 ('\\', Some((next_pos, '\"'))) => {
                     skips.push(*next_pos);
                     let _ = s.next();
                 }
+                ('\\', Some((_, 'x'))) if !is_raw => {
+                    for _ in 0..3 {  // consume `\xAB` literal
+                        if let Some((pos, _)) = s.next() {
+                            skips.push(pos);
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                ('\\', Some((_, 'u'))) if !is_raw => {
+                    if let Some((pos, _)) = s.next() {
+                        skips.push(pos);
+                    }
+                    if let Some((next_pos, next_c)) = s.next() {
+                        if next_c == '{' {
+                            skips.push(next_pos);
+                            let mut i = 0;  // consume up to 6 hexanumeric chars + closing `}`
+                            while let (Some((next_pos, c)), true) = (s.next(), i < 7) {
+                                if c.is_digit(16) {
+                                    skips.push(next_pos);
+                                } else if c == '}' {
+                                    skips.push(next_pos);
+                                    break;
+                                } else {
+                                    break;
+                                }
+                                i += 1;
+                            }
+                        } else if next_c.is_digit(16) {
+                            skips.push(next_pos);
+                            // We suggest adding `{` and `}` when appropriate, accept it here as if it
+                            // were correct
+                            let mut i = 0;  // consume up to 6 hexanumeric chars
+                            while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
+                                if c.is_digit(16) {
+                                    skips.push(next_pos);
+                                } else {
+                                    break;
+                                }
+                                i += 1;
+                            }
+                        }
+                    }
+                }
                 _ if eat_ws => {  // `take_while(|c| c.is_whitespace())`
                     eat_ws = false;
                 }
diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs
index 3c6c15c06bb..5c25ae502ff 100644
--- a/src/test/ui/fmt/format-string-error-2.rs
+++ b/src/test/ui/fmt/format-string-error-2.rs
@@ -69,4 +69,19 @@ raw  { \n
     //~^^ ERROR invalid format string
     println!("\t{}");
     //~^ ERROR 1 positional argument in format string
+
+    // note: `\x7B` is `{`
+    println!("\x7B}\u{8} {", 1);
+    //~^ ERROR invalid format string: expected `'}'` but string was terminated
+
+    println!("\x7B}\u8 {", 1);
+    //~^ ERROR incorrect unicode escape sequence
+    //~| ERROR argument never used
+
+    // note: raw strings don't escape `\xFF` and `\u{FF}` sequences
+    println!(r#"\x7B}\u{8} {"#, 1);
+    //~^ ERROR invalid format string: unmatched `}` found
+
+    println!(r#"\x7B}\u8 {"#, 1);
+    //~^ ERROR invalid format string: unmatched `}` found
 }
diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr
index face0bc0f5f..ae62ed66338 100644
--- a/src/test/ui/fmt/format-string-error-2.stderr
+++ b/src/test/ui/fmt/format-string-error-2.stderr
@@ -1,3 +1,15 @@
+error: incorrect unicode escape sequence
+  --> $DIR/format-string-error-2.rs:77:20
+   |
+LL |     println!("/x7B}/u8 {", 1);
+   |                    ^^
+   |
+help: format of unicode escape sequences is `/u{…}`
+  --> $DIR/format-string-error-2.rs:77:20
+   |
+LL |     println!("/x7B}/u8 {", 1);
+   |                    ^^
+
 error: invalid format string: expected `'}'`, found `'a'`
   --> $DIR/format-string-error-2.rs:5:5
    |
@@ -139,5 +151,39 @@ error: 1 positional argument in format string, but no arguments were given
 LL |     println!("/t{}");
    |                 ^^
 
-error: aborting due to 14 previous errors
+error: invalid format string: expected `'}'` but string was terminated
+  --> $DIR/format-string-error-2.rs:74:27
+   |
+LL |     println!("/x7B}/u{8} {", 1);
+   |                          -^ expected `'}'` in format string
+   |                          |
+   |                          because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: argument never used
+  --> $DIR/format-string-error-2.rs:77:28
+   |
+LL |     println!("/x7B}/u8 {", 1);
+   |              ------------  ^ argument never used
+   |              |
+   |              formatting specifier missing
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error-2.rs:82:21
+   |
+LL |     println!(r#"/x7B}/u{8} {"#, 1);
+   |                     ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+  --> $DIR/format-string-error-2.rs:85:21
+   |
+LL |     println!(r#"/x7B}/u8 {"#, 1);
+   |                     ^ unmatched `}` in format string
+   |
+   = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 19 previous errors