Tracking Issue: Procedural Macro Diagnostics (RFC 1566) #54140
Description
This is a tracking issue for diagnostics for procedural macros spawned off from #38356.
Overview
Current Status
- Implemented under
feature(proc_macro_diagnostic)
- In use by Rocket, Diesel, Maud
Next Steps
- Initial diagnostic API for proc-macros. #44125
- Implement introspection methods (Add inspection and setter methods to proc_macro::Diagnostic. #52896)
- Implement multi-span support (Add inspection and setter methods to proc_macro::Diagnostic. #52896)
- Implement lint id for warnings (Implement #[proc_macro_warning] to generate LintId for macro-generated warnings #135432)
- Document thoroughly
- Stabilize
Summary
The initial API was implemented in #44125 and is being used by crates like Rocket and Diesel to emit user-friendly diagnostics. Apart from thorough documentation, I see two blockers for stabilization:
-
Multi-Span Support
At present, it is not possible to create/emit a diagnostic via
proc_macro
that points to more than oneSpan
. The internal diagnostics API makes this possible, and we should expose this as well.The changes necessary to support this are fairly minor: a
Diagnostic
should encapsulate aVec<Span>
as opposed to aSpan
, and thespan_
methods should be made generic such that either aSpan
or aVec<Span>
(ideally also a&[Vec]
) can be passed in. This makes it possible for a user to pass in an emptyVec
, but this case can be handled as if noSpan
was explicitly set. -
Lint-Associated Warnings
At present, if a
proc_macro
emits a warning, it is unconditional as it is not associated with a lint: the user can never silence the warning. I propose that we require proc-macro authors to associate every warning with a lint-level so that the consumer can turn it off.No API has been formally proposed for this feature. I informally proposed that we allow proc-macros to create lint-levels in an ad-hoc manner; this differs from what happens internally, where all lint-levels have to be known apriori. In code, such an API might look lIke:
val.span.warning(lint!(unknown_media_type), "unknown media type");
The
lint!
macro might check for uniqueness and generate a (hidden) structure for internal use. Alternatively, the proc-macro author could simply pass in a string:"unknown_media_type"
.