From f53c145ef18db6543e8e5420e172e04b6054db2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Jul 2018 20:50:30 -0700 Subject: [PATCH 01/19] Improve suggestion for missing fmt str in println Avoid using `concat!(fmt, "\n")` to improve the diagnostics being emitted when the first `println!()` argument isn't a formatting string literal. --- src/libstd/macros.rs | 10 ++++- src/libsyntax/ext/base.rs | 25 ++++++----- src/libsyntax_ext/concat.rs | 15 +++---- src/libsyntax_ext/format.rs | 28 +++++++++--- .../conditional_array_execution.nll.stderr | 14 ++---- src/test/ui/const-eval/issue-43197.nll.stderr | 14 ++---- src/test/ui/const-eval/issue-44578.nll.stderr | 14 ++---- src/test/ui/fmt/format-string-error.rs | 2 + src/test/ui/fmt/format-string-error.stderr | 20 ++++----- src/test/ui/macros/bad_hello.rs | 5 ++- src/test/ui/macros/bad_hello.stderr | 20 ++++++--- src/test/ui/macros/format-foreign.stderr | 5 ++- .../ui/macros/format-unused-lables.stderr | 43 +++++++++---------- src/test/ui/macros/trace-macro.stderr | 9 ++-- 14 files changed, 122 insertions(+), 102 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 75f038407c127..a4a6ed73c61cf 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -155,8 +155,14 @@ macro_rules! print { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! println { () => (print!("\n")); - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); + ($fmt:expr) => ({ + print!($fmt); + print!("\n"); + }); + ($fmt:expr, $($arg:tt)*) => ({ + print!($fmt, $($arg)*); + print!("\n"); + }); } /// Macro for printing to the standard error. diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5ec44fb589818..b55c4f99206c4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -959,29 +959,34 @@ impl<'a> ExtCtxt<'a> { /// Extract a string literal from the macro expanded version of `expr`, /// emitting `err_msg` if `expr` is not a string literal. This does not stop /// compilation on error, merely emits a non-fatal error and returns None. -pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P, err_msg: &str) - -> Option> { +pub fn expr_to_spanned_string<'a>( + cx: &'a mut ExtCtxt, + expr: P, + err_msg: &str, +) -> Result, DiagnosticBuilder<'a>> { // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. let expr = expr.map(|mut expr| { expr.span = expr.span.apply_mark(cx.current_expansion.mark); expr }); - // we want to be able to handle e.g. concat("foo", "bar") + // we want to be able to handle e.g. `concat!("foo", "bar")` let expr = cx.expander().fold_expr(expr); - match expr.node { + Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(s, style) => return Some(respan(expr.span, (s, style))), - _ => cx.span_err(l.span, err_msg) + ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), + _ => cx.struct_span_err(l.span, err_msg) }, - _ => cx.span_err(expr.span, err_msg) - } - None + _ => cx.struct_span_err(expr.span, err_msg) + }) } pub fn expr_to_string(cx: &mut ExtCtxt, expr: P, err_msg: &str) -> Option<(Symbol, ast::StrStyle)> { - expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node) + expr_to_spanned_string(cx, expr, err_msg) + .map_err(|mut err| err.emit()) + .ok() + .map(|s| s.node) } /// Non-fatally assert that `tts` is empty. Note that this function diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 69b4a83764e46..d58f4ce17e2f7 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -27,6 +27,7 @@ pub fn expand_syntax_ext( None => return base::DummyResult::expr(sp), }; let mut accumulator = String::new(); + let mut missing_literal = vec![]; for e in es { match e.node { ast::ExprKind::Lit(ref lit) => match lit.node { @@ -51,17 +52,15 @@ pub fn expand_syntax_ext( } }, _ => { - let mut err = cx.struct_span_err(e.span, "expected a literal"); - let snippet = cx.codemap().span_to_snippet(e.span).unwrap(); - err.span_suggestion( - e.span, - "you might be missing a string literal to format with", - format!("\"{{}}\", {}", snippet), - ); - err.emit(); + missing_literal.push(e.span); } } } + if missing_literal.len() > 0 { + let mut err = cx.struct_span_err(missing_literal, "expected a literal"); + err.note("only `&str` literals can be passed to `concat!()`"); + err.emit(); + } let sp = sp.apply_mark(cx.current_expansion.mark); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 8587d11b22786..6abf987d0ab70 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -703,10 +703,24 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect(); let mut macsp = ecx.call_site(); macsp = macsp.apply_mark(ecx.current_expansion.mark); - let msg = "format argument must be a string literal."; + let msg = "format argument must be a string literal"; + let fmt_sp = efmt.span; let fmt = match expr_to_spanned_string(ecx, efmt, msg) { - Some(fmt) => fmt, - None => return DummyResult::raw_expr(sp), + Ok(fmt) => fmt, + Err(mut err) => { + let sugg_fmt = match args.len() { + 0 => "{}".to_string(), + _ => format!("{}{{}}", "{}, ".repeat(args.len())), + + }; + err.span_suggestion( + fmt_sp.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{}\", ", sugg_fmt), + ); + err.emit(); + return DummyResult::raw_expr(sp); + }, }; let mut cx = Context { @@ -818,7 +832,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, errs.iter().map(|&(sp, _)| sp).collect::>(), "multiple unused formatting arguments" ); - diag.span_label(cx.fmtsp, "multiple unused arguments in this statement"); + diag.span_label(cx.fmtsp, "multiple missing formatting arguments"); diag } }; @@ -861,8 +875,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } if show_doc_note { - diag.note(concat!(stringify!($kind), " formatting not supported; see \ - the documentation for `std::fmt`")); + diag.note(concat!( + stringify!($kind), + " formatting not supported; see the documentation for `std::fmt`", + )); } }}; } diff --git a/src/test/ui/const-eval/conditional_array_execution.nll.stderr b/src/test/ui/const-eval/conditional_array_execution.nll.stderr index 8bc302a2befa4..3f82311d469ae 100644 --- a/src/test/ui/const-eval/conditional_array_execution.nll.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.nll.stderr @@ -28,25 +28,19 @@ LL | println!("{}", FOO); | ^^^ referenced constant has errors error[E0080]: referenced constant has errors - --> $DIR/conditional_array_execution.rs:19:5 + --> $DIR/conditional_array_execution.rs:19:14 | LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | ----- attempt to subtract with overflow ... LL | println!("{}", FOO); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^ error[E0080]: erroneous constant used - --> $DIR/conditional_array_execution.rs:19:5 + --> $DIR/conditional_array_execution.rs:19:14 | LL | println!("{}", FOO); - | ^^^^^^^^^^^^^^^---^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^ --- referenced constant has errors error[E0080]: referenced constant has errors --> $DIR/conditional_array_execution.rs:19:20 diff --git a/src/test/ui/const-eval/issue-43197.nll.stderr b/src/test/ui/const-eval/issue-43197.nll.stderr index 5819e6a9254a7..e25cb29c11475 100644 --- a/src/test/ui/const-eval/issue-43197.nll.stderr +++ b/src/test/ui/const-eval/issue-43197.nll.stderr @@ -51,25 +51,19 @@ LL | println!("{} {}", X, Y); | ^ referenced constant has errors error[E0080]: referenced constant has errors - --> $DIR/issue-43197.rs:24:5 + --> $DIR/issue-43197.rs:24:14 | LL | const X: u32 = 0-1; | --- attempt to subtract with overflow ... LL | println!("{} {}", X, Y); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^^^^ error[E0080]: erroneous constant used - --> $DIR/issue-43197.rs:24:5 + --> $DIR/issue-43197.rs:24:14 | LL | println!("{} {}", X, Y); - | ^^^^^^^^^^^^^^^^^^-^^^^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^^^^ - referenced constant has errors error[E0080]: referenced constant has errors --> $DIR/issue-43197.rs:24:26 diff --git a/src/test/ui/const-eval/issue-44578.nll.stderr b/src/test/ui/const-eval/issue-44578.nll.stderr index eeb152e00ea47..da040747991a4 100644 --- a/src/test/ui/const-eval/issue-44578.nll.stderr +++ b/src/test/ui/const-eval/issue-44578.nll.stderr @@ -1,23 +1,17 @@ error[E0080]: referenced constant has errors - --> $DIR/issue-44578.rs:35:5 + --> $DIR/issue-44578.rs:35:14 | LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; | ------------------------------------ index out of bounds: the len is 1 but the index is 1 ... LL | println!("{}", as Foo>::AMT); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^ error[E0080]: erroneous constant used - --> $DIR/issue-44578.rs:35:5 + --> $DIR/issue-44578.rs:35:14 | LL | println!("{}", as Foo>::AMT); - | ^^^^^^^^^^^^^^^--------------------------^^ - | | - | referenced constant has errors - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ^^^^ -------------------------- referenced constant has errors error[E0080]: referenced constant has errors --> $DIR/issue-44578.rs:35:20 diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index 5b13686240e7c..e48aa489f4359 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -10,8 +10,10 @@ fn main() { println!("{"); + //~^ ERROR invalid format string: expected `'}'` but string was terminated println!("{{}}"); println!("}"); + //~^ ERROR invalid format string: unmatched `}` found let _ = format!("{_foo}", _foo = 6usize); //~^ ERROR invalid format string: invalid argument name `_foo` let _ = format!("{_}", _ = 6usize); diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index ff766ddc8fa67..4c7ef11b29ef0 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -1,23 +1,21 @@ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error.rs:12:5 + --> $DIR/format-string-error.rs:12:16 | LL | println!("{"); - | ^^^^^^^^^^^^^^ expected `'}'` in format string + | ^ expected `'}'` in format string | = note: if you intended to print `{`, you can escape it using `{{` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/format-string-error.rs:14:5 + --> $DIR/format-string-error.rs:15:15 | LL | println!("}"); - | ^^^^^^^^^^^^^^ unmatched `}` in format string + | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: invalid format string: invalid argument name `_foo` - --> $DIR/format-string-error.rs:15:23 + --> $DIR/format-string-error.rs:17:23 | LL | let _ = format!("{_foo}", _foo = 6usize); | ^^^^ invalid argument name in format string @@ -25,7 +23,7 @@ LL | let _ = format!("{_foo}", _foo = 6usize); = note: argument names cannot start with an underscore error: invalid format string: invalid argument name `_` - --> $DIR/format-string-error.rs:17:23 + --> $DIR/format-string-error.rs:19:23 | LL | let _ = format!("{_}", _ = 6usize); | ^ invalid argument name in format string @@ -33,7 +31,7 @@ LL | let _ = format!("{_}", _ = 6usize); = note: argument names cannot start with an underscore error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error.rs:19:23 + --> $DIR/format-string-error.rs:21:23 | LL | let _ = format!("{"); | ^ expected `'}'` in format string @@ -41,7 +39,7 @@ LL | let _ = format!("{"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error.rs:21:22 + --> $DIR/format-string-error.rs:23:22 | LL | let _ = format!("}"); | ^ unmatched `}` in format string @@ -49,7 +47,7 @@ LL | let _ = format!("}"); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: expected `'}'`, found `'/'` - --> $DIR/format-string-error.rs:23:23 + --> $DIR/format-string-error.rs:25:23 | LL | let _ = format!("{/}"); | ^ expected `}` in format string diff --git a/src/test/ui/macros/bad_hello.rs b/src/test/ui/macros/bad_hello.rs index 174dcc9b6cd3f..cccaf7998c98b 100644 --- a/src/test/ui/macros/bad_hello.rs +++ b/src/test/ui/macros/bad_hello.rs @@ -9,5 +9,8 @@ // except according to those terms. fn main() { - println!(3 + 4); //~ ERROR expected a literal + println!(3 + 4); + //~^ ERROR format argument must be a string literal + println!(3, 4); + //~^ ERROR format argument must be a string literal } diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr index 0bfb060f84416..87ea515182f15 100644 --- a/src/test/ui/macros/bad_hello.stderr +++ b/src/test/ui/macros/bad_hello.stderr @@ -1,12 +1,22 @@ -error: expected a literal +error: format argument must be a string literal --> $DIR/bad_hello.rs:12:14 | -LL | println!(3 + 4); //~ ERROR expected a literal +LL | println!(3 + 4); | ^^^^^ help: you might be missing a string literal to format with | -LL | println!("{}", 3 + 4); //~ ERROR expected a literal - | ^^^^^^^^^^^ +LL | println!("{}", 3 + 4); + | ^^^^^ + +error: format argument must be a string literal + --> $DIR/bad_hello.rs:14:14 + | +LL | println!(3, 4); + | ^ +help: you might be missing a string literal to format with + | +LL | println!("{}, {}", 3, 4); + | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 6804ce95fa873..401b2f6d67e39 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -2,12 +2,13 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:12:30 | LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments - | -------------------------^^^^^^^^--^^^^^^^--^-- multiple unused arguments in this statement + | -------------- ^^^^^^^^ ^^^^^^^ ^ + | | + | multiple missing formatting arguments | = help: `%.*3$s` should be written as `{:.2$}` = help: `%s` should be written as `{}` = note: printf formatting not supported; see the documentation for `std::fmt` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: argument never used --> $DIR/format-foreign.rs:13:29 diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index 777b492dcb65f..f764190438f33 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -2,24 +2,21 @@ error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:12:22 | LL | println!("Test", 123, 456, 789); - | -----------------^^^--^^^--^^^-- multiple unused arguments in this statement - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + | ------ ^^^ ^^^ ^^^ + | | + | multiple missing formatting arguments error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:16:9 | -LL | / println!("Test2", -LL | | 123, //~ ERROR multiple unused formatting arguments - | | ^^^ -LL | | 456, - | | ^^^ -LL | | 789 - | | ^^^ -LL | | ); - | |______- multiple unused arguments in this statement - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +LL | println!("Test2", + | ------- multiple missing formatting arguments +LL | 123, //~ ERROR multiple unused formatting arguments + | ^^^ +LL | 456, + | ^^^ +LL | 789 + | ^^^ error: named argument never used --> $DIR/format-unused-lables.rs:21:35 @@ -30,18 +27,18 @@ LL | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never u error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:24:9 | -LL | / println!("Some more $STUFF", -LL | | "woo!", //~ ERROR multiple unused formatting arguments - | | ^^^^^^ -LL | | STUFF= -LL | | "things" - | | ^^^^^^^^ -LL | | , UNUSED="args"); - | |_______________________^^^^^^_- multiple unused arguments in this statement +LL | println!("Some more $STUFF", + | ------------------ multiple missing formatting arguments +LL | "woo!", //~ ERROR multiple unused formatting arguments + | ^^^^^^ +LL | STUFF= +LL | "things" + | ^^^^^^^^ +LL | , UNUSED="args"); + | ^^^^^^ | = help: `$STUFF` should be written as `{STUFF}` = note: shell formatting not supported; see the documentation for `std::fmt` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 938f876872f2f..c98e42ea647d0 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,8 +5,9 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `print ! ( concat ! ( "Hello, World!" , "/n" ) )` - = note: expanding `print! { concat ! ( "Hello, World!" , "/n" ) }` - = note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, World!" , "/n" ) ) - )` + = note: to `{ print ! ( "Hello, World!" ) ; print ! ( "/n" ) ; }` + = note: expanding `print! { "Hello, World!" }` + = note: to `$crate :: io :: _print ( format_args ! ( "Hello, World!" ) )` + = note: expanding `print! { "/n" }` + = note: to `$crate :: io :: _print ( format_args ! ( "/n" ) )` From fbce952193d38328c39262cf2fb7f7bfbe088a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jul 2018 11:52:11 -0700 Subject: [PATCH 02/19] review comments: modify note wording and change `println` - Don't print the newline on its own to avoid the possibility of printing it out of order due to `stdout` locking. - Modify wording of `concat!()` with non-literals to not mislead into believing that only `&str` literals are accepted. - Add test for `concat!()` with non-literals. --- src/libstd/macros.rs | 9 +-------- src/libsyntax_ext/concat.rs | 2 +- src/test/ui/macros/bad-concat.rs | 18 ++++++++++++++++++ src/test/ui/macros/bad-concat.stderr | 10 ++++++++++ src/test/ui/macros/trace-macro.stderr | 9 ++++----- 5 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/macros/bad-concat.rs create mode 100644 src/test/ui/macros/bad-concat.stderr diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a4a6ed73c61cf..7f3c8fcdd5aa9 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -155,14 +155,7 @@ macro_rules! print { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! println { () => (print!("\n")); - ($fmt:expr) => ({ - print!($fmt); - print!("\n"); - }); - ($fmt:expr, $($arg:tt)*) => ({ - print!($fmt, $($arg)*); - print!("\n"); - }); + ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*))); } /// Macro for printing to the standard error. diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index d58f4ce17e2f7..99dba8af754fa 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -58,7 +58,7 @@ pub fn expand_syntax_ext( } if missing_literal.len() > 0 { let mut err = cx.struct_span_err(missing_literal, "expected a literal"); - err.note("only `&str` literals can be passed to `concat!()`"); + err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); } let sp = sp.apply_mark(cx.current_expansion.mark); diff --git a/src/test/ui/macros/bad-concat.rs b/src/test/ui/macros/bad-concat.rs new file mode 100644 index 0000000000000..e7adee8ce8597 --- /dev/null +++ b/src/test/ui/macros/bad-concat.rs @@ -0,0 +1,18 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x: u32 = 42; + let y: f64 = 3.14; + let z = "foo"; + let _ = concat!(x, y, z, "bar"); + //~^ ERROR expected a literal + //~| NOTE only literals +} diff --git a/src/test/ui/macros/bad-concat.stderr b/src/test/ui/macros/bad-concat.stderr new file mode 100644 index 0000000000000..b97e4f268241c --- /dev/null +++ b/src/test/ui/macros/bad-concat.stderr @@ -0,0 +1,10 @@ +error: expected a literal + --> $DIR/bad-concat.rs:15:21 + | +LL | let _ = concat!(x, y, z, "bar"); + | ^ ^ ^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: aborting due to previous error + diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index c98e42ea647d0..6d8a329be8048 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,9 +5,8 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `{ print ! ( "Hello, World!" ) ; print ! ( "/n" ) ; }` - = note: expanding `print! { "Hello, World!" }` - = note: to `$crate :: io :: _print ( format_args ! ( "Hello, World!" ) )` - = note: expanding `print! { "/n" }` - = note: to `$crate :: io :: _print ( format_args ! ( "/n" ) )` + = note: to `print ! ( "{}/n" , format_args ! ( "Hello, World!" ) )` + = note: expanding `print! { "{}/n" , format_args ! ( "Hello, World!" ) }` + = note: to `$crate :: io :: _print ( + format_args ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) )` From e613bfb7015744c25ce838b64bf8db31acff49f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jul 2018 12:28:42 -0700 Subject: [PATCH 03/19] Same change as `println` for `eprintln` --- src/libstd/macros.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 7f3c8fcdd5aa9..527bab759b04b 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -211,8 +211,7 @@ macro_rules! eprint { #[stable(feature = "eprint", since = "1.19.0")] macro_rules! eprintln { () => (eprint!("\n")); - ($fmt:expr) => (eprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*)); + ($($arg:tt)*) => (eprint!("{}\n", format_args!($($arg)*))); } #[macro_export] From a47653214f8f8561196acf25b8898e7148f1c052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 15 Jul 2018 14:36:19 -0700 Subject: [PATCH 04/19] Fix hir tree test --- src/test/run-make-fulldeps/hir-tree/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/hir-tree/Makefile b/src/test/run-make-fulldeps/hir-tree/Makefile index 2e100b269e14b..483d68fd64656 100644 --- a/src/test/run-make-fulldeps/hir-tree/Makefile +++ b/src/test/run-make-fulldeps/hir-tree/Makefile @@ -5,4 +5,4 @@ all: $(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs - $(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir + $(CGREP) '"Hello, Rustaceans!"' < $(TMPDIR)/input.hir From 154dee2dccd45f929b0a3d2ce2d45739513f77c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 19 Jul 2018 18:53:26 -0700 Subject: [PATCH 05/19] rework println --- src/libfmt_macros/lib.rs | 6 +++++- src/libstd/macros.rs | 26 ++++++++++++++++++++++++-- src/libsyntax_ext/format.rs | 22 ++++++++++++++++++++-- src/libsyntax_ext/lib.rs | 10 ++++++++++ src/test/ui/macros/trace-macro.stderr | 8 ++++---- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 51c3efb41ad97..ee590bc3b5ecf 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -273,7 +273,11 @@ impl<'a> Parser<'a> { } } else { let msg = format!("expected `{:?}` but string was terminated", c); - let pos = self.input.len() + 1; // point at closing `"` + // point at closing `"`, unless the last char is `\n` to account for `println` + let pos = match self.input.chars().last() { + Some('\n') => self.input.len(), + _ => self.input.len() + 1, + }; if c == '}' { self.err_with_note(msg, format!("expected `{:?}`", c), diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 527bab759b04b..a4bcf7fd26c5c 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -153,9 +153,17 @@ macro_rules! print { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! println { () => (print!("\n")); - ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*))); + ($($arg:tt)*) => ({ + #[cfg(not(stage0))] { + ($crate::io::_print(format_args_nl!($($arg)*))); + } + #[cfg(stage0)] { + print!("{}\n", format_args!($($arg)*)) + } + }) } /// Macro for printing to the standard error. @@ -211,7 +219,8 @@ macro_rules! eprint { #[stable(feature = "eprint", since = "1.19.0")] macro_rules! eprintln { () => (eprint!("\n")); - ($($arg:tt)*) => (eprint!("{}\n", format_args!($($arg)*))); + ($fmt:expr) => (eprint!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*)); } #[macro_export] @@ -397,6 +406,19 @@ pub mod builtin { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); } + /// Internal version of [`format_args`]. + /// + /// This macro differs from [`format_args`] in that it appends a newline to the format string + /// and nothing more. It is perma-unstable. + /// + /// [`format_args`]: ../std/macro.format_args.html + #[doc(hidden)] + #[unstable(feature = "println_format_args", issue="0")] + #[macro_export] + macro_rules! format_args_nl { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); + } /// Inspect an environment variable at compile time. /// /// This macro will expand to the value of the named environment variable at diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 6abf987d0ab70..d3e5adf683505 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -683,7 +683,20 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { Some((efmt, args, names)) => { - MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names)) + MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, false)) + } + None => DummyResult::expr(sp), + } +} + +pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt, + mut sp: Span, + tts: &[tokenstream::TokenTree]) + -> Box { + sp = sp.apply_mark(ecx.current_expansion.mark); + match parse_args(ecx, sp, tts) { + Some((efmt, args, names)) => { + MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, true)) } None => DummyResult::expr(sp), } @@ -695,7 +708,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, efmt: P, args: Vec>, - names: HashMap) + names: HashMap, + append_newline: bool) -> P { // NOTE: this verbose way of initializing `Vec>` is because // `ArgumentType` does not derive `Clone`. @@ -706,6 +720,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let msg = "format argument must be a string literal"; let fmt_sp = efmt.span; let fmt = match expr_to_spanned_string(ecx, efmt, msg) { + Ok(mut fmt) if append_newline => { + fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0)); + fmt + } Ok(fmt) => fmt, Err(mut err) => { let sugg_fmt = match args.len() { diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index bdf7a8d704042..ff76e788b3c29 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -139,6 +139,16 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, unstable_feature: None, edition: hygiene::default_edition(), }); + register(Symbol::intern("format_args_nl"), + NormalTT { + expander: Box::new(format::expand_format_args_nl), + def_info: None, + allow_internal_unstable: true, + allow_internal_unsafe: false, + local_inner_macros: false, + unstable_feature: None, + edition: hygiene::default_edition(), + }); for (name, ext) in user_exts { register(name, ext); diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 6d8a329be8048..2a30d9837517e 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,8 +5,8 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `print ! ( "{}/n" , format_args ! ( "Hello, World!" ) )` - = note: expanding `print! { "{}/n" , format_args ! ( "Hello, World!" ) }` - = note: to `$crate :: io :: _print ( - format_args ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) )` + = note: to `{ + # [ cfg ( not ( stage0 ) ) ] { + ( $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ) ; } # [ + cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) } }` From f4306ffbfcb2280f180e51ce6421e1c6c28dccec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 19 Jul 2018 23:14:00 -0700 Subject: [PATCH 06/19] Use correct spans for format string errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When encountering format string errors in a raw string, or regular string literal with embedded newlines, account for the positional change to use correct spans. :drive by fix: 🚗 --- src/Cargo.lock | 3 ++ src/libfmt_macros/Cargo.toml | 3 ++ src/libfmt_macros/lib.rs | 40 ++++++++++++---- src/librustc/traits/on_unimplemented.rs | 6 +-- src/libsyntax_ext/format.rs | 2 +- src/test/ui/fmt/format-string-error.rs | 34 +++++++++++++ src/test/ui/fmt/format-string-error.stderr | 56 ++++++++++++++++++---- 7 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8299dea1c4b0e..c59c110849577 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -715,6 +715,9 @@ dependencies = [ [[package]] name = "fmt_macros" version = "0.0.0" +dependencies = [ + "syntax 0.0.0", +] [[package]] name = "fnv" diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index b3f4d2deae2fc..6e6af9c2ff5e7 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -7,3 +7,6 @@ version = "0.0.0" name = "fmt_macros" path = "lib.rs" crate-type = ["dylib"] + +[dependencies] +syntax = { path = "../libsyntax" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index ee590bc3b5ecf..54cf3d24173f7 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -28,6 +28,8 @@ pub use self::Alignment::*; pub use self::Flag::*; pub use self::Count::*; +extern crate syntax; + use std::str; use std::string; use std::iter; @@ -150,18 +152,27 @@ pub struct Parser<'a> { pub errors: Vec, /// Current position of implicit positional argument pointer curarg: usize, + /// The style of the string (raw or not), used to position spans correctly + style: syntax::ast::StrStyle, + /// How many newlines have been seen in the string so far, to adjust the error spans + seen_newlines: usize, } impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option> { + let raw = match self.style { + syntax::ast::StrStyle::Raw(raw) => raw as usize + self.seen_newlines, + _ => 0, + }; if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { + let pos = pos + raw + 1; self.cur.next(); if self.consume('{') { - Some(String(self.string(pos + 1))) + Some(String(self.string(pos))) } else { let ret = Some(NextArgument(self.argument())); self.must_consume('}'); @@ -169,8 +180,8 @@ impl<'a> Iterator for Parser<'a> { } } '}' => { + let pos = pos + raw + 1; self.cur.next(); - let pos = pos + 1; if self.consume('}') { Some(String(self.string(pos))) } else { @@ -184,6 +195,10 @@ impl<'a> Iterator for Parser<'a> { None } } + '\n' => { + self.seen_newlines += 1; + Some(String(self.string(pos))) + } _ => Some(String(self.string(pos))), } } else { @@ -194,12 +209,14 @@ impl<'a> Iterator for Parser<'a> { impl<'a> Parser<'a> { /// Creates a new parser for the given format string - pub fn new(s: &'a str) -> Parser<'a> { + pub fn new(s: &'a str, style: syntax::ast::StrStyle) -> Parser<'a> { Parser { input: s, cur: s.char_indices().peekable(), errors: vec![], curarg: 0, + style, + seen_newlines: 0, } } @@ -262,14 +279,19 @@ impl<'a> Parser<'a> { /// found, an error is emitted. fn must_consume(&mut self, c: char) { self.ws(); + let raw = match self.style { + syntax::ast::StrStyle::Raw(raw) => raw as usize, + _ => 0, + }; + let padding = raw + self.seen_newlines; if let Some(&(pos, maybe)) = self.cur.peek() { if c == maybe { self.cur.next(); } else { self.err(format!("expected `{:?}`, found `{:?}`", c, maybe), format!("expected `{}`", c), - pos + 1, - pos + 1); + pos + padding + 1, + pos + padding + 1); } } else { let msg = format!("expected `{:?}` but string was terminated", c); @@ -282,8 +304,8 @@ impl<'a> Parser<'a> { self.err_with_note(msg, format!("expected `{:?}`", c), "if you intended to print `{`, you can escape it using `{{`", - pos, - pos); + pos + padding, + pos + padding); } else { self.err(msg, format!("expected `{:?}`", c), pos, pos); } @@ -540,7 +562,7 @@ mod tests { use super::*; fn same(fmt: &'static str, p: &[Piece<'static>]) { - let parser = Parser::new(fmt); + let parser = Parser::new(fmt, syntax::ast::StrStyle::Cooked); assert!(parser.collect::>>() == p); } @@ -556,7 +578,7 @@ mod tests { } fn musterr(s: &str) { - let mut p = Parser::new(s); + let mut p = Parser::new(fmt, syntax::ast::StrStyle::Cooked); p.next(); assert!(!p.errors.is_empty()); } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 0550cf7c6d2c0..33d5502eba000 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -15,7 +15,7 @@ use ty::{self, TyCtxt, GenericParamDefKind}; use util::common::ErrorReported; use util::nodemap::FxHashMap; -use syntax::ast::{MetaItem, NestedMetaItem}; +use syntax::ast::{self, MetaItem, NestedMetaItem}; use syntax::attr; use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; @@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); - let parser = Parser::new(&self.0); + let parser = Parser::new(&self.0, ast::StrStyle::Cooked); let mut result = Ok(()); for token in parser { match token { @@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Some((name, value)) }).collect::>(); - let parser = Parser::new(&self.0); + let parser = Parser::new(&self.0, ast::StrStyle::Cooked); parser.map(|p| { match p { Piece::String(s) => s, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index d3e5adf683505..7acfb08020fd9 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -763,7 +763,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, }; let fmt_str = &*fmt.node.0.as_str(); - let mut parser = parse::Parser::new(fmt_str); + let mut parser = parse::Parser::new(fmt_str, fmt.node.1); let mut pieces = vec![]; while let Some(mut piece) = parser.next() { diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index e48aa489f4359..f39110ebc5dcc 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-tab + fn main() { println!("{"); //~^ ERROR invalid format string: expected `'}'` but string was terminated @@ -24,4 +26,36 @@ fn main() { //~^ ERROR invalid format string: unmatched `}` found let _ = format!("{\\}"); //~^ ERROR invalid format string: expected `'}'`, found `'\\'` + let _ = format!("\n\n\n{\n\n\n"); + //~^ ERROR invalid format string + let _ = format!(r###" + + + + {"###); + //~^ ERROR invalid format string + let _ = format!(r###" + + + + { + +"###); + //~^^ ERROR invalid format string + let _ = format!(r###" + + + + } + +"###); + //~^^^ ERROR invalid format string + let _ = format!(r###" + + + + } + +"###); + //~^^^ ERROR invalid format string: unmatched `}` found } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 4c7ef11b29ef0..9c84fd2521891 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -1,5 +1,5 @@ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error.rs:12:16 + --> $DIR/format-string-error.rs:14:16 | LL | println!("{"); | ^ expected `'}'` in format string @@ -7,7 +7,7 @@ LL | println!("{"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error.rs:15:15 + --> $DIR/format-string-error.rs:17:15 | LL | println!("}"); | ^ unmatched `}` in format string @@ -15,7 +15,7 @@ LL | println!("}"); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: invalid argument name `_foo` - --> $DIR/format-string-error.rs:17:23 + --> $DIR/format-string-error.rs:19:23 | LL | let _ = format!("{_foo}", _foo = 6usize); | ^^^^ invalid argument name in format string @@ -23,7 +23,7 @@ LL | let _ = format!("{_foo}", _foo = 6usize); = note: argument names cannot start with an underscore error: invalid format string: invalid argument name `_` - --> $DIR/format-string-error.rs:19:23 + --> $DIR/format-string-error.rs:21:23 | LL | let _ = format!("{_}", _ = 6usize); | ^ invalid argument name in format string @@ -31,7 +31,7 @@ LL | let _ = format!("{_}", _ = 6usize); = note: argument names cannot start with an underscore error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error.rs:21:23 + --> $DIR/format-string-error.rs:23:23 | LL | let _ = format!("{"); | ^ expected `'}'` in format string @@ -39,7 +39,7 @@ LL | let _ = format!("{"); = note: if you intended to print `{`, you can escape it using `{{` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error.rs:23:22 + --> $DIR/format-string-error.rs:25:22 | LL | let _ = format!("}"); | ^ unmatched `}` in format string @@ -47,10 +47,50 @@ LL | let _ = format!("}"); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: expected `'}'`, found `'/'` - --> $DIR/format-string-error.rs:25:23 + --> $DIR/format-string-error.rs:27:23 | LL | let _ = format!("{/}"); | ^ expected `}` in format string -error: aborting due to 7 previous errors +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:29:29 + | +LL | let _ = format!("/n/n/n{/n/n/n"); + | ^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:35:3 + | +LL | {"###); + | ^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:42:1 + | +LL | + | ^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:49:2 + | +LL | } + | ^ 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.rs:57:9 + | +LL | } + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 12 previous errors From 85da68cb6d5e0fa69da4ae2c64ed56ce3622f73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 19 Jul 2018 23:19:13 -0700 Subject: [PATCH 07/19] Rebase and fix text changed by master --- src/test/ui/issue-11692-1.stderr | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ui/issue-11692-1.stderr b/src/test/ui/issue-11692-1.stderr index daf53af3ace99..bee73e9f568b6 100644 --- a/src/test/ui/issue-11692-1.stderr +++ b/src/test/ui/issue-11692-1.stderr @@ -1,8 +1,12 @@ -error: format argument must be a string literal. +error: format argument must be a string literal --> $DIR/issue-11692-1.rs:12:12 | LL | print!(test!()); | ^^^^^^^ +help: you might be missing a string literal to format with + | +LL | print!("{}", test!()); + | ^^^^^ error: aborting due to previous error From 052159be5349338f872b676c6593ee74cc1d5eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 20 Jul 2018 09:15:22 -0700 Subject: [PATCH 08/19] fix incorrect position of chars in fmt str --- src/libfmt_macros/lib.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 54cf3d24173f7..6f4989c3e87d8 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -169,10 +169,9 @@ impl<'a> Iterator for Parser<'a> { if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { - let pos = pos + raw + 1; self.cur.next(); if self.consume('{') { - Some(String(self.string(pos))) + Some(String(self.string(pos + 1))) } else { let ret = Some(NextArgument(self.argument())); self.must_consume('}'); @@ -180,17 +179,17 @@ impl<'a> Iterator for Parser<'a> { } } '}' => { - let pos = pos + raw + 1; self.cur.next(); if self.consume('}') { - Some(String(self.string(pos))) + Some(String(self.string(pos + 1))) } else { + let err_pos = pos + raw + 1; self.err_with_note( "unmatched `}` found", "unmatched `}`", "if you intended to print `}`, you can escape it using `}}`", - pos, - pos, + err_pos, + err_pos, ); None } @@ -283,15 +282,17 @@ impl<'a> Parser<'a> { syntax::ast::StrStyle::Raw(raw) => raw as usize, _ => 0, }; + let padding = raw + self.seen_newlines; if let Some(&(pos, maybe)) = self.cur.peek() { if c == maybe { self.cur.next(); } else { + let pos = pos + padding + 1; self.err(format!("expected `{:?}`, found `{:?}`", c, maybe), format!("expected `{}`", c), - pos + padding + 1, - pos + padding + 1); + pos, + pos); } } else { let msg = format!("expected `{:?}` but string was terminated", c); From 9112e1a4cdbc549ef58d496ff02f146c85857717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 20 Jul 2018 11:04:23 -0700 Subject: [PATCH 09/19] fix rebase --- src/libfmt_macros/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 6f4989c3e87d8..52223b2343ca8 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -579,7 +579,7 @@ mod tests { } fn musterr(s: &str) { - let mut p = Parser::new(fmt, syntax::ast::StrStyle::Cooked); + let mut p = Parser::new(s, syntax::ast::StrStyle::Cooked); p.next(); assert!(!p.errors.is_empty()); } From 8b59fbc951dabc714ff882674db01e58d44db98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 20 Jul 2018 13:43:06 -0700 Subject: [PATCH 10/19] fix grep test looking for newline --- src/test/run-make-fulldeps/hir-tree/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make-fulldeps/hir-tree/Makefile b/src/test/run-make-fulldeps/hir-tree/Makefile index 483d68fd64656..2e100b269e14b 100644 --- a/src/test/run-make-fulldeps/hir-tree/Makefile +++ b/src/test/run-make-fulldeps/hir-tree/Makefile @@ -5,4 +5,4 @@ all: $(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs - $(CGREP) '"Hello, Rustaceans!"' < $(TMPDIR)/input.hir + $(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir From 83a8af50bbf704b5cdf2cbbab481e0e936ed03a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 12:16:06 -0700 Subject: [PATCH 11/19] Suggest space separated format str literal --- src/libsyntax_ext/format.rs | 2 +- src/test/ui/macros/bad_hello.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 7acfb08020fd9..9f153c36733b3 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -728,7 +728,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, Err(mut err) => { let sugg_fmt = match args.len() { 0 => "{}".to_string(), - _ => format!("{}{{}}", "{}, ".repeat(args.len())), + _ => format!("{}{{}}", "{} ".repeat(args.len())), }; err.span_suggestion( diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr index 87ea515182f15..c675eede2152b 100644 --- a/src/test/ui/macros/bad_hello.stderr +++ b/src/test/ui/macros/bad_hello.stderr @@ -15,8 +15,8 @@ LL | println!(3, 4); | ^ help: you might be missing a string literal to format with | -LL | println!("{}, {}", 3, 4); - | ^^^^^^^^^ +LL | println!("{} {}", 3, 4); + | ^^^^^^^^ error: aborting due to 2 previous errors From 00d500052c72775ab994b5634195976f85b4e0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 15:50:46 -0700 Subject: [PATCH 12/19] Gate `format_args_nll` behind feature flag --- src/libstd/macros.rs | 2 +- src/libsyntax/ext/expand.rs | 1 + src/libsyntax/feature_gate.rs | 4 ++++ src/libsyntax_ext/format.rs | 15 +++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a4bcf7fd26c5c..49de9f8027164 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -413,7 +413,7 @@ pub mod builtin { /// /// [`format_args`]: ../std/macro.format_args.html #[doc(hidden)] - #[unstable(feature = "println_format_args", issue="0")] + #[unstable(feature = "format_args_nl", issue="0")] #[macro_export] macro_rules! format_args_nl { ($fmt:expr) => ({ /* compiler built-in */ }); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1241e230b26d6..4d1ca50a89375 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1592,6 +1592,7 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, fn enable_custom_derive = custom_derive, + fn enable_format_args_nl = format_args_nl, fn use_extern_macros_enabled = use_extern_macros, fn macros_in_extern_enabled = macros_in_extern, fn proc_macro_mod = proc_macro_mod, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0f200479fe282..5b5453d5502ab 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -129,6 +129,7 @@ declare_features! ( // rustc internal, for now: (active, intrinsics, "1.0.0", None, None), (active, lang_items, "1.0.0", None, None), + (active, format_args_nl, "1.29.0", None, None), (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), (active, linkage, "1.0.0", Some(29603), None), @@ -1327,6 +1328,9 @@ pub const EXPLAIN_LOG_SYNTAX: &'static str = pub const EXPLAIN_CONCAT_IDENTS: &'static str = "`concat_idents` is not stable enough for use and is subject to change"; +pub const EXPLAIN_FORMAT_ARGS_NL: &'static str = + "`format_args_nl` is only for internal language use and is subject to change"; + pub const EXPLAIN_TRACE_MACROS: &'static str = "`trace_macros` is not stable enough for use and is subject to change"; pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str = diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 9f153c36733b3..5b8f059fd141b 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -17,6 +17,7 @@ use syntax::ast; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; +use syntax::feature_gate; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::Symbol; @@ -693,6 +694,20 @@ pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt, mut sp: Span, tts: &[tokenstream::TokenTree]) -> Box { + //if !ecx.ecfg.enable_allow_internal_unstable() { + + // For some reason, the only one that actually works for `println` is the first check + if !sp.allows_unstable() // the enclosing span is marked as `#[allow_insternal_unsable]` + || !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled? + || !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]` + { + feature_gate::emit_feature_err(&ecx.parse_sess, + "format_args_nl", + sp, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_FORMAT_ARGS_NL); + return base::DummyResult::expr(sp); + } sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { Some((efmt, args, names)) => { From a7a68370a72cc553c8ca983fe593062235360b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 15:56:37 -0700 Subject: [PATCH 13/19] Change `eprintln!()` Address #30143 as well. `writeln!()` hasn't been changed. --- src/libstd/macros.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 49de9f8027164..f06b8f621f263 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -217,10 +217,17 @@ macro_rules! eprint { /// ``` #[macro_export] #[stable(feature = "eprint", since = "1.19.0")] +#[allow_internal_unstable] macro_rules! eprintln { () => (eprint!("\n")); - ($fmt:expr) => (eprint!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*)); + ($($arg:tt)*) => ({ + #[cfg(not(stage0))] { + ($crate::io::_eprint(format_args_nl!($($arg)*))); + } + #[cfg(stage0)] { + eprint!("{}\n", format_args!($($arg)*)) + } + }) } #[macro_export] From 93b2bb01a961fdb61a4aeaf6bc6bdcab9ccedbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 16:18:06 -0700 Subject: [PATCH 14/19] Remove dependency on `libsyntax` --- src/Cargo.lock | 3 --- src/libfmt_macros/Cargo.toml | 3 --- src/libfmt_macros/lib.rs | 18 +++++------------- src/librustc/traits/on_unimplemented.rs | 6 +++--- src/libsyntax_ext/format.rs | 6 +++++- 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c59c110849577..8299dea1c4b0e 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -715,9 +715,6 @@ dependencies = [ [[package]] name = "fmt_macros" version = "0.0.0" -dependencies = [ - "syntax 0.0.0", -] [[package]] name = "fnv" diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index 6e6af9c2ff5e7..b3f4d2deae2fc 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -7,6 +7,3 @@ version = "0.0.0" name = "fmt_macros" path = "lib.rs" crate-type = ["dylib"] - -[dependencies] -syntax = { path = "../libsyntax" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 52223b2343ca8..3d17ccec12161 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -28,8 +28,6 @@ pub use self::Alignment::*; pub use self::Flag::*; pub use self::Count::*; -extern crate syntax; - use std::str; use std::string; use std::iter; @@ -152,8 +150,8 @@ pub struct Parser<'a> { pub errors: Vec, /// Current position of implicit positional argument pointer curarg: usize, - /// The style of the string (raw or not), used to position spans correctly - style: syntax::ast::StrStyle, + /// `Some(raw count)` when the string is "raw", used to position spans correctly + style: Option, /// How many newlines have been seen in the string so far, to adjust the error spans seen_newlines: usize, } @@ -162,10 +160,7 @@ impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option> { - let raw = match self.style { - syntax::ast::StrStyle::Raw(raw) => raw as usize + self.seen_newlines, - _ => 0, - }; + let raw = self.style.map(|raw| raw + self.seen_newlines).unwrap_or(0); if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { @@ -208,7 +203,7 @@ impl<'a> Iterator for Parser<'a> { impl<'a> Parser<'a> { /// Creates a new parser for the given format string - pub fn new(s: &'a str, style: syntax::ast::StrStyle) -> Parser<'a> { + pub fn new(s: &'a str, style: Option) -> Parser<'a> { Parser { input: s, cur: s.char_indices().peekable(), @@ -278,10 +273,7 @@ impl<'a> Parser<'a> { /// found, an error is emitted. fn must_consume(&mut self, c: char) { self.ws(); - let raw = match self.style { - syntax::ast::StrStyle::Raw(raw) => raw as usize, - _ => 0, - }; + let raw = self.style.unwrap_or(0); let padding = raw + self.seen_newlines; if let Some(&(pos, maybe)) = self.cur.peek() { diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 33d5502eba000..925d3504f75fc 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -15,7 +15,7 @@ use ty::{self, TyCtxt, GenericParamDefKind}; use util::common::ErrorReported; use util::nodemap::FxHashMap; -use syntax::ast::{self, MetaItem, NestedMetaItem}; +use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; @@ -242,7 +242,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); - let parser = Parser::new(&self.0, ast::StrStyle::Cooked); + let parser = Parser::new(&self.0, None); let mut result = Ok(()); for token in parser { match token { @@ -298,7 +298,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Some((name, value)) }).collect::>(); - let parser = Parser::new(&self.0, ast::StrStyle::Cooked); + let parser = Parser::new(&self.0, None); parser.map(|p| { match p { Piece::String(s) => s, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 5b8f059fd141b..c63cc3727eda0 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -778,7 +778,11 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, }; let fmt_str = &*fmt.node.0.as_str(); - let mut parser = parse::Parser::new(fmt_str, fmt.node.1); + let str_style = match fmt.node.1 { + ast::StrStyle::Cooked => None, + ast::StrStyle::Raw(raw) => Some(raw as usize), + }; + let mut parser = parse::Parser::new(fmt_str, str_style); let mut pieces = vec![]; while let Some(mut piece) = parser.next() { From 915ff0b9699c9cf39b5d80fc3aeb6c7e047dd280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 17:17:49 -0700 Subject: [PATCH 15/19] fix logic bug --- src/libsyntax_ext/format.rs | 4 ++-- src/test/ui/feature-gate-format_args_nl.rs | 0 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/feature-gate-format_args_nl.rs diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index c63cc3727eda0..755d2b476b716 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -698,8 +698,8 @@ pub fn expand_format_args_nl<'cx>(ecx: &'cx mut ExtCtxt, // For some reason, the only one that actually works for `println` is the first check if !sp.allows_unstable() // the enclosing span is marked as `#[allow_insternal_unsable]` - || !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled? - || !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]` + && !ecx.ecfg.enable_allow_internal_unstable() // NOTE: when is this enabled? + && !ecx.ecfg.enable_format_args_nl() // enabled using `#[feature(format_args_nl]` { feature_gate::emit_feature_err(&ecx.parse_sess, "format_args_nl", diff --git a/src/test/ui/feature-gate-format_args_nl.rs b/src/test/ui/feature-gate-format_args_nl.rs new file mode 100644 index 0000000000000..e69de29bb2d1d From 118b0f9a02113fe7462ca5c94780912919dbce02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 17:35:09 -0700 Subject: [PATCH 16/19] Fix tidy by adding new feature gate test --- src/test/ui/feature-gate-format_args_nl.rs | 13 +++++++++++++ src/test/ui/feature-gate-format_args_nl.stderr | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/feature-gate-format_args_nl.stderr diff --git a/src/test/ui/feature-gate-format_args_nl.rs b/src/test/ui/feature-gate-format_args_nl.rs index e69de29bb2d1d..b976d57f9c179 100644 --- a/src/test/ui/feature-gate-format_args_nl.rs +++ b/src/test/ui/feature-gate-format_args_nl.rs @@ -0,0 +1,13 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use +} diff --git a/src/test/ui/feature-gate-format_args_nl.stderr b/src/test/ui/feature-gate-format_args_nl.stderr new file mode 100644 index 0000000000000..a79535641a627 --- /dev/null +++ b/src/test/ui/feature-gate-format_args_nl.stderr @@ -0,0 +1,11 @@ +error[E0658]: `format_args_nl` is only for internal language use and is subject to change + --> $DIR/feature-gate-format_args_nl.rs:12:5 + | +LL | format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(format_args_nl)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 6aa17a3c687c3e78ba65953f88d763ab2b437384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 17:59:17 -0700 Subject: [PATCH 17/19] Don't use the new `eprintln` for stage0 and stage1 I'm not entirely sure why (or if) this is needed. --- src/libstd/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index f06b8f621f263..6309ca069fec1 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -221,10 +221,10 @@ macro_rules! eprint { macro_rules! eprintln { () => (eprint!("\n")); ($($arg:tt)*) => ({ - #[cfg(not(stage0))] { + #[cfg(all(not(stage0), not(stage1)))] { ($crate::io::_eprint(format_args_nl!($($arg)*))); } - #[cfg(stage0)] { + #[cfg(any(stage0, stage1))] { eprint!("{}\n", format_args!($($arg)*)) } }) From 3c817259e3ff08b673c74b48742d118a238befe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 18:24:10 -0700 Subject: [PATCH 18/19] fix tidy ~ again --- src/libstd/macros.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6309ca069fec1..76f38646308d8 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -413,19 +413,6 @@ pub mod builtin { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); } - /// Internal version of [`format_args`]. - /// - /// This macro differs from [`format_args`] in that it appends a newline to the format string - /// and nothing more. It is perma-unstable. - /// - /// [`format_args`]: ../std/macro.format_args.html - #[doc(hidden)] - #[unstable(feature = "format_args_nl", issue="0")] - #[macro_export] - macro_rules! format_args_nl { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); - } /// Inspect an environment variable at compile time. /// /// This macro will expand to the value of the named environment variable at From dc563d950017fedaa4690165d2d8b9b3e6cbd982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Jul 2018 20:48:15 -0700 Subject: [PATCH 19/19] fix test --- src/libfmt_macros/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 3d17ccec12161..9952e5f64d6ab 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -555,7 +555,7 @@ mod tests { use super::*; fn same(fmt: &'static str, p: &[Piece<'static>]) { - let parser = Parser::new(fmt, syntax::ast::StrStyle::Cooked); + let parser = Parser::new(fmt, None); assert!(parser.collect::>>() == p); } @@ -571,7 +571,7 @@ mod tests { } fn musterr(s: &str) { - let mut p = Parser::new(s, syntax::ast::StrStyle::Cooked); + let mut p = Parser::new(s, None); p.next(); assert!(!p.errors.is_empty()); }