1
1
use proc_macro2:: TokenStream as TokenStream2 ;
2
2
use quote:: quote;
3
- use syn:: { parse_quote_spanned, DataEnum , DeriveInput , Fields , Type , Variant } ;
3
+ use syn:: { parse_quote_spanned, visit :: Visit as _ , DataEnum , DeriveInput , Fields , Type , Variant } ;
4
4
5
5
use crate :: {
6
6
config_for_enum_with_attrs, config_for_variant, macro_name, position_of_selected_field,
7
+ TypeVisitor ,
7
8
} ;
8
9
9
10
pub ( crate ) struct EnumDeriver {
@@ -43,6 +44,8 @@ impl EnumDeriver {
43
44
let outer = enum_ident;
44
45
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
45
46
47
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
48
+
46
49
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
47
50
48
51
for variant in self . variants ( ) ? {
@@ -65,6 +68,10 @@ impl EnumDeriver {
65
68
let inner_field = fields[ selection_index] ;
66
69
let inner_ty = & inner_field. ty ;
67
70
71
+ if self . uses_generic_const_or_type ( inner_ty) {
72
+ continue ;
73
+ }
74
+
68
75
let field_expressions: Vec < _ > = fields
69
76
. iter ( )
70
77
. enumerate ( )
@@ -92,7 +99,7 @@ impl EnumDeriver {
92
99
} ;
93
100
94
101
impls. push ( quote ! {
95
- impl :: core:: convert:: From <#inner_ty> for #outer_ty {
102
+ impl #impl_generics :: core:: convert:: From <#inner_ty> for #outer_ty #type_generics #where_clause {
96
103
fn from( inner: #inner_ty) -> Self {
97
104
#expression
98
105
}
@@ -116,6 +123,8 @@ impl EnumDeriver {
116
123
let outer = enum_ident;
117
124
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
118
125
126
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
127
+
119
128
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
120
129
121
130
for variant in self . variants ( ) ? {
@@ -139,6 +148,10 @@ impl EnumDeriver {
139
148
let inner_ident = inner_field. ident . as_ref ( ) ;
140
149
let inner_ty = & inner_field. ty ;
141
150
151
+ if self . uses_generic_const_or_type ( inner_ty) {
152
+ continue ;
153
+ }
154
+
142
155
let pattern = match & variant. fields {
143
156
Fields :: Named ( _) => {
144
157
let field = inner_ident;
@@ -154,10 +167,10 @@ impl EnumDeriver {
154
167
} ;
155
168
156
169
impls. push ( quote ! {
157
- impl :: core:: convert:: TryFrom <#outer_ty> for #inner_ty {
158
- type Error = #outer_ty;
170
+ impl #impl_generics :: core:: convert:: TryFrom <#outer_ty #type_generics > for #inner_ty #where_clause {
171
+ type Error = #outer_ty #type_generics ;
159
172
160
- fn try_from( outer: #outer_ty) -> Result <Self , Self :: Error > {
173
+ fn try_from( outer: #outer_ty #type_generics ) -> Result <Self , Self :: Error > {
161
174
match outer {
162
175
#pattern => Ok ( inner) ,
163
176
err => Err ( err)
@@ -183,6 +196,8 @@ impl EnumDeriver {
183
196
let outer = enum_ident;
184
197
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
185
198
199
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
200
+
186
201
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
187
202
188
203
for variant in self . variants ( ) ? {
@@ -205,6 +220,10 @@ impl EnumDeriver {
205
220
let inner_field = fields[ selection_index] ;
206
221
let inner_ty = & inner_field. ty ;
207
222
223
+ if self . uses_generic_const_or_type ( inner_ty) {
224
+ continue ;
225
+ }
226
+
208
227
let field_expressions: Vec < _ > = fields
209
228
. iter ( )
210
229
. enumerate ( )
@@ -232,7 +251,7 @@ impl EnumDeriver {
232
251
} ;
233
252
234
253
impls. push ( quote ! {
235
- impl :: enumcapsulate:: FromVariant <#inner_ty> for #outer_ty {
254
+ impl #impl_generics :: enumcapsulate:: FromVariant <#inner_ty> for #outer_ty #type_generics #where_clause {
236
255
fn from_variant( inner: #inner_ty) -> Self {
237
256
#expression
238
257
}
@@ -256,6 +275,8 @@ impl EnumDeriver {
256
275
let outer = enum_ident;
257
276
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
258
277
278
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
279
+
259
280
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
260
281
261
282
for variant in self . variants ( ) ? {
@@ -279,6 +300,10 @@ impl EnumDeriver {
279
300
let inner_ident = inner_field. ident . as_ref ( ) ;
280
301
let inner_ty = & inner_field. ty ;
281
302
303
+ if self . uses_generic_const_or_type ( inner_ty) {
304
+ continue ;
305
+ }
306
+
282
307
let pattern = match & variant. fields {
283
308
Fields :: Named ( _) => {
284
309
let field = inner_ident;
@@ -293,11 +318,13 @@ impl EnumDeriver {
293
318
Fields :: Unit => continue ,
294
319
} ;
295
320
321
+ let where_clause = match where_clause {
322
+ Some ( where_clause) => quote ! { #where_clause #inner_ty: Clone } ,
323
+ None => quote ! { where #inner_ty: Clone } ,
324
+ } ;
325
+
296
326
impls. push ( quote ! {
297
- impl :: enumcapsulate:: AsVariant <#inner_ty> for #outer_ty
298
- where
299
- #inner_ty: Clone
300
- {
327
+ impl #impl_generics :: enumcapsulate:: AsVariant <#inner_ty> for #outer_ty #type_generics #where_clause {
301
328
fn as_variant( & self ) -> Option <#inner_ty> {
302
329
match self {
303
330
#pattern => Some ( inner. clone( ) ) ,
@@ -324,6 +351,8 @@ impl EnumDeriver {
324
351
let outer = enum_ident;
325
352
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
326
353
354
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
355
+
327
356
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
328
357
329
358
for variant in self . variants ( ) ? {
@@ -347,6 +376,9 @@ impl EnumDeriver {
347
376
let inner_ident = inner_field. ident . as_ref ( ) ;
348
377
let inner_ty = & inner_field. ty ;
349
378
379
+ if self . uses_generic_const_or_type ( inner_ty) {
380
+ continue ;
381
+ }
350
382
let pattern = match & variant. fields {
351
383
Fields :: Named ( _) => {
352
384
let field = inner_ident;
@@ -362,7 +394,7 @@ impl EnumDeriver {
362
394
} ;
363
395
364
396
impls. push ( quote ! {
365
- impl :: enumcapsulate:: AsVariantRef <#inner_ty> for #outer_ty {
397
+ impl #impl_generics :: enumcapsulate:: AsVariantRef <#inner_ty> for #outer_ty #type_generics #where_clause {
366
398
fn as_variant_ref( & self ) -> Option <& #inner_ty> {
367
399
match self {
368
400
#pattern => Some ( inner) ,
@@ -389,6 +421,8 @@ impl EnumDeriver {
389
421
let outer = enum_ident;
390
422
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
391
423
424
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
425
+
392
426
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
393
427
394
428
for variant in self . variants ( ) ? {
@@ -412,6 +446,10 @@ impl EnumDeriver {
412
446
let inner_ident = inner_field. ident . as_ref ( ) ;
413
447
let inner_ty = & inner_field. ty ;
414
448
449
+ if self . uses_generic_const_or_type ( inner_ty) {
450
+ continue ;
451
+ }
452
+
415
453
let pattern = match & variant. fields {
416
454
Fields :: Named ( _) => {
417
455
let field = inner_ident;
@@ -427,7 +465,7 @@ impl EnumDeriver {
427
465
} ;
428
466
429
467
impls. push ( quote ! {
430
- impl :: enumcapsulate:: AsVariantMut <#inner_ty> for #outer_ty {
468
+ impl #impl_generics :: enumcapsulate:: AsVariantMut <#inner_ty> for #outer_ty #type_generics #where_clause {
431
469
fn as_variant_mut( & mut self ) -> Option <& mut #inner_ty> {
432
470
match self {
433
471
#pattern => Some ( inner) ,
@@ -454,6 +492,8 @@ impl EnumDeriver {
454
492
let outer = enum_ident;
455
493
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
456
494
495
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
496
+
457
497
let mut impls: Vec < TokenStream2 > = vec ! [ ] ;
458
498
459
499
for variant in self . variants ( ) ? {
@@ -477,6 +517,10 @@ impl EnumDeriver {
477
517
let inner_ident = inner_field. ident . as_ref ( ) ;
478
518
let inner_ty = & inner_field. ty ;
479
519
520
+ if self . uses_generic_const_or_type ( inner_ty) {
521
+ continue ;
522
+ }
523
+
480
524
let pattern = match & variant. fields {
481
525
Fields :: Named ( _) => {
482
526
let field = inner_ident;
@@ -492,7 +536,7 @@ impl EnumDeriver {
492
536
} ;
493
537
494
538
impls. push ( quote ! {
495
- impl :: enumcapsulate:: IntoVariant <#inner_ty> for #outer_ty {
539
+ impl #impl_generics :: enumcapsulate:: IntoVariant <#inner_ty> for #outer_ty #type_generics #where_clause {
496
540
fn into_variant( self ) -> Result <#inner_ty, Self > {
497
541
match self {
498
542
#pattern => Ok ( inner) ,
@@ -523,8 +567,10 @@ impl EnumDeriver {
523
567
let outer = enum_ident;
524
568
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
525
569
570
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
571
+
526
572
let tokens = quote ! {
527
- impl :: enumcapsulate:: VariantDowncast for #outer_ty { }
573
+ impl #impl_generics :: enumcapsulate:: VariantDowncast for #outer_ty #type_generics #where_clause { }
528
574
} ;
529
575
530
576
Ok ( tokens)
@@ -545,6 +591,8 @@ impl EnumDeriver {
545
591
let outer = enum_ident;
546
592
let outer_ty: Type = parse_quote_spanned ! { outer. span( ) => #outer } ;
547
593
594
+ let ( impl_generics, type_generics, where_clause) = self . input . generics . split_for_impl ( ) ;
595
+
548
596
let variants = self . variants ( ) ?;
549
597
550
598
let discriminant_ident = quote:: format_ident!( "{outer}Discriminant" ) ;
@@ -592,7 +640,7 @@ impl EnumDeriver {
592
640
Ok ( quote ! {
593
641
#discriminant_enum
594
642
595
- impl :: enumcapsulate:: VariantDiscriminant for #outer_ty {
643
+ impl #impl_generics :: enumcapsulate:: VariantDiscriminant for #outer_ty #type_generics #where_clause {
596
644
type Discriminant = #discriminant_ident;
597
645
598
646
fn variant_discriminant( & self ) -> Self :: Discriminant {
@@ -604,4 +652,12 @@ impl EnumDeriver {
604
652
}
605
653
} )
606
654
}
655
+
656
+ fn uses_generic_const_or_type ( & self , ty : & syn:: Type ) -> bool {
657
+ let mut visitor = TypeVisitor :: new ( & self . input . generics ) ;
658
+
659
+ visitor. visit_type ( ty) ;
660
+
661
+ visitor. uses_const_or_type_param ( )
662
+ }
607
663
}
0 commit comments