@@ -8,15 +8,15 @@ use self::variant::ChoiceVariant;
8
8
use crate :: { default_lifetime, TypeAttrs } ;
9
9
use proc_macro2:: TokenStream ;
10
10
use quote:: quote;
11
- use syn:: { DeriveInput , Ident , Lifetime } ;
11
+ use syn:: { DeriveInput , GenericParam , Generics , Ident , LifetimeParam } ;
12
12
13
13
/// Derive the `Choice` trait for an enum.
14
14
pub ( crate ) struct DeriveChoice {
15
15
/// Name of the enum type.
16
16
ident : Ident ,
17
17
18
- /// Lifetime of the type .
19
- lifetime : Option < Lifetime > ,
18
+ /// Generics of the enum .
19
+ generics : Generics ,
20
20
21
21
/// Variants of this `Choice`.
22
22
variants : Vec < ChoiceVariant > ,
@@ -33,13 +33,6 @@ impl DeriveChoice {
33
33
) ,
34
34
} ;
35
35
36
- // TODO(tarcieri): properly handle multiple lifetimes
37
- let lifetime = input
38
- . generics
39
- . lifetimes ( )
40
- . next ( )
41
- . map ( |lt| lt. lifetime . clone ( ) ) ;
42
-
43
36
let type_attrs = TypeAttrs :: parse ( & input. attrs ) ?;
44
37
let variants = data
45
38
. variants
@@ -49,30 +42,33 @@ impl DeriveChoice {
49
42
50
43
Ok ( Self {
51
44
ident : input. ident ,
52
- lifetime ,
45
+ generics : input . generics . clone ( ) ,
53
46
variants,
54
47
} )
55
48
}
56
49
57
50
/// Lower the derived output into a [`TokenStream`].
58
51
pub fn to_tokens ( & self ) -> TokenStream {
59
52
let ident = & self . ident ;
53
+ let mut generics = self . generics . clone ( ) ;
60
54
61
- let lifetime = match self . lifetime {
62
- Some ( ref lifetime) => quote ! ( #lifetime) ,
63
- None => {
64
- let lifetime = default_lifetime ( ) ;
65
- quote ! ( #lifetime)
66
- }
67
- } ;
68
-
69
- // Lifetime parameters
70
- // TODO(tarcieri): support multiple lifetimes
71
- let lt_params = self
72
- . lifetime
73
- . as_ref ( )
74
- . map ( |_| lifetime. clone ( ) )
75
- . unwrap_or_default ( ) ;
55
+ // Use the first lifetime parameter as lifetime for Decode/Encode lifetime
56
+ // if none found, add one.
57
+ let lifetime = generics
58
+ . lifetimes ( )
59
+ . next ( )
60
+ . map ( |lt| lt. lifetime . clone ( ) )
61
+ . unwrap_or_else ( || {
62
+ let lt = default_lifetime ( ) ;
63
+ generics
64
+ . params
65
+ . insert ( 0 , GenericParam :: Lifetime ( LifetimeParam :: new ( lt. clone ( ) ) ) ) ;
66
+ lt
67
+ } ) ;
68
+
69
+ // We may or may not have inserted a lifetime.
70
+ let ( _, ty_generics, where_clause) = self . generics . split_for_impl ( ) ;
71
+ let ( impl_generics, _, _) = generics. split_for_impl ( ) ;
76
72
77
73
let mut can_decode_body = Vec :: new ( ) ;
78
74
let mut decode_body = Vec :: new ( ) ;
@@ -89,13 +85,13 @@ impl DeriveChoice {
89
85
}
90
86
91
87
quote ! {
92
- impl <#lifetime> :: der:: Choice <#lifetime> for #ident<#lt_params> {
88
+ impl #impl_generics :: der:: Choice <#lifetime> for #ident #ty_generics #where_clause {
93
89
fn can_decode( tag: :: der:: Tag ) -> bool {
94
90
matches!( tag, #( #can_decode_body) |* )
95
91
}
96
92
}
97
93
98
- impl <#lifetime> :: der:: Decode <#lifetime> for #ident<#lt_params> {
94
+ impl #impl_generics :: der:: Decode <#lifetime> for #ident #ty_generics #where_clause {
99
95
type Error = :: der:: Error ;
100
96
101
97
fn decode<R : :: der:: Reader <#lifetime>>( reader: & mut R ) -> :: der:: Result <Self > {
@@ -111,7 +107,7 @@ impl DeriveChoice {
111
107
}
112
108
}
113
109
114
- impl <#lt_params> :: der:: EncodeValue for #ident<#lt_params> {
110
+ impl #impl_generics :: der:: EncodeValue for #ident #ty_generics #where_clause {
115
111
fn encode_value( & self , encoder: & mut impl :: der:: Writer ) -> :: der:: Result <( ) > {
116
112
match self {
117
113
#( #encode_body) *
@@ -125,7 +121,7 @@ impl DeriveChoice {
125
121
}
126
122
}
127
123
128
- impl <#lt_params> :: der:: Tagged for #ident<#lt_params> {
124
+ impl #impl_generics :: der:: Tagged for #ident #ty_generics #where_clause {
129
125
fn tag( & self ) -> :: der:: Tag {
130
126
match self {
131
127
#( #tagged_body) *
@@ -165,7 +161,7 @@ mod tests {
165
161
166
162
let ir = DeriveChoice :: new ( input) . unwrap ( ) ;
167
163
assert_eq ! ( ir. ident, "Time" ) ;
168
- assert_eq ! ( ir. lifetime , None ) ;
164
+ assert_eq ! ( ir. generics . lifetimes ( ) . next ( ) , None ) ;
169
165
assert_eq ! ( ir. variants. len( ) , 2 ) ;
170
166
171
167
let utc_time = & ir. variants [ 0 ] ;
@@ -205,7 +201,10 @@ mod tests {
205
201
206
202
let ir = DeriveChoice :: new ( input) . unwrap ( ) ;
207
203
assert_eq ! ( ir. ident, "ImplicitChoice" ) ;
208
- assert_eq ! ( ir. lifetime. unwrap( ) . to_string( ) , "'a" ) ;
204
+ assert_eq ! (
205
+ ir. generics. lifetimes( ) . next( ) . unwrap( ) . lifetime. to_string( ) ,
206
+ "'a"
207
+ ) ;
209
208
assert_eq ! ( ir. variants. len( ) , 3 ) ;
210
209
211
210
let bit_string = & ir. variants [ 0 ] ;
0 commit comments