Auto merge of #90473 - joshtriplett:stabilize-format-args-capture, r=Mark-Simulacrum
stabilize format args capture Works as expected, and there are widespread reports of success with it, as well as interest in it. RFC: rust-lang/rfcs#2795 Tracking issue: https://github.com/rust-lang/rust/issues/67984 Addressing items from the tracking issue: - We don't support capturing arguments from a non-literal format string like `format_args!(concat!(...))`. We could add that in a future enhancement, or we can decide that it isn't supported (as suggested in https://github.com/rust-lang/rust/issues/67984#issuecomment-801394736 ). - I've updated the documentation. - `panic!` now supports capture as well. - There are potentially opportunities to further improve diagnostics for invalid usage, such as if it looks like the user tried to use an expression rather than a variable. However, such cases are all already caught and provide reasonable syntax errors now, and we can always provided even friendlier diagnostics in the future.
This commit is contained in:
commit
c26746af5a
22 changed files with 83 additions and 167 deletions
|
@ -3,7 +3,7 @@
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
|
|
|
@ -527,17 +527,9 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
self.verify_arg_type(Exact(idx), ty)
|
self.verify_arg_type(Exact(idx), ty)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
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 macros is
|
// For the moment capturing variables from format strings expanded from macros is
|
||||||
// disabled (see RFC #2795)
|
// disabled (see RFC #2795)
|
||||||
let can_capture = capture_feature_enabled && self.is_literal;
|
if self.is_literal {
|
||||||
|
|
||||||
if can_capture {
|
|
||||||
// Treat this name as a variable to capture from the surrounding scope
|
// Treat this name as a variable to capture from the surrounding scope
|
||||||
let idx = self.args.len();
|
let idx = self.args.len();
|
||||||
self.arg_types.push(Vec::new());
|
self.arg_types.push(Vec::new());
|
||||||
|
@ -559,23 +551,15 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
};
|
};
|
||||||
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
|
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
|
||||||
|
|
||||||
if capture_feature_enabled && !self.is_literal {
|
err.note(&format!(
|
||||||
err.note(&format!(
|
"did you intend to capture a variable `{}` from \
|
||||||
"did you intend to capture a variable `{}` from \
|
the surrounding scope?",
|
||||||
the surrounding scope?",
|
name
|
||||||
name
|
));
|
||||||
));
|
err.note(
|
||||||
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",
|
||||||
when the format string is expanded from a macro",
|
);
|
||||||
);
|
|
||||||
} else if self.ecx.parse_sess().unstable_features.is_nightly_build() {
|
|
||||||
err.help(&format!(
|
|
||||||
"if you intended to capture `{}` from the surrounding scope, add \
|
|
||||||
`#![feature(format_args_capture)]` to the crate attributes",
|
|
||||||
name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(backtrace)]
|
#![feature(backtrace)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(destructuring_assignment)]
|
#![feature(destructuring_assignment)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
|
|
|
@ -301,6 +301,8 @@ declare_features! (
|
||||||
(accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
|
(accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
|
||||||
/// Allows dereferencing raw pointers during const eval.
|
/// Allows dereferencing raw pointers during const eval.
|
||||||
(accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None),
|
(accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None),
|
||||||
|
/// Allows capturing variables in scope using format_args!
|
||||||
|
(accepted, format_args_capture, "1.58.0", Some(67984), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: accepted features
|
// feature-group-end: accepted features
|
||||||
|
|
|
@ -539,9 +539,6 @@ declare_features! (
|
||||||
/// Be more precise when looking for live drops in a const context.
|
/// Be more precise when looking for live drops in a const context.
|
||||||
(active, const_precise_live_drops, "1.46.0", Some(73255), None),
|
(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),
|
|
||||||
|
|
||||||
/// Allows `if let` guard in match arms.
|
/// Allows `if let` guard in match arms.
|
||||||
(active, if_let_guard, "1.47.0", Some(51114), None),
|
(active, if_let_guard, "1.47.0", Some(51114), None),
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(iter_order_by)]
|
#![feature(iter_order_by)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(map_try_insert)]
|
#![feature(map_try_insert)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
|
|
@ -58,7 +58,7 @@ This API is completely unstable and subject to change.
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(format_args_capture)]
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(is_sorted)]
|
#![feature(is_sorted)]
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
//! format!("The number is {}", 1); // => "The number is 1"
|
//! format!("The number is {}", 1); // => "The number is 1"
|
||||||
//! format!("{:?}", (3, 4)); // => "(3, 4)"
|
//! format!("{:?}", (3, 4)); // => "(3, 4)"
|
||||||
//! format!("{value}", value=4); // => "4"
|
//! format!("{value}", value=4); // => "4"
|
||||||
|
//! let people = "Rustaceans";
|
||||||
|
//! format!("Hello {people}!"); // => "Hello Rustaceans!"
|
||||||
//! format!("{} {}", 1, 2); // => "1 2"
|
//! format!("{} {}", 1, 2); // => "1 2"
|
||||||
//! format!("{:04}", 42); // => "0042" with leading zeros
|
//! format!("{:04}", 42); // => "0042" with leading zeros
|
||||||
//! format!("{:#?}", (100, 200)); // => "(
|
//! format!("{:#?}", (100, 200)); // => "(
|
||||||
|
@ -80,6 +82,19 @@
|
||||||
//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b"
|
//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! If a named parameter does not appear in the argument list, `format!` will
|
||||||
|
//! reference a variable with that name in the current scope.
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! let argument = 2 + 2;
|
||||||
|
//! format!("{argument}"); // => "4"
|
||||||
|
//!
|
||||||
|
//! fn make_string(a: u32, b: &str) -> String {
|
||||||
|
//! format!("{b} {a}")
|
||||||
|
//! }
|
||||||
|
//! make_string(927, "label"); // => "label 927"
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
//! It is not valid to put positional parameters (those without names) after
|
//! It is not valid to put positional parameters (those without names) after
|
||||||
//! arguments that have names. Like with positional parameters, it is not
|
//! arguments that have names. Like with positional parameters, it is not
|
||||||
//! valid to provide named parameters that are unused by the format string.
|
//! valid to provide named parameters that are unused by the format string.
|
||||||
|
@ -98,6 +113,8 @@
|
||||||
//! println!("Hello {:1$}!", "x", 5);
|
//! println!("Hello {:1$}!", "x", 5);
|
||||||
//! println!("Hello {1:0$}!", 5, "x");
|
//! println!("Hello {1:0$}!", 5, "x");
|
||||||
//! println!("Hello {:width$}!", "x", width = 5);
|
//! println!("Hello {:width$}!", "x", width = 5);
|
||||||
|
//! let width = 5;
|
||||||
|
//! println!("Hello {:width$}!", "x");
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! This is a parameter for the "minimum width" that the format should take up.
|
//! This is a parameter for the "minimum width" that the format should take up.
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
#![feature(fmt_internals)]
|
#![feature(fmt_internals)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(inherent_ascii_escape)]
|
#![feature(inherent_ascii_escape)]
|
||||||
|
#![cfg_attr(bootstrap, feature(format_args_capture))]
|
||||||
#![feature(inplace_iteration)]
|
#![feature(inplace_iteration)]
|
||||||
#![feature(iter_advance_by)]
|
#![feature(iter_advance_by)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
# `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`
|
|
|
@ -1,6 +0,0 @@
|
||||||
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`
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
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
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(format_args_capture)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo`
|
format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo`
|
||||||
format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar`
|
format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: there is no argument named `foo`
|
error: there is no argument named `foo`
|
||||||
--> $DIR/format-args-capture-macro-hygiene.rs:4:13
|
--> $DIR/format-args-capture-macro-hygiene.rs:2:13
|
||||||
|
|
|
|
||||||
LL | format!(concat!("{foo}"));
|
LL | format!(concat!("{foo}"));
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -9,7 +9,7 @@ LL | format!(concat!("{foo}"));
|
||||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: there is no argument named `bar`
|
error: there is no argument named `bar`
|
||||||
--> $DIR/format-args-capture-macro-hygiene.rs:5:13
|
--> $DIR/format-args-capture-macro-hygiene.rs:3:13
|
||||||
|
|
|
|
||||||
LL | format!(concat!("{ba", "r} {}"), 1);
|
LL | format!(concat!("{ba", "r} {}"), 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(format_args_capture)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
//~^ ERROR: cannot find value `foo` in this scope
|
//~^ ERROR: cannot find value `foo` in this scope
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: named argument never used
|
error: named argument never used
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:10:51
|
--> $DIR/format-args-capture-missing-variables.rs:8:51
|
||||||
|
|
|
|
||||||
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||||
| ------------------- ^ named argument never used
|
| ------------------- ^ named argument never used
|
||||||
|
@ -7,37 +7,37 @@ LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||||
| formatting specifier missing
|
| formatting specifier missing
|
||||||
|
|
||||||
error[E0425]: cannot find value `foo` in this scope
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:4:17
|
--> $DIR/format-args-capture-missing-variables.rs:2:17
|
||||||
|
|
|
|
||||||
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `bar` in this scope
|
error[E0425]: cannot find value `bar` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:4:26
|
--> $DIR/format-args-capture-missing-variables.rs:2:26
|
||||||
|
|
|
|
||||||
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `foo` in this scope
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:8:14
|
--> $DIR/format-args-capture-missing-variables.rs:6:14
|
||||||
|
|
|
|
||||||
LL | format!("{foo}");
|
LL | format!("{foo}");
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `valueb` in this scope
|
error[E0425]: cannot find value `valueb` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:10:23
|
--> $DIR/format-args-capture-missing-variables.rs:8:23
|
||||||
|
|
|
|
||||||
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||||
| ^^^^^^^^ not found in this scope
|
| ^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `foo` in this scope
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:16:9
|
--> $DIR/format-args-capture-missing-variables.rs:14:9
|
||||||
|
|
|
|
||||||
LL | {foo}
|
LL | {foo}
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `foo` in this scope
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
--> $DIR/format-args-capture-missing-variables.rs:21:13
|
--> $DIR/format-args-capture-missing-variables.rs:19:13
|
||||||
|
|
|
|
||||||
LL | panic!("{foo} {bar}", bar=1);
|
LL | panic!("{foo} {bar}", bar=1);
|
||||||
| ^^^^^ not found in this scope
|
| ^^^^^ not found in this scope
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(format_args_capture)]
|
|
||||||
#![feature(cfg_panic)]
|
#![feature(cfg_panic)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -25,10 +25,10 @@ fn main() {
|
||||||
//~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
|
//~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
|
||||||
|
|
||||||
format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
//~^ ERROR: there is no argument named `foo`
|
//~^ ERROR: cannot find value `foo` in this scope
|
||||||
//~^^ ERROR: there is no argument named `bar`
|
//~^^ ERROR: cannot find value `bar` in this scope
|
||||||
|
|
||||||
format!("{foo}"); //~ ERROR: no argument named `foo`
|
format!("{foo}"); //~ ERROR: cannot find value `foo` in this scope
|
||||||
format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
|
format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
|
||||||
format!("{}", 1, 2); //~ ERROR: argument never used
|
format!("{}", 1, 2); //~ ERROR: argument never used
|
||||||
format!("{1}", 1, 2); //~ ERROR: argument never used
|
format!("{1}", 1, 2); //~ ERROR: argument never used
|
||||||
|
@ -43,7 +43,7 @@ fn main() {
|
||||||
// bad named arguments, #35082
|
// bad named arguments, #35082
|
||||||
|
|
||||||
format!("{valuea} {valueb}", valuea=5, valuec=7);
|
format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||||
//~^ ERROR there is no argument named `valueb`
|
//~^ ERROR cannot find value `valueb` in this scope
|
||||||
//~^^ ERROR named argument never used
|
//~^^ ERROR named argument never used
|
||||||
|
|
||||||
// bad syntax of the format string
|
// bad syntax of the format string
|
||||||
|
@ -60,7 +60,7 @@ fn main() {
|
||||||
{foo}
|
{foo}
|
||||||
|
|
||||||
"##);
|
"##);
|
||||||
//~^^^ ERROR: there is no argument named `foo`
|
//~^^^ ERROR: cannot find value `foo` in this scope
|
||||||
|
|
||||||
// bad syntax in format string with multiple newlines, #53836
|
// bad syntax in format string with multiple newlines, #53836
|
||||||
format!("first number: {}
|
format!("first number: {}
|
||||||
|
|
|
@ -58,30 +58,6 @@ LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
|
||||||
|
|
|
|
||||||
= note: positional arguments are zero-based
|
= note: positional arguments are zero-based
|
||||||
|
|
||||||
error: there is no argument named `foo`
|
|
||||||
--> $DIR/ifmt-bad-arg.rs:27:17
|
|
||||||
|
|
|
||||||
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
|
error: multiple unused formatting arguments
|
||||||
--> $DIR/ifmt-bad-arg.rs:32:17
|
--> $DIR/ifmt-bad-arg.rs:32:17
|
||||||
|
|
|
|
||||||
|
@ -156,14 +132,6 @@ LL | format!("{foo} {} {}", foo=1, 2);
|
||||||
| |
|
| |
|
||||||
| named argument
|
| named argument
|
||||||
|
|
||||||
error: there is no argument named `valueb`
|
|
||||||
--> $DIR/ifmt-bad-arg.rs:45:23
|
|
||||||
|
|
|
||||||
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
|
error: named argument never used
|
||||||
--> $DIR/ifmt-bad-arg.rs:45:51
|
--> $DIR/ifmt-bad-arg.rs:45:51
|
||||||
|
|
|
|
||||||
|
@ -208,14 +176,6 @@ LL | format!("foo %s baz", "bar");
|
||||||
|
|
|
|
||||||
= note: printf formatting not supported; see the documentation for `std::fmt`
|
= note: printf formatting not supported; see the documentation for `std::fmt`
|
||||||
|
|
||||||
error: there is no argument named `foo`
|
|
||||||
--> $DIR/ifmt-bad-arg.rs:60:9
|
|
||||||
|
|
|
||||||
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'`
|
error: invalid format string: expected `'}'`, found `'t'`
|
||||||
--> $DIR/ifmt-bad-arg.rs:75:1
|
--> $DIR/ifmt-bad-arg.rs:75:1
|
||||||
|
|
|
|
||||||
|
@ -302,6 +262,36 @@ LL | println!("{:.*}");
|
||||||
= note: positional arguments are zero-based
|
= note: positional arguments are zero-based
|
||||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
|
--> $DIR/ifmt-bad-arg.rs:27:17
|
||||||
|
|
|
||||||
|
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `bar` in this scope
|
||||||
|
--> $DIR/ifmt-bad-arg.rs:27:26
|
||||||
|
|
|
||||||
|
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
|
--> $DIR/ifmt-bad-arg.rs:31:14
|
||||||
|
|
|
||||||
|
LL | format!("{foo}");
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `valueb` in this scope
|
||||||
|
--> $DIR/ifmt-bad-arg.rs:45:23
|
||||||
|
|
|
||||||
|
LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
|
||||||
|
| ^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
|
--> $DIR/ifmt-bad-arg.rs:60:9
|
||||||
|
|
|
||||||
|
LL | {foo}
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/ifmt-bad-arg.rs:78:32
|
--> $DIR/ifmt-bad-arg.rs:78:32
|
||||||
|
|
|
|
||||||
|
@ -324,4 +314,5 @@ LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
|
||||||
|
|
||||||
error: aborting due to 36 previous errors
|
error: aborting due to 36 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
Some errors have detailed explanations: E0308, E0425.
|
||||||
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue