Uh oh!
There was an error while loading. Please reload this page.
Stabilize attributes on closure and method call expressions - #159581
Stabilize attributes on closure and method call expressions#159581Unique-Usman wants to merge 1 commit into
Conversation
rustbot
commented
Jul 19, 2026
Some changes occurred in tests/ui/sanitizer cc @rcvalle |
rustbot
commented
Jul 19, 2026
r? @folkertdev rustbot has assigned @folkertdev. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
We generally do reference updates separately. you can open a PR over there and link it to this one.
Allow outer attributes directly on closure and method-call expressions without requiring stmt_expr_attributes. This also covers parenthesized expressions and complete method-call chains. Keep the feature gate for other expression kinds, including function calls, field accesses, indexing, binary expressions, and literals.\n\nUpdate UI tests and the Rust Reference to reflect the newly stable positions, and remove now-unused stmt_expr_attributes declarations from closure and coroutine tests. Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
a5c7c08 to
e040823Comparerust-log-analyzer
commented
Jul 19, 2026
The job Click to see the possible cause of the failure (guessed by this bot) |
RalfJung
commented
Jul 20, 2026
Some of this already is stable, isn't it? This works on stable: fnfoo(x:Option<i32>){
x.map(#[inline] |y| y+1);// does not work: let closure = (#[inline] || 42);}OTOH with a So, looks like attributes on expressions are already partially stabilized, but this stabilizes them a bit more? |
mejrs
commented
Jul 20, 2026
You have to add curlies, it's also allowed for the trailing expression in a block: let _x = {#[inline]
|| ()};but tool attributes are not allowed there on stable let _x = {#[rustfmt::skip]
|| ()}; |
This form is already stabilized, this is a summary of what has already being stabilized before this pr #15701 (comment)
Exactly, it stabilized unambiguous expression forms. |
This will need to be audited by me for historical context and macros, and by @fmease for the current parser state. Using something being a closure or a method call as a criterion seems to be a distraction, if something like #[attr]
method.call() + rhs;starts working after this PR, it means the core ambiguity preventing the stabilization is not resolved. UPD: #124099 was reverted due to breakage on real code, things are going to be very sad. |
Unique-Usman
commented
Jul 20, 2026
This is already being stabilized before this pr.
Thanks for the comment, definitely, auditing the pr will really be appreciated. I have actually done a sort of deep study and understanding of what has already being stabilzed and what was not stabilized and for what reason they were not stabilized and also added the relevant links or discussions which confirms what was stabilized or what was not and I wrote a detailed summary for that here: #15701 (comment) and also suggested a pathway forward and which lead to me working on this pr and the fact that some people show interest in it. I will add the link of the summary to the stabilization report. Thanks once again. |
mejrs
commented
Jul 20, 2026
Where? I don't think this should be stabilized, |
Unique-Usman
commented
Jul 20, 2026
oops, confirming it again, I was using the rust compiled version of this pr. @petrochenkov, thanks for pointing this out. This pr should not stabilized attribute of this particular expression. |
rustbot
commented
Jul 22, 2026
Reminder, once the PR becomes ready for a review, use |
Unique-Usman
commented
Jul 22, 2026
Do you mean, having a seperate feature gate for the features stabilized by this pr ? |
WaffleLapkin
commented
Jul 22, 2026
@Unique-Usman I mean changing the existing gate to only allow things that we want to stabilize. |
Unique-Usman
commented
Jul 22, 2026
@WaffleLapkin sorry, again, please can kindly break it down, I am not getting it. Thanks. |
WaffleLapkin
commented
Jul 22, 2026
@Unique-Usman I want you to change what Then you will have two PRs:
|
petrochenkov
commented
Jul 23, 2026
I'm not yet convinced this is the subset that we can or want to stabilize, so it's probably premature to make the changes. |
Unique-Usman
commented
Jul 23, 2026
Noted and thanks. |
Unique-Usman
commented
Jul 23, 2026
yep, I will wait for your auditing. Thanks for the help. |
☔ The latest upstream changes (presumably #159814) made this pull request unmergeable. Please resolve the merge conflicts by rebasing. |
petrochenkov
commented
Jul 27, 2026
This topic is also closely related to this issue
|
petrochenkov
commented
Jul 27, 2026
Another ambiguous case not addressed by #124099 and related to this issue #[attr1]
$expr;where In the "attribute is always an unary prefix operator" model the example above will contain two expression attributes, in the "attributes starting a statement are always statement attributes" the example will instead contain one statement attribute and one expression attribute inside the invisible parentheses introduced by |
Unique-Usman
commented
Jul 28, 2026
@petrochenkov thanks for the follow up, the question now is what is your suggestion to get this pr to land ? thanks |
petrochenkov
commented
Jul 28, 2026
This is waiting on me now, I planned to implement the suggestion from #159581 (comment) today and start crater, but didn't get to it. |
Unique-Usman
commented
Jul 28, 2026
ok, I will be expecting. |
petrochenkov
commented
Jul 30, 2026
|
View all comments
Stabilization report
Summary
This PR partially stabilizes outer attributes on expressions under the existing
stmt_expr_attributesfeature.It stabilizes attributes directly on closure expressions and method-call
expressions, including parenthesized forms and complete method-call chains:
RFC 16 proposed broader support for attributes on statements and expressions.
Several unambiguous positions have already become stable, including statements,
blocks, match arms, and elements of arrays, tuples, and function argument lists.
General expression attributes remain unstable because it may be unclear which
expression an initial attribute applies to.
This stabilization selects closures and method calls, whose attribute targets
are clear, while leaving the remaining expression and subexpression cases
behind
stmt_expr_attributes.Tracking and related work:
stmt_expr_attributestracking issue #15701Two I opened together with this one for reference update and the for rejecting cfg one expressions that cannot be safely remove:
cfgon expressions that cannot be safely removed #159580cc @rust-lang/lang @rust-lang/lang-advisors @rust-lang/lang-docs @rust-lang/compiler
What is stabilized
Closure expressions
Outer attributes may be placed directly on closures without enabling
stmt_expr_attributes:This stabilizes the attribute position. Existing target validation still
determines whether a particular attribute may be applied to a closure.
Method-call expressions
Outer attributes may be placed directly on method-call expressions:
For a method-call chain, the attribute applies to the complete resulting
method-call expression:
Parentheses around a closure or method call do not change whether the position
is stable:
What is not stabilized
The
stmt_expr_attributesfeature itself remains unstable. Attributes on otherexpression kinds continue to require the feature gate.
For example, these remain unstable:
Although
object.method().fieldcontains a method call, its outer expression isa field expression, so it is outside this stabilization.
This PR does not decide the behavior of attributes on arbitrary literals,
function calls, field expressions, indexing, binary expressions, or other
remaining expression and subexpression positions.
There is also a detailed summary report I created after deeply studying what was stabilized, what has not been stabilized and where were they confirmed to be stabilized and the summary can be find here: - #15701 (comment)
Design
The primary concern with general expression attributes is identifying the
expression to which an initial attribute belongs. For example:
#[attr] a + bcan raise readability and precedence questions about whether the attribute
belongs to
aor to the complete binary expression.Closures have a distinct syntactic introducer:
#[attr] || expressionMethod calls form a clear postfix expression:
For chained calls, the complete chain is represented by an outer method-call
expression. The attribute consequently applies to the complete chain.
This partial stabilization does not introduce additional feature gates. The
existing
stmt_expr_attributesgate remains active for all expression kindsoutside the stated boundary.
Interaction with
cfgStabilizing an attribute position does not mean that
#[cfg]may remove anexpression required by its parent.
For example:
cannot be configured away because that would leave the initializer incomplete.
It continues to produce:
rust-lang/rust#159580
ensures that
cfgon expressions that cannot be safely removed is rejectedregardless of whether the configuration evaluates to true or false.
Positions where
cfgcan safely remove a complete element, such as an array,tuple, or function argument element, are unaffected.
Implementation
The parser and AST already support this syntax, so this stabilization does not
change the grammar or AST representation.
The expression-attribute feature-gate checker now receives the attributed
ast::Expr. Before emitting thestmt_expr_attributesdiagnostic, itrecognizes:
ExprKind::ClosureExprKind::MethodCallExprKind::Parencontaining either of those expressionsThe expression node is passed through the relevant ordinary expansion,
optional-expression expansion, and
cfg_evalconfiguration paths so that theyall apply the same stability rule.
The
stmt_expr_attributesentry remains incompiler/rustc_feature/src/unstable.rs; it is not moved toaccepted.rs.Test coverage
Positive tests cover:
cfg_eval.#[inline],#[cold],#[coroutine], capture-analysis, and#[track_caller]uses on closures.Negative tests verify that the following remain gated:
Configuration tests verify that a required method-call expression cannot be
removed with
#[cfg(false)].Existing closure-analysis tests were updated only to remove their obsolete E0658
expectations. Their intended capture-analysis diagnostics remain. Coroutine
tests no longer enable
stmt_expr_attributessolely to place#[coroutine]ona closure.
Compatibility and language interactions
This is an additive change. Programs previously accepted on stable Rust remain
accepted, so a crater run is not expected to be necessary.
This stabilization:
cfg_eval, coroutines, or individual unstable attributes.stmt_expr_attributesfor all other expression kinds.Tools and documentation
No Cargo, rustdoc, Clippy, rustup, or docs.rs changes are required because no new
syntax or AST form is introduced. The syntax was already available on nightly.
Rustfmt and rust-analyzer use the existing expression-attribute syntax, but
their behavior should be confirmed during review.
Reference PR #2314:
method-call expression.
inline,cold, andinstruction_setdocumentation so that itno longer describes direct closure expression attributes as unsupported.
The Reference PR must be reviewed and approved by the lang-docs team before this
stabilization is merged.
Outstanding concerns
No known implementation or soundness issue specifically blocks this narrow
stabilization.
The broader design questions tracked in
#15701 and
#127436 remain relevant to
the expression kinds that are not being stabilized.
An existing FIXME notes differences between ordinary and optional expression
feature-gating paths. Both paths are updated and tested by this implementation,
so it does not block this stabilization.
Contributors and prior work
The current work builds on contributions from:
original RFC;
[rust-lang/rust#29850](Implements RFC 16, attributes on statements and expressions. #29850);
[rust-lang/rust#36995](stabilise ?, attributes on stmts, deprecate Reflect #36995);
the remaining feature into narrower stabilization candidates;
#[cfg]safetyfix, tests, and Reference update.
Acknowledgments
Thanks to the authors and implementers of RFC 16 and to everyone involved in
the expression-attribute discussions, implementations, and previous
stabilizations, including the contributors to #15701, #32796, #36995, #127436,
#134661, #159580, and the corresponding Reference work. Thanks to my rust compiler mentor @estebank and thanks to @WaffleLapkin for helping.