Skip to content

destringlyfy lint infrastructure - #164607

Open
mejrs wants to merge 7 commits into
rust-lang:mainfrom
mejrs:lint_name
Open

mejrs wants to merge 7 commits into
rust-lang:mainfrom
mejrs:lint_name

Conversation

@mejrs

@mejrs mejrs commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

View all comments

Currently, lints are passed as strings and parsed/split/reformatted/compared/etc in many many places. It's not always clear whether that string includes the tool or not.

Instead, they are passed around as:

pub struct LintName {
    pub tool: Option<Symbol>,
    pub name: Symbol,
}

r? @JonathanBrouwer

@rustbot

rustbot commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_ir

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) 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 Oct 19, 2026
@rustbot

rustbot commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

JonathanBrouwer is currently at their maximum review capacity.
They may take a while to respond.

@mejrs

mejrs commented Oct 19, 2026 •

Copy link
Copy Markdown
Member Author

haven't updated clippy yet. But I think I can do a perf run.

@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 19, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Oct 19, 2026
destringlyfy lint infrastructure
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 3dcd667 (3dcd66770271913d28347dd2820933e94b0f53a4)
Base parent: 07ea2af (07ea2af746e09a0e9e3ac9b39ee866bd9bf702a2)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (3dcd667): comparison URL.

Overall result: ❌✅ regressions and improvements - BENCHMARK(S) FAILED

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

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

❗ ❗ ❗ ❗ ❗
Warning ⚠️: The following benchmark(s) failed to build:

  • libc-0.2.172
  • Job failure

❗ ❗ ❗ ❗ ❗

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.3% [0.2%, 0.5%] 5
Improvements ✅
(primary)
-0.4% [-1.3%, -0.1%] 45
Improvements ✅
(secondary)
-0.1% [-0.1%, -0.1%] 2
All ❌✅ (primary) -0.4% [-1.3%, -0.1%] 45

Max RSS (memory usage)

Results (primary -1.0%, 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)
4.1% [0.5%, 9.5%] 7
Improvements ✅
(primary)
-1.0% [-1.0%, -1.0%] 1
Improvements ✅
(secondary)
-5.5% [-8.3%, -3.2%] 8
All ❌✅ (primary) -1.0% [-1.0%, -1.0%] 1

Cycles

Results (primary 2.2%, secondary 0.6%)

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

mean range count
Regressions ❌
(primary)
2.2% [2.2%, 2.2%] 1
Regressions ❌
(secondary)
3.1% [0.5%, 12.1%] 8
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.7% [-4.2%, -0.6%] 6
All ❌✅ (primary) 2.2% [2.2%, 2.2%] 1

Binary size

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

Bootstrap: 489.513s -> 489.49s (-0.00%)
Artifact size: 409.13 MiB -> 409.09 MiB (-0.01%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Oct 19, 2026
@Kivooeo

Kivooeo commented Oct 20, 2026

Copy link
Copy Markdown
Member

huh, any ideas why this might happenened in libc?

   thread 'rustc' (1970916) panicked at /rustc-dev/3dcd66770271913d28347dd2820933e94b0f53a4/compiler/rustc_lint/src/levels.rs:839:25:
    renamed lint does not exist: rustdoc::bare_urls

@mejrs

mejrs commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

huh, any ideas why this might happenened in libc?

   thread 'rustc' (1970916) panicked at /rustc-dev/3dcd66770271913d28347dd2820933e94b0f53a4/compiler/rustc_lint/src/levels.rs:839:25:
    renamed lint does not exist: rustdoc::bare_urls

it's one of the cases where a function takes (lint, tool) but in this case it's passed (rustdoc::bare_urls, None). i just didnt catch this one, it happened for clippy lints too.

@rust-log-analyzer

This comment has been minimized.

@rustbot

rustbot commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Oct 20, 2026

@ada4a ada4a left a comment •

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.

Please apologize the drive-by review. The idea seems very sensible, just some minor questions 👀

View changes since this review

Comment thread compiler/rustc_attr_ir/src/lint.rs Outdated
#[derive(Copy, Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)]
pub struct LintName {
/// The lint's tool name, if present.
pub tool: Option<Symbol>,

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.

Imo it would make sense to leave this as Option<Ident>, so that you don't need to ads a separate LintCheck.tool_span field?

/// produces multiple `LintCheck`s, one with a span pointing to `foo`
/// and another pointing to `bar`.
pub lint_span: Span,
pub lint_name: LintName,

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.

Maybe put this inside LintName as well, as it seems pretty related?

@rust-log-analyzer

This comment has been minimized.

@mejrs

mejrs commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

Please apologize the drive-by review. The idea seems very sensible, just some minor questions 👀

No need to apologize, all reviews are welcome :)

To answer your question w/r to spans: it would make comparing different LintNames complicated, because lint names with equal values but different spans will compare unequal.

And Span: !Ord, so this would require manual Ord impls, and I'd rather not go there...

@mejrs

mejrs commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

Also, possible followups:

  • clippy has it's own LintName, it could use this one instead
  • store all the builtin lints as symbols rather than string literals. just pre-interning them may also matter for perf.

@mejrs

mejrs commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@ada4a

ada4a commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

To answer your question w/r to spans: it would make comparing different LintNames complicated, because lint names with equal values but different spans will compare unequal.

And Span: !Ord, so this would require manual Ord impls, and I'd rather not go there...

I guess it'd be nice to have a wrapper like

struct SpannedLintName {
    tool: Option<Ident>,
    name: Symbol,
    /// The span of the complete lint name
    span: Span,
}

and use that inside LintCheck,
but converting it to/from LintName would probably not be zero-cost, so idk...

@rust-bors

rust-bors Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 767dd6c (767dd6cf7268381167f2af26e795d4de6291f3fc)
Base parent: a7c37f9 (a7c37f9f0ee5e93396106e9de20f4a86b4154e63)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (767dd6c): comparison URL.

Overall result: ❌✅ regressions and improvements - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never rustc-perf
@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.4% [0.4%, 0.5%] 3
Improvements ✅
(primary)
-0.4% [-1.3%, -0.1%] 44
Improvements ✅
(secondary)
-0.1% [-0.1%, -0.1%] 3
All ❌✅ (primary) -0.4% [-1.3%, -0.1%] 44

Max RSS (memory usage)

Results (secondary -1.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)
4.0% [0.5%, 9.7%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-5.4% [-9.4%, -0.7%] 7
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.6%, secondary 1.3%)

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.1%, 3.1%] 2
Regressions ❌
(secondary)
3.5% [0.4%, 12.8%] 10
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.1% [-6.7%, -1.2%] 5
All ❌✅ (primary) 2.6% [2.1%, 3.1%] 2

Binary size

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

Bootstrap: 491.717s -> 488.128s (-0.73%)
Artifact size: 408.99 MiB -> 408.98 MiB (-0.00%)

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

mejrs commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

I guess it'd be nice to have a wrapper like

I don't think it'd help much at this time, we also won't need this if we move lint registration into the attribute parser.


impl LintName {
pub fn new(segments: impl Iterator<Item = Symbol>) -> LintName {
let segments = segments.collect::<Vec<_>>();

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

Follow-up (unless you want to fix this immediately): Are we losing performance in this collect?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

its a bit vestigial (and it's easier to match on it), but i'll take a look

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.

I was thinking do it as a follow-up so we can independently measure a performance effect, and see if the change is worth it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sure

LintName { tool, name }
}

/// Panics if `lint` is empty.

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

I feel this comment is misleading if we only do this with debug_assertions

View changes since the review

LL - #[warn(clippy::dead_cod)]
LL + #[warn(dead_code)]
|
| ^^^^^^^^^^^^^^^^ help: did you mean: `dead_code`

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

I kinda prefer the old diagnostic here? Why did this change and how hard is this to undo?

View changes since the review

Comment thread compiler/rustc_middle/src/lint.rs
/// produces multiple `LintCheck`s, one with a span pointing to `foo`
/// and another pointing to `bar`.
pub lint_span: Span,
pub lint_name: LintName,

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

My dream solution would be to get anLintId here instead of syms.
I'm gonna do a quick experiment to see how realistic that is

View changes since the review

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.

First exploration seems to show potential here, I think this should be possible! (with a few minor hacks)
I'm going to try this in depth tomorrow

@mejrs mejrs Oct 25, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

how realistic that is

there are some reasons to not do this:

  • how do you represent a lint that doesn't exist, because e.g. the input is wrong or it belongs to a tool that isn't currently running
  • you'd need to move Lint and LintId far down in the crate graph to do this
  • it would be incompatible with implementing lint resolution for proc/decl macro lints, because we'd likely need to run queries to retrieve the lint information

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.

how do you represent a lint that doesn't exist, because e.g. the input is wrong or it belongs to a tool that isn't currently running

I think that could either stay in the HIR by name if it's useful, and if it's not useful removed entirely.

you'd need to move Lint and LintId far down in the crate graph to do this

rustc_attr_ir can depend directly on rustc_lint_defs. It already does transitively so it doesn't even worsen bootstrap times.

it would be incompatible with implementing lint resolution for proc/decl macro lints, because we'd likely need to run queries to retrieve the lint information

The only information we'd need is from the LintStore, which is available very early through the DynLintStore in Session


The only significant problem I've encountered so far is that LintIds are not encodable, so can't be part of the HIR. I was thinking to encode the index of the lint in LintStore::lints (field) instead.

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.

I got nerd-sniped too hard so this is part 1 of this approach: #164918

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

Fwiw, I think our approaches are actually mostly compatible. It's still possible to introduce a LintName type and use it in most places that your PR does, and I think that would be good. It's just that it shouldn't be what's stored in the LintCheck type

@JonathanBrouwer JonathanBrouwer Oct 25, 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.

This PR also has better perf than #164918 (tho both are improvements) so doing both definitely makes sense

@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 Oct 25, 2026
@mejrs

mejrs commented Oct 25, 2026

Copy link
Copy Markdown
Member Author

fwiw, what I want to experiment with next is to make Lint store a LintName rather than a &'static str

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

CheckLintNameResult::NoLint(suggestion)
}

fn check_tool_name_for_backwards_compat(

@mejrs mejrs Oct 25, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This code made:

  • legacy_numeric_constants work as clippy::legacy_numeric_constants
  • #[warn(DEAD_CODE)] would say that "in rustc" there is a lint named dead_code

The fix was simply to delete it, with no other effects.

@rust-bors

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

rustbot commented Oct 26, 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

A-attributes Area: Attributes (`#[…]`, `#![…]`) perf-regression Performance regression. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. 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.

7 participants