Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make lint diagnostics responsible for providing their primary span #125208

Closed
wants to merge 4 commits into from

Conversation

fmease
Copy link
Member

@fmease fmease commented May 17, 2024

Summary and Rustc-Dev-Facing Changes

Instead of passing the primary span of lint diagnostics separately — namely to the functions tcx.emit_span_lint and tcx.emit_node_span_lint —, make lint diagnostics responsible for “storing” (providing) their span. I've removed the two aforementioned methods. You are now expected to use tcx.emit_lint and tcx.emit_node_lint respectively and to provide the primary span when deriving LintDiagnostic (via #[primary_span]) / implementing LintDiagnostic manually (via LintDiagnostic::span).

Note

FIXME(fmease): Mention how early lints are handled.

Motivation

Making the general format of #[derive(LintDiagnostic)] identical to #[derive(Diagnostic)]. I bet this has lead to slight confusion or annoyances before. Moreover, it enables deriving both traits at once (see #125169 for the motivation).

Approach

As outlined in #125169 (comment), the naïve approach of doing the same as Diagnostic doesn't work for LintDiagnostic, i.e., setting the primary span with Diag::span inside decorate_lint (that's into_diag for Diagnostic) because lint_level (lint_level_impl) needs access to the primary spans before decorating the Diag to be able to filter out some lints (namely if they come from an external macro) etc.

Therefore, I had to introduce a new method to LintDiagnostic: fn span(&self) -> Option<MultiSpan> (similar to the existing method LintDiagnostic::msg).

Commits

  1. The 1st commit addresses #125169 (comment). It contains the necessary changes to the linting APIs. It doesn't build on its own due to the removed APIs. Split out for easier reviewing.
  2. The 2nd commit updates all existing lint diagnostics to use the new APIs. Most of them are mindless, monotonous, obvious changes. Some changes are slightly more involved out of necessity. I've verified (partly programmatically, partly manually) that all lint diags that used to have a primary span still have a primary span.
  3. The 3rd commit updates the fulldeps UI tests that exercise the (lint) diagnostic API
  4. The 4th commit fixes #125169. I've only deduplicated the lint diagnostic structs mentioned in the issue and haven't gone looking for other structs that may benefit from deriving both Diagnostic and LintDiagnostic because I didn't have the time to do so yet.

Meta

Fixes #125169.

I'll submit a rustc-dev-guide PR later.
I hope this doesn't need an MCP, it's pretty straight forward.

cc @davidtwco
r? @nnethercote or anyone on compiler who has the energy to review 82 files

@fmease fmease added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 17, 2024
@rustbot rustbot added A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic 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 May 17, 2024
@fmease
Copy link
Member Author

fmease commented May 17, 2024

@bors p=1 prone to bitrot

@fmease fmease force-pushed the lint-diags-store-their-span branch from 44d8cb9 to 68763a5 Compare May 17, 2024 11:20
@fmease fmease marked this pull request as ready for review May 17, 2024 11:20
@rustbot
Copy link
Collaborator

rustbot commented May 17, 2024

rustc_macros::diagnostics was changed

cc @davidtwco, @compiler-errors, @TaKO8Ki

Some changes occurred in exhaustiveness checking

cc @Nadrieril

Some changes occurred in match checking

cc @Nadrieril

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@fmease fmease removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 17, 2024
@fmease fmease changed the title Make lint diagnostics responsible for storing their span Make lint diagnostics responsible for storing their primary span May 17, 2024
@fmease fmease force-pushed the lint-diags-store-their-span branch from 68763a5 to b5bee8b Compare May 17, 2024 11:26
@rust-log-analyzer

This comment has been minimized.

@fmease fmease 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 May 17, 2024
@fmease fmease changed the title Make lint diagnostics responsible for storing their primary span Make lint diagnostics responsible for providing their primary span May 17, 2024
@fmease fmease force-pushed the lint-diags-store-their-span branch from b5bee8b to 5d6cff6 Compare May 17, 2024 14:50
@fmease fmease 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 May 17, 2024
@rust-log-analyzer

This comment has been minimized.

@fmease fmease force-pushed the lint-diags-store-their-span branch from 5d6cff6 to ce91022 Compare May 17, 2024 15:32
@rust-log-analyzer

This comment has been minimized.

@Xiretza
Copy link
Contributor

Xiretza commented May 17, 2024

I foresee lots of merge conflicts with #124417 :/

@fmease fmease force-pushed the lint-diags-store-their-span branch from ce91022 to d8ce69b Compare May 17, 2024 16:43
@fmease
Copy link
Member Author

fmease commented May 17, 2024

@Xiretza Happy to block this PR on yours and do the rebasing myself here.

@fmease fmease added the S-blocked Status: Marked as blocked ❌ on something else such as an RFC or other implementation work. label May 17, 2024
@bors
Copy link
Contributor

bors commented May 18, 2024

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

@nnethercote
Copy link
Contributor

@Xiretza Happy to block this PR on yours and do the rebasing myself here.

@fmease: this seems fine to me but I guess you're still waiting on this.

Copy link
Member

@davidtwco davidtwco left a comment

Choose a reason for hiding this comment

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

This looks good to me, r=me once you're ready to see this merged

@fmease fmease force-pushed the lint-diags-store-their-span branch from aee03c5 to b22eadf Compare October 24, 2024 17:35
@fmease
Copy link
Member Author

fmease commented Oct 24, 2024

@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 24, 2024
@bors
Copy link
Contributor

bors commented Oct 24, 2024

⌛ Trying commit b22eadf with merge 9de008a...

bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 24, 2024
…r=<try>

Make lint diagnostics responsible for providing their primary span

### Summary and Rustc-Dev-Facing Changes

Instead of passing the primary span of lint diagnostics separately — namely to the functions `tcx.emit_span_lint` and `tcx.emit_node_span_lint` —, make lint diagnostics responsible for “storing” (providing) their span. I've removed the two aforementioned methods. You are now expected to use `tcx.emit_lint` and `tcx.emit_node_lint` respectively and to provide the primary span when deriving `LintDiagnostic` (via `#[primary_span]`) / implementing `LintDiagnostic` manually (via `LintDiagnostic::span`).

### Motivation

Making the general format of `#[derive(LintDiagnostic)]` identical to `#[derive(Diagnostic)]`. I bet this has lead to slight confusion or annoyances before. Moreover, it enables deriving both traits at once (see rust-lang#125169 for the motivation).

### Approach

As outlined in rust-lang#125169 (comment), the naïve approach of doing the same as `Diagnostic` doesn't work for `LintDiagnostic`, i.e., setting the primary span with `Diag::span` inside `decorate_lint` (that's `into_diag` for `Diagnostic`) because `lint_level` (`lint_level_impl`) needs access to the primary spans before decorating the `Diag` to be able to filter out some lints (namely if they come from an external macro) etc.

Therefore, I had to introduce a new method to `LintDiagnostic`: `fn span(&self) -> Option<MultiSpan>` (similar to the existing method `LintDiagnostic::msg`).

### Commits

1. The 1st commit addresses [rust-lang#125169 (comment)](rust-lang#125169 (comment)). It contains the necessary changes to the linting APIs. It doesn't build on its own due to the removed APIs. Split out for easier reviewing.
2. The 2nd commit updates all existing lint diagnostics to use the new APIs. Most of them are mindless, monotonous, obvious changes. Some changes are *slightly* more involved out of necessity. I've verified (partly programmatically, partly manually) that all lint diags that used to have a primary span still have a primary span.
3. The 3rd commit updates the fulldeps UI tests that exercise the (lint) diagnostic API
4. The 4th commit fixes [rust-lang#125169](rust-lang#125169). I've only deduplicated the lint diagnostic structs mentioned in the issue and haven't gone looking for other structs that may benefit from deriving both `Diagnostic` and `LintDiagnostic` because I didn't have the time to do so yet.

### Meta

Fixes rust-lang#125169.

I'll submit a rustc-dev-guide PR later.
I hope this doesn't need an MCP, it's pretty straight forward.

cc `@davidtwco`
r? `@nnethercote` or anyone on compiler who has the energy to review 82 files
@fmease fmease force-pushed the lint-diags-store-their-span branch from b22eadf to 775527e Compare October 24, 2024 17:41
@fmease
Copy link
Member Author

fmease commented Oct 24, 2024

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Oct 24, 2024

⌛ Trying commit 775527e with merge 6932f95...

bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 24, 2024
…r=<try>

Make lint diagnostics responsible for providing their primary span

### Summary and Rustc-Dev-Facing Changes

Instead of passing the primary span of lint diagnostics separately — namely to the functions `tcx.emit_span_lint` and `tcx.emit_node_span_lint` —, make lint diagnostics responsible for “storing” (providing) their span. I've removed the two aforementioned methods. You are now expected to use `tcx.emit_lint` and `tcx.emit_node_lint` respectively and to provide the primary span when deriving `LintDiagnostic` (via `#[primary_span]`) / implementing `LintDiagnostic` manually (via `LintDiagnostic::span`).

> [!NOTE]
> FIXME(fmease): Mention how early lints are handled.

### Motivation

Making the general format of `#[derive(LintDiagnostic)]` identical to `#[derive(Diagnostic)]`. I bet this has lead to slight confusion or annoyances before. Moreover, it enables deriving both traits at once (see rust-lang#125169 for the motivation).

### Approach

As outlined in rust-lang#125169 (comment), the naïve approach of doing the same as `Diagnostic` doesn't work for `LintDiagnostic`, i.e., setting the primary span with `Diag::span` inside `decorate_lint` (that's `into_diag` for `Diagnostic`) because `lint_level` (`lint_level_impl`) needs access to the primary spans before decorating the `Diag` to be able to filter out some lints (namely if they come from an external macro) etc.

Therefore, I had to introduce a new method to `LintDiagnostic`: `fn span(&self) -> Option<MultiSpan>` (similar to the existing method `LintDiagnostic::msg`).

### Commits

1. The 1st commit addresses [rust-lang#125169 (comment)](rust-lang#125169 (comment)). It contains the necessary changes to the linting APIs. It doesn't build on its own due to the removed APIs. Split out for easier reviewing.
2. The 2nd commit updates all existing lint diagnostics to use the new APIs. Most of them are mindless, monotonous, obvious changes. Some changes are *slightly* more involved out of necessity. I've verified (partly programmatically, partly manually) that all lint diags that used to have a primary span still have a primary span.
3. The 3rd commit updates the fulldeps UI tests that exercise the (lint) diagnostic API
4. The 4th commit fixes [rust-lang#125169](rust-lang#125169). I've only deduplicated the lint diagnostic structs mentioned in the issue and haven't gone looking for other structs that may benefit from deriving both `Diagnostic` and `LintDiagnostic` because I didn't have the time to do so yet.

### Meta

Fixes rust-lang#125169.

I'll submit a rustc-dev-guide PR later.
I hope this doesn't need an MCP, it's pretty straight forward.

cc `@davidtwco`
r? `@nnethercote` or anyone on compiler who has the energy to review 82 files
@bors
Copy link
Contributor

bors commented Oct 24, 2024

☀️ Try build successful - checks-actions
Build commit: 6932f95 (6932f95f7e07a6e1df8a6e7bc81854d5eaab79c6)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (6932f95): comparison URL.

Overall result: ✅ improvements - no action needed

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.4% [-0.4%, -0.4%] 1
Improvements ✅
(secondary)
-0.6% [-1.6%, -0.1%] 3
All ❌✅ (primary) -0.4% [-0.4%, -0.4%] 1

Max RSS (memory usage)

Results (primary 2.1%, secondary 3.2%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.1% [1.3%, 2.8%] 2
Regressions ❌
(secondary)
3.2% [2.9%, 3.6%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.1% [1.3%, 2.8%] 2

Cycles

Results (primary -2.4%, secondary 3.1%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

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

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 785.158s -> 785.364s (0.03%)
Artifact size: 333.66 MiB -> 333.68 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Oct 25, 2024
@nnethercote
Copy link
Contributor

David gave a soft approval for an earlier version of this, so it makes sense to officially hand it over now that it seems close to being ready.

r? @davidtwco

@rustbot rustbot assigned davidtwco and unassigned nnethercote Oct 25, 2024
@Dylan-DPC Dylan-DPC 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 Oct 25, 2024
@fmease
Copy link
Member Author

fmease commented Oct 25, 2024

Yesterday I coincidentally stumbled upon this Zulip post from 2024-09-25 which essentially declares the current diagnostic translation effort (#100717) unfruitful and unmaintained. While I only read this post yesterday, I have been aware of this fact for some time.

Therefore I don't want to burden davidtwco with re-reviewing >1000 lines and I'm also fine with closing this PR.

Of course, not a lot has changed. It's essentially a rebase from a 5 month old master. I stalled the rebase until now because I knew that this approach (of making lint diagnostics responsible or providing their primary span) does not scale to early (buffered) lints. I came to realize that when reviewing PR #124417 (which made early lints translatable) and implementing PR #125410 (which won back some of the perf regressions caused by the former).

You say it doesn't scale to early (buffered) lints, so how did you succeed in rebasing then while keeping perf in check? Well, I've cheated a little bit. The statement "lints diagnostics are responsible for providing their primary span" now only holds for non-early lints. The early lint diagnostics don't provide a #[primary_span] / return None for LintDiagnostic::span(&self) -> Option<MultiSpan> with the hidden assumption/knowledge1 that it's supplied separately in opt_span_lint_with_diagnostics from BufferedEarlyLint.span.

For perf reasons, we can't eagerly "lower" BuiltinLintDiag to lint diagnostics ("impl LintDiagnostic") inside opt_span_lint_with_diagnostics via decorate_lint2. However, only if we lower eagerly, we can truly make early lint diagnostics responsible for providing their primary span – and that's off the table. Re. perf, the lowering step is expensive and therefore we delay this step as far back as possible. Namely we don't want to lower lint diagnostics that end up not getting emitted (due to lint levels). We achieve this by letting lint_level decide … which takes a Span that is used in its decision process! We need the primary span(s) before lowering to lint diagnostics, therefore lint diagnostics cannot possibly provide their primary span!

This creates a divide between early and late LintDiagnostics which is unacceptable in my opinion. I wanted to bring {,Lint}Diagnostic closer together for ease of understanding and use. This simply doesn't work if LintDiagnostic itself is divided. As such, I no longer believe in this PR.

Footnotes

  1. Well, I did add comments in the LintDiagnostic::span cases but not in the #[derive(LintDiagnostic)] ones (there are simply too many).

  2. See the merged commit https://github.com/rust-lang/rust/pull/125410/commits/37bf2d2dabdbdce9473b0fed1708fcbf31ba9c1a which reverted this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic 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.

rustc_macros: Make it possible to derive both Diagnostic and LintDiagnostic on the same type
10 participants