From 6b95f3102d657a5cd0549213a073b28c7e0fe609 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 12 Oct 2019 15:07:13 +0100 Subject: [PATCH 1/6] Add `format_args_capture` feature --- src/librustc_builtin_macros/format.rs | 61 ++++++++++++++++-- src/librustc_feature/active.rs | 3 + src/librustc_parse_format/lib.rs | 2 +- src/librustc_span/symbol.rs | 1 + .../fmt/feature-gate-format-args-capture.rs | 6 ++ .../feature-gate-format-args-capture.stderr | 20 ++++++ .../fmt/format-args-capture-macro-hygiene.rs | 6 ++ .../format-args-capture-macro-hygiene.stderr | 22 +++++++ .../format-args-capture-missing-variables.rs | 22 +++++++ ...rmat-args-capture-missing-variables.stderr | 52 ++++++++++++++++ src/test/ui/fmt/format-args-capture.rs | 62 +++++++++++++++++++ src/test/ui/if/ifmt-bad-arg.stderr | 15 +++++ 12 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/fmt/feature-gate-format-args-capture.rs create mode 100644 src/test/ui/fmt/feature-gate-format-args-capture.stderr create mode 100644 src/test/ui/fmt/format-args-capture-macro-hygiene.rs create mode 100644 src/test/ui/fmt/format-args-capture-macro-hygiene.stderr create mode 100644 src/test/ui/fmt/format-args-capture-missing-variables.rs create mode 100644 src/test/ui/fmt/format-args-capture-missing-variables.stderr create mode 100644 src/test/ui/fmt/format-args-capture.rs diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index e574b076bf84c..538d513c5d6ea 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -107,6 +107,9 @@ struct Context<'a, 'b> { arg_spans: Vec, /// All the formatting arguments that have formatting flags set, in order for diagnostics. arg_with_formatting: Vec>, + + /// Whether this format string came from a string literal, as opposed to a macro. + is_literal: bool, } /// Parses the arguments from the given list of tokens, returning the diagnostic @@ -498,10 +501,59 @@ impl<'a, 'b> Context<'a, 'b> { self.verify_arg_type(Exact(idx), ty) } None => { - let msg = format!("there is no argument named `{}`", name); - let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp); - let mut err = self.ecx.struct_span_err(sp, &msg[..]); - err.emit(); + let capture_feature_enabled = self + .ecx + .ecfg + .features + .map_or(false, |features| features.format_args_capture); + + // For the moment capturing variables from format strings expanded from + // literals is disabled (see RFC #2795) + let can_capture = capture_feature_enabled && self.is_literal; + + if can_capture { + // Treat this name as a variable to capture from the surrounding scope + let idx = self.args.len(); + self.arg_types.push(Vec::new()); + self.arg_unique_types.push(Vec::new()); + self.args.push( + self.ecx.expr_ident(self.fmtsp, Ident::new(name, self.fmtsp)), + ); + self.names.insert(name, idx); + self.verify_arg_type(Exact(idx), ty) + } else { + let msg = format!("there is no argument named `{}`", name); + let sp = if self.is_literal { + *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + } else { + self.fmtsp + }; + let mut err = self.ecx.struct_span_err(sp, &msg[..]); + + if capture_feature_enabled && !self.is_literal { + err.note(&format!( + "did you intend to capture a variable `{}` from \ + the surrounding scope?", + name + )); + err.note( + "for hygiene reasons format_args! cannot capture variables \ + when the format string is expanded from a macro", + ); + } else if self.ecx.parse_sess().unstable_features.is_nightly_build() { + err.note(&format!( + "did you intend to capture a variable `{}` from \ + the surrounding scope?", + name + )); + err.help( + "add `#![feature(format_args_capture)]` to the crate \ + attributes to enable", + ); + } + + err.emit(); + } } } } @@ -951,6 +1003,7 @@ pub fn expand_preparsed_format_args( invalid_refs: Vec::new(), arg_spans, arg_with_formatting: Vec::new(), + is_literal: parser.is_literal, }; // This needs to happen *after* the Parser has consumed all pieces to create all the spans diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index e2d497a3adab3..11c1908b57cac 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -577,6 +577,9 @@ declare_features! ( /// Be more precise when looking for live drops in a const context. (active, const_precise_live_drops, "1.46.0", Some(73255), None), + /// Allows capturing variables in scope using format_args! + (active, format_args_capture, "1.46.0", Some(67984), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/librustc_parse_format/lib.rs b/src/librustc_parse_format/lib.rs index a5b5a1090cbfd..7db62f3493ede 100644 --- a/src/librustc_parse_format/lib.rs +++ b/src/librustc_parse_format/lib.rs @@ -190,7 +190,7 @@ pub struct Parser<'a> { /// Whether the source string is comes from `println!` as opposed to `format!` or `print!` append_newline: bool, /// Whether this formatting string is a literal or it comes from a macro. - is_literal: bool, + pub is_literal: bool, /// Start position of the current line. cur_line_start: usize, /// Start and end byte offset of every line of the format string. Excludes diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 06d1f36622b94..185ce1afde90e 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -338,6 +338,7 @@ symbols! { forbid, format_args, format_args_nl, + format_args_capture, from, From, from_desugaring, diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.rs b/src/test/ui/fmt/feature-gate-format-args-capture.rs new file mode 100644 index 0000000000000..21af91610915f --- /dev/null +++ b/src/test/ui/fmt/feature-gate-format-args-capture.rs @@ -0,0 +1,6 @@ +fn main() { + format!("{foo}"); //~ ERROR: there is no argument named `foo` + + // panic! doesn't hit format_args! unless there are two or more arguments. + panic!("{foo} {bar}", bar=1); //~ ERROR: there is no argument named `foo` +} diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.stderr b/src/test/ui/fmt/feature-gate-format-args-capture.stderr new file mode 100644 index 0000000000000..bbd4d759fb548 --- /dev/null +++ b/src/test/ui/fmt/feature-gate-format-args-capture.stderr @@ -0,0 +1,20 @@ +error: there is no argument named `foo` + --> $DIR/feature-gate-format-args-capture.rs:2:14 + | +LL | format!("{foo}"); + | ^^^^^ + | + = note: did you intend to capture a variable `foo` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + +error: there is no argument named `foo` + --> $DIR/feature-gate-format-args-capture.rs:5:13 + | +LL | panic!("{foo} {bar}", bar=1); + | ^^^^^ + | + = note: did you intend to capture a variable `foo` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs new file mode 100644 index 0000000000000..6ca7dcc216f3a --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs @@ -0,0 +1,6 @@ +#![feature(format_args_capture)] + +fn main() { + format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo` + format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar` +} diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr new file mode 100644 index 0000000000000..42039c33d2fec --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -0,0 +1,22 @@ +error: there is no argument named `foo` + --> $DIR/format-args-capture-macro-hygiene.rs:4:13 + | +LL | format!(concat!("{foo}")); + | ^^^^^^^^^^^^^^^^ + | + = note: did you intend to capture a variable `foo` from the surrounding scope? + = note: for hygiene reasons format_args! cannot capture variables when the format string is expanded from a macro + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: there is no argument named `bar` + --> $DIR/format-args-capture-macro-hygiene.rs:5:13 + | +LL | format!(concat!("{ba", "r} {}"), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: did you intend to capture a variable `bar` from the surrounding scope? + = note: for hygiene reasons format_args! cannot capture variables when the format string is expanded from a macro + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.rs b/src/test/ui/fmt/format-args-capture-missing-variables.rs new file mode 100644 index 0000000000000..3c596ae3bb899 --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-missing-variables.rs @@ -0,0 +1,22 @@ +#![feature(format_args_capture)] + +fn main() { + format!("{} {foo} {} {bar} {}", 1, 2, 3); + //~^ ERROR: cannot find value `foo` in this scope + //~^^ ERROR: cannot find value `bar` in this scope + + format!("{foo}"); //~ ERROR: cannot find value `foo` in this scope + + format!("{valuea} {valueb}", valuea=5, valuec=7); + //~^ ERROR cannot find value `valueb` in this scope + //~^^ ERROR named argument never used + + format!(r##" + + {foo} + + "##); + //~^^^^^ ERROR: cannot find value `foo` in this scope + + panic!("{foo} {bar}", bar=1); //~ ERROR: cannot find value `foo` in this scope +} diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.stderr b/src/test/ui/fmt/format-args-capture-missing-variables.stderr new file mode 100644 index 0000000000000..c3d740eef9d3c --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-missing-variables.stderr @@ -0,0 +1,52 @@ +error: named argument never used + --> $DIR/format-args-capture-missing-variables.rs:10:51 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ------------------- ^ named argument never used + | | + | formatting specifier missing + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-missing-variables.rs:4:13 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `bar` in this scope + --> $DIR/format-args-capture-missing-variables.rs:4:13 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-missing-variables.rs:8:13 + | +LL | format!("{foo}"); + | ^^^^^^^ not found in this scope + +error[E0425]: cannot find value `valueb` in this scope + --> $DIR/format-args-capture-missing-variables.rs:10:13 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-missing-variables.rs:14:13 + | +LL | format!(r##" + | _____________^ +LL | | +LL | | {foo} +LL | | +LL | | "##); + | |_______^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-missing-variables.rs:21:12 + | +LL | panic!("{foo} {bar}", bar=1); + | ^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs new file mode 100644 index 0000000000000..89dcfd8300435 --- /dev/null +++ b/src/test/ui/fmt/format-args-capture.rs @@ -0,0 +1,62 @@ +// run-pass +#![feature(format_args_capture)] + +fn main() { + named_argument_takes_precedence_to_captured(); + panic_with_single_argument_does_not_get_formatted(); + panic_with_multiple_arguments_is_formatted(); + formatting_parameters_can_be_captured(); +} + +fn named_argument_takes_precedence_to_captured() { + let foo = "captured"; + let s = format!("{foo}", foo="named"); + assert_eq!(&s, "named"); + + let s = format!("{foo}-{foo}-{foo}", foo="named"); + assert_eq!(&s, "named-named-named"); + + let s = format!("{}-{bar}-{foo}", "positional", bar="named"); + assert_eq!(&s, "positional-named-captured"); +} + +fn panic_with_single_argument_does_not_get_formatted() { + // panic! with a single argument does not perform string formatting. + // RFC #2795 suggests that this may need to change so that captured arguments are formatted. + // For stability reasons this will need to part of an edition change. + + let msg = std::panic::catch_unwind(|| { + panic!("{foo}"); + }).unwrap_err(); + + assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}")) +} + +fn panic_with_multiple_arguments_is_formatted() { + let foo = "captured"; + + let msg = std::panic::catch_unwind(|| { + panic!("{}-{bar}-{foo}", "positional", bar="named"); + }).unwrap_err(); + + assert_eq!(msg.downcast_ref::(), Some(&"positional-named-captured".to_string())) +} + +fn formatting_parameters_can_be_captured() { + let width = 9; + let precision = 3; + + let x = 7.0; + + let s = format!("{x:width$}"); + assert_eq!(&s, " 7"); + + let s = format!("{x: $DIR/ifmt-bad-arg.rs:27:26 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); | ^^^^^ + | + = note: did you intend to capture a variable `bar` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable error: there is no argument named `foo` --> $DIR/ifmt-bad-arg.rs:31:14 | LL | format!("{foo}"); | ^^^^^ + | + = note: did you intend to capture a variable `foo` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:32:17 @@ -155,6 +164,9 @@ error: there is no argument named `valueb` | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | ^^^^^^^^ + | + = note: did you intend to capture a variable `valueb` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:51 @@ -205,6 +217,9 @@ error: there is no argument named `foo` | LL | {foo} | ^^^^^ + | + = note: did you intend to capture a variable `foo` from the surrounding scope? + = help: add `#![feature(format_args_capture)]` to the crate attributes to enable error: invalid format string: expected `'}'`, found `'t'` --> $DIR/ifmt-bad-arg.rs:75:1 From 8caf60407033e84592821a3f7b3917fe80d343e0 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 27 Jun 2020 18:13:47 +0100 Subject: [PATCH 2/6] Improve messaging from PR feedback --- src/librustc_builtin_macros/format.rs | 14 +++++--------- .../fmt/feature-gate-format-args-capture.stderr | 6 ++---- src/test/ui/if/ifmt-bad-arg.stderr | 15 +++++---------- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 538d513c5d6ea..16e11fecf2963 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -507,8 +507,8 @@ impl<'a, 'b> Context<'a, 'b> { .features .map_or(false, |features| features.format_args_capture); - // For the moment capturing variables from format strings expanded from - // literals is disabled (see RFC #2795) + // For the moment capturing variables from format strings expanded from macros is + // disabled (see RFC #2795) let can_capture = capture_feature_enabled && self.is_literal; if can_capture { @@ -541,15 +541,11 @@ impl<'a, 'b> Context<'a, 'b> { when the format string is expanded from a macro", ); } else if self.ecx.parse_sess().unstable_features.is_nightly_build() { - err.note(&format!( - "did you intend to capture a variable `{}` from \ - the surrounding scope?", + err.help(&format!( + "if you intended to capture `{}` from the surrounding scope, add \ + `#![feature(format_args_capture)]` to the crate attributes", name )); - err.help( - "add `#![feature(format_args_capture)]` to the crate \ - attributes to enable", - ); } err.emit(); diff --git a/src/test/ui/fmt/feature-gate-format-args-capture.stderr b/src/test/ui/fmt/feature-gate-format-args-capture.stderr index bbd4d759fb548..f08f1651cb622 100644 --- a/src/test/ui/fmt/feature-gate-format-args-capture.stderr +++ b/src/test/ui/fmt/feature-gate-format-args-capture.stderr @@ -4,8 +4,7 @@ error: there is no argument named `foo` LL | format!("{foo}"); | ^^^^^ | - = note: did you intend to capture a variable `foo` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: there is no argument named `foo` --> $DIR/feature-gate-format-args-capture.rs:5:13 @@ -13,8 +12,7 @@ error: there is no argument named `foo` LL | panic!("{foo} {bar}", bar=1); | ^^^^^ | - = note: did you intend to capture a variable `foo` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: aborting due to 2 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index cbcb1df49851a..0ff478826f728 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -64,8 +64,7 @@ error: there is no argument named `foo` LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); | ^^^^^ | - = note: did you intend to capture a variable `foo` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: there is no argument named `bar` --> $DIR/ifmt-bad-arg.rs:27:26 @@ -73,8 +72,7 @@ error: there is no argument named `bar` LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); | ^^^^^ | - = note: did you intend to capture a variable `bar` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `bar` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: there is no argument named `foo` --> $DIR/ifmt-bad-arg.rs:31:14 @@ -82,8 +80,7 @@ error: there is no argument named `foo` LL | format!("{foo}"); | ^^^^^ | - = note: did you intend to capture a variable `foo` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:32:17 @@ -165,8 +162,7 @@ error: there is no argument named `valueb` LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | ^^^^^^^^ | - = note: did you intend to capture a variable `valueb` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `valueb` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:51 @@ -218,8 +214,7 @@ error: there is no argument named `foo` LL | {foo} | ^^^^^ | - = note: did you intend to capture a variable `foo` from the surrounding scope? - = help: add `#![feature(format_args_capture)]` to the crate attributes to enable + = help: if you intended to capture `foo` from the surrounding scope, add `#![feature(format_args_capture)]` to the crate attributes error: invalid format string: expected `'}'`, found `'t'` --> $DIR/ifmt-bad-arg.rs:75:1 From a1217cb29de22aae3cda717e78d1edd3e9d8ffd1 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 27 Jun 2020 21:18:02 +0100 Subject: [PATCH 3/6] Add `format_args_capture` to the unstable book --- .../library-features/format-args-capture.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/format-args-capture.md diff --git a/src/doc/unstable-book/src/library-features/format-args-capture.md b/src/doc/unstable-book/src/library-features/format-args-capture.md new file mode 100644 index 0000000000000..64b1b3d81bd83 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/format-args-capture.md @@ -0,0 +1,47 @@ +# `format_args_capture` + +The tracking issue for this feature is: [#67984] + +[#67984]: https://github.com/rust-lang/rust/issues/67984 + +------------------------ + +Enables `format_args!` (and macros which use `format_args!` in their implementation, such +as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope. +This avoids the need to pass named parameters when the binding in question +already exists in scope. + +```rust +#![feature(format_args_capture)] + +let (person, species, name) = ("Charlie Brown", "dog", "Snoopy"); + +// captures named argument `person` +print!("Hello {person}"); + +// captures named arguments `species` and `name` +format!("The {species}'s name is {name}."); +``` + +This also works for formatting parameters such as width and precision: + +```rust +#![feature(format_args_capture)] + +let precision = 2; +let s = format!("{:.precision$}", 1.324223); + +assert_eq!(&s, "1.32"); +``` + +A non-exhaustive list of macros which benefit from this functionality include: +- `format!` +- `print!` and `println!` +- `eprint!` and `eprintln!` +- `write!` and `writeln!` +- `panic!` +- `unreachable!` +- `unimplemented!` +- `todo!` +- `assert!` and similar +- macros in many thirdparty crates, such as `log` From 1a0343217d34b5ef60bf7c0a86376dcddf90b8cd Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 30 Jun 2020 23:33:26 +0100 Subject: [PATCH 4/6] Amend wording of note --- src/librustc_builtin_macros/format.rs | 2 +- src/test/ui/fmt/format-args-capture-macro-hygiene.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 16e11fecf2963..019432035fe34 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -537,7 +537,7 @@ impl<'a, 'b> Context<'a, 'b> { name )); err.note( - "for hygiene reasons format_args! cannot capture variables \ + "to avoid ambiguity format_args! cannot capture variables \ when the format string is expanded from a macro", ); } else if self.ecx.parse_sess().unstable_features.is_nightly_build() { diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr index 42039c33d2fec..55bd97bafe8b3 100644 --- a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -5,7 +5,7 @@ LL | format!(concat!("{foo}")); | ^^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `foo` from the surrounding scope? - = note: for hygiene reasons format_args! cannot capture variables when the format string is expanded from a macro + = note: to avoid ambiguity format_args! cannot capture variables when the format string is expanded from a macro = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `bar` @@ -15,7 +15,7 @@ LL | format!(concat!("{ba", "r} {}"), 1); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `bar` from the surrounding scope? - = note: for hygiene reasons format_args! cannot capture variables when the format string is expanded from a macro + = note: to avoid ambiguity format_args! cannot capture variables when the format string is expanded from a macro = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors From 10ebb2cbb291ead33e8e20519611e962b594db50 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Wed, 1 Jul 2020 11:35:17 +0100 Subject: [PATCH 5/6] Update src/librustc_builtin_macros/format.rs Apply suggestion from varkor Co-authored-by: varkor --- src/librustc_builtin_macros/format.rs | 2 +- src/test/ui/fmt/format-args-capture-macro-hygiene.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 019432035fe34..4cc83f8e31c20 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -537,7 +537,7 @@ impl<'a, 'b> Context<'a, 'b> { name )); err.note( - "to avoid ambiguity format_args! cannot capture variables \ + "to avoid ambiguity, `format_args!` cannot capture variables \ when the format string is expanded from a macro", ); } else if self.ecx.parse_sess().unstable_features.is_nightly_build() { diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr index 55bd97bafe8b3..0c5915149cd60 100644 --- a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr +++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -5,7 +5,7 @@ LL | format!(concat!("{foo}")); | ^^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `foo` from the surrounding scope? - = note: to avoid ambiguity format_args! cannot capture variables when the format string is expanded from a macro + = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `bar` @@ -15,7 +15,7 @@ LL | format!(concat!("{ba", "r} {}"), 1); | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `bar` from the surrounding scope? - = note: to avoid ambiguity format_args! cannot capture variables when the format string is expanded from a macro + = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors From 93d662fd9d0e39145ac45fc08f35a619e0cb3f8c Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Fri, 3 Jul 2020 18:17:53 +0100 Subject: [PATCH 6/6] Ignore test with panic on wasm targets --- src/test/ui/fmt/format-args-capture.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index 89dcfd8300435..7490632110c85 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -1,4 +1,6 @@ // run-pass +// ignore-wasm32 +// ignore-wasm64 #![feature(format_args_capture)] fn main() {