println! accepts non-string literals as the format string:
fn main() {
println!(12.3);
}
print! does not:
fn main() {
print!(12.3);
}
error: format argument must be a string literal.
--> src/main.rs:2:12
|
2 | print!(12.3);
| ^^^^
This is because println! is implemented as calling print! with the result of concat!:
https://github.com/rust-lang/rust/blob/1.23.0/src/libstd/macros.rs#L150-L154
print! just calls format_args:
https://github.com/rust-lang/rust/blob/1.23.0/src/libstd/macros.rs#L119-L121
However, concat! stringifies its argument:
https://github.com/rust-lang/rust/blob/1.23.0/src/libsyntax_ext/concat.rs#L32-L54
This means that the "format string" can be any of:
Personally, I don't think that println! should accept non-string arguments, but it may be too late to put that particular genie back in the bottle?
One "solution" would be to wrap a dummy concat call in the print! implementation to perform the same coercion.
cc @jseyfried @alexcrichton
The same applies for write / writeln and eprint / eprintln.
Duplicate of #30143. There's not really anything we can do here without breaking back compat.
@sfackler
not really anything we can do here
Why not change print! to add a concat! call so they behave the same?
The writeln/etc behavior is a bug, not a feature.
is a bug, not a feature.
I mean... "bugs" get fixed. This has been declared unfixable, so it's now a "feature". Unless somehow epochs will allow us to undo that mistake, isn't it better to be consistently broken?
I do not agree that making a misfeature larger for "consistency" is a good idea.
https://github.com/rust-lang/rust/pull/41192#issuecomment-300289463
(In general, no one had a clear reason we didn't want this behavior even for print!)
I have a reason: it is really annoying to accidentally leave off format arguments and have the result compile and print your template string. println!("foo: {}").
I'm not understanding your example:
error: 1 positional argument in format string, but no arguments were given
--> src/main.rs:10:5
|
10 | println!("foo: {}");
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate
Oops, I thought I remembered that doing weird things but must have been thinking of something else.
Regardless, though, this is a duplicate of that issue. As far as I know, no one actually intentionally uses this behavior. I don't know why we would go out of our way to extend the support of a weird oddity.
As a more real argument as to why this behavior is bad, it seems better to know that the formatting functions expect a string literal first always, as opposed to a string literal first, unless you want to print a literal value, in which case you can just put it in. If we did anything like this IMO, we'd want println!(x) to be equivalent to println!("{}", x).
So I feel like overall consensus though is that this is a duplicate issue and we don't want to "fix" (i.e., for consistency) print! and also don't want to remove (non backwards compatibly) the concat! from println!. Is that correct? If so, then we should close.
@sfackler : I think you remembered your issue backward. If you use println!(foo) it will print foo (as the string) instead of reminding you that you're missing a format string.
Ah yeah that might have been it.
Closing as duplicate of #30143
Most helpful comment
I do not agree that making a misfeature larger for "consistency" is a good idea.