[][src]Crate proc_macro_error

proc-macro-error

This crate aims to make error reporting in proc-macros simple and easy to use. Migrate from panic!-based errors for as little effort as possible!

Also, there's ability to append a dummy token stream to your errors.

Limitations

Guide

Macros

First of all - all the emitting-related API must be used within a function annotated with #[proc_macro_error] attribute. You'll just get a panic otherwise, no errors will be shown.

Most of the time you want to use the macros.

Syntax

All the macros have pretty much the same syntax:

  1. This example is not tested
    abort!(single_expr)

    Shortcut for Diagnostic::from(expr).abort(). There's no way to attach notes in this form!

  2. This example is not tested
    abort!(span, message)

    The first argument is an expression the span info should be taken from. It can be either

    • [proc_macro::Span]
    • [proc_macro2::Span]
    • Anything that implements [quote::ToTokens], in other words, almost every type
    • in syn and proc_macro2. This form gives the best looking error messages and should be used whenever possible!

    The second argument is the error message, it must implement [ToString].

  3. This example is not tested
    abort!(span, format_literal, format_args...)

    This form is pretty much the same as 2, except format!(format_literal, format_args...) will be used to for the message instead of [ToString].

That's it. abort!, emit_warning, emit_error share this exact syntax.

abort_call_site!, emit_call_site_warning, emit_call_site_error lack 1 form and do not take span in 2 and 3 forms. Those are essentially shortcuts for macro!(Span::call_site(), args...).

diagnostic! requires Level instance between span and second argument (1 form is the same).

Important!

If you have some type from proc_macro or syn to point to, do not call .span() on it but rather use it directly:

let ty: syn::Type = syn::parse2(input).unwrap();
abort!(ty, "BOOM");
//     ^^ <-- avoid .span()

.span() calls work too, but you may experience regressions in message quality.

Note attachments

  1. Every macro can have "note" attachments (only 2 and 3 form).
This example is not tested
let opt_help = if have_some_info { Some("did you mean `this`?") } else { None };

abort!(
    span, message; // <--- attachments start with `;` (semicolon)

    help = "format {} {}", "arg1", "arg2"; // <--- every attachment ends with `;`,
                                           //      maybe except the last one

    note = "to_string"; // <--- one arg uses `.to_string()` instead of `format!()`

    yay = "I see what {} did here", "you"; // <--- "help =" and "hint =" are mapped
                                           // to Diagnostic::help,
                                           // anything else is Diagnostic::note

    wow = note_span => "custom span"; // <--- attachments can have their own span
                                      //      it takes effect only on nightly though

    hint =? opt_help; // <-- "optional" attachment, get displayed only if `Some`
                      //     must be single `Option` expression

    note =? note_span => opt_help // <-- optional attachments can have custom spans too
);

#[proc_macro_error] attribute

This attribute MUST be present on the top level of your macro.

This attribute performs the setup and cleanup necessary to make things work.

Syntax

#[proc_macro_error] or #[proc_macro_error(settings...)], where settings... is a comma-separated list of:

Diagnostic type

Diagnostic type is intentionally designed to be API compatible with proc_macro::Diagnostic. Not all API is implemented, only the part that can be reasonably implemented on stable.

Re-exports

pub use crate::dummy::append_dummy;
pub use crate::dummy::set_dummy;

Modules

dummy

Facility to emit dummy implementations (or whatever) in case an error happen.

Macros

abort

Abort proc-macro execution right now and display the error.

abort_call_site

Shortcut for abort!(Span::call_site(), msg...). This macro is still preferable over plain panic, panics are not for error reporting.

diagnostic

Build Diagnostic instance from provided arguments.

emit_call_site_error

Shortcut for emit_error!(Span::call_site(), ...). This macro is still preferable over plain panic, panics are not for error reporting..

emit_call_site_warning

Shortcut for emit_warning!(Span::call_site(), ...).

emit_error

Emit an error while not aborting the proc-macro right away.

emit_warning

Emit a warning. Warnings are not errors and compilation won't fail because of them.

Structs

Diagnostic

Represents a single diagnostic message

Enums

Level

Represents a diagnostic level

Traits

OptionExt

This traits expands Option with some handy shortcuts.

ResultExt

This traits expands Result<T, Into<Diagnostic>> with some handy shortcuts.

Functions

abort_if_dirty

Abort macro execution and display all the emitted errors, if any.

Attribute Macros

proc_macro_error