diff options
Diffstat (limited to 'proc-macro-error/README.md')
-rw-r--r-- | proc-macro-error/README.md | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/proc-macro-error/README.md b/proc-macro-error/README.md deleted file mode 100644 index d6d1086..0000000 --- a/proc-macro-error/README.md +++ /dev/null @@ -1,206 +0,0 @@ -# proc-macro-error - -[![travis ci](https://travis-ci.org/CreepySkeleton/proc-macro-error.svg?branch=master)](https://travis-ci.org/CreepySkeleton/proc-macro-error) -[![docs.rs](https://docs.rs/proc-macro-error/badge.svg)](https://docs.rs/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][crate::dummy] to your errors. - -```toml -[dependencies] -proc-macro-error = "0.4" -``` - -*Supports rustc 1.31 and up* - -[Documentation and guide][guide] - -## What emitted errors look like - -``` -error: multiple error part: multi2 - - = note: help message test - = help: Option help test - = note: I see what you did here... - - --> $DIR/multi-error.rs:4:18 - | -4 | make_fn!(multi1, multi2, _, multi3); - | ^^^^^^ -``` - -## Examples - -### Panic-like usage - -```rust -use proc_macro_error::*; -use proc_macro::TokenStream; -use syn::{DeriveInput, parse_macro_input}; -use quote::quote; - -// This is your main entry point -#[proc_macro] -// this attribute *MUST* be placed on top of the #[proc_macro] function -#[proc_macro_error] -pub fn make_answer(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - - if let Err(err) = some_logic(&input) { - // we've got a span to blame, let's use it - // This immediately aborts the proc-macro and shows the error - abort!(err.span, "You made an error, go fix it: {}", err.msg); - } - - // `Result` has some handy shortcuts if your error type implements - // `Into<MacroError>`. `Option` has one unconditionally. - more_logic(&input).expect_or_abort("What a careless user, behave!"); - - if !more_logic_for_logic_god(&input) { - // We don't have an exact location this time, - // so just highlight the proc-macro invocation itself - abort_call_site!( - "Bad, bad user! Now go stand in the corner and think about what you did!"); - } - - // Now all the processing is done, return `proc_macro::TokenStream` - quote!(/* stuff */).into() -} -``` - -### `proc_macro::Diagnostic`-like usage - -```rust -use proc_macro_error::*; -use proc_macro::TokenStream; -use syn::{spanned::Spanned, DeriveInput, ItemStruct, Fields, Attribute , parse_macro_input}; -use quote::quote; - -fn process_attrs(attrs: &[Attribute]) -> Vec<Attribute> { - attrs - .iter() - .filter_map(|attr| match process_attr(attr) { - Ok(res) => Some(res), - Err(msg) => { - emit_error!(attr.span(), "Invalid attribute: {}", msg); - None - } - }) - .collect() -} - -fn process_fields(_attrs: &Fields) -> Vec<TokenStream> { - // processing fields in pretty much the same way as attributes - unimplemented!() -} - -#[proc_macro] -#[proc_macro_error] -pub fn make_answer(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemStruct); - let attrs = process_attrs(&input.attrs); - - // abort right now if some errors were encountered - // at the attributes processing stage - abort_if_dirty(); - - let fields = process_fields(&input.fields); - - // no need to think about emitted errors - // #[proc_macro_error] will handle them for you - // - // just return a TokenStream as you normally would - quote!(/* stuff */).into() -} -``` - -## 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. - -## MSRV policy - -`proc_macro_error` will always be compatible with proc-macro holy trinity: -`proc_macro2`, `syn`, `quote` crates. In other words, if the trinity is available -to you than `proc_macro_error` is available too. - -## Motivation - -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 your macro and convert it to -a [`compile_error!`][compl_err] 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. Almost nobody does it, - simple `.expect` is 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::Diagnostic`][] is finally stable. - Not cool. - -- Later sucks because there's no way to carry out span info via `panic!`. `rustc` will highlight - the whole 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 `None` or out-of-range indexing) or for early development stages - when you need a prototype ASAP and error handling can wait. Mixing these usages only - messes things up. - -- There is [`proc_macro::Diagnostic`][] which 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::Diagnostic` - and delegates to it whenever possible. Once `Diagnostics` is 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 span information - over to user. -- It must take as little effort as possible to migrate from `panic!`. Ideally, a new - macro with the same semantics plus ability to carry out span info. We should also keep - in mind the existence of [`proc_macro::Diagnostic`][] . -- **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_errors]` attribute and change panics to -[`abort!`]/[`abort_call_site!`] where appropriate, see [the Guide][guide]. - -## Disclaimer -Please note that **this crate is not intended to be used in any way other -than proc-macro error reporting**, use `Result` and `?` for anything else. - -<br> - -#### License - -<sup> -Licensed under either of <a href="LICENSE-APACHE">Apache License, Version -2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. -</sup> - -<br> - -<sub> -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this crate by you, as defined in the Apache-2.0 license, shall -be dual licensed as above, without any additional terms or conditions. -</sub> - - -[compl_err]: https://doc.rust-lang.org/std/macro.compile_error.html -[`proc_macro::Diagnostic`]: https://doc.rust-lang.org/proc_macro/struct.Diagnostic.html - -[crate::dummy]: https://docs.rs/proc-macro-error/0.4/proc_macro_error/dummy/index.html -[crate::multi]: https://docs.rs/proc-macro-error/0.4/proc_macro_error/multi/index.html - -[`abort_call_site!`]: https://docs.rs/proc-macro-error/0.4/proc_macro_error/macro.abort_call_site.html -[`abort!`]: https://docs.rs/proc-macro-error/0.4/proc_macro_error/macro.abort.html -[guide]: https://docs.rs/proc-macro-error |