Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

print! and println! (and other similar macro pairs) accept differing types of "format strings" #47441

Closed
shepmaster opened this issue Jan 15, 2018 · 17 comments
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@shepmaster
Copy link
Member

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:

  • string literal
  • floating point literal
  • character literal
  • integer literal
  • boolean literal
@shepmaster shepmaster added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 15, 2018
@shepmaster
Copy link
Member Author

shepmaster commented Jan 15, 2018

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.

@eddyb
Copy link
Member

eddyb commented Jan 15, 2018

cc @jseyfried @alexcrichton

@shepmaster shepmaster changed the title print! and println! accept differing types of "format strings" print! and println! (and other similar macro pairs) accept differing types of "format strings" Jan 15, 2018
@shepmaster
Copy link
Member Author

The same applies for write / writeln and eprint / eprintln.

@sfackler
Copy link
Member

Duplicate of #30143. There's not really anything we can do here without breaking back compat.

@shepmaster
Copy link
Member Author

@sfackler

not really anything we can do here

Why not change print! to add a concat! call so they behave the same?

@sfackler
Copy link
Member

The writeln/etc behavior is a bug, not a feature.

@shepmaster
Copy link
Member Author

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?

@sfackler
Copy link
Member

I do not agree that making a misfeature larger for "consistency" is a good idea.

@shepmaster
Copy link
Member Author

#41192 (comment)

(In general, no one had a clear reason we didn't want this behavior even for print!)

@sfackler
Copy link
Member

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: {}").

@shepmaster
Copy link
Member Author

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

@sfackler
Copy link
Member

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.

@sfackler
Copy link
Member

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).

@Mark-Simulacrum
Copy link
Member

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.

@matthieu-m
Copy link
Contributor

@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.

@sfackler
Copy link
Member

Ah yeah that might have been it.

@XAMPPRocky
Copy link
Member

Closing as duplicate of #30143

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants