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