@@ -175,12 +175,23 @@ fn impl_struct(input: Struct) -> TokenStream {
175175 #ty #body
176176 }
177177 } ;
178- let from_impl = quote_spanned ! { span=>
178+ let mut from_impl = quote_spanned ! { span=>
179179 #[ automatically_derived]
180180 impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
181181 #from_function
182182 }
183183 } ;
184+ if let Some ( from) = type_parameter_of_box ( from_field. ty ) {
185+ let body = from_some_source ( from_field, backtrace_field, quote ! ( :: thiserror:: #private:: Box :: new( #source_var) ) ) ;
186+ from_impl. extend ( quote_spanned ! { span=>
187+ #[ automatically_derived]
188+ impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
189+ fn from( #source_var: #from) -> Self {
190+ #ty #body
191+ }
192+ }
193+ } ) ;
194+ }
184195 Some ( quote ! {
185196 #[ allow(
186197 deprecated,
@@ -450,12 +461,23 @@ fn impl_enum(input: Enum) -> TokenStream {
450461 #ty:: #variant #body
451462 }
452463 } ;
453- let from_impl = quote_spanned ! { span=>
464+ let mut from_impl = quote_spanned ! { span=>
454465 #[ automatically_derived]
455466 impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
456467 #from_function
457468 }
458469 } ;
470+ if let Some ( boxed) = type_parameter_of_box ( from_field. ty ) {
471+ let body = from_some_source ( from_field, backtrace_field, quote ! ( :: thiserror:: #private:: Box :: new( #source_var) ) ) ;
472+ from_impl. extend ( quote_spanned ! { span=>
473+ #[ automatically_derived]
474+ impl #impl_generics :: core:: convert:: From <#boxed> for #ty #ty_generics #where_clause {
475+ fn from( #source_var: #boxed) -> Self {
476+ #ty:: #variant #body
477+ }
478+ }
479+ } ) ;
480+ }
459481 Some ( quote ! {
460482 #[ allow(
461483 deprecated,
@@ -524,12 +546,20 @@ fn from_initializer(
524546 backtrace_field : Option < & Field > ,
525547 source_var : & Ident ,
526548) -> TokenStream {
527- let from_member = & from_field. member ;
528549 let some_source = if type_is_option ( from_field. ty ) {
529550 quote ! ( :: core:: option:: Option :: Some ( #source_var) )
530551 } else {
531552 quote ! ( #source_var)
532553 } ;
554+ from_some_source ( from_field, backtrace_field, some_source)
555+ }
556+
557+ fn from_some_source (
558+ from_field : & Field ,
559+ backtrace_field : Option < & Field < ' _ > > ,
560+ some_source : TokenStream ,
561+ ) -> TokenStream {
562+ let from_member = & from_field. member ;
533563 let backtrace = backtrace_field. map ( |backtrace_field| {
534564 let backtrace_member = & backtrace_field. member ;
535565 if type_is_option ( backtrace_field. ty ) {
@@ -582,3 +612,29 @@ fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
582612 _ => None ,
583613 }
584614}
615+
616+ fn type_parameter_of_box ( ty : & Type ) -> Option < & Type > {
617+ let path = match ty {
618+ Type :: Path ( ty) => & ty. path ,
619+ _ => return None ,
620+ } ;
621+
622+ let last = path. segments . last ( ) . unwrap ( ) ;
623+ if last. ident != "Box" {
624+ return None ;
625+ }
626+
627+ let bracketed = match & last. arguments {
628+ PathArguments :: AngleBracketed ( bracketed) => bracketed,
629+ _ => return None ,
630+ } ;
631+
632+ if bracketed. args . len ( ) != 1 {
633+ return None ;
634+ }
635+
636+ match & bracketed. args [ 0 ] {
637+ GenericArgument :: Type ( arg) => Some ( arg) ,
638+ _ => None ,
639+ }
640+ }
0 commit comments