Skip to content

Tracking Issue: Procedural Macro Diagnostics (RFC 1566) #54140

Open

Description

@SergioBenitez

View all comments

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

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:

  1. Multi-Span Support

    At present, it is not possible to create/emit a diagnostic via proc_macro that points to more than one Span. 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 a Vec<Span> as opposed to a Span, and the span_ methods should be made generic such that either a Span or a Vec<Span> (ideally also a &[Vec]) can be passed in. This makes it possible for a user to pass in an empty Vec, but this case can be handled as if no Span was explicitly set.

  2. 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".

Activity

  1. sgrif commented on Sep 11, 2018

    @sgrif
    Contributor

    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)

  2. sgrif commented on Sep 11, 2018

    @sgrif
    Contributor

    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 separate MultiSpan type

  3. SergioBenitez commented on Sep 11, 2018

    @SergioBenitez
    ContributorAuthor

    @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.

    Similarly, I'm not sure we actually need to address multi-span support before this API can be stabilized.

    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.

    It could also be done by changing Span itself to be an enum, rather than having a separate MultiSpan type.

    Right, that works too.

  4. sgrif commented on Sep 11, 2018

    @sgrif
    Contributor

    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.

    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.

    Sure, but the change is so minor, so why not do it now?

    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.

    I don't think enough experience has been had with the current API to merit its stabilization.

    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.

  5. SergioBenitez commented on Sep 11, 2018

    @SergioBenitez
    ContributorAuthor

    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.

    Yeah, that's exactly what I was thinking.

    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.

    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.

  6. sgrif commented on Sep 11, 2018

    @sgrif
    Contributor
  7. zackmdavis commented on Sep 12, 2018

    @zackmdavis
    Contributor

    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.)

  8. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Sep 12, 2018
  9. SergioBenitez commented on Sep 12, 2018

    @SergioBenitez
    ContributorAuthor

    @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, rustcs evolving needs and the proc_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 while proc_macro authors can have a stable, concrete API to build with. Eventually, features from the former can makes their way into the latter.

  10. lambda-fairy commented on Sep 14, 2018

    @lambda-fairy
    Contributor

    Maud also uses the diagnostic API. It would benefit from both features described in the summary:

    1. 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.

    2. 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.

  11. macpp commented on Sep 21, 2018

    @macpp

    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 ?

  12. added
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    T-langRelevant to the language team
    on Oct 1, 2018
  13. 105 remaining items

  14. weiznich commented on Jan 12, 2025

    @weiznich
    Contributor

    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::Serialize could 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.

  15. added
    I-lang-radarItems that are on lang's radar and will need eventual work or consideration.
    and removed
    I-lang-nominatedNominated for discussion during a lang team meeting.
    on Jan 26, 2025
  16. added
    B-experimentalBlocker: In-tree experiment; RFC pending, not yet approved or unneeded (requires FCP to stabilize).
    on Feb 19, 2025
  17. traviscross commented on Feb 19, 2025

    @traviscross
    Contributor

    In the lang meeting on 2025-02-19, we discussed the #[proc_macro_lint] work (e.g. in #135432) under the proc_macro_diagnostic feature 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_macro library, 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.

  18. moved this from Exploration to Needs champion in Lang team featureson Feb 21, 2025
  19. moved this from Needs champion to Exploration in Lang team featureson Mar 5, 2025
  20. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
  21. removed
    I-libs-radarLibs issues that are tracked on the team's radar.
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-decl-macros-1-2Area: Declarative macros 1.2A-diagnosticsArea: Messages for errors, warnings, and lintsB-experimentalBlocker: In-tree experiment; RFC pending, not yet approved or unneeded (requires FCP to stabilize).B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-proc_macro_diagnostic`#![feature(proc_macro_diagnostic)]`I-lang-radarItems that are on lang's radar and will need eventual work or consideration.T-langRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions