-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue: Procedural Macro Diagnostics (RFC 1566) #54140
Comments
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) |
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 |
@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:
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. |
I think "having a thing we can ship" is a decent reason, but I also think an API that only supports
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. |
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. |
Should we be going through the RFC process for additions to the API here?
(I noticed that `Diagnostic` itself actually never got an RFC)
…On Tue, Sep 11, 2018 at 3:26 PM Sergio Benitez ***@***.***> wrote:
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.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#54140 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABdWK2Gpoc6vTWz8fKpJmVaGysf9w7-Uks5uaCpsgaJpZM4WkOKO>
.
|
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 |
@zackmdavis The API being exposed by the diagnostics API in In general, |
Maud also uses the diagnostic API. It would benefit from both features described in the summary:
|
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 |
Something I find confusing about the current nightly API: does Currently I must use In my opinion:
|
@dhardy |
Okay, fair enough; not sure why I some panic messages sometimes and not others.
I guess |
Personally I'd prefer not exposing a The compiler will not proceed with type checking if your macro emits at least one error, so you can get away with returning nonsense (like |
@macpp It's not possible today. I agree that something like this should exist, but much thought needs to be given to the API that's exposed. The API you propose, for instance, puts the onus of tracking line and column information on the user, and makes it possible to produce a The API that I've considered is having a mechanism by which a impl TokenStream {
fn from_source_file<P: AsRef<Path>>(path: P) -> Result<TokenStream>;
} This would make it possible to get arbitrary (but "well-formed") spans anywhere in the file. As a bonus, it means you can reuse libraries that work with |
Well, of course if you deal with .rs files, then panic("bad configuration in config.toml file: line X column Y") Unfortunately, i forgot about |
@macpp No, that would work for almost any kind of text file. A |
And that strings inside single quotes must contain a single codepoint, which eliminates a lot more things (including TOML files) that have arbitrary strings in single quotes. Even the "delimiters must be balanced" requires that the file use the same idea of where a delimiter is and isn't valid. For example the source file must agree that a In short, I don't have a problem with having a |
Forcing the end user to either add a dependency or reinvent the wheel for something that can be trivially done (and is already implemented for the internal diagnostics) seems needlessly restrictive. The default could be to eagerly emit, as that is likely what a majority of uses will be. However, having the ability to emit a diagnostic Even if there were a More generally, if the diagnostic isn't being emitted on drop, how would the API even work? It would necessarily emit the diagnostic on |
Ah, I see now that the differences are rather significant, in fact. The methods for
Is the handle
That's somewhat true. If all we have are the by-move builder methods, this would be true, but I did suggest that we have
To be fair, this is because there is no mechanism for Rust to expose an AST in a compatibility-safe manner. I don't think the existence of
But this is really inconvenient. You're effectively asking users to duplicate the entire logical
The fair comparison would be |
Ah that's true. In fact, I implemented it in
I think that's fine, although I'd love to hear why you feel this way.
Got it. Would diagnostics be emitted if a panic occurs? If so, this would mean that an in-progress diagnostic will be emitted even if it's not complete as this API provides no means by which In short, I don't see what advantage lazily emitting diagnostics provides. It's really unclear to me when you should expect a diagnostic to be emitted, and if there are cases in which it won't be emitted. |
They are Copy. (This is mentioned in my comment: "impl Copy for DiagnosticHandle".)
Oh oops. Fixed.
That's already explained in my comment: the diagnostics are emitted when the proc macro finishes executing. So, we can still add more information to diagnostics as long as the proc macro runs. |
How often does one need lazy diagnostic functionality? Aren't most use cases easily restructured to work with eager diagnostics? For lazy diagnostics, we need to decide between The main reason for keeping the stable surface of the |
We can either not show any diagnostics if the proc macro panics, or just show everything until the panic. I prefer the latter. I don't think having an "incomplete diagnostic" is surprising or a problem, as it would work just the same as println!(): println!("a");
panic!();
println!("b");
// "a" shown, followed by a panic message.
// "b" not shown. let diag = error(span, "a");
panic!();
diag.note("b");
// error "a" shown, followed by a panic message.
// note "b" not shown. An error without a note or label is still useful. And it's directly followed by the "proc macro panicked" message that explains it went 💥. |
Subjectively and personally, to me it doesn't really matter what gets emitted when it panics. I won't trust any of the output up until that point anyway given my experience with compilers. I'd rather see the crash fixed and getting complete output again before I trust whatever I see up until that point. |
This is about when the proc macro panics, not when the entire compiler panics. Rustc catches proc macro panics and presents them as regular errors. Almost every proc macro currently uses panics to report errors as the diagnostics api isn't stable. It will take a while for the entire ecosystem to move to the diagnostics api, until which it is expected that errors will be reported as a mix of the diagnostics api and panics. As such I think it is important for panics to still cause diagnostics to be emitted. |
I forgot to mention that @estebank and I also discussed this. While I mostly agreed with the quote above, @estebank convinced me there are enough use cases for non-lint warnings/notes that we probably shouldn't block the warning and note diagnostic API on having a lint API. (For example, proc macros specifically used for their warnings, like a We can always add a |
that's becoming less true since a decent amount of proc macros now use |
But, they all still have to build a nice message with notes and help. Having diagnostics being stable lets all the proc macros have the same UI as rust compiler errors. |
I know the discussion was earlier, but I do agree we shouldn't block this from going anywhere due to the lint API. I think we should start off with something basic like what Sergio suggested with a simple |
This is a tracking issue for diagnostics for procedural macros spawned off from #38356.
Overview
Current Status
proc_macro_diagnostics
(Initial diagnostic API for proc-macros. #44125).syn
.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:
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:
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"
.The text was updated successfully, but these errors were encountered: