Skip to content

Inlining/flattening of format_args!() accidentally exposed as stable through const #139136

Closed
@m-ou-se

Description

@m-ou-se

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:

  1. 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
  2. Make all these examples work. (We probably want that in the future.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-fmtArea: `core::fmt`C-bugCategory: This is a bug.T-langRelevant to the language team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions