Skip to content

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

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

Albab-Hasan wants to merge 2 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 Resolved
@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 Resolved
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.

@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
@rust-bors

This comment has been minimized.

@Albab-Hasan
Albab-Hasan force-pushed the expect-derive-cfg-experiment branch from 840adfb to a453be6 Compare October 29, 2026 16:50
@rustbot

This comment has been minimized.

@Albab-Hasan

Copy link
Copy Markdown
Contributor Author

@Urgau

t-lang ruling: #150553 (comment)

i rewrote it on top of the lint attribute port. it reads the adts LintCheck list with find_attr! now and the name resolution in add_hir_inner moved into a resolve_lint_check helper so both paths share it.

@rustbot ready

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 29, 2026
@Urgau Urgau removed the S-waiting-on-t-lang Status: Awaiting decision from T-lang label Oct 29, 2026
@Urgau

Urgau commented Oct 29, 2026

Copy link
Copy Markdown
Member

From a high level, this looks fine to me, but I know @petrochenkov had some opinions.

r? petrochenkov

@rustbot rustbot assigned petrochenkov and unassigned Urgau Oct 29, 2026
@Albab-Hasan

Albab-Hasan commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

@Urgau can you start a perf in the meantime?

@Urgau

Urgau commented Oct 30, 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 Oct 30, 2026
@rust-bors

This comment has been minimized.

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

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

rust-bors Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: c05c3cc (c05c3ccb14356e8376051ad69e38f0e9f80d0506)
Base parent: 92b5b8c (92b5b8c87c61b20adc9001b41baf587634a74734)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (c05c3cc): comparison URL.

Overall result: no relevant changes - 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

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

Max RSS (memory usage)

Results (secondary -1.0%)

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)
- - 0
Improvements ✅
(secondary)
-1.0% [-1.0%, -1.0%] 1
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.1%, secondary 3.1%)

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

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

Binary size

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

Bootstrap: 484.843s -> 485.586s (0.15%)
Artifact size: 406.61 MiB -> 406.77 MiB (0.04%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 30, 2026
@rust-bors

This comment has been minimized.

these record the current behaviour where an #[expect] on a derived item is not shared with the generated impls, so the lint still fires in derived code
impls generated by a builtin derive now inherit the #[expect] attributes of the derived-from item at lint level time, reusing the expectation id of the item instead of copying the attribute during expansion, so cfg re-parsing of the derive input cannot create a second expectation

the lint name resolution of add_hir_inner moves into resolve_lint_check so the inheritance can reuse it without emitting diagnostics twice
@Albab-Hasan
Albab-Hasan force-pushed the expect-derive-cfg-experiment branch from a453be6 to 8c9aa73 Compare November 1, 2026 02:58
@rustbot

rustbot commented Nov 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.

This branch has not been deployed

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

Labels

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.

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