Repository navigation
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_lint] 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_macrothat 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
Diagnosticshould encapsulate aVec<Span>as opposed to aSpan, and thespan_methods should be made generic such that either aSpanor 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 noSpanwas explicitly set. -
Lint-Associated Warnings
At present, if a
proc_macroemits 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
- StatusShow more project fieldsExploration
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
Spanitself to be an enum, rather than having a separateMultiSpantypeSergioBenitez 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 fixsubcommand 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_macrotoday 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,
rustcs evolving needs and theproc_macrodiagnostics API aim for stability prohibit the two from being identical. This is a good thing, however:rustccan experiment with unstable APIs as much as it wants without being concerned about stability whileproc_macroauthors 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
Diagnosticssomething equivalent to :fn new_raw<T: Into<String>>(start: LineColumn, end: LineColumn, file: &path::Path, level: Level, message: T) -> Diagnostic?105 remaining items
weiznich commentedon Jan 12, 2025
Most of the recent discussion seems to focus around how to declare lint groups for the warning. I've not attended the meeting @joshtriplett wrote about but I would like to ask if it's really required to have a mechanism to declare these groups in such fine way from the beginning. After all the easiest possible solution would be to put all proc-macro emitted warnings in the same lint group, which would users allow to suppress these warnings, although not at the finest possible level. Another solution would be to derive these lint groups automatically based on the proc macro that emitted this lint. So a warning coming from
serde::Serializecould then be suppressed by something like#[allow(proc_macro_waring::serde::Serialize)](name just matching that that brought this proc macro in scope, exact syntax up to discussion, but that's not relevant for the proposal). This would allow to suppress warnings on proc macro level. I agree that there might be use-cases that would want to emit warnings for different purposes, but I would expect that these are not the common case. Most proc-macros don't emit warning or just emit a relatively low number of different warnings (like 1).Both proposals should be future proof for extending them with an explicit way to declare lint groups, but going with either of the proposals would hopefully unblock the underlying rather important feature of error handling and emitting warnings at all from proc-macros. I would allow to bikesheed the exact syntax of declaring these lint groups later on.
traviscross commentedon Feb 19, 2025
In the lang meeting on 2025-02-19, we discussed the
#[proc_macro_lint]work (e.g. in #135432) under theproc_macro_diagnosticfeature flag and approved a lang experiment. Our feeling is that we'd expect to see an RFC for this before putting it on the path to stabilization.We discussed who would liaison / shepherd / champion this, but deferred that to discussion after the meeting. We felt that this did need such a person appointed to help this be a success.
My own view, which seemed to receive general agreement, about the role of lang in this, is that while many details of the implementation of this fall within the
proc_macrolibrary, high level, lang owns what proc macros can do (which here, is the ability to emit lints) and the general shape and user-experience for those capabilities. This is part of what the eventual RFC would cover here.Deprecate export for spec generation in spec shaking v2 (stellar#1876)
Deprecate export for spec generation in spec shaking v2 (#1876)