Skip to content

Conversation

@ShoyuVanilla
Copy link
Member

Resolves #145739

I ran crater with #149291.
While there are still a few seemingly flaky, spurious results, no crates appear to be affected by this breaking change.

The only hit from the lint was
https://github.com/multiversx/mx-sdk-rs/blob/813927c03a7b512a3c6ef9a15690eaf87872cc5c/framework/meta-lib/src/tools/rustc_version_warning.rs#L19-L30,
which performs formatting on consts of type ::semver::Version. These constants contain a nested ::semver::Identifier (Version.pre.identifier) that has a custom destructor. However, this case is not impacted by the change, so no breakage is expected.

@rustbot
Copy link
Collaborator

rustbot commented Dec 12, 2025

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred in compiler/rustc_ast_lowering/src/format.rs

cc @m-ou-se

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 12, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 12, 2025

r? @spastorino

rustbot has assigned @spastorino.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rust-log-analyzer

This comment has been minimized.

@ShoyuVanilla
Copy link
Member Author

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 13, 2025
@ShoyuVanilla
Copy link
Member Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 13, 2025
@theemathas theemathas added the I-lang-nominated Nominated for discussion during a lang team meeting. label Dec 14, 2025
@theemathas
Copy link
Contributor

Nominating as per #145739 (comment)

@traviscross traviscross added P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang T-lang Relevant to the language team needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. labels Dec 14, 2025
@traviscross
Copy link
Contributor

traviscross commented Dec 14, 2025

It'd be worth adding a test for the drop behavior.

@traviscross
Copy link
Contributor

traviscross commented Dec 14, 2025

Given that this makes more sense for the language, along with the clean crater results and the intuition that it'd be surprising if anything actually leaned on this, I propose:

@rfcbot fcp merge lang

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Dec 14, 2025

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Dec 14, 2025
@m-ou-se m-ou-se assigned m-ou-se and unassigned spastorino Dec 17, 2025
@m-ou-se
Copy link
Member

m-ou-se commented Dec 24, 2025

I don't think we should do this. It will make the generated code for println!("{x} {x}"); less efficient, as it will get two separate arguments instead of one.

I don't want to end up in a situation where it would make sense for Clippy to suggest something like:

warning: using the same placeholder multiple times is inefficient as of Rust 1.94.0
 --> src/main.rs:3:5
  |
3 |     println!("{x} {x}");
  |     ^^^^^^^^^^^^^^^^^^^
  |
help: change this to
  |
3 -     println!("{x} {x}");
3 +     println!("{x} {x}", x = x);
  |

Adding , x = x shouldn't make a difference. If adding that makes the resulting code more efficient, I strongly feel like we've done something wrong.

@rust-rfcbot concern equivalence

@m-ou-se
Copy link
Member

m-ou-se commented Dec 24, 2025

I don't think using the same variable multiple times in a format string is common enough [..]

I think that situation is quite common actually. E.g.

println!("Accepted: {n_accepted}/{n_total}, Rejected: {n_rejected}/{n_total}");

format!("ip link {interface} down && ip link {interface} up");

println!("{indent}line 1\n{indent}line 2");

error!("Feature `{feature}` not enabled. To enable {feature}, add `#![feature({feature})]`.");

warn!("Integer literal out of range for {ty}. The range of {ty} is {min}{ty}..={max}{ty}.");

@workingjubilee
Copy link
Member

The RFC specifically says that it should be equivalent to format_args!("{name}", name = name).

https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html

@theemathas
Copy link
Contributor

@workingjubilee This has been previously discussed at #145739 (comment)

@workingjubilee
Copy link
Member

Yes, I'm stating that throwing out this equivalence because of wonkiness when using things that are often specifically highlighted as notoriously bad ideas is a bad idea.

@traviscross
Copy link
Contributor

traviscross commented Dec 25, 2025

Could we get what we want as a lang matter and keep most of the optimization benefit by doing the optimization only when it's guaranteed to not be observable, e.g. when values of the type don't need to be dropped and can't be interior mutable? Is that feasible?

@dianne
Copy link
Contributor

dianne commented Jan 14, 2026

Could we get what we want as a lang matter and keep most of the optimization benefit by doing the optimization only when it's guaranteed to not be observable, e.g. when values of the type don't need to be dropped and can't be interior mutable? Is that feasible?

I don't think there's much we can do about pathological Debug or Display impls that make it observable when something is formatted. In general, that doesn't even require interior mutability. Rust's type system just isn't equipped to reason about it; we don't have pure functions. I think the best we could get is to treat derived impls as trusted if fields' impls are trusted and do a pass where we mess with how format_args! expands based on whether we can prove formatting doesn't execute any untrusted code. But that leaves a lot of uses unoptimized and it's overengineered if all it's solving is this.

If we're only concerned with how many drop-sensitive temporaries are created, this is much easier to solve. We could optimize in the most common case (multiple mentions of local variables in a formatting string) without even needing type information when expanding format_args!, since taking a reference to a variable won't create a temporary; it's just named constants and nullary constructors where that can be an issue.

@joshtriplett joshtriplett added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Jan 21, 2026
@jackh726
Copy link
Member

I'm just gonna initiate a perf run to just see if there is any observable regressions under the current changes (though, recognizing a negative signal here is not super meaningful).

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Jan 21, 2026
Do not deduplicate captured args while expanding `format_args!`
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 21, 2026
@traviscross
Copy link
Contributor

@rfcbot fcp cancel

@rust-rfcbot
Copy link
Collaborator

@traviscross proposal cancelled.

@rust-rfcbot rust-rfcbot removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Jan 21, 2026
@traviscross traviscross added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jan 21, 2026
@traviscross
Copy link
Contributor

@rfcbot fcp merge lang,libs-api

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Jan 21, 2026

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Jan 21, 2026
@BurntSushi
Copy link
Member

I shared @m-ou-se's concern from above:

I don't think we should do this. It will make the generated code for println!("{x} {x}"); less efficient, as it will get two separate arguments instead of one.

I don't want to end up in a situation where it would make sense for Clippy to suggest something like:

warning: using the same placeholder multiple times is inefficient as of Rust 1.94.0
 --> src/main.rs:3:5
  |
3 |     println!("{x} {x}");
  |     ^^^^^^^^^^^^^^^^^^^
  |
help: change this to
  |
3 -     println!("{x} {x}");
3 +     println!("{x} {x}", x = x);
  |

Adding , x = x shouldn't make a difference. If adding that makes the resulting code more efficient, I strongly feel like we've done something wrong.

@rfcbot concern equivalence

@traviscross
Copy link
Contributor

traviscross commented Jan 21, 2026

@BurntSushi, @the8472, perhaps you could speak to the suggestion that we can optimize things at other layers, e.g. as @dianne described:

If we're only concerned with how many drop-sensitive temporaries are created, this is much easier to solve. We could optimize in the most common case (multiple mentions of local variables in a formatting string) without even needing type information when expanding format_args!, since taking a reference to a variable won't create a temporary; it's just named constants and nullary constructors where that can be an issue.

@traviscross
Copy link
Contributor

Also, could you both speak to whether, for these optimization reasons, you'd similarly expect that we would desugar format_args!("{x.f} {x.f}") as format_args!("{0} {0}", x.f)? For format_args!("{x.y} {x.y.z}"), what desugaring would you expect?

@rust-bors
Copy link
Contributor

rust-bors bot commented Jan 21, 2026

☀️ Try build successful (CI)
Build commit: 0282858 (0282858611f50e7d4c722e4a5295fc552f7236a1, parent: 625b63f9e148d511e187c71e5f70643ee62c77fb)

@rust-timer
Copy link
Collaborator

Queued 0282858 with parent 625b63f, future comparison URL.
There are currently 0 preceding artifacts in the queue.
It will probably take at least ~1.0 hours until the benchmark run finishes.

@the8472
Copy link
Member

the8472 commented Jan 21, 2026

It's more that my expectation is that these ought to be pure and we should optimize accordingly. And I haven't seen anyone making the argument that real-world code actually expects or relies on side-effects happening in print expressions, so why should we go out of our way to make code less efficient to enable something nobody needs?

We could optimize in the most common case (multiple mentions of local variables in a formatting string) without even needing type information when expanding format_args!, since taking a reference to a variable won't create a temporary

I guess that'd be fine, yeah.

@RalfJung
Copy link
Member

RalfJung commented Jan 21, 2026

We already enabled that -- you can have drop glue in consts, and you can print consts. So the question is, do we have nice regular behavior or do we add weird exceptions to the semantics of the language?

@the8472
Copy link
Member

the8472 commented Jan 21, 2026

Arguably macros are not semantics of the language, but arbitrary stuff a macro does to rewrite your code, no?

@RalfJung
Copy link
Member

Insofar as format_args is a builtin macro, its behavior is part of the language.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. I-lang-nominated Nominated for discussion during a lang team meeting. I-libs-api-nominated Nominated for discussion during a libs-api team meeting. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-waiting-on-perf Status: Waiting on a perf run to be completed. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

format_args deduplicates consts with interior mutability or destructor