- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Implement #[proc_macro_lint] to generate LintId for macro-generated warnings #135432
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
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 collisionCould you add a test case for this?
No need to fix it right now though.
| /// 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?
| 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::newpath instead
Same for adding the #[allow(non_upper_case_globals)] attribute, it's better to adjust the lint directly.
| 
 +1 i would really rather this use inert attributes, not active ones. that would work better with tool namespaces as well, since you don't have inconsistency on whether the lint names can be renamed. | 
| 
 we could call this  | 
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 staticcontained 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_macrocrate. The value's type isproc_macro::LintId, which implementsCopyandDebug.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_macroneeds to be redesigned to require that aLintIdmust always be provided when a macro creates a warning. In this PR, I have made this change only forDiagnostic::span_warningandDiagnostic::warning. There is another constructorDiagnostic::newwhich takes aproc_macro::Leveland 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
LintIdneeds to be integrated into theallow/warn/denylint level system. If a cratefoo_macrosdefines aLintIdcalledambiguous_thing, and it is re-exported in the crate root of a cratefoo, then users offooneed to be able to writeallow(foo::ambiguous_thing)ordeny(foo::ambiguous_thing).Procedural macro
LintIdneeds to be integrated with theunknown_lintslint. If a user writesdeny(foo::ambiguous_thing)whenfoois not a proc macro crate declaring aambiguous_thinglint 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).