Implement #[proc_macro_lint] to generate LintId for macro-generated warnings by dtolnay · Pull Request #135432 · rust-lang/rust (original) (raw)

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 a pub static contained in the crate root with type proc_macro::LintId. The attribute fills in a unique value for the static's value:

use proc_macro::{LintId, TokenStream};

#[proc_macro_lint] pub static ambiguous_thing: LintId;

#[proc_macro_derive(Foo)] pub fn derive_foo(input: TokenStream) -> TokenStream { if ... { proc_macro::warning(crate::ambiguous_thing, span, "..."); } ... }

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 the proc_macro crate. The value's type is proc_macro::LintId, which implements Copy and Debug.

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

Importantly, none of the above blocks stabilization of warning diagnostics APIs in proc_macro (as long as we do it carefully, i.e. not Diagnostic::new).