Split register_tool into register_attribute_tool and register_lint_tool#158038
Split register_tool into register_attribute_tool and register_lint_tool#158038nbdd0121 wants to merge 4 commits into
Conversation
It is also removed.
This splits the functionality to two parts per RFC. The `#![register_tool]` attribute registers the tool in both ways. Semantics remain unchanged and will be adjusted in later commit.
Under the RFC, it's not an error to register tool multiple times, but it is an error to register a predefined tool, or register "rustc" tool.
|
Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_attr_parsing cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_hir/src/attrs |
|
r? @wesleywiser rustbot has assigned @wesleywiser. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
Error seems to be flaky rustdoc test: #157747 |
|
r? me (Or Jonathan I suppose) |
|
Can you expand on the "resolution yet to be implemented" thing? I was under the impression there would be no resolution and it'd all be, essentially, stringly typed. |
In https://github.com/rust-lang/rfcs/blob/master/text/3808-register-tool.md it mentioned that ambiguity between tool attribute and other resolution should be an error, and also that tool attribute is not affected by no_implicit_prelude. These are technically breaking changes so I'd want to split it to another PR so it gets a crater run. |
There was a problem hiding this comment.
Typically when there are multiple attributes which are semantically related, we "merge" them into a single attribute. See https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html#how-this-crate-works
This implementation doesn't; you'd be dealing with RegisteredTool { kind: sym::register_lint_tool, ..}, RegisteredTool { kind: sym::register_tool, ..} and RegisteredTool { kind: sym::register_attribute_tool, ..}. That's three attributes, effectively. I've pointed at some places that need changes for that.
Also, my understanding from the rfc is that resolution and ambiguity errors are only for attribute_tool? i.e. #[my_tool::thing]? and not #[allow(my_tool::lint)]?
| RegisterTool { | ||
| kind: Symbol, | ||
| tools: ThinVec<Ident>, | ||
| }, |
There was a problem hiding this comment.
So I would expect this to look like...
| RegisterTool { | |
| kind: Symbol, | |
| tools: ThinVec<Ident>, | |
| }, | |
| RegisterTool { | |
| lint_tools: ThinVec<Ident>, | |
| attribute_tools: ThinVec<Ident>, | |
| }, |
and if you use register_tool the name would be put into both of those.
There was a problem hiding this comment.
^ Agreed on this, it must never be possible to have two of the same variant in an attribute list in the HIR
There was a problem hiding this comment.
Attribute tools and lint tools are handled very differently in the compiler, and there're very few cases you'd want to know both, so I want to keep the queries distinct.
Perhaps I should split the HIR attr to two variants two? But I do want to avoid duplicated code because the parsing of the two attributes are very similar.
There was a problem hiding this comment.
You could just make a function that parsers the attributes, and call that from the two distinct attribute parsers
There was a problem hiding this comment.
This doesn't work as this will run into Attribute ["register_tool"] has multiple accepters
| pub(crate) struct RegisterAttributeTool; | ||
| pub(crate) struct RegisterLintTool; | ||
| pub(crate) struct RegisterTool; | ||
|
|
||
| impl CombineAttributeParser for RegisterToolParser { | ||
| const PATH: &[Symbol] = &[sym::register_tool]; | ||
| pub(crate) trait RegisterToolKind: 'static { | ||
| const SYMBOL: Symbol; | ||
| } | ||
|
|
||
| impl RegisterToolKind for RegisterAttributeTool { | ||
| const SYMBOL: Symbol = sym::register_attribute_tool; | ||
| } | ||
|
|
||
| impl RegisterToolKind for RegisterLintTool { | ||
| const SYMBOL: Symbol = sym::register_lint_tool; | ||
| } | ||
|
|
||
| impl RegisterToolKind for RegisterTool { | ||
| const SYMBOL: Symbol = sym::register_tool; | ||
| } | ||
|
|
||
| pub(crate) struct RegisterToolParser<Kind>(Kind); | ||
|
|
||
| impl<K: RegisterToolKind> CombineAttributeParser for RegisterToolParser<K> { | ||
| const PATH: &[Symbol] = &[K::SYMBOL]; | ||
| type Item = Ident; | ||
| const CONVERT: ConvertFn<Self::Item> = |tools, _span| AttributeKind::RegisterTool(tools); | ||
| const CONVERT: ConvertFn<Self::Item> = | ||
| |tools, _span| AttributeKind::RegisterTool { kind: K::SYMBOL, tools }; |
There was a problem hiding this comment.
And this would need to implement AttributeParser directly. For example see the stability parser:
#[stable], #[unstable] and #[rustc_allowed_through_unstable_modules] into a single semantic attribute.
|
|
||
| if let Some(Attribute::Parsed(AttributeKind::RegisterTool(tools))) = | ||
| if let Some(Attribute::Parsed(AttributeKind::RegisterTool { kind: _, tools })) = | ||
| AttributeParser::parse_limited(sess, pre_configured_attrs, &[sym]) |
There was a problem hiding this comment.
Unfortunately you can only use parse_limited for one attribute at a time; you can't parse multiple attributes at a time. Feel free to make a function that allows multiple attributes though, if you need it.
| /// Tool modules introduced with `#![register_tool]`. | ||
| ToolPrelude, | ||
| /// Tool modules introduced with `#![register_tool]` or `#![register_attribute_tool]`. | ||
| ToolAttributePrelude, |
There was a problem hiding this comment.
| ToolAttributePrelude, | |
| AttributeToolPrelude, |
It's a prelude for tools, not for attributes.
I'd probably just keep the ToolPrelude naming here, because lints do no go through name resolution, but may be better to be more explicit for readers less aware of the context.
| #![register_attribute_tool(qux)] | ||
| #![register_attribute_tool(qux)] |
There was a problem hiding this comment.
@jyn514 is there a specific reason for
#![register_attribute_tool(qux)]
#![register_attribute_tool(qux)]to be allowed?
I don't see the explanation in the RFC.
Duplicate definitions are typically prohibited in name resolution.
|
Naming nit: "attribute" is long, so it's usually abbreviated to "attr" in the compiler, so all the |
Please, assign me when the resolution part is submitted. |
|
☔ The latest upstream changes (presumably #158124) made this pull request unmergeable. Please resolve the merge conflicts by rebasing. |
Tracking issue: #66079
This implements the attribute parsing part of RFC 3808. The resolution part is yet to be implemented.
cc @jyn514