Rollup merge of #73670 - davidhewitt:format-args-capture, r=varkor
Add `format_args_capture` feature This is the initial implementation PR for [RFC 2795](https://github.com/rust-lang/rfcs/pull/2795). Note that, as dicussed in the tracking issue (#67984), the feature gate has been called `format_args_capture`. Next up I guess I need to add documentation for this feature. I've not written any docs before for rustc / std so I would appreciate suggestions on where I should add docs.
This commit is contained in:
commit
4a8d9ea80f
13 changed files with 305 additions and 5 deletions
6
src/test/ui/fmt/feature-gate-format-args-capture.rs
Normal file
6
src/test/ui/fmt/feature-gate-format-args-capture.rs
Normal file
|
|
@ -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`
|
||||
}
|
||||
18
src/test/ui/fmt/feature-gate-format-args-capture.stderr
Normal file
18
src/test/ui/fmt/feature-gate-format-args-capture.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error: there is no argument named `foo`
|
||||
--> $DIR/feature-gate-format-args-capture.rs:2:14
|
||||
|
|
||||
LL | format!("{foo}");
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | panic!("{foo} {bar}", bar=1);
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
||||
6
src/test/ui/fmt/format-args-capture-macro-hygiene.rs
Normal file
6
src/test/ui/fmt/format-args-capture-macro-hygiene.rs
Normal file
|
|
@ -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`
|
||||
}
|
||||
22
src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
Normal file
22
src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
Normal file
|
|
@ -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: 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`
|
||||
--> $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: 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
|
||||
|
||||
22
src/test/ui/fmt/format-args-capture-missing-variables.rs
Normal file
22
src/test/ui/fmt/format-args-capture-missing-variables.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
52
src/test/ui/fmt/format-args-capture-missing-variables.stderr
Normal file
52
src/test/ui/fmt/format-args-capture-missing-variables.stderr
Normal file
|
|
@ -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`.
|
||||
64
src/test/ui/fmt/format-args-capture.rs
Normal file
64
src/test/ui/fmt/format-args-capture.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// run-pass
|
||||
// ignore-wasm32
|
||||
// ignore-wasm64
|
||||
#![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::<String>(), 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:<width$}");
|
||||
assert_eq!(&s, "7 ");
|
||||
|
||||
let s = format!("{x:-^width$}");
|
||||
assert_eq!(&s, "----7----");
|
||||
|
||||
let s = format!("{x:-^width$.precision$}");
|
||||
assert_eq!(&s, "--7.000--");
|
||||
}
|
||||
|
|
@ -63,18 +63,24 @@ error: there is no argument named `foo`
|
|||
|
|
||||
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | format!("{foo}");
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
@ -155,6 +161,8 @@ error: there is no argument named `valueb`
|
|||
|
|
||||
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
@ -205,6 +213,8 @@ error: there is no argument named `foo`
|
|||
|
|
||||
LL | {foo}
|
||||
| ^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue