Skip to content

Disallow ambiguous attributes on expressions (take 2) - #160235

Open
petrochenkov wants to merge 1 commit into
rust-lang:mainfrom
petrochenkov:ambattr2
Open

Disallow ambiguous attributes on expressions (take 2)#160235
petrochenkov wants to merge 1 commit into
rust-lang:mainfrom
petrochenkov:ambattr2

Conversation

@petrochenkov

Copy link
Copy Markdown
Contributor

Previous reverted attempt - #124099.
cc #159581

TODO:

@rustbot

rustbot commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

The parser was modified, potentially altering the grammar of (stable) Rust
which would be a breaking change.

cc @fmease

@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. labels Jul 30, 2026
@rustbot

rustbot commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

r? @chenyukang

rustbot has assigned @chenyukang.
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 75 candidates
  • Random selection from 16 candidates

@petrochenkov petrochenkov 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 Jul 30, 2026
@rust-log-analyzer

This comment has been minimized.

@rustbot

rustbot commented Aug 2, 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.

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[TIMING:end] tool::ToolBuild { build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "tidy", path: "src/tools/tidy", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "", cargo_args: [], artifact_kind: Binary } -- 13.015
[TIMING:end] tool::Tidy { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu } -- 0.000
fmt check
Diff in /checkout/tests/codegen-llvm/loop-attrs/unroll-loop-metadata.rs:50:
     // CHECK-LABEL: @unroll_never
     // CHECK: !llvm.loop ![[DISABLE:[0-9]+]]
     let mut i = 0;
-    let _return = (1 + (#[unroll(never)]
-    loop {
-        unsafe { maybe_has_side_effect() }
-        i += 1;
-        if i >= 10 {
-            break 1;
-        }
-    }));
+    let _return = (1
+        + (#[unroll(never)]
+        loop {
+            unsafe { maybe_has_side_effect() }
+            i += 1;
+            if i >= 10 {
+                break 1;

@petrochenkov

Copy link
Copy Markdown
Contributor Author

Attributes in expressions, purely from syntactic point of view, at parsing time.
I.e. no distinction between active or inert, or built-in or custom attributes.
And without considering #159581 (comment).

Not syntactically suspicious (top level expressions):

Definitely can stabilize after accounting for macro attributes and #159581 (comment).

// let initializer
let x = #[attr] 10;
let x = #[attr] 10 else { ... };

// const or static item initializer
const C: u8 = #[attr] 10;
static C: u8 = #[attr] 10;

// enum discriminant value
enum E { V = #[attr] 10 }

// field default
struct S { field: u8 = #[attr] 10 }

// key value attribute
#[key = #[attr] value]

// `match` arm
match 10 {
    11 => #[attr] 12,
}

// struct literals fields
let x = Struct { field: #[attr] 10, ... }

// struct literals rest
let x = Struct { field: 10, ..#[attr] base }

// for loop iterator
for x in #[attr] 10 { ... }

// if condition
if #[attr] 10 { ... }

// while condition
while #[attr] 10 { ... }

// match scrutinee
match #[attr] 10 { ... }

// method call arguments
r.method(#[attr] 10, ...)

// array element or size
[#[attr] 10, 11, 12]
[#[attr] 10; 11]
[10; #[attr] 11]
[u8; #[attr] 11]

// function call argument
func(#[attr] 10, 11, 12)

// tuple element
(#[attr] 10, 11, 12)

// move expression
move(#[attr] 10)

// indexing argument
array[#[attr] 10]

// parentheses
(#[attr] 10)

// const generic defaults
fn foo<const C: u8 = #[attr] 10>() {}

// const parameter constraint
foo::<C = #[attr] 10>()

// const generic arguments (if supported at all)
foo::<#[attr] 10>()

// type ascription
builtin # type_ascribe(#[attr] 10, u8)

// unsafe binder casts
builtin # wrap_binder(#[attr] 10, u8)

// various inline asm operands
asm!("code", in("r") #[attr] x)

// some syntax for contracts, I didn't look closely

Semi-suspicious (top level expressions):

I don't see any actual issues, just would be interesting how often these will occur in the crater run.

Can stabilize (after accounting for macro attributes and #159581 (comment)) or not stabilize.

// closure body
let x = || #[attr] 10;

// break, return, yield, become, and yeet expressions
break #[attr] 10
return #[attr] 10
yield #[attr] 10
become #[attr] 10
do yeet #[attr] 10

// match or pattern guard conditions
pat if #[attr] true

// `expr` matcher as an await or yield receiver
$expr.await // `$expr` is `#[attr] 10`
$expr.yield // `$expr` is `#[attr] 10`

// `expr` matcher as a use receiver
$expr.use // `$expr` is `#[attr] 10`

// `expr` matcher as a field receiver
$expr.field // `$expr` is `#[attr] 10`

// `expr` matcher as a method receiver
$expr.method() // `$expr` is `#[attr] 10`

// `expr` matcher as a callable in a function call
$expr() // `$expr` is `#[attr] 10`

// `expr` matcher as an indexable expression
$expr[] // `$expr` is `#[attr] 10`

// `expr` matcher as a try expression
$expr? // `$expr` is `#[attr] 10`

Semi-suspicious (non-top level expressions):

I don't see any actual issues, just would be interesting how often these will occur in the crater run.

Can stabilize (after accounting for macro attributes and #159581 (comment)) or not stabilize.

// binary operator rhs
10 + #[attr] 11

// assignment rhs
lhs = #[attr] rhs
lhs += #[attr] rhs

// range rhs
10 .. #[attr] 11

// let expressions in if/while
if let x = #[attr] 10 && x == 11 { ... }

// prefix unary operator
- #[attr] 10

// reference operator
& #[attr] 10
& raw mut #[attr] 10

Suspicious (top level expressions):

Cannot stabilize, this is a long stanging issue with too permissive pattern parsing.

// `expr` matcher as a pattern
match 10 { $expr => {} } // `$expr` is `#[attr] 10`

// `expr` matcher in a range pattern
match 10 { $expr .. $expr => {} } // `$expr` is `#[attr] 10`

Suspicious (non-top level expressions):

Cannot stabilize.

// binary operator lhs
#[attr] 10 + 11

// assignment lhs
#[attr] lhs = rhs
#[attr] lhs += rhs

// range lhs
#[attr] 10 .. 11

// cast expressions
#[attr] 10 as u8

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

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants