@@ -14,7 +14,7 @@ pub fn derive_asn1_read(input: proc_macro::TokenStream) -> proc_macro::TokenStre
1414 let lifetime_name = add_lifetime_if_none ( & mut generics) ;
1515 add_bounds (
1616 & mut generics,
17- all_field_types ( & input. data ) ,
17+ all_field_types ( & input. data , & input . generics ) ,
1818 syn:: parse_quote!( asn1:: Asn1Readable <#lifetime_name>) ,
1919 syn:: parse_quote!( asn1:: Asn1DefinedByReadable <#lifetime_name, asn1:: ObjectIdentifier >) ,
2020 false ,
@@ -61,9 +61,10 @@ pub fn derive_asn1_write(input: proc_macro::TokenStream) -> proc_macro::TokenStr
6161 let mut input = syn:: parse_macro_input!( input as syn:: DeriveInput ) ;
6262
6363 let name = input. ident ;
64+ let fields = all_field_types ( & input. data , & input. generics ) ;
6465 add_bounds (
6566 & mut input. generics ,
66- all_field_types ( & input . data ) ,
67+ fields ,
6768 syn:: parse_quote!( asn1:: Asn1Writable ) ,
6869 syn:: parse_quote!( asn1:: Asn1DefinedByWritable <asn1:: ObjectIdentifier >) ,
6970 true ,
@@ -275,16 +276,33 @@ fn add_lifetime_if_none(generics: &mut syn::Generics) -> syn::Lifetime {
275276 generics. lifetimes ( ) . next ( ) . unwrap ( ) . lifetime . clone ( )
276277}
277278
278- fn all_field_types ( data : & syn:: Data ) -> Vec < ( syn:: Type , OpType , bool ) > {
279+ fn all_field_types ( data : & syn:: Data , generics : & syn:: Generics ) -> Vec < ( syn:: Type , OpType , bool ) > {
280+ let generic_params = generics
281+ . params
282+ . iter ( )
283+ . filter_map ( |p| {
284+ if let syn:: GenericParam :: Type ( tp) = p {
285+ Some ( tp. ident . clone ( ) )
286+ } else {
287+ None
288+ }
289+ } )
290+ . collect :: < Vec < _ > > ( ) ;
291+
279292 let mut field_types = vec ! [ ] ;
280293 match data {
281294 syn:: Data :: Struct ( v) => {
282- add_field_types ( & mut field_types, & v. fields , None ) ;
295+ add_field_types ( & mut field_types, & v. fields , None , & generic_params ) ;
283296 }
284297 syn:: Data :: Enum ( v) => {
285298 for variant in & v. variants {
286299 let ( op_type, _) = extract_field_properties ( & variant. attrs ) ;
287- add_field_types ( & mut field_types, & variant. fields , Some ( op_type) ) ;
300+ add_field_types (
301+ & mut field_types,
302+ & variant. fields ,
303+ Some ( op_type) ,
304+ & generic_params,
305+ ) ;
288306 }
289307 }
290308 syn:: Data :: Union ( _) => panic ! ( "Unions not supported" ) ,
@@ -296,27 +314,74 @@ fn add_field_types(
296314 field_types : & mut Vec < ( syn:: Type , OpType , bool ) > ,
297315 fields : & syn:: Fields ,
298316 op_type : Option < OpType > ,
317+ generic_params : & [ syn:: Ident ] ,
299318) {
300319 match fields {
301320 syn:: Fields :: Named ( v) => {
302321 for f in & v. named {
303- add_field_type ( field_types, f, op_type. clone ( ) ) ;
322+ add_field_type ( field_types, f, op_type. clone ( ) , generic_params ) ;
304323 }
305324 }
306325 syn:: Fields :: Unnamed ( v) => {
307326 for f in & v. unnamed {
308- add_field_type ( field_types, f, op_type. clone ( ) ) ;
327+ add_field_type ( field_types, f, op_type. clone ( ) , generic_params ) ;
309328 }
310329 }
311330 syn:: Fields :: Unit => { }
312331 }
313332}
314333
334+ fn type_contains_generic_param ( t : & syn:: Type , generic_params : & [ syn:: Ident ] ) -> bool {
335+ match t {
336+ syn:: Type :: Array ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
337+ syn:: Type :: BareFn ( _) => todo ! ( "BareFn" ) ,
338+ syn:: Type :: Group ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
339+ syn:: Type :: ImplTrait ( _) => todo ! ( "ImplTrait" ) ,
340+ syn:: Type :: Infer ( _) => false ,
341+ syn:: Type :: Macro ( _) => false ,
342+ syn:: Type :: Never ( _) => false ,
343+ syn:: Type :: Paren ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
344+ syn:: Type :: Path ( v) => {
345+ if let Some ( q) = & v. qself {
346+ if type_contains_generic_param ( & q. ty , generic_params) {
347+ return true ;
348+ }
349+ } else if generic_params. contains ( & v. path . segments [ 0 ] . ident ) {
350+ return true ;
351+ }
352+ v. path . segments . iter ( ) . any ( |s| match & s. arguments {
353+ syn:: PathArguments :: AngleBracketed ( a) => a. args . iter ( ) . any ( |ga| match ga {
354+ syn:: GenericArgument :: Type ( t) => type_contains_generic_param ( t, generic_params) ,
355+ _ => false ,
356+ } ) ,
357+ syn:: PathArguments :: Parenthesized ( _) => todo ! ( "ParenthesizedGenericArguments" ) ,
358+ syn:: PathArguments :: None => false ,
359+ } )
360+ }
361+ syn:: Type :: Ptr ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
362+ syn:: Type :: Reference ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
363+ syn:: Type :: Slice ( v) => type_contains_generic_param ( & v. elem , generic_params) ,
364+ syn:: Type :: TraitObject ( _) => todo ! ( "TraitObject" ) ,
365+ syn:: Type :: Tuple ( v) => v
366+ . elems
367+ . iter ( )
368+ . any ( |t| type_contains_generic_param ( t, generic_params) ) ,
369+ syn:: Type :: Verbatim ( _) => false ,
370+
371+ _ => false ,
372+ }
373+ }
374+
315375fn add_field_type (
316376 field_types : & mut Vec < ( syn:: Type , OpType , bool ) > ,
317377 f : & syn:: Field ,
318378 op_type : Option < OpType > ,
379+ generic_params : & [ syn:: Ident ] ,
319380) {
381+ if !type_contains_generic_param ( & f. ty , generic_params) {
382+ return ;
383+ }
384+
320385 // If we have an op_type here, it means it came from an enum variant. In
321386 // that case, even though it wasn't marked "required", it is for the
322387 // purposes of how we're using it.
0 commit comments