Skip to content

Add a lint helper attribute namespace - #163625

Open
mejrs wants to merge 5 commits into
rust-lang:mainfrom
mejrs:lint_helper_namespace-
Open

mejrs wants to merge 5 commits into
rust-lang:mainfrom
mejrs:lint_helper_namespace-

Conversation

@mejrs

@mejrs mejrs commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

View all comments

(and also port over three rustc lint attributes, as proof of concept)

This PR implements parsing for the lint tool namespace (#[lint::attribute]) but doesn't add it as a builtin tool, so #![register_tool(lint)] is also required to use it. It raises an error on an unknown attribute within that namespace.

The primary motivations for creating this namespace are:

What is a "lint helper"

Attributes that change how or if a lint is emitted. Think of many of the internal attributes like #[rustc_as_ptr] , #[rustc_pass_by_value] etc. Other examples are #[deprecated] and #[must_not_suspend]. Even clippy has such a thing: #[clippy::format_args].

On breaking changes

This doesn't add lint as a built-in tool (like diagnostic, rustfmt, clippy etc are) so this pr is not a breaking change. The breaking changes are opt-in by using #![register_tool(lint)] in the crate root which is unstable at this time.

The way this PR is implemented means that, even if users could use #![register_tool(lint)] stably, they cannot stably use the namespace because an unknown attribute is an error and all valid attributes in it, at this time, are also feature gated. So there is no commitment to stability until we choose to stabilize an attribute in it.

Going forward

We can require using #![register_tool(lint)] indefinitely. It's possible to not require this this by adding lint as a builtin tool, but this (assuming #162597) breaks

#[lint::as_ptr]
struct Foo;

mod lint {
    pub use derive as as_ptr;
}

However as nobody on github does this it's probably only theoretically breaking. It's non-breaking to add it across an edition.

r? @estebank
cc @WaffleLapkin @petrochenkov

@rustbot

rustbot commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

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

@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. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 1, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@petrochenkov petrochenkov self-assigned this Oct 2, 2026
@mejrs
mejrs force-pushed the lint_helper_namespace- branch from 6ca0789 to 1656f72 Compare October 2, 2026 16:32
@rustbot

rustbot commented Oct 2, 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 2, 2026
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@petrochenkov

Copy link
Copy Markdown
Contributor

I originally self-assigned because I'd seen the word "namespace", which means something big, like type/value/macro namespaces.
But this is only adds a new "tool module" (in rustc-internal terms) like diagnostic, so it doesn't add something new to the language.

@petrochenkov petrochenkov removed their assignment Oct 14, 2026
@WaffleLapkin
WaffleLapkin self-requested a review October 16, 2026 12:43
@WaffleLapkin WaffleLapkin self-assigned this Oct 16, 2026
@mejrs
mejrs force-pushed the lint_helper_namespace- branch from 1656f72 to 4339030 Compare October 19, 2026 13:57
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@mejrs
mejrs force-pushed the lint_helper_namespace- branch from 4339030 to c839f3f Compare October 28, 2026 22:21
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@mejrs
mejrs force-pushed the lint_helper_namespace- branch from c839f3f to d99929a Compare October 29, 2026 00:06
@rust-bors

This comment has been minimized.

@mejrs
mejrs force-pushed the lint_helper_namespace- branch from d99929a to 9748663 Compare October 31, 2026 17:10
@rustbot

This comment has been minimized.

@mejrs

mejrs commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

@WaffleLapkin, @estebank, is either of you be able to review this?

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 3, 2026
@mejrs

mejrs commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

One question: does this mean that users now won't be able to provide a lint tool that they register? register_tool(lint) only enables the internal machinery only?

If it's registered as a tool, we parse #[lint::attr] and it's either an error or feature gate, if it's not registered it's also an error. Given this, it would be unpractical for someone to design a tool named lint and assign their own meaning to these lint attributes, just like it would be impractical for a tool to assign it's own meaning to #[no_mangle] or #[repr(C)].

Comment thread library/alloc/src/boxed.rs Resolved
Comment thread library/alloc/src/vec/mod.rs Resolved
@mejrs
mejrs force-pushed the lint_helper_namespace- branch from 9748663 to ce0826e Compare November 3, 2026 09:48
@rust-bors rust-bors Bot 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Nov 3, 2026
@rust-bors

rust-bors Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

⚠️ A new commit ce0826ead59ea81eb4f0ae1586ca36231b8092f9 was pushed.

This pull request was unapproved.

@rustbot

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

@mejrs

mejrs commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

@bors r=estebank

@rust-bors

rust-bors Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

📌 Commit ce0826e has been tentatively approved by estebank

It will be put into the queue for this repository once PR CI succeeds.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 3, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Nov 3, 2026
…tebank

Add a lint helper attribute namespace

(and also port over three rustc lint attributes, as proof of concept)

This PR implements parsing for the `lint` tool namespace (`#[lint::attribute]`) but doesn't add it as a builtin tool, so `#![register_tool(lint)]` is also required to use it. It raises an error on an unknown attribute within that namespace.

The primary motivations for creating this namespace are:
- creating a place for attributes like `trivial_field_reads` (rust-lang#160666) and `c_buffer_length` (rust-lang#162565) to live, as these IMO do not belong in the diagnostic namespace.
- make it easier to unstably land lints and lint helper attributes, as these currently suffer from the "any new built-in attribute is a breaking change" problem.
- implementing (part of) rust-lang#160808

### What is a "lint helper"

Attributes that change how or if a lint is emitted. Think of many of the internal attributes like `#[rustc_as_ptr]` , `#[rustc_pass_by_value]` etc. Other examples are `#[deprecated]` and `#[must_not_suspend]`. Even `clippy` has such a thing: `#[clippy::format_args]`.

### On breaking changes

This doesn't add `lint` as a built-in tool (like `diagnostic`, `rustfmt`, `clippy` etc are) so this pr is not a breaking change. The breaking changes are opt-in by using `#![register_tool(lint)]` in the crate root which is unstable at this time.

The way this PR is implemented means that, even if users could use `#![register_tool(lint)]` stably, they cannot stably use the namespace because an unknown attribute is an error and all valid attributes in it, at this time, are also feature gated. So there is no commitment to stability until we choose to stabilize an attribute in it.

### Going forward

We can require using `#![register_tool(lint)]` indefinitely. It's possible to not require this this by adding `lint` as a builtin tool, but this (assuming rust-lang#162597) breaks
```rust
#[lint::as_ptr]
struct Foo;

mod lint {
    pub use derive as as_ptr;
}
```
However as [nobody on github does this](https://github.com/search?type=code&q=%22%23%5Blint%3A%3A%22+language%3ARust) it's probably only theoretically breaking. It's non-breaking to add it across an edition.

r? @estebank
cc @WaffleLapkin @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Nov 3, 2026
…uwer

Rollup of 20 pull requests

Successful merges:

 - #149245 (Make inline attributes apply to the generated `poll` in async fn)
 - #163495 (Parallelize AST -> HIR lowering)
 - #164304 ([perf] Reuse CanonicalVarKinds if no new variables were added)
 - #165109 (Avoid building a region map when erasing bound regions)
 - #163393 (std: Use getexecpath() for current_exe() on OpenBSD)
 - #163625 (Add a lint helper attribute namespace )
 - #164414 (Add `let_underscore_drop_guard` lint.)
 - #165342 (Avoid unnecessary MIR traversals in CheckPackedRef lint)
 - #165351 (delegation: insert probing adjustments before args check adjustments)
 - #165358 (Reenable some cg_gcc tests that were disabled)
 - #165377 (Make `no_implicit_prelude` not suppress tool attributes)
 - #165397 (Add codegen test for unused match arms removed after inlining)
 - #165398 (Rework parallel reproducibility tests)
 - #162608 (Avoid oscillating line wrapping due to symbol indices)
 - #164241 (make the safety documentation consistent in Ptr module)
 - #165029 (Use `MalformedLintAttributeInput` in more places)
 - #165203 (AIX: Implement TLS destructor guard in std and update dynamic-loading-cdylib test)
 - #165230 (Fix rigidity assertion ICE)
 - #165293 (unstable-book: update default-visibility.md to link to tracking issue)
 - #165374 (Refactorings in preparation for the move trait)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Nov 3, 2026
…tebank

Add a lint helper attribute namespace

(and also port over three rustc lint attributes, as proof of concept)

This PR implements parsing for the `lint` tool namespace (`#[lint::attribute]`) but doesn't add it as a builtin tool, so `#![register_tool(lint)]` is also required to use it. It raises an error on an unknown attribute within that namespace.

The primary motivations for creating this namespace are:
- creating a place for attributes like `trivial_field_reads` (rust-lang#160666) and `c_buffer_length` (rust-lang#162565) to live, as these IMO do not belong in the diagnostic namespace.
- make it easier to unstably land lints and lint helper attributes, as these currently suffer from the "any new built-in attribute is a breaking change" problem.
- implementing (part of) rust-lang#160808

### What is a "lint helper"

Attributes that change how or if a lint is emitted. Think of many of the internal attributes like `#[rustc_as_ptr]` , `#[rustc_pass_by_value]` etc. Other examples are `#[deprecated]` and `#[must_not_suspend]`. Even `clippy` has such a thing: `#[clippy::format_args]`.

### On breaking changes

This doesn't add `lint` as a built-in tool (like `diagnostic`, `rustfmt`, `clippy` etc are) so this pr is not a breaking change. The breaking changes are opt-in by using `#![register_tool(lint)]` in the crate root which is unstable at this time.

The way this PR is implemented means that, even if users could use `#![register_tool(lint)]` stably, they cannot stably use the namespace because an unknown attribute is an error and all valid attributes in it, at this time, are also feature gated. So there is no commitment to stability until we choose to stabilize an attribute in it.

### Going forward

We can require using `#![register_tool(lint)]` indefinitely. It's possible to not require this this by adding `lint` as a builtin tool, but this (assuming rust-lang#162597) breaks
```rust
#[lint::as_ptr]
struct Foo;

mod lint {
    pub use derive as as_ptr;
}
```
However as [nobody on github does this](https://github.com/search?type=code&q=%22%23%5Blint%3A%3A%22+language%3ARust) it's probably only theoretically breaking. It's non-breaking to add it across an edition.

r? @estebank
cc @WaffleLapkin @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Nov 3, 2026
…uwer

Rollup of 21 pull requests

Successful merges:

 - #165416 (fix unsoundness when compiling `[diverging_const; 0]`)
 - #149245 (Make inline attributes apply to the generated `poll` in async fn)
 - #163495 (Parallelize AST -> HIR lowering)
 - #164304 ([perf] Reuse CanonicalVarKinds if no new variables were added)
 - #165109 (Avoid building a region map when erasing bound regions)
 - #163393 (std: Use getexecpath() for current_exe() on OpenBSD)
 - #163625 (Add a lint helper attribute namespace )
 - #164414 (Add `let_underscore_drop_guard` lint.)
 - #165342 (Avoid unnecessary MIR traversals in CheckPackedRef lint)
 - #165351 (delegation: insert probing adjustments before args check adjustments)
 - #165358 (Reenable some cg_gcc tests that were disabled)
 - #165377 (Make `no_implicit_prelude` not suppress tool attributes)
 - #165397 (Add codegen test for unused match arms removed after inlining)
 - #165398 (Rework parallel reproducibility tests)
 - #162608 (Avoid oscillating line wrapping due to symbol indices)
 - #164241 (make the safety documentation consistent in Ptr module)
 - #165029 (Use `MalformedLintAttributeInput` in more places)
 - #165203 (AIX: Implement TLS destructor guard in std and update dynamic-loading-cdylib test)
 - #165230 (Fix rigidity assertion ICE)
 - #165293 (unstable-book: update default-visibility.md to link to tracking issue)
 - #165374 (Refactorings in preparation for the move trait)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Nov 3, 2026
…tebank

Add a lint helper attribute namespace

(and also port over three rustc lint attributes, as proof of concept)

This PR implements parsing for the `lint` tool namespace (`#[lint::attribute]`) but doesn't add it as a builtin tool, so `#![register_tool(lint)]` is also required to use it. It raises an error on an unknown attribute within that namespace.

The primary motivations for creating this namespace are:
- creating a place for attributes like `trivial_field_reads` (rust-lang#160666) and `c_buffer_length` (rust-lang#162565) to live, as these IMO do not belong in the diagnostic namespace.
- make it easier to unstably land lints and lint helper attributes, as these currently suffer from the "any new built-in attribute is a breaking change" problem.
- implementing (part of) rust-lang#160808

### What is a "lint helper"

Attributes that change how or if a lint is emitted. Think of many of the internal attributes like `#[rustc_as_ptr]` , `#[rustc_pass_by_value]` etc. Other examples are `#[deprecated]` and `#[must_not_suspend]`. Even `clippy` has such a thing: `#[clippy::format_args]`.

### On breaking changes

This doesn't add `lint` as a built-in tool (like `diagnostic`, `rustfmt`, `clippy` etc are) so this pr is not a breaking change. The breaking changes are opt-in by using `#![register_tool(lint)]` in the crate root which is unstable at this time.

The way this PR is implemented means that, even if users could use `#![register_tool(lint)]` stably, they cannot stably use the namespace because an unknown attribute is an error and all valid attributes in it, at this time, are also feature gated. So there is no commitment to stability until we choose to stabilize an attribute in it.

### Going forward

We can require using `#![register_tool(lint)]` indefinitely. It's possible to not require this this by adding `lint` as a builtin tool, but this (assuming rust-lang#162597) breaks
```rust
#[lint::as_ptr]
struct Foo;

mod lint {
    pub use derive as as_ptr;
}
```
However as [nobody on github does this](https://github.com/search?type=code&q=%22%23%5Blint%3A%3A%22+language%3ARust) it's probably only theoretically breaking. It's non-breaking to add it across an edition.

r? @estebank
cc @WaffleLapkin @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Nov 3, 2026
…uwer

Rollup of 20 pull requests

Successful merges:

 - #149245 (Make inline attributes apply to the generated `poll` in async fn)
 - #163495 (Parallelize AST -> HIR lowering)
 - #164304 ([perf] Reuse CanonicalVarKinds if no new variables were added)
 - #165109 (Avoid building a region map when erasing bound regions)
 - #163393 (std: Use getexecpath() for current_exe() on OpenBSD)
 - #163625 (Add a lint helper attribute namespace )
 - #164414 (Add `let_underscore_drop_guard` lint.)
 - #165342 (Avoid unnecessary MIR traversals in CheckPackedRef lint)
 - #165351 (delegation: insert probing adjustments before args check adjustments)
 - #165358 (Reenable some cg_gcc tests that were disabled)
 - #165377 (Make `no_implicit_prelude` not suppress tool attributes)
 - #165397 (Add codegen test for unused match arms removed after inlining)
 - #165398 (Rework parallel reproducibility tests)
 - #162608 (Avoid oscillating line wrapping due to symbol indices)
 - #164241 (make the safety documentation consistent in Ptr module)
 - #165029 (Use `MalformedLintAttributeInput` in more places)
 - #165203 (AIX: Implement TLS destructor guard in std and update dynamic-loading-cdylib test)
 - #165230 (Fix rigidity assertion ICE)
 - #165293 (unstable-book: update default-visibility.md to link to tracking issue)
 - #165374 (Refactorings in preparation for the move trait)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Nov 3, 2026
…tebank

Add a lint helper attribute namespace

(and also port over three rustc lint attributes, as proof of concept)

This PR implements parsing for the `lint` tool namespace (`#[lint::attribute]`) but doesn't add it as a builtin tool, so `#![register_tool(lint)]` is also required to use it. It raises an error on an unknown attribute within that namespace.

The primary motivations for creating this namespace are:
- creating a place for attributes like `trivial_field_reads` (rust-lang#160666) and `c_buffer_length` (rust-lang#162565) to live, as these IMO do not belong in the diagnostic namespace.
- make it easier to unstably land lints and lint helper attributes, as these currently suffer from the "any new built-in attribute is a breaking change" problem.
- implementing (part of) rust-lang#160808

### What is a "lint helper"

Attributes that change how or if a lint is emitted. Think of many of the internal attributes like `#[rustc_as_ptr]` , `#[rustc_pass_by_value]` etc. Other examples are `#[deprecated]` and `#[must_not_suspend]`. Even `clippy` has such a thing: `#[clippy::format_args]`.

### On breaking changes

This doesn't add `lint` as a built-in tool (like `diagnostic`, `rustfmt`, `clippy` etc are) so this pr is not a breaking change. The breaking changes are opt-in by using `#![register_tool(lint)]` in the crate root which is unstable at this time.

The way this PR is implemented means that, even if users could use `#![register_tool(lint)]` stably, they cannot stably use the namespace because an unknown attribute is an error and all valid attributes in it, at this time, are also feature gated. So there is no commitment to stability until we choose to stabilize an attribute in it.

### Going forward

We can require using `#![register_tool(lint)]` indefinitely. It's possible to not require this this by adding `lint` as a builtin tool, but this (assuming rust-lang#162597) breaks
```rust
#[lint::as_ptr]
struct Foo;

mod lint {
    pub use derive as as_ptr;
}
```
However as [nobody on github does this](https://github.com/search?type=code&q=%22%23%5Blint%3A%3A%22+language%3ARust) it's probably only theoretically breaking. It's non-breaking to add it across an edition.

r? @estebank
cc @WaffleLapkin @petrochenkov
rust-bors Bot pushed a commit that referenced this pull request Nov 3, 2026
…uwer

Rollup of 22 pull requests

Successful merges:

 - #149245 (Make inline attributes apply to the generated `poll` in async fn)
 - #164304 ([perf] Reuse CanonicalVarKinds if no new variables were added)
 - #165109 (Avoid building a region map when erasing bound regions)
 - #163393 (std: Use getexecpath() for current_exe() on OpenBSD)
 - #163625 (Add a lint helper attribute namespace )
 - #164414 (Add `let_underscore_drop_guard` lint.)
 - #165342 (Avoid unnecessary MIR traversals in CheckPackedRef lint)
 - #165351 (delegation: insert probing adjustments before args check adjustments)
 - #165358 (Reenable some cg_gcc tests that were disabled)
 - #165377 (Make `no_implicit_prelude` not suppress tool attributes)
 - #165397 (Add codegen test for unused match arms removed after inlining)
 - #165398 (Rework parallel reproducibility tests)
 - #162232 (Replace `builtin #` with `k#`)
 - #162608 (Avoid oscillating line wrapping due to symbol indices)
 - #164241 (make the safety documentation consistent in Ptr module)
 - #164258 (clarify when `Vec::into_boxed_slice()` is in-place)
 - #165029 (Use `MalformedLintAttributeInput` in more places)
 - #165203 (AIX: Implement TLS destructor guard in std and update dynamic-loading-cdylib test)
 - #165230 (Fix rigidity assertion ICE)
 - #165293 (unstable-book: update default-visibility.md to link to tracking issue)
 - #165374 (Refactorings in preparation for the move trait)
 - #165421 (another Enzyme submodule update for nested autodiff)

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 (`#[…]`, `#![…]`) S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library 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