Skip to content

Commit

Permalink
Merge pull request #76 from dtolnay/span
Browse files Browse the repository at this point in the history
Improve span of missing Display impl error
  • Loading branch information
dtolnay authored Apr 11, 2020
2 parents b649704 + 4885372 commit 382445c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
4 changes: 4 additions & 0 deletions impl/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ pub enum Input<'a> {
}

pub struct Struct<'a> {
pub original: &'a DeriveInput,
pub attrs: Attrs<'a>,
pub ident: Ident,
pub generics: &'a Generics,
pub fields: Vec<Field<'a>>,
}

pub struct Enum<'a> {
pub original: &'a DeriveInput,
pub attrs: Attrs<'a>,
pub ident: Ident,
pub generics: &'a Generics,
Expand Down Expand Up @@ -58,6 +60,7 @@ impl<'a> Struct<'a> {
display.expand_shorthand(&fields);
}
Ok(Struct {
original: node,
attrs,
ident: node.ident.clone(),
generics: &node.generics,
Expand Down Expand Up @@ -86,6 +89,7 @@ impl<'a> Enum<'a> {
})
.collect::<Result<_>>()?;
Ok(Enum {
original: node,
attrs,
ident: node.ident.clone(),
generics: &node.generics,
Expand Down
29 changes: 26 additions & 3 deletions impl/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::ast::{Enum, Field, Input, Struct};
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::spanned::Spanned;
use syn::{DeriveInput, Member, PathArguments, Result, Type};
use syn::{Data, DeriveInput, Member, PathArguments, Result, Type, Visibility};

pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
let input = Input::from_syn(node)?;
Expand Down Expand Up @@ -135,8 +135,10 @@ fn impl_struct(input: Struct) -> TokenStream {
}
});

let error_trait = spanned_error_trait(input.original);

quote! {
impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
#source_method
#backtrace_method
}
Expand Down Expand Up @@ -321,8 +323,10 @@ fn impl_enum(input: Enum) -> TokenStream {
})
});

let error_trait = spanned_error_trait(input.original);

quote! {
impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
#source_method
#backtrace_method
}
Expand Down Expand Up @@ -382,3 +386,22 @@ fn type_is_option(ty: &Type) -> bool {
_ => false,
}
}

fn spanned_error_trait(input: &DeriveInput) -> TokenStream {
let vis_span = match &input.vis {
Visibility::Public(vis) => Some(vis.pub_token.span()),
Visibility::Crate(vis) => Some(vis.crate_token.span()),
Visibility::Restricted(vis) => Some(vis.pub_token.span()),
Visibility::Inherited => None,
};
let data_span = match &input.data {
Data::Struct(data) => data.struct_token.span(),
Data::Enum(data) => data.enum_token.span(),
Data::Union(data) => data.union_token.span(),
};
let first_span = vis_span.unwrap_or(data_span);
let last_span = input.ident.span();
let path = quote_spanned!(first_span=> std::error::);
let error = quote_spanned!(last_span=> Error);
quote!(#path #error)
}
7 changes: 3 additions & 4 deletions tests/ui/missing-display.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
error[E0277]: `MyError` doesn't implement `std::fmt::Display`
--> $DIR/missing-display.rs:3:10
--> $DIR/missing-display.rs:4:1
|
3 | #[derive(Error, Debug)]
| ^^^^^ `MyError` cannot be formatted with the default formatter
4 | pub enum MyError {
| ^^^^^^^^^^^^^^^^ `MyError` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `MyError`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

0 comments on commit 382445c

Please sign in to comment.