-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Attributes for tools, 2.0 #2103
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
- Feature Name: tool_attributes | ||
- Feature Name: tool_attributes, tool_lints | ||
- Start Date: 2016-09-22 | ||
- RFC PR: | ||
- Rust Issue: | ||
|
@@ -33,6 +33,9 @@ crate, it will read the attibute and skip formatting `foo` (note that we make no | |
provision for reading the attribute or doing anything with it, that is all up to | ||
the tool). | ||
|
||
This RFC proposes a second mechanism for scoping lints for tools. Similar to | ||
attributes, we propose a subset of a hypothetical long-term solution. | ||
|
||
This RFC supersedes #1755. | ||
|
||
# Motivation | ||
|
@@ -70,10 +73,16 @@ Rustfmt is mostly ready to move towards stabilisation, but requires some kind of | |
reasonable long-term solution and addresses the needs of some important tools | ||
today. | ||
|
||
Similarly, tools (e.g., Clippy) may want to use their own lints without the | ||
compiler warning about unused lints. E.g., we want a user to be able to write | ||
`#![allow(clippy::some_lint)]` in their crate without warning. | ||
|
||
|
||
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
### Attributes | ||
|
||
This section assumes that attributes (e.g., `#[test]`) have already been taught. | ||
|
||
You can use attibutes in your crate to pass information to tools. For now, this | ||
|
@@ -99,6 +108,21 @@ mod baz { | |
} | ||
``` | ||
|
||
### Lints | ||
|
||
This section assumes lints have already been taught. | ||
|
||
Lints can be defined hierarchically as a path, as well as just a single name. | ||
For example, `nonstandard_style::non_snake_case_functions` and | ||
`nonstandard_style::uppercase_variables`. Note this RFC is not proposing | ||
changing any existing lints, just extending the current lint naming system. Lint | ||
names cannot be imported using `use`. | ||
|
||
Lints can be enforced by tools other than the compiler. For example, Clippy | ||
provides a large suite of lints to catch common mistakes and improve your Rust | ||
code. Lints for tools are prefixed with the tool name, e.g., `clippy::box_vec`. | ||
|
||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
|
@@ -127,6 +151,8 @@ tries to find a macro using the [macro name resolution rules](https://github.com | |
If this fails, then it reports a macro not found error. The compiler *may* | ||
suggest mis-typed attributes (declared or built-in). | ||
|
||
A similar opt-in mechanism will exist for lints. | ||
|
||
|
||
## Proposed for immediate implementation | ||
|
||
|
@@ -138,12 +164,12 @@ feature gate. | |
E.g., `#[rustdoc::foo]` will be permitted in stable Rust code; `#[rustdoc]` will | ||
still be treated as a custom attribute. | ||
|
||
The initial list of allowed prefixes is `rustc`, `rustdoc`, and `rls`. As tools | ||
are added to the distribution, they will be allowed as path prefixes in | ||
attributes. We expect to add `rustfmt` and `clippy` in the near future. Note | ||
that whether one of these names can be used does not depend on whether the | ||
relevant component is installed on the user's system; this is a simple, | ||
universal white list. | ||
The initial list of allowed prefixes is `rustc`, `rustdoc`, and `rls` (but see | ||
note below on activation). As tools are added to the distribution, they will be | ||
allowed as path prefixes in attributes. We expect to add `rustfmt` and `clippy` | ||
in the near future. Note that whether one of these names can be used does not | ||
depend on whether the relevant component is installed on the user's system; this | ||
is a simple, universal white list. | ||
|
||
Given the earlier rules on name resolution, these attributes would shadow any | ||
attribute macro with the same name. This is not problematic because a macro | ||
|
@@ -155,6 +181,29 @@ Tool-scoped attributes should be preserved by the compiler for as long as | |
possible through compilation. This allows tools which plug into the compiler | ||
(like Clippy) to observe these attributes on items during type checking, etc. | ||
|
||
Likewise, white-listed tools may be used a prefix for lints. So for example, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: |
||
`rustfmt::foo` and `clippy::bar` are both valid lint names, from the compiler's | ||
perspective. | ||
|
||
|
||
### Activation and unused attibutes/lints | ||
|
||
For each name on the whitelist, it is indicated if the name is active for | ||
attributes or lints. A name is only activated if required. So for example, | ||
`rustdoc` will not be activated at all until it takes advantage of this feature. | ||
I expect `clippy` will be activated only for lints, and `rustfmt` only for | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
attributes. | ||
|
||
A tool that has an active name *must* check for unused lints/attibutes. For | ||
example, if `rustfmt` becomes active for attributes, and only recognises | ||
`rustfmt::skip`, it must produce a warning if a user uses `rustfmt::foo` in | ||
their code. | ||
|
||
These two requirements together mean that we do not lose checking of unused | ||
attributes/lints in any circumstance and we can move to having the compiler | ||
check for unused attributes/lints as part of a possible long-term solution | ||
without introducing new warnings or errors. | ||
|
||
|
||
### Forward and backward compatability | ||
|
||
|
@@ -174,13 +223,6 @@ term solution? One could imagine either leaving them implicit (similar to the | |
libraries prelude) or using warning cycles or an epoch to move them to explicit | ||
opt-in. | ||
|
||
Another hazard is that if in the long-term solution, the compiler checks | ||
attribute paths for validity rather than only the prefix. For example, if | ||
Rustfmt only defines `skip`, then `#[rustfmt::foo]` would not give an error | ||
under this proposal, but would in the long term. Given that `#[rustfmt::foo]` is | ||
almost certainly a mistake today, it seems easy to migrate to a stricter system | ||
with a warning cycle. | ||
|
||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
@@ -190,9 +232,9 @@ attributes (I consider this a feature, not a bug, but others may differ). | |
|
||
Some tools are clearly given special treatment. | ||
|
||
We permit some useless attributes without warning (e.g., `#[rustfmt::foo]`, | ||
assuming Rustfmt does nothing with `foo`). Tools could (and probably should) | ||
warn or error on such attributes. | ||
We permit some useless attributes without warning from the compiler (e.g., | ||
`#[rustfmt::foo]`, assuming Rustfmt does nothing with `foo`). However, tools | ||
should warn or error on such attributes. | ||
|
||
We are not planning any infrastructure to help tools use these attributes. That | ||
seems fine for now, I imagine a long-term solution should include some library | ||
|
@@ -216,3 +258,5 @@ Are there other tools that should be included on the whitelist (`#[test]` perhap | |
|
||
Should we try and move some top-level attributes that are compiler-specific | ||
(rather than language-specific) to use `#[rustc::]`? (E.g., `crate_type`). | ||
|
||
How should the compiler expose path lints to lint plugins/lint tools? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd assume as an initial step, We can extend As a third option, we can hide the lint registering methods behind a wrapper, which at creation time gets its tool name once, and then forwards it to the rustc data structures. That requires some more implementation effort, and can be done after the second option if it is deemed necessary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like an inconsistent prioritization to me.
It would be good if resolution for attribute paths worked consistently with the rest of resolution,
as if attribute names were just names defined in macro namespace with usual scoping, shadowing, etc.
In particular, I see parallels with built-in types, std prelude types and user defined types.
#[test]
) -> std prelude (e.g.Box
), found as a fallback if no user-defined names are found.#[repr]
) -> built-in types (e.g.u8
), language prelude, found as a fallback if no std prelude names are found.This way we can always introduce new built-in attributes without breaking user-defined macros, like it was done with
u128
/i128
for types.Now attributes for tools need to somehow be fitted into this scheme.
This test implies that they should shadow everything when enabled (e.g. through
--extern-attr
) and break macros. I'd actually expect the opposite priority and placing them into the language prelude for example.(There shouldn't be conflicts there due to different number of path segments - 1 for built-in, >1 for extern).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a good change, thanks!