@@ -220,6 +220,77 @@ fn is_phantom_deser_data(ty: &syn::Type) -> bool {
220220 false
221221}
222222
223+ /// Add trait bounds for associated (de)serialization types based on bounds on
224+ /// type parameters.
225+ fn add_ser_deser_bounds < T : quote:: ToTokens > (
226+ derive_input : & DeriveInput ,
227+ types_with_generics : & [ T ] ,
228+ where_clause_ser : & mut WhereClause ,
229+ where_clause_des : & mut WhereClause ,
230+ ) {
231+ // If there are bounded type parameters which are fields of the
232+ // struct, we need to impose the same bounds on the SerType and on
233+ // the DeserType.
234+ derive_input. generics . params . iter ( ) . for_each ( |param| {
235+ if let syn:: GenericParam :: Type ( t) = param {
236+ let ty = & t. ident ;
237+
238+ // We are just interested in types with bounds that are
239+ // types of fields of the struct.
240+ //
241+ // Note that types_with_generics contains also field types
242+ // *containing* a type parameter, but that just slows down
243+ // the search.
244+ if !t. bounds . is_empty ( )
245+ && types_with_generics
246+ . iter ( )
247+ . any ( |x| * ty == x. to_token_stream ( ) . to_string ( ) )
248+ {
249+ // Add a lifetime so we express bounds on DeserType
250+ let mut lifetimes = Punctuated :: new ( ) ;
251+ lifetimes. push ( GenericParam :: Lifetime ( LifetimeParam {
252+ attrs : vec ! [ ] ,
253+ lifetime : syn:: Lifetime :: new (
254+ "'epserde_desertype" ,
255+ proc_macro2:: Span :: call_site ( ) ,
256+ ) ,
257+ colon_token : None ,
258+ bounds : Punctuated :: new ( ) ,
259+ } ) ) ;
260+
261+ // Add the type bounds to the DeserType
262+ where_clause_des
263+ . predicates
264+ . push ( WherePredicate :: Type ( PredicateType {
265+ lifetimes : Some ( BoundLifetimes {
266+ for_token : token:: For :: default ( ) ,
267+ lt_token : token:: Lt :: default ( ) ,
268+ lifetimes,
269+ gt_token : token:: Gt :: default ( ) ,
270+ } ) ,
271+ bounded_ty : syn:: parse_quote!(
272+ <#ty as epserde:: deser:: DeserializeInner >:: DeserType <' epserde_desertype>
273+ ) ,
274+ colon_token : token:: Colon :: default ( ) ,
275+ bounds : t. bounds . clone ( ) ,
276+ } ) ) ;
277+
278+ // Add the type bounds to the SerType
279+ where_clause_ser
280+ . predicates
281+ . push ( WherePredicate :: Type ( PredicateType {
282+ lifetimes : None ,
283+ bounded_ty : syn:: parse_quote!(
284+ <#ty as epserde:: ser:: SerializeInner >:: SerType
285+ ) ,
286+ colon_token : token:: Colon :: default ( ) ,
287+ bounds : t. bounds . clone ( ) ,
288+ } ) ) ;
289+ }
290+ }
291+ } ) ;
292+ }
293+
223294/// Generate an ε-serde implementation for custom types.
224295///
225296/// It generates implementations for the traits `CopyType`,
@@ -265,7 +336,7 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
265336 ..
266337 } = CommonDeriveInput :: new ( derive_input. clone ( ) , vec ! [ ] ) ;
267338
268- let out = match derive_input. data {
339+ let out = match & derive_input. data {
269340 Data :: Struct ( s) => {
270341 let mut fields_types = vec ! [ ] ;
271342 let mut fields_names = vec ! [ ] ;
@@ -434,61 +505,12 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
434505 }
435506 }
436507 } else {
437- // If there are bounded type parameters which are fields of the
438- // struct, we need to impose the same bounds on the SerType and on
439- // the DeserType.
440- derive_input. generics . params . iter ( ) . for_each ( |param| {
441- if let GenericParam :: Type ( t) = param {
442- let ty = & t. ident ;
443-
444- // We are just interested in types with bounds that are
445- // types of fields of the struct.
446- //
447- // Note that types_with_generics contains also field types
448- // *containing* a type parameter, but that just slows down
449- // the search.
450- if ! t. bounds . is_empty ( ) &&
451- types_with_generics. iter ( ) . any ( |x| * ty == x. to_token_stream ( ) . to_string ( ) ) {
452-
453- let mut lifetimes = Punctuated :: new ( ) ;
454- // Add a lifetime so we express bounds on DeserType
455- lifetimes. push ( GenericParam :: Lifetime ( LifetimeParam {
456- attrs : vec ! [ ] ,
457- lifetime : syn:: Lifetime :: new ( "'epserde_desertype" , proc_macro2:: Span :: call_site ( ) ) ,
458- colon_token : None ,
459- bounds : Punctuated :: new ( ) ,
460- } ) ) ;
461- // Add the type bounds to the DeserType
462- where_clause_des
463- . predicates
464- . push ( WherePredicate :: Type ( PredicateType {
465- lifetimes : Some ( BoundLifetimes {
466- for_token : token:: For :: default ( ) ,
467- lt_token : token:: Lt :: default ( ) ,
468- lifetimes,
469- gt_token : token:: Gt :: default ( ) ,
470- } ) ,
471- bounded_ty : syn:: parse_quote!(
472- <#ty as epserde:: deser:: DeserializeInner >:: DeserType <' epserde_desertype>
473- ) ,
474- colon_token : token:: Colon :: default ( ) ,
475- bounds : t. bounds . clone ( ) ,
476- } ) ) ;
477-
478- // Add the type bounds to the SerType
479- where_clause_ser
480- . predicates
481- . push ( WherePredicate :: Type ( PredicateType {
482- lifetimes : None ,
483- bounded_ty : syn:: parse_quote!(
484- <#ty as epserde:: ser:: SerializeInner >:: SerType
485- ) ,
486- colon_token : token:: Colon :: default ( ) ,
487- bounds : t. bounds . clone ( ) ,
488- } ) ) ;
489- }
490- }
491- } ) ;
508+ add_ser_deser_bounds (
509+ & derive_input,
510+ & types_with_generics,
511+ & mut where_clause_ser,
512+ & mut where_clause_des,
513+ ) ;
492514
493515 quote ! {
494516 #[ automatically_derived]
@@ -817,61 +839,12 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
817839 }
818840 }
819841 } else {
820- // If there are bounded type parameters which are fields of the
821- // struct, we need to impose the same bounds on the SerType and on
822- // the DeserType.
823- derive_input. generics . params . iter ( ) . for_each ( |param| {
824- if let GenericParam :: Type ( t) = param {
825- let ty = & t. ident ;
826-
827- // We are just interested in types with bounds that are
828- // types of fields of the struct.
829- //
830- // Note that types_with_generics contains also field types
831- // *containing* a type parameter, but that just slows down
832- // the search.
833- if ! t. bounds . is_empty ( ) &&
834- types_with_generics. iter ( ) . any ( |x| * ty == x. to_token_stream ( ) . to_string ( ) ) {
835-
836- let mut lifetimes = Punctuated :: new ( ) ;
837- // Add a lifetime so we express bounds on DeserType
838- lifetimes. push ( GenericParam :: Lifetime ( LifetimeParam {
839- attrs : vec ! [ ] ,
840- lifetime : syn:: Lifetime :: new ( "'epserde_desertype" , proc_macro2:: Span :: call_site ( ) ) ,
841- colon_token : None ,
842- bounds : Punctuated :: new ( ) ,
843- } ) ) ;
844- // Add the type bounds to the DeserType
845- where_clause_des
846- . predicates
847- . push ( WherePredicate :: Type ( PredicateType {
848- lifetimes : Some ( BoundLifetimes {
849- for_token : token:: For :: default ( ) ,
850- lt_token : token:: Lt :: default ( ) ,
851- lifetimes,
852- gt_token : token:: Gt :: default ( ) ,
853- } ) ,
854- bounded_ty : syn:: parse_quote!(
855- <#ty as epserde:: deser:: DeserializeInner >:: DeserType <' epserde_desertype>
856- ) ,
857- colon_token : token:: Colon :: default ( ) ,
858- bounds : t. bounds . clone ( ) ,
859- } ) ) ;
860-
861- // Add the type bounds to the SerType
862- where_clause_ser
863- . predicates
864- . push ( WherePredicate :: Type ( PredicateType {
865- lifetimes : None ,
866- bounded_ty : syn:: parse_quote!(
867- <#ty as epserde:: ser:: SerializeInner >:: SerType
868- ) ,
869- colon_token : token:: Colon :: default ( ) ,
870- bounds : t. bounds . clone ( ) ,
871- } ) ) ;
872- }
873- }
874- } ) ;
842+ add_ser_deser_bounds (
843+ & derive_input,
844+ & types_with_generics,
845+ & mut where_clause_ser,
846+ & mut where_clause_des,
847+ ) ;
875848
876849 quote ! {
877850 #[ automatically_derived]
0 commit comments