You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
From the documentation on std::fmt, section "Precision" (highlighting in bold by me):
There are three possible ways to specify the desired precision:
[...]
An asterisk .*:
.* means that this {...} is associated with two* format inputs rather than one: the first input holds the usize precision, and the second holds the value to print. Note that in this case, if one uses the format string {<arg>:<spec>.*}, then the <arg> part refers to the value to print, and the precision must come in the input preceding <arg>.
The bold part does not fit the current behavior. Consider the following snippet:
According to the documentation, one would expect this program to output 2.0 foobar. Instead, rustc fails to compile it:
error[[E0308]](https://doc.rust-lang.org/nightly/error-index.html#E0308): mismatched types
[--> src/main.rs:2:26
](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021#) |
2 | println!("{2:.*}{}", "foobar", 1, 2.0);
| ---------------------^^^^^^^^---------
| | |
| | expected `usize`, found `&str`
| arguments to this function are incorrect
|
= note: expected reference `&usize`
found reference `&&str`
note: associated function defined here
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
After glancing at the implementation, it looks to me like in the asterisk case, the precision is always the next implicit positional argument:
The current implementation determines the argument that will be formatted only after the argument containing the precision. This is the reason why the documentation fits the behavior for implicit positional parameters (like {:.*}). However, this doesn't help in the case of explicit positional parameters (like {42:.*}) and named parameters (like {foobar:.*}) – the precision usually does not come in the input preceding <arg>, as stated by the documentation.
In my opinion, this is not an implementation bug, but a documentation bug – the behavior hasn't changed since at least Rust 1.0, see https://godbolt.org/z/xf61oP6hE. It would probably be unwise to change it now as some crates may depend on it. I'd be happy to open a pull request fixing the documentation – there are a few other things I want to enhance in the std::fmt documentation anyway.
…triplett
std::fmt: Various fixes and improvements to documentation
This PR contains the following changes:
- **Added argument index comments to examples for specifying precision**
The examples for specifying the precision have comments explaining which
argument the specifier is referring to. However, for implicit positional
arguments, the examples simply refer to "next arg". To simplify following the
comments, "next arg" was supplemented with the actual resulting argument index.
- **Fixed documentation for specifying precision via `.*`**
The documentation stated that in case of the syntax `{<arg>:<spec>.*}`, "the
`<arg>` part refers to the value to print, and the precision must come in the
input preceding `<arg>`". This is not correct: the <arg> part does indeed refer
to the value to print, but the precision does not come in the input preciding
arg, but in the next implicit input (as if specified with {}).
Fixesrust-lang#96413.
- **Fix the grammar documentation**
According to the grammar documented, the format specifier `{: }` should not be
legal because of the whitespace it contains. However, in reality, this is
perfectly fine because the actual implementation allows spaces before the
closing brace. Fixesrust-lang#71088.
Also, the exact meaning of most of the terminal symbols was not specified, for
example the meaning of `identifier`.
- **Removed reference to Formatter::buf and other private fields**
Formatter::buf is not a public field and therefore isn't very helpful in user-
facing documentation. Also, the other public fields of Formatter were removed
during stabilization of std::fmt (4af3494) and can only be accessed via
getters.
- **Improved list of formatting macros**
Two improvements:
1. write! can not only receive a `io::Write`, but also a `fmt::Write` as first argument.
2. The description texts now contain links to the actual macros for easier
navigation.
From the documentation on
std::fmt
, section "Precision" (highlighting in bold by me):The bold part does not fit the current behavior. Consider the following snippet:
Playground link
According to the documentation, one would expect this program to output
2.0 foobar
. Instead, rustc fails to compile it:After glancing at the implementation, it looks to me like in the asterisk case, the precision is always the next implicit positional argument:
rust/compiler/rustc_parse_format/src/lib.rs
Lines 577 to 585 in 055bf4c
The current implementation determines the argument that will be formatted only after the argument containing the precision. This is the reason why the documentation fits the behavior for implicit positional parameters (like
{:.*}
). However, this doesn't help in the case of explicit positional parameters (like{42:.*}
) and named parameters (like{foobar:.*}
) – theprecision
usually does not come in the input preceding<arg>
, as stated by the documentation.In my opinion, this is not an implementation bug, but a documentation bug – the behavior hasn't changed since at least Rust 1.0, see https://godbolt.org/z/xf61oP6hE. It would probably be unwise to change it now as some crates may depend on it. I'd be happy to open a pull request fixing the documentation – there are a few other things I want to enhance in the
std::fmt
documentation anyway.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: