proc-macro-error 0.4.0

Almost drop-in replacement to panics in proc-macros
Documentation

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

  • Warnings are emitted only on nightly, they're ignored on stable.
  • "help" suggestions cannot have their own span info on stable, (they inherit parent span).
  • If a panic occurs somewhere in your macro no errors will be displayed. This is not a technical limitation but intentional design, panic is not for error reporting.

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.

For most of the time you will be using macros.

Very much panic-like usage - abort execution and show the error. Expands to ! (never type).

Shortcut for abort!(Span::call_site(), ...). Expands to ! (never type).

proc_macro::Diagnostic-like usage - emit the error but do not abort the macro. The compilation will fail nonetheless. Expands to () (unit type).

Shortcut for emit_error!(Span::call_site(), ...). Expands to () (unit type).

Like emit_error! but emit a warning instead of error. The compilation will succeed. Expands to () (unit type).

Beware: warnings are nightly only, they are completely ignored on stable.

Shortcut for emit_warning!(Span::call_site(), ...). Expands to () (unit type).

Build instance of Diagnostic in format-like style.

Syntax

All the macros have pretty much the same syntax:

abort!(single_expr)

Shortcut for `Diagnostic::from().abort()`

2.  ```ignore
abort!(span, message)

Shortcut for Diagnostic::spanned(span, message.to_string()).abort()

abort!(span, format_literal, format_args...)

Shortcut for `Diagnostic::spanned(span, format!(format_literal, format_args...)).abort()`

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.

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

#### Note attachments

3.  Every macro can have "note" attachments (only 2 and 3 form).
```ignore
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
)

Diagnostic type

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