Closed
Description
format_args!()
can currently only be stored (and used later) if it has no arguments:
let a = format_args!("1 + 1 = 2"); // ok
let b = format_args!("1 + 1 = {}", 2); // error
println!("{a} {b}");
However, format_args!("1 + 1 = {}", 2)
is optimized to (effectively) format_args!("1 + 1 = 2")
as part of ast lowering.
To avoid allowing more code because of this optimization, the lowering results in a slightly different expansion that would still result in the same error. (By using &none()
rather than &[]
.)
However, I had failed to consider the effect in a const
:
However, because of #135139, we now have:
const X: std::fmt::Arguments = format_args!("1 + 1 = 2"); // ok
const Y: std::fmt::Arguments = format_args!("1 + 1 = {}", 2); // ok
const Z: std::fmt::Arguments = format_args!("1 + 1 = {}", 1 + 1); // error
println!("{X} {Y} {Z}");
(The expression for Y is subject to format_args inlining/flattening. The one for Z is not.)
It means there can be code out there that relies on format_args inlining/flattening working the way it does today.
Two solutions:
- Make the
Y
example fail to compile as well. This would be a (small?) breaking change. Don't allow flattened format_args in const. #139624 - Make all these examples work. (We probably want that in the future.)