Makes error reporting in procedural macros nice and easy
This crate aims to make error reporting in proc-macros simple and easy to use.
panic!-based errors for as little effort as possible!
Also, you can explicitly append a dummy token stream to your errors.
To achieve his, this crate serves as a tiny shim around
compile_error!. It detects the most preferable way to emit errors based on compiler's version.
When the underlying diagnostic type is finally stabilized, this crate will be simply
delegating to it, requiring no changes in your code!
So you can just use this crate and have both some of
available on stable ahead of time and your error-reporting code future-proof.
 = "1.0"
Supports rustc 1.31 and up
This is how the error is rendered in a terminal:
And this is what your users will see in their IDE:
use ; use TokenStream; use ; use quote; // This is your main entry point // This attribute *MUST* be placed on top of the #[proc_macro] function
use *; use TokenStream; use ; use quote;
Real world examples
- Warnings are emitted only on nightly, they are ignored on stable.
- "help" suggestions can't have their own span info on stable, (essentially inheriting the parent span).
- If your macro happens to trigger a panic, no errors will be displayed. This is not a
technical limitation but rather intentional design.
panicis not for error reporting.
proc_macro_error will always be compatible with proc-macro Holy Trinity:
quote crates. In other words, if the Trinity is available
to you -
proc_macro_error is available too.
If you want to use
synstructure, you're going to have to put the attribute inside the
decl_derive!invocation. Unfortunately, due to some bug in pre-1.34 rustc, putting proc-macro attributes inside macro invocations doesn't work, so your MSRV is effectively 1.34.
Error handling in proc-macros sucks. There's not much of a choice today:
you either "bubble up" the error up to the top-level of the macro and convert it to
compile_error! invocation or just use a good old panic. Both these ways suck:
Former sucks because it's quite redundant to unroll a proper error handling just for critical errors that will crash the macro anyway; so people mostly choose not to bother with it at all and use panic. Simple
.expectis too tempting.
Also, if you do decide to implement this
Result-based architecture in your macro you're going to have to rewrite it entirely once
proc_macro::Diagnosticis finally stable. Not cool.
Later sucks because there's no way to carry out the span info via
rustcwill highlight the invocation itself but not some specific token inside it.
Furthermore, panics aren't for error-reporting at all; panics are for bug-detecting (like unwrapping on
Noneor out-of-range indexing) or for early development stages when you need a prototype ASAP so error handling can wait. Mixing these usages only messes things up.
proc_macro::Diagnosticwhich is awesome but it has been experimental for more than a year and is unlikely to be stabilized any time soon.
This crate's API is intentionally designed to be compatible with
proc_macro::Diagnosticand delegates to it whenever possible. Once
Diagnosticsis stable this crate will always delegate to it, no code changes will be required on user side.
That said, we need a solution, but this solution must meet these conditions:
- It must be better than
panic!. The main point: it must offer a way to carry the span information over to user.
- It must take as little effort as possible to migrate from
panic!. Ideally, a new macro with similar semantics plus ability to carry out span info.
- It must maintain compatibility with
- It must be usable on stable.
This crate aims to provide such a mechanism. All you have to do is annotate your top-level
#[proc_macro] function with
#[proc_macro_error] attribute and change panics to
abort_call_site! where appropriate, see the Guide.
Please note that this crate is not intended to be used in any way other
than error reporting in procedural macros, use
? (possibly along with one of the
many helpers out there) for anything else.