diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2016-11-12 10:38:42 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-12 10:38:42 +0200 |
| commit | 048daa62246abc5dd441c34ffd2834cb6e173060 (patch) | |
| tree | a38e3b75c73b28708201e08b37268499879998a8 | |
| parent | 5439cb5bdc7557f20a9dbedb57a636da68445440 (diff) | |
| parent | 3c17abc4d955080baa410e9b697bf5be37b0d079 (diff) | |
| download | rust-048daa62246abc5dd441c34ffd2834cb6e173060.tar.gz rust-048daa62246abc5dd441c34ffd2834cb6e173060.zip | |
Rollup merge of #37695 - estebank:unescaped-curly, r=alexcrichton
On fmt string with unescaped `{` note how to escape
On cases of malformed format strings where a `{` hasn't been properly escaped, like `println!("{");`, present a NOTE explaining how to escape the `{` char.
Fix #34300.
| -rw-r--r-- | src/libfmt_macros/lib.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax_ext/format.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/fmt/format-string-error.rs | 16 | ||||
| -rw-r--r-- | src/test/ui/fmt/format-string-error.stderr | 20 |
4 files changed, 61 insertions, 6 deletions
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index e7d401f0929..b179a16e55e 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -139,7 +139,7 @@ pub struct Parser<'a> { input: &'a str, cur: iter::Peekable<str::CharIndices<'a>>, /// Error messages accumulated during parsing - pub errors: Vec<string::String>, + pub errors: Vec<(string::String, Option<string::String>)>, /// Current position of implicit positional argument pointer curarg: usize, } @@ -165,7 +165,9 @@ impl<'a> Iterator for Parser<'a> { if self.consume('}') { Some(String(self.string(pos + 1))) } else { - self.err("unmatched `}` found"); + self.err_with_note("unmatched `}` found", + "if you intended to print `}`, \ + you can escape it using `}}`"); None } } @@ -192,7 +194,14 @@ impl<'a> Parser<'a> { /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. fn err(&mut self, msg: &str) { - self.errors.push(msg.to_owned()); + self.errors.push((msg.to_owned(), None)); + } + + /// Notifies of an error. The message doesn't actually need to be of type + /// String, but I think it does when this eventually uses conditions so it + /// might as well start using it now. + fn err_with_note(&mut self, msg: &str, note: &str) { + self.errors.push((msg.to_owned(), Some(note.to_owned()))); } /// Optionally consumes the specified character. If the character is not at @@ -222,7 +231,13 @@ impl<'a> Parser<'a> { self.err(&format!("expected `{:?}`, found `{:?}`", c, maybe)); } } else { - self.err(&format!("expected `{:?}` but string was terminated", c)); + let msg = &format!("expected `{:?}` but string was terminated", c); + if c == '}' { + self.err_with_note(msg, + "if you intended to print `{`, you can escape it using `{{`"); + } else { + self.err(msg); + } } } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 117bb39f8e7..6eba8baf5b8 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -756,8 +756,12 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } if !parser.errors.is_empty() { - cx.ecx.span_err(cx.fmtsp, - &format!("invalid format string: {}", parser.errors.remove(0))); + let (err, note) = parser.errors.remove(0); + let mut e = cx.ecx.struct_span_err(cx.fmtsp, &format!("invalid format string: {}", err)); + if let Some(note) = note { + e.note(¬e); + } + e.emit(); return DummyResult::raw_expr(sp); } if !cx.literal.is_empty() { diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs new file mode 100644 index 00000000000..ec715b3f0ba --- /dev/null +++ b/src/test/ui/fmt/format-string-error.rs @@ -0,0 +1,16 @@ +// Copyright 2016 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. + +fn main() { + println!("{"); + println!("{{}}"); + println!("}"); +} + diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr new file mode 100644 index 00000000000..58b392f0b8d --- /dev/null +++ b/src/test/ui/fmt/format-string-error.stderr @@ -0,0 +1,20 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:12:5 + | +12 | println!("{"); + | ^^^^^^^^^^^^^^ + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in a macro outside of the current crate + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:14:5 + | +14 | println!("}"); + | ^^^^^^^^^^^^^^ + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in a macro outside of the current crate + +error: aborting due to 2 previous errors + |
