mirror of
https://github.com/dtolnay/thiserror.git
synced 2025-04-04 21:37:57 +03:00
Support backtrace in From impl
This commit is contained in:
parent
f40910293b
commit
46de723f20
3 changed files with 38 additions and 7 deletions
|
@ -90,12 +90,13 @@ fn impl_struct(input: Struct) -> TokenStream {
|
|||
});
|
||||
|
||||
let from_impl = input.from_field().map(|from_field| {
|
||||
let member = &from_field.member;
|
||||
let backtrace_field = input.backtrace_field();
|
||||
let from = from_field.ty;
|
||||
let body = from_initializer(from_field, backtrace_field);
|
||||
quote! {
|
||||
impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
|
||||
fn from(source: #from) -> Self {
|
||||
#ty { #member: source }
|
||||
#ty #body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,13 +244,14 @@ fn impl_enum(input: Enum) -> TokenStream {
|
|||
|
||||
let from_impls = input.variants.iter().filter_map(|variant| {
|
||||
let from_field = variant.from_field()?;
|
||||
let backtrace_field = variant.backtrace_field();
|
||||
let variant = &variant.ident;
|
||||
let member = &from_field.member;
|
||||
let from = from_field.ty;
|
||||
let body = from_initializer(from_field, backtrace_field);
|
||||
Some(quote! {
|
||||
impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
|
||||
fn from(source: #from) -> Self {
|
||||
#ty::#variant { #member: source }
|
||||
#ty::#variant #body
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -280,6 +282,26 @@ fn fields_pat(fields: &[Field]) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream {
|
||||
let from_member = &from_field.member;
|
||||
let backtrace = backtrace_field.map(|backtrace_field| {
|
||||
let backtrace_member = &backtrace_field.member;
|
||||
if type_is_option(backtrace_field.ty) {
|
||||
quote! {
|
||||
#backtrace_member: std::option::Option::Some(std::backtrace::Backtrace::capture()),
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#backtrace_member: std::backtrace::Backtrace::capture(),
|
||||
}
|
||||
}
|
||||
});
|
||||
quote!({
|
||||
#from_member: source,
|
||||
#backtrace
|
||||
})
|
||||
}
|
||||
|
||||
fn type_is_option(ty: &Type) -> bool {
|
||||
let path = match ty {
|
||||
Type::Path(ty) => &ty.path,
|
||||
|
|
|
@ -51,6 +51,12 @@ impl Variant<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Field<'_> {
|
||||
pub(crate) fn is_backtrace(&self) -> bool {
|
||||
type_is_backtrace(self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
|
||||
for field in fields {
|
||||
if field.attrs.from.is_some() {
|
||||
|
@ -82,7 +88,7 @@ fn backtrace_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
|
|||
}
|
||||
}
|
||||
for field in fields {
|
||||
if type_is_backtrace(field.ty) {
|
||||
if field.is_backtrace() {
|
||||
return Some(&field);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> {
|
|||
let mut from_field = None;
|
||||
let mut source_field = None;
|
||||
let mut backtrace_field = None;
|
||||
let mut has_backtrace = false;
|
||||
for field in fields {
|
||||
if let Some(from) = field.attrs.from {
|
||||
if from_field.is_some() {
|
||||
|
@ -125,7 +126,9 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> {
|
|||
));
|
||||
}
|
||||
backtrace_field = Some(field);
|
||||
has_backtrace = true;
|
||||
}
|
||||
has_backtrace |= field.is_backtrace();
|
||||
}
|
||||
if let (Some(from_field), Some(source_field)) = (from_field, source_field) {
|
||||
if !same_member(from_field, source_field) {
|
||||
|
@ -136,10 +139,10 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> {
|
|||
}
|
||||
}
|
||||
if let Some(from_field) = from_field {
|
||||
if fields.len() > 1 {
|
||||
if fields.len() > 1 + has_backtrace as usize {
|
||||
return Err(Error::new_spanned(
|
||||
from_field.attrs.from,
|
||||
"deriving From requires no fields other than source",
|
||||
"deriving From requires no fields other than source and backtrace",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue