-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Implement #[proc_macro_lint] to generate LintId for macro-generated warnings #135432
base: master
Are you sure you want to change the base?
Conversation
r? @Nadrieril rustbot has assigned @Nadrieril. Use |
Some changes occurred in src/tools/clippy cc @rust-lang/clippy HIR ty lowering was modified cc @fmease |
This comment has been minimized.
This comment has been minimized.
e76936f
to
9cd8b2d
Compare
HIR ty lowering was modified cc @fmease Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
This comment has been minimized.
This comment has been minimized.
r? compiler |
9cd8b2d
to
3fbd1b4
Compare
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer |
This comment has been minimized.
This comment has been minimized.
3fbd1b4
to
5b19998
Compare
@rustbot ready |
This comment was marked as resolved.
This comment was marked as resolved.
5b19998
to
ab550d9
Compare
ab550d9
to
529f3f0
Compare
Updated with rename from |
529f3f0
to
46a07be
Compare
@rustbot labels +I-lang-nominated
|
This comment was marked as resolved.
This comment was marked as resolved.
46a07be
to
c4e62d9
Compare
Some changes occurred in compiler/rustc_passes/src/check_attr.rs |
Rebased to resolve conflict with #136751 in compiler/rustc_builtin_macros/src/proc_macro_harness.rs. |
☔ The latest upstream changes (presumably #136845) made this pull request unmergeable. Please resolve the merge conflicts. |
Seems reasonable. I think we should plan on being able to integrate the same |
We discussed this in today's @rust-lang/lang meeting. We're happy to approve this as a lang experiment. Using a path to identify a lint for the purposes of emitting it and suppressing/denying/etc it seems like the correct answer. (We definitely want to see paths used rather than strings.) All the details of the |
This is a relatively major compiler change due to the newly introduced definitions, so I wanted to review the changes from that point of view before merging. |
Note that as a lang experiment without an accepted RFC, the |
From the language point of view I don't like the amount of language extension that is done here to support a niche feature.
Naturally, I'd prefer to avoid both of these extensions (with the second one automatically avoidable if the first one is removed). Is it really necessary to support arbitrary exporting and renaming of proc macro lints (and require arbitrary path resolution to support it)?
|
Technically, the implementation is mostly good, I'll leave some comments a bit later. |
extern crate proc_macro; | ||
|
||
use proc_macro::LintId; | ||
//~^ use of unstable library feature `proc_macro_diagnostic` |
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.
//~^ use of unstable library feature `proc_macro_diagnostic` | |
//~^ ERROR use of unstable library feature `proc_macro_diagnostic` |
Could you use full annotations in all of the tests?
|
||
#[proc_macro_lint] | ||
pub static ambiguous_thing: LintId; | ||
//~^ the name `ambiguous_thing` is defined multiple times |
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.
If string is used for the lint ID, then you can get ID collisions using macros 2.0.
macro m() { #[proc_macro_lint] pub static lint_name: LintId; }
m!();
m!(); // No "defined multiple times" error due to hygiene, but there is a lint ID collision
Could you add a test case for this?
No need to fix it right now though.
@@ -600,6 +600,8 @@ declare_features! ( | |||
(unstable, postfix_match, "1.79.0", Some(121618)), | |||
/// Allows `use<..>` precise capturign on impl Trait in traits. | |||
(unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), | |||
/// Allows `#[proc_macro_lint]` in procedural macro crates. | |||
(unstable, proc_macro_diagnostic, "CURRENT_RUSTC_VERSION", Some(54140)), |
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.
Hmm, looks like we already have proc_macro_diagnostic
as a library feature.
Is the intent to just put the new attribute under that umbrella feature for now?
@@ -101,7 +101,10 @@ pub enum DefKind { | |||
AssocConst, | |||
|
|||
// Macro namespace | |||
/// `#[proc_macro]` or `#[proc_macro_attribute]` or `#[proc_macro_derive]` |
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.
It is used for declarative macros as well.
|
||
if let Err(terr) = ocx.eq(&cause, param_env, expected, actual) { | ||
let mut diag = | ||
self.tcx.dcx().create_err(errors::ProcMacroLintWrongType { span: hir_ty.span }); |
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.
Is this custom reporting necessary?
static a: NonLintId = LintId::new("foo");
will report a type mismatch anyway.
(Also this looks a bit out of place in attribute checking.)
Ident::new(kw::PathRoot, span), | ||
Ident::new(sym::proc_macro, span), | ||
Ident::new(sym::LintId, span), | ||
Ident::new(sym::new, span), |
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.
It should be better to make LintId::new
a lang item and add the static initializer in AST lowering using make_lang_item_path
.
This will allow to
- avoid a mutable AST visitor, their use should be minimized because they stand in the way of plans like keeping AST on arena, etc.
- avoid the edition hack above, lang item collection will be used to "resolve" the
LintId::new
path instead
Same for adding the #[allow(non_upper_case_globals)]
attribute, it's better to adjust the lint directly.
This PR unblocks an initial round of stabilizations of #54140 as discussed in #54140 (comment).
An id for a procedural macro warning is declared using
#[proc_macro_lint]
on apub static
contained in the crate root with typeproc_macro::LintId
. The attribute fills in a unique value for the static's value:Within the same proc macro crate, the static (
ambiguous_thing
) exists in the value namespace. It can be used as a value for passing to public APIs provided by theproc_macro
crate. The value's type isproc_macro::LintId
, which implementsCopy
andDebug
.Downstream of the proc macro crate, the same static exists in the macro namespace. It can be re-exported in the macro namespace using
pub use
. Currently it is not useful for anything else.The use of 2 namespaces in such a way is identical to how all proc macros already work. For example, inside a proc macro crate containing
#[proc_macro] pub fn foo(input: TokenStream) -> TokenStream
, this function exists in the value namespace and is callable as a function. In downstream crates, the same function exists in the macro namespace and is callable as a function-like macro.Future work
Some of the public unstable API of
proc_macro
needs to be redesigned to require that aLintId
must always be provided when a macro creates a warning. In this PR, I have made this change only forDiagnostic::span_warning
andDiagnostic::warning
. There is another constructorDiagnostic::new
which takes aproc_macro::Level
and can be passedLevel::Warning
. In this PR I have not touched that function, which means it is not on track for stabilizing. This is fine because it has already fallen out of favor in the tracking issue discussion and was not suggested for stabilization. See for example Tracking Issue: Procedural Macro Diagnostics (RFC 1566) #54140 (comment).Procedural macro
LintId
needs to be integrated into theallow
/warn
/deny
lint level system. If a cratefoo_macros
defines aLintId
calledambiguous_thing
, and it is re-exported in the crate root of a cratefoo
, then users offoo
need to be able to writeallow(foo::ambiguous_thing)
ordeny(foo::ambiguous_thing)
.Procedural macro
LintId
needs to be integrated with theunknown_lints
lint. If a user writesdeny(foo::ambiguous_thing)
whenfoo
is not a proc macro crate declaring aambiguous_thing
lint id, nor is this resolved as a re-export of such a lint id, this needs to triggerunknown_lints
.Rustdoc will need to render documentation for lint ids.
Mechanism for a proc macro crate to set a default level for each of its lints. By default they are warn-by-default, but some lints might be better as allow-by-default or deny-by-default.
A style lint that enforces a case convention for lint ids (snake_case).
Rust-analyzer will want to provide autocomplete for proc macro lint ids inside
allow
/warn
/deny
.Importantly, none of the above blocks stabilization of warning diagnostics APIs in
proc_macro
(as long as we do it carefully, i.e. notDiagnostic::new
).