@@ -4520,50 +4520,7 @@ pub(crate) fn codegen(
4520
4520
}
4521
4521
4522
4522
if let Some ( max_len) = context. options ( ) . tuple_varargs_len {
4523
- let mut methods = Vec :: with_capacity ( result. variadic_methods . len ( ) ) ;
4524
- let mut impls = ( 0 ..=max_len)
4525
- . map ( |len| {
4526
- (
4527
- ( 0 ..len)
4528
- . map ( |len| quote:: format_ident!( "t{}" , len) )
4529
- . collect :: < Vec < _ > > ( ) ,
4530
- vec ! [ ] ,
4531
- )
4532
- } )
4533
- . collect :: < Vec < _ > > ( ) ;
4534
- for ( name, VariadicMethodInfo { args, ret, exprs } ) in
4535
- result. variadic_methods . drain ( )
4536
- {
4537
- let call_name = quote:: format_ident!( "call_{}" , name) ;
4538
- methods. push ( quote ! {
4539
- unsafe fn #call_name( self , #( #args) , * ) #ret
4540
- } ) ;
4541
-
4542
- for ( fields, methods) in & mut impls {
4543
- methods. push ( quote ! {
4544
- unsafe fn #call_name( self , #( #args) , * ) #ret {
4545
- let ( #( #fields, ) * ) = self ;
4546
- #name( #( #exprs) , * , #( #fields) , * )
4547
- }
4548
- } ) ;
4549
- }
4550
- }
4551
- result. items . push ( quote ! {
4552
- pub trait VarArgs {
4553
- #( #methods; ) *
4554
- }
4555
- } ) ;
4556
-
4557
- for ( fields, methods) in impls {
4558
- let params = ( 0 ..fields. len ( ) )
4559
- . map ( |len| quote:: format_ident!( "T{}" , len) )
4560
- . collect :: < Vec < _ > > ( ) ;
4561
- result. items . push ( quote ! {
4562
- impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
4563
- #( #methods) *
4564
- }
4565
- } ) ;
4566
- }
4523
+ utils:: generate_varargs_trait ( max_len, & mut result) ;
4567
4524
}
4568
4525
4569
4526
postprocessing:: postprocessing ( result. items , context. options ( ) )
@@ -5105,4 +5062,78 @@ pub mod utils {
5105
5062
5106
5063
true
5107
5064
}
5065
+
5066
+ pub ( super ) fn generate_varargs_trait (
5067
+ max_len : usize ,
5068
+ result : & mut super :: CodegenResult ,
5069
+ ) {
5070
+ // This will hold the identifiers to be used for the fields of the tuples `t0, ..., tn` as
5071
+ // well as the identifiers of the type parameters for each field type of the tuples `T0, ..., TN`.
5072
+ // FIXME (pvdrz): what if these identifiers are already in use?
5073
+ let ( fields, params) : ( Vec < _ > , Vec < _ > ) = ( 0 ..max_len)
5074
+ . map ( |len| {
5075
+ (
5076
+ quote:: format_ident!( "t{}" , len) ,
5077
+ quote:: format_ident!( "T{}" , len) ,
5078
+ )
5079
+ } )
5080
+ . unzip ( ) ;
5081
+
5082
+ // This will hold the methods to be declared in the `VarArgs` trait as well as the
5083
+ // bodies of the implementations of such methods for each tuple length.
5084
+ let ( trait_method_decls, trait_method_impl_fns) : ( Vec < _ > , Vec < _ > ) =
5085
+ result
5086
+ . variadic_methods
5087
+ . drain ( )
5088
+ . map ( |( name, info) | {
5089
+ let super :: VariadicMethodInfo { args, ret, exprs } = info;
5090
+
5091
+ // The name of the `VarArgs` trait method associated with this method.
5092
+ // FIXME (pvdrz): what these identifiers are already in use?
5093
+ let trait_method_name =
5094
+ quote:: format_ident!( "call_{}" , name) ;
5095
+
5096
+ // The declaration of the `VarArgs` trait method associated with this method.
5097
+ let trait_method_decl = quote ! {
5098
+ unsafe fn #trait_method_name( self , #( #args) , * ) #ret
5099
+ } ;
5100
+
5101
+ // The implementations of the `VarArgs` trait method associated with this
5102
+ // method for each tuple length.
5103
+ let trait_method_impls = ( 0 ..=fields. len ( ) )
5104
+ . map ( |index| {
5105
+ let fields = & fields[ ..index] ;
5106
+ quote ! {
5107
+ #trait_method_decl {
5108
+ let ( #( #fields, ) * ) = self ;
5109
+ #name( #( #exprs) , * , #( #fields) , * )
5110
+ }
5111
+ }
5112
+ } )
5113
+ . collect :: < Vec < _ > > ( ) ;
5114
+
5115
+ ( trait_method_decl, trait_method_impls)
5116
+ } )
5117
+ . unzip ( ) ;
5118
+
5119
+ // Push the trait with the method declarations.
5120
+ result. items . push ( quote ! {
5121
+ pub trait VarArgs {
5122
+ #( #trait_method_decls; ) *
5123
+ }
5124
+ } ) ;
5125
+
5126
+ for index in 0 ..=params. len ( ) {
5127
+ let params = & params[ ..index] ;
5128
+ let methods =
5129
+ trait_method_impl_fns. iter ( ) . map ( |impls| & impls[ index] ) ;
5130
+
5131
+ // Push the implementation the trait for each tuple.
5132
+ result. items . push ( quote ! {
5133
+ impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
5134
+ #( #methods) *
5135
+ }
5136
+ } ) ;
5137
+ }
5138
+ }
5108
5139
}
0 commit comments