pub struct Error { /* private fields */ }
Expand description
Error returned when a Syn parser cannot parse the input tokens.
Error reporting in proc macros
The correct way to report errors back to the compiler from a procedural
macro is by emitting an appropriately spanned invocation of
compile_error!
in the generated code. This produces a better diagnostic
message than simply panicking the macro.
When parsing macro input, the parse_macro_input!
macro handles the
conversion to compile_error!
automatically.
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, ItemFn};
#[proc_macro_attribute]
pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as MyAttrArgs);
let input = parse_macro_input!(input as ItemFn);
/* ... */
}
struct MyAttrArgs {
...
}
impl Parse for MyAttrArgs {
fn parse(input: ParseStream) -> Result<Self> {
...
}
}
For errors that arise later than the initial parsing stage, the
.to_compile_error()
or .into_compile_error()
methods can be used to
perform an explicit conversion to compile_error!
.
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
// fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
expand::my_derive(input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
Implementations§
source§impl Error
impl Error
sourcepub fn new<T: Display>(span: Span, message: T) -> Self
pub fn new<T: Display>(span: Span, message: T) -> Self
Usually the ParseStream::error
method will be used instead, which
automatically uses the correct span from the current position of the
parse stream.
Use Error::new
when the error needs to be triggered on some span other
than where the parse stream is currently positioned.
Example
use syn::{Error, Ident, LitStr, Result, Token};
use syn::parse::ParseStream;
// Parses input that looks like `name = "string"` where the key must be
// the identifier `name` and the value may be any string literal.
// Returns the string literal.
fn parse_name(input: ParseStream) -> Result<LitStr> {
let name_token: Ident = input.parse()?;
if name_token != "name" {
// Trigger an error not on the current position of the stream,
// but on the position of the unexpected identifier.
return Err(Error::new(name_token.span(), "expected `name`"));
}
input.parse::<Token![=]>()?;
let s: LitStr = input.parse()?;
Ok(s)
}
sourcepub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self
pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self
Creates an error with the specified message spanning the given syntax tree node.
Unlike the Error::new
constructor, this constructor takes an argument
tokens
which is a syntax tree node. This allows the resulting Error
to attempt to span all tokens inside of tokens
. While you would
typically be able to use the Spanned
trait with the above Error::new
constructor, implementation limitations today mean that
Error::new_spanned
may provide a higher-quality error message on
stable Rust.
When in doubt it’s recommended to stick to Error::new
(or
ParseStream::error
)!
sourcepub fn span(&self) -> Span
pub fn span(&self) -> Span
The source location of the error.
Spans are not thread-safe so this function returns Span::call_site()
if called from a different thread than the one on which the Error
was
originally created.
sourcepub fn to_compile_error(&self) -> TokenStream
pub fn to_compile_error(&self) -> TokenStream
Render the error as an invocation of compile_error!
.
The parse_macro_input!
macro provides a convenient way to invoke
this method correctly in a procedural macro.
sourcepub fn into_compile_error(self) -> TokenStream
pub fn into_compile_error(self) -> TokenStream
Render the error as an invocation of compile_error!
.
Example
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, Error};
#[proc_macro_derive(MyTrait)]
pub fn derive_my_trait(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
my_trait::expand(input)
.unwrap_or_else(Error::into_compile_error)
.into()
}
mod my_trait {
use proc_macro2::TokenStream;
use syn::{DeriveInput, Result};
pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> {
/* ... */
}
}
Trait Implementations§
source§impl Error for Error
impl Error for Error
1.30.0 · source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · source§fn description(&self) -> &str
fn description(&self) -> &str
source§impl Extend<Error> for Error
impl Extend<Error> for Error
source§fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T)
fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T)
source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)