Skip to content

Stabilize optimize attribute - #157273

Open
veluca93 wants to merge 1 commit into
rust-lang:mainfrom
veluca93:optimize-attribte
Open

Stabilize optimize attribute#157273
veluca93 wants to merge 1 commit into
rust-lang:mainfrom
veluca93:optimize-attribte

Conversation

@veluca93

@veluca93 veluca93 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

View all comments

This commit stabilizes the #[optimize] attribute, which allows for more fine-grained control of optimization levels.

Stabilization report

Summary

Tracking issue: #54882
Reference PRs: rust-lang/reference#2278

cc @rust-lang/lang @rust-lang/lang-advisors @rust-lang/t-compiler

What is stabilized

// Instructs the optimization pipeline to prioritize smaller code size over speed.
#[optimize(size)]
pub fn binary_size_sensitive() {
    // ...
}

// Instructs the optimization pipeline to prioritize execution speed over code size.
#[optimize(speed)]
pub fn performance_critical() {
    // ...
}

// Disables optimizations entirely for this item.
#[optimize(none)]
pub fn debug_only() {
    // ...
}

What isn't stabilized

We might want to allow specifying a per-function optimization level (i.e. #[optimize(level = 3)]). To my understanding, backend support for this is not quite there yet (and this - or other - extensions have consequently not been implemented yet).

Applying the attribute on a module level is also not implemented yet.

Design

Reference

RFC history

Answers to unresolved question

  • Should we also implement optimize(always)? optimize(level=x)?

Not yet.

  • Should there be any way to specify what global optimization for speed level is used in conjunction with the optimization for speed option (e.g. -Copt-level=s3 could be equivalent to -Copt-level=3 and #[optimize(size)] on the crate item).

Not yet.

Post-RFC changes

The optimize(none) variant was added. The variants above were discussed here: #54882 (comment)

Key points

Nightly uses

The standard library itself uses this attribute in a few places

Implementation

Major part

Coverage

Tool changes

Trivial changes to rust-analyzer to support the new attribute as an inert attribute: rust-lang/rust-analyzer#22511

Type system, opsem

Breaks the AM?

As far as the AM is concerned, this attribute doesn't exist.

Acknowledgments

Most of the work was not done by me, I'm just writing the stabilization report :-)

@nagisa did the initial implementation, @clubby789 implemented optimize(none) and fixed the attribute being allowed in too many places.

@rustbot

rustbot commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead.

cc @rust-lang/rust-analyzer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. labels Jun 1, 2026
@rustbot

rustbot commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

r? @JohnTitor

rustbot has assigned @JohnTitor.
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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 73 candidates
  • Random selection from 17 candidates

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@veluca93
veluca93 force-pushed the optimize-attribte branch from deb33c2 to 1de7123 Compare June 1, 2026 20:28
@rustbot

This comment has been minimized.

@veluca93
veluca93 force-pushed the optimize-attribte branch from 1de7123 to 56db805 Compare June 1, 2026 20:30
@veluca93 veluca93 changed the title stabilize optimize attribute (size, speed, and none) stabilize optimize attribute Jun 1, 2026
@tgross35

tgross35 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Given the interactions here, I expect this will need a lang+compiler FCP

@rustbot label +I-lang-nominated +I-compiler-nominated

See some recent discussion about this feature on Zulip #t-lang > status of #[optimize] attribute

@rustbot rustbot added I-compiler-nominated Nominated for discussion during a compiler team meeting. I-lang-nominated Nominated for discussion during a lang team meeting. labels Jun 1, 2026
@tgross35 tgross35 added needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. T-lang Relevant to the language team and removed T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 1, 2026
@rust-log-analyzer

This comment has been minimized.

@JohnTitor JohnTitor added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 1, 2026
@JohnTitor

Copy link
Copy Markdown
Member

Marking as S-blocked given the current status.

@veluca93
veluca93 force-pushed the optimize-attribte branch from 56db805 to 680ec3c Compare June 1, 2026 22:03
@rustbot

rustbot commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

These commits modify tests/rustdoc-json.
rustdoc-json is a public (but unstable) interface.

Please ensure that if you've changed the output:

  • It's intentional.
  • The FORMAT_VERSION in src/librustdoc-json-types is bumped if necessary.

cc @aDotInTheVoid, @obi1kenobi

@rustbot rustbot added the A-rustdoc-json Area: Rustdoc JSON backend label Jun 1, 2026
@obi1kenobi

Copy link
Copy Markdown
Member

With my cargo-semver-checks hat on: do we expect this attribute to have SemVer implications?

For example, can applying or removing this attribute on an item influence the contexts in which that item may be used without compile errors or other changes that would be considered public-API-breaking?

@veluca93

veluca93 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

With my cargo-semver-checks hat on: do we expect this attribute to have SemVer implications?

For example, can applying or removing this attribute on an item influence the contexts in which that item may be used without compile errors or other changes that would be considered public-API-breaking?

I don't believe this is possible - the attribute should only influence how the compiler optimizes functions, and compiler optimizations should not have any visible effects.

Comment thread tests/ui/feature-gates/feature-gate-optimize_attribute.stderr Outdated

@jieyouxu jieyouxu Jun 2, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion: hm, I wonder if this attribute deserves an entry in the rustc book (a bit like lint levels), because while sure there's the Reference PR, but this is more like a compiler knob?

View changes since the review

Comment thread tests/ui/attributes/optimize.rs
@veluca93

veluca93 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@rfcbot concern should-apply-to-closures

I think this attribute should apply to closures. Not doing so would make sense if we viewed closures as standalone anonymous function objects, but I think it is better to view them as callable extensions of the current function. In this view, code inside a closure is "part of" the enclosing function.

My proposal is different from how #[inline] applies to closures today. But on reflection, I think it would be a mistake to base the behavior of every new codegen attribute on inline, especially when it comes to closures. The inline hint is framed around the mechanics of the function call boundary itself, and its implications are sensitive to the context of caller and callee as well as the compiler and backend implementations. It is not obvious that the inline setting for a function should be applied to a closure, especially in the case of inline(never).

optimize, on the other hand, has a much smoother applicability relationship, and we can say that what applies to an outer function should likely apply to a closure. We have a stable precedent in #[target_feature], which applies to closures in a function. I think coverage (not yet stable) should behave similarly. What all of these have in common is that they apply to the function body rather than the call boundary.

See #158901.

@fee1-dead

fee1-dead commented Jul 9, 2026

Copy link
Copy Markdown
Member

@traviscross said above:

I still expect this attribute to affect only the item to which it is applied, in the same way as inline and our other codegen attributes. We treat closures as a kind of pseudo-item for this purpose.

I am thus marking the linked PR as S-waiting-on-team since there appears to be disagreement on whether closures should be affected.

@traviscross

Copy link
Copy Markdown
Contributor

I am thus marking the linked PR as S-waiting-on-team since there appears to be disagreement on whether closures should be affected.

For my part, I'm OK with applying this to nested closures. I see the appeal: reducing the degree to which things change when you move code into a closure. Separately, afterward, I'd like us to work to make our existing codegen attributes consistent with this new system. And I'd like us to find a way to fix the hygiene issue when macros introduce attributed closures.

One question: do we want optimize(none) to imply inline(never), or no? This came up as a question when @tmandry and I discussed. Doing so is in tension with the framing that we propagate codegen attributes that apply to the body but not to the function boundary. I'd lean toward separating these back out (though I understand there would remain coupling at the LLVM level). It seems OK to me if optimize(none) code ends up inlined and subject to the optimization level of what it's inlined into.

@traviscross

Copy link
Copy Markdown
Contributor

We talked about this in the lang call today. @tmandry will give a fuller write-up. In summary, we do not want to specify optimize(none) as implying inline(never), but, of course, the compiler is always free to not inline.

@traviscross traviscross removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Jul 15, 2026
@tmandry

tmandry commented Jul 16, 2026

Copy link
Copy Markdown
Member

In summary, we do not want to specify optimize(none) as implying inline(never), but, of course, the compiler is always free to not inline.

That's right. To summarize the model the lang team liked:

  • optimize sets the optimization goal of a function body, and closure bodies are part of the body of their containing function.
  • inline sets the inline policy of a function call boundary, and closures have their own boundary.
  • Neither should imply the other at the language level.
  • The compiler is free to change how it inlines to better implement the optimization goal, or vice versa. Both attributes are best-effort, and the implementation approach is allowed to change or ignore the attributes altogether.

If a particular combination of attributes is ineffective, given how our compiler or backend work, we should probably lint on that combination. I don't think we need to block stabilization on such a lint.

@nagisa

nagisa commented Jul 16, 2026

Copy link
Copy Markdown
Member

Inheritance of this attribute was also a part of the original rfc that introduced the attribute: https://github.com/rust-lang/rfcs/blob/master/text/2412-optimize-attr.md#reference-level-explanation (4th paragraph.)

@traviscross

Copy link
Copy Markdown
Contributor

Inheritance of this attribute was also a part of the original rfc that introduced the attribute: https://github.com/rust-lang/rfcs/blob/master/text/2412-optimize-attr.md#reference-level-explanation (4th paragraph.)

(It was left as an unresolved question.)

@rust-bors

This comment has been minimized.

@scottmcm

Copy link
Copy Markdown
Member

@rfcbot concern optimize-none-not-being-none-muddles-motivation

Ralf pointed out in #128657 (comment) that the PR implementing optimize(none) actually force-enabled some optimization passes that can remove UB.

If it's not "none" (and I guess also different from opt-level=0 or that change wouldn't have been needed?) but "well, sorta none but also optimized enough that operations on ZSTs don't make it to codegen (and maybe more things)", now I'm puzzled what the point of it is.

Did people actually want optimize(debug) or something?

@veluca93

veluca93 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

@rfcbot concern optimize-none-not-being-none-muddles-motivation

Ralf pointed out in #128657 (comment) that the PR implementing optimize(none) actually force-enabled some optimization passes that can remove UB.

If it's not "none" (and I guess also different from opt-level=0 or that change wouldn't have been needed?) but "well, sorta none but also optimized enough that operations on ZSTs don't make it to codegen (and maybe more things)", now I'm puzzled what the point of it is.

Did people actually want optimize(debug) or something?

FWIW I am significantly more interested in optimize(size) and optimize(speed) -- enough that I'd be happy to skip stabilizing optimize(none) for now.

(And among those, I moreover care more about optimize(size))

@veluca93

Copy link
Copy Markdown
Contributor Author

@rfcbot concern optimize-none-not-being-none-muddles-motivation

Ralf pointed out in #128657 (comment) that the PR implementing optimize(none) actually force-enabled some optimization passes that can remove UB.

If it's not "none" (and I guess also different from opt-level=0 or that change wouldn't have been needed?) but "well, sorta none but also optimized enough that operations on ZSTs don't make it to codegen (and maybe more things)", now I'm puzzled what the point of it is.

Did people actually want optimize(debug) or something?

Reading back the comments on the tracking issue, it seems that people do indeed want optimize(debug). I don't have especially strong opinions on the naming, but I will note that optimize(none) matches the C++ name for equivalent functionality (https://clang.llvm.org/docs/AttributeReference.html#optnone, which does not guarantee no optimizations either)

rust-bors Bot pushed a commit that referenced this pull request Jul 26, 2026
…leywiser,scottmcm

Closures inherit #[optimize] from the enclosing function by default.

Tracking issue: #54882
Stabilization PR: #157273
@veluca93
veluca93 force-pushed the optimize-attribte branch from 3aa06ad to 3a17308 Compare July 26, 2026 22:34
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

This commit stabilizes the `#[optimize]` attribute, which allows for more fine-grained control
of optimization levels.
@veluca93
veluca93 force-pushed the optimize-attribte branch from 3a17308 to 03bd1ac Compare July 27, 2026 08:35
@rustbot

rustbot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Jul 27, 2026
…leywiser,scottmcm

Closures inherit #[optimize] from the enclosing function by default.

Tracking issue: rust-lang/rust#54882
Stabilization PR: rust-lang/rust#157273
@tmandry

tmandry commented Jul 28, 2026

Copy link
Copy Markdown
Member

@rustbot label I-lang-nominated

See #157273 (comment). Nominating for team guidance on whether to ship this as optimize(none), optimize(debug), or leave it out for the current stabilization.

@rustbot rustbot added the I-lang-nominated Nominated for discussion during a lang team meeting. label Jul 28, 2026
@clubby789

Copy link
Copy Markdown
Contributor

Ralf pointed out in #128657 (comment) that the PR implementing optimize(none) actually force-enabled some optimization passes that can remove UB.

Just for current context, that issue was actually unrelated to is_required/optimize(none): rust-lang/miri#5226 (comment)
The semantics of optimize(none) are being worked on in #160015 and #160057

@RalfJung

RalfJung commented Jul 28, 2026

Copy link
Copy Markdown
Member

The semantics of optimize(none)

Yeah so that's the question I was about to bring up here. :)

Should optimize(none) be like -Copt-level=0 or should it be somehow even less optimized than that? Personally it feels to me like -Copt-level=0 makes most sense. (That would be -Zmir-opt-level=1 at the moment but that exact mapping is an unstable implementation detail.)

FWIW the same question comes up for optimize(speed). Is that like -O? (I'm not even sure how that one is currently implemented.)

@rust-bors

rust-bors Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #160102) made this pull request unmergeable. Please resolve the merge conflicts by rebasing.

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-rustdoc-json Area: Rustdoc JSON backend 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-lang-radar Items that are on lang's radar and will need eventual work or consideration. needs-reference-pr This language change needs an approved Reference PR 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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.