@@ -174,12 +174,23 @@ fn impl_struct(input: Struct) -> TokenStream {
174174 #ty #body
175175 }
176176 } ;
177- let from_impl = quote_spanned ! { span=>
177+ let mut from_impl = quote_spanned ! { span=>
178178 #[ automatically_derived]
179179 impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
180180 #from_function
181181 }
182182 } ;
183+ if let Some ( from) = type_parameter_of_box ( from_field. ty ) {
184+ let body = from_some_source ( from_field, backtrace_field, quote ! ( :: thiserror:: __private:: Box :: new( #source_var) ) ) ;
185+ from_impl. extend ( quote_spanned ! { span=>
186+ #[ automatically_derived]
187+ impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
188+ fn from( #source_var: #from) -> Self {
189+ #ty #body
190+ }
191+ }
192+ } ) ;
193+ }
183194 Some ( quote ! {
184195 #[ allow(
185196 deprecated,
@@ -449,12 +460,23 @@ fn impl_enum(input: Enum) -> TokenStream {
449460 #ty:: #variant #body
450461 }
451462 } ;
452- let from_impl = quote_spanned ! { span=>
463+ let mut from_impl = quote_spanned ! { span=>
453464 #[ automatically_derived]
454465 impl #impl_generics :: core:: convert:: From <#from> for #ty #ty_generics #where_clause {
455466 #from_function
456467 }
457468 } ;
469+ if let Some ( boxed) = type_parameter_of_box ( from_field. ty ) {
470+ let body = from_some_source ( from_field, backtrace_field, quote ! ( :: thiserror:: __private:: Box :: new( #source_var) ) ) ;
471+ from_impl. extend ( quote_spanned ! { span=>
472+ #[ automatically_derived]
473+ impl #impl_generics :: core:: convert:: From <#boxed> for #ty #ty_generics #where_clause {
474+ fn from( #source_var: #boxed) -> Self {
475+ #ty:: #variant #body
476+ }
477+ }
478+ } ) ;
479+ }
458480 Some ( quote ! {
459481 #[ allow(
460482 deprecated,
@@ -523,12 +545,20 @@ fn from_initializer(
523545 backtrace_field : Option < & Field > ,
524546 source_var : & Ident ,
525547) -> TokenStream {
526- let from_member = & from_field. member ;
527548 let some_source = if type_is_option ( from_field. ty ) {
528549 quote ! ( :: core:: option:: Option :: Some ( #source_var) )
529550 } else {
530551 quote ! ( #source_var)
531552 } ;
553+ from_some_source ( from_field, backtrace_field, some_source)
554+ }
555+
556+ fn from_some_source (
557+ from_field : & Field ,
558+ backtrace_field : Option < & Field < ' _ > > ,
559+ some_source : TokenStream ,
560+ ) -> TokenStream {
561+ let from_member = & from_field. member ;
532562 let backtrace = backtrace_field. map ( |backtrace_field| {
533563 let backtrace_member = & backtrace_field. member ;
534564 if type_is_option ( backtrace_field. ty ) {
@@ -581,3 +611,29 @@ fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
581611 _ => None ,
582612 }
583613}
614+
615+ fn type_parameter_of_box ( ty : & Type ) -> Option < & Type > {
616+ let path = match ty {
617+ Type :: Path ( ty) => & ty. path ,
618+ _ => return None ,
619+ } ;
620+
621+ let last = path. segments . last ( ) . unwrap ( ) ;
622+ if last. ident != "Box" {
623+ return None ;
624+ }
625+
626+ let bracketed = match & last. arguments {
627+ PathArguments :: AngleBracketed ( bracketed) => bracketed,
628+ _ => return None ,
629+ } ;
630+
631+ if bracketed. args . len ( ) != 1 {
632+ return None ;
633+ }
634+
635+ match & bracketed. args [ 0 ] {
636+ GenericArgument :: Type ( arg) => Some ( arg) ,
637+ _ => None ,
638+ }
639+ }
0 commit comments