Skip to content

fulfill #[expect] expectations from derive generated code - #158943

Open
Albab-Hasan wants to merge 5 commits into
rust-lang:mainfrom
Albab-Hasan:expect-derive-cfg-experiment
Open

fulfill #[expect] expectations from derive generated code#158943
Albab-Hasan wants to merge 5 commits into
rust-lang:mainfrom
Albab-Hasan:expect-derive-cfg-experiment

Conversation

@Albab-Hasan

@Albab-Hasan Albab-Hasan commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

View all comments

an #[expect] on an item now covers the impls #[derive] generates from it. done at lint level building by reusing the items own expectation ids. no expansion changes at all so the cfg/cfg_attr attr id desync that forced the revert of #152289 in #153055 cant happen.

context in the issue thread starting at #150553 (comment)

fixes #150553

r? @Urgau

@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 8, 2026
@Albab-Hasan
Albab-Hasan marked this pull request as draft July 8, 2026 06:30
@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 Jul 8, 2026
Comment thread compiler/rustc_lint/src/levels.rs Outdated
@Albab-Hasan
Albab-Hasan requested a review from Urgau July 9, 2026 07:21
@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 Jul 9, 2026
@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

@Urgau hey can u pls look into this? sorry for the bother

@Urgau

Urgau commented Jul 11, 2026

Copy link
Copy Markdown
Member

Thanks, that looks better. I will take a closer look tomorrow or Monday.

You can switch to ready for review.

@Albab-Hasan
Albab-Hasan marked this pull request as ready for review July 11, 2026 15:34
@Urgau

Urgau commented Jul 12, 2026

Copy link
Copy Markdown
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 12, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 12, 2026
…try>

fulfill `#[expect]` expectations from derive generated code
@rust-bors

rust-bors Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: c23f6fe (c23f6feec7b496697f70c4f2fb0777995536ae15)
Base parent: b69e089 (b69e089eb3ec9976ddec602bf18c3d6a8ce72512)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (c23f6fe): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

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

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.1% [0.0%, 0.1%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.1% [-0.2%, -0.0%] 4
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary 2.6%, secondary 1.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [2.6%, 2.6%] 1
Regressions ❌
(secondary)
5.0% [4.6%, 5.3%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.6% [-2.4%, -0.9%] 2
All ❌✅ (primary) 2.6% [2.6%, 2.6%] 1

Cycles

Results (secondary 5.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
8.9% [1.6%, 25.7%] 9
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.3% [-4.8%, -2.0%] 4
All ❌✅ (primary) - - 0

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 489.358s -> 489.445s (0.02%)
Artifact size: 389.32 MiB -> 389.81 MiB (0.12%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 12, 2026
levels.add_command_line();
}

levels.inherit_derive_expectations(owner);

@Urgau Urgau Jul 12, 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.

Can you add a comment in

explaining why #[expect] is not on that list and pointing to this code?

View changes since the review

Comment thread compiler/rustc_lint/src/levels.rs Outdated
Comment thread compiler/rustc_lint/src/levels.rs Outdated
}
let hir::OwnerNode::Item(item) = tcx.hir_owner_node(owner) else { return };
let hir::ItemKind::Impl(impl_) = &item.kind else { return };
if !item.span.in_derive_expansion() {

@Urgau Urgau Jul 12, 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.

Have you tested what happens with a proc-macro?

Could you add a test case with Span::call_site, Span::mixed_site and Span::def_site.


@petrochenkov I know you've worked on spans/hygiene data before. Do you know if we can trust the ExpnData will always be right?

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Of course not, procedural macros can assign any spans they want to the produced tokens.

@petrochenkov petrochenkov Jul 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The general approach from #152289 seems right to me, compared to what this PR attempts to do.
Maybe in some modified form, with expects downgrated to allows or something.

Not sure why it relied on AttrIds being preserved. The mental model is that any proc macro generates tokens, and the tokens are then parsed. Built-in proc macros do optimize things by generating AST directly and skipping the parsing, but that's only an optimization, and the observable behavior should be as if the tokens were produced and parsed.

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.

That's what I also though, thanks for confirming it.

@Albab-Hasan unless there is a way to not rely (at all!) on the spans (and it's hygiene data), this approach seems like a dead-end.

@Albab-Hasan Albab-Hasan Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll look into it; see if anything can be done. if not I'll close this pr

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.

Maybe in some modified form, with expects downgrated to allows or something.

I proposed that to T-lang, but they explicitly wants #[expect] to act as one, since a warning may only be emitted in the derived code.

Not sure why it relied on AttrIds being preserved.

That's how the implementation of expectation works. StableLintExpectationId takes an attr_index.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

#[expect] to act as one, since a warning may only be emitted in the derived code.

Then it does require introducing some new infrastructure to preserve "item grouping", to implement this properly.

In #158980 we have a similar situation for cfg traces for derived impls used by rustdoc, but the traces can be best effort and use hacks.

@Albab-Hasan
Albab-Hasan requested a review from Urgau July 15, 2026 06:38
@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

the impl is now recognized through expn_that_defined, the def collectors record of which expansion created the definition. its recorded compiler side when the expansion output is collected into the AST so the spans a proc macro puts on its tokens have zero influence on it. name resolution already trusts this record for hygienic_eq.

the gate also requires the expansion to be a builtin derive, macro_def_id carrying #[rustc_builtin_macro]. builtin derives always emit impls for exactly the item they were applied to so the self type resolution cant point anywhere else. proc macro derives are out entirely whatever spans they use. added the test you asked for.

this also holds under the tokens-then-parse model @petrochenkov described. if builtin derives went through print and reparse the impl would still be collected under the same derive ExpnId. thats the difference to #152289 which needed AttrIds to survive the token roundtrip.

the check itself is tcx.is_builtin_derived which already exists and is what coherence uses to validate derive(CoercePointee) impls. it read def_span(..).ctxt().outer_expn_data() before. moved it to expn_that_defined so it stops depending on spans there too.

@petrochenkov

Copy link
Copy Markdown
Contributor

I like the idea with expn_that_defined.
It is also used for similar ad-hoc grouping for items produced by the same glob delegation (#157601).

Both this feature and #158980 ideally need some proper design, accounting for macro calls in all positions, not just derives in item positions.
The common thing is that some property from a macro call is propagated to all the code produced by that macro, and the property cannot be expressed as tokens.

#[expect] in particular can be used in non-item positions and should supposedly behave consistently - expect on a macro call is propagated to all nodes produced from that macro as a group. That's what the lang team want really implies.

@Urgau

Urgau commented Jul 16, 2026

Copy link
Copy Markdown
Member

#[expect] in particular can be used in non-item positions and should supposedly behave consistently - expect on a macro call is propagated to all nodes produced from that macro as a group. That's what the lang team want really implies.

I guess that depends if we want user derives to behave the same as the builtin one. We currently only duplicate #[allow], #[warn], ... for builtin derives, we don't do it for user derives (playground). For builtin derives I don't think we need to worry about about non-item, I'm not sure if we need to handle non-impl items either.

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 19, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 19, 2026
…try>

fulfill `#[expect]` expectations from derive generated code
@rust-bors

rust-bors Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 5f44591 (5f44591224c798c2230d2c7e919375cf84bfb648)
Base parent: c904ba3 (c904ba32e22c9d6fd31140b4283c5cc6c6b2fb5c)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (5f44591): comparison URL.

Overall result: ❌ regressions - no action needed

Benchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up.

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

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.2% [0.2%, 0.2%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

This perf run didn't have relevant results for this metric.

Cycles

Results (primary -2.5%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-2.5% [-2.7%, -2.1%] 3
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -2.5% [-2.7%, -2.1%] 3

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 486.808s -> 488.065s (0.26%)
Artifact size: 389.45 MiB -> 390.08 MiB (0.16%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 19, 2026
@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

is this good or would more optimization be preffered?

@Urgau

Urgau commented Jul 19, 2026

Copy link
Copy Markdown
Member

Thanks, that's plenty optimized. I will take another look in the next days.

@petrochenkov petrochenkov self-assigned this Jul 19, 2026
@petrochenkov petrochenkov removed their assignment Jul 20, 2026
@Urgau Urgau 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 Jul 20, 2026
@rust-bors

This comment has been minimized.

Albab-Hasan and others added 5 commits September 1, 2026 10:39
an `#[expect]` on an item now covers the impls `#[derive]` generates from it. lint level building recognizes a derive generated impl and applies the derived from items `#[expect]` attrs to it reusing their expectation ids. a lint triggered in the derived code is suppressed and fulfills the original expectation because the id is literally the same one. one written attr is one expectation. fulfilled from either site. reported exactly once when genuinely unfulfilled.

copying the attr during expansion was tried before and reverted because `cfg`/`cfg_attr` processing re-parses the derive input from tokens and attr ids dont survive that. here identity never travels through token streams so theres nothing to desync.

fixes rust-lang#150553
Co-authored-by: Urgau <3616612+Urgau@users.noreply.github.com>
… hygiene

Proc macros can assign arbitrary spans to the tokens they produce, so span
expansion data cannot prove an impl came from a derive. Gate expectation
inheritance on is_builtin_derived instead, and change that helper to read
expn_that_defined, the def collector's record of which expansion created
the definition, which token spans cannot influence. Only builtin derive
macros are covered; a new test checks that a proc-macro derive emitting
automatically_derived impls with call_site, mixed_site or def_site spans
never inherits or fulfills expectations.
@Albab-Hasan
Albab-Hasan force-pushed the expect-derive-cfg-experiment branch from 643122c to 840adfb Compare September 1, 2026 04:59
@rustbot

rustbot commented Sep 1, 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.

@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

@Urgau rebased onto master

@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

@rustbot label -S-blocked +S-waiting-on-review

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

Urgau commented Sep 1, 2026

Copy link
Copy Markdown
Member

Still waiting for T-lang, specifically at #150553 (comment).

@rustbot labels -S-waiting-on-review +S-waiting-on-t-lang

@rustbot rustbot added S-waiting-on-t-lang Status: Awaiting decision from T-lang and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-t-lang Status: Awaiting decision from T-lang 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.

#[expect(redundant_lifetimes)] doesn't work when #[derive(Debug)] is present

5 participants