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
- 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_lint] to generate LintId for macro-generated warnings #135432)Document thoroughlyStabilize
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"
.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Activity
sgrif commentedon Sep 11, 2018
I'd argue that support for associating warnings with lints should be a separate RFC, and shouldn't block moving forward with unsilenceable warnings (with the expectation that anything to associate warnings with lints would need to be an additional API)
sgrif commentedon Sep 11, 2018
Similarly, I'm not sure we actually need to address multi-span support before this API can be stabilized. The proposed change there involves changing some methods to be generic, which is considered a minor change under RFC #1105. It could also be done by changing
Span
itself to be an enum, rather than having a separateMultiSpan
typeSergioBenitez commentedon Sep 11, 2018
@sgrif I suppose the question is: should unsilenceable warnings be allowed at all? I can't think of a reason to remove this control from the end-user. And, if we agree that they shouldn't be allowed, then we should fix the API before stabilizing anything to account for this. I'd really rather not have four warning methods:
warning
,span_warning
,lint_warning
,lint_span_warning
.Sure, but the change is so minor, so why not do it now? What's more, as much as I want this to stabilize as soon as possible, I don't think enough experience has been had with the current API to merit its stabilization. I think we should implement these two features, announce them broadly so others can play with them, gather feedback, and then stabilize.
Right, that works too.
sgrif commentedon Sep 11, 2018
I think "having a thing we can ship" is a decent reason, but I also think an API that only supports
error
/help
/note
, but not errors is sufficiently useful to ship even without warnings. I'd support doing that if it meant we didn't block this on yet another API -- Mostly I just want to avoid having perfect be the enemy of good here.Because we have a perfectly workable API that's being used in the wild right now that we could focus on stabilizing instead. Typically we always trend towards the more conservative option on this sort of thing, shipping an MVP that's forward compatible with extensions we might want in the future.
So what needs to happen for that? Should we do a public call for testing? Definitely adding more docs is huge. I suppose it'd be good to see what serde looks like using this API as well.
SergioBenitez commentedon Sep 11, 2018
Yeah, that's exactly what I was thinking.
I don't think this is an eccentric proposal in any way. When folks play with this, they should have this feature. In any case, I'll be implementing this soon, unless someone beats me to it, as Rocket needs it.
sgrif commentedon Sep 11, 2018
zackmdavis commentedon Sep 12, 2018
Maybe it's too late (I'm lacking context here), but is there any hope of unifying proc-macro diagnostics with those emitted by the compiler itself? It seems sad and unmotivated to have two parallel implementations of diagnostics. (Rustc's diagnostics also have a suggestions API (albeit still somewhat in flux) that harbors a lot of promise given the new
cargo fix
subcommand that it would be nice for the Rocket/Diesel/&c. proc-macro world to also benefit from.)SergioBenitez commentedon Sep 12, 2018
@zackmdavis The API being exposed by the diagnostics API in
proc_macro
today is a refinement of the internal API; they're already quite unified, with minor differences to account for the context in which they are used. The implementation is a thin shell over the internal implementation.In general,
rustc
s evolving needs and theproc_macro
diagnostics API aim for stability prohibit the two from being identical. This is a good thing, however:rustc
can experiment with unstable APIs as much as it wants without being concerned about stability whileproc_macro
authors can have a stable, concrete API to build with. Eventually, features from the former can makes their way into the latter.lambda-fairy commentedon Sep 14, 2018
Maud also uses the diagnostic API. It would benefit from both features described in the summary:
Multi-span support – Currently, the duplicate attribute check emits two separate diagnostics for each error. It would be cleaner to emit a single diagnostic instead.
Lint-associated warnings – We want to warn on non-standard HTML elements and attributes. But we also want to let the user silence this warning, for forward compatibility with future additions to HTML.
macpp commentedon Sep 21, 2018
Is there any way to emit warning for arbitrary file? It could be usefull for macros that read additional data from external files (like derive(Template) in https://github.com/djc/askama ) .
If it's not possible, how problematic it is to add to
Diagnostics
something equivalent to :fn new_raw<T: Into<String>>(start: LineColumn, end: LineColumn, file: &path::Path, level: Level, message: T) -> Diagnostic
?184 remaining items