@@ -4494,50 +4494,7 @@ pub(crate) fn codegen(
4494
4494
}
4495
4495
4496
4496
if let Some ( max_len) = context. options ( ) . tuple_varargs_len {
4497
- let mut methods = Vec :: with_capacity ( result. variadic_methods . len ( ) ) ;
4498
- let mut impls = ( 0 ..=max_len)
4499
- . map ( |len| {
4500
- (
4501
- ( 0 ..len)
4502
- . map ( |len| quote:: format_ident!( "t{}" , len) )
4503
- . collect :: < Vec < _ > > ( ) ,
4504
- vec ! [ ] ,
4505
- )
4506
- } )
4507
- . collect :: < Vec < _ > > ( ) ;
4508
- for ( name, VariadicMethodInfo { args, ret, exprs } ) in
4509
- result. variadic_methods . drain ( )
4510
- {
4511
- let call_name = quote:: format_ident!( "call_{}" , name) ;
4512
- methods. push ( quote ! {
4513
- unsafe fn #call_name( self , #( #args) , * ) #ret
4514
- } ) ;
4515
-
4516
- for ( fields, methods) in & mut impls {
4517
- methods. push ( quote ! {
4518
- unsafe fn #call_name( self , #( #args) , * ) #ret {
4519
- let ( #( #fields, ) * ) = self ;
4520
- #name( #( #exprs) , * , #( #fields) , * )
4521
- }
4522
- } ) ;
4523
- }
4524
- }
4525
- result. items . push ( quote ! {
4526
- pub trait VarArgs {
4527
- #( #methods; ) *
4528
- }
4529
- } ) ;
4530
-
4531
- for ( fields, methods) in impls {
4532
- let params = ( 0 ..fields. len ( ) )
4533
- . map ( |len| quote:: format_ident!( "T{}" , len) )
4534
- . collect :: < Vec < _ > > ( ) ;
4535
- result. items . push ( quote ! {
4536
- impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
4537
- #( #methods) *
4538
- }
4539
- } ) ;
4540
- }
4497
+ utils:: generate_varargs_trait ( max_len, & mut result) ;
4541
4498
}
4542
4499
4543
4500
result. items
@@ -5079,4 +5036,78 @@ pub mod utils {
5079
5036
5080
5037
true
5081
5038
}
5039
+
5040
+ pub ( super ) fn generate_varargs_trait (
5041
+ max_len : usize ,
5042
+ result : & mut super :: CodegenResult ,
5043
+ ) {
5044
+ // This will hold the identifiers to be used for the fields of the tuples `t0, ..., tn` as
5045
+ // well as the identifiers of the type parameters for each field type of the tuples `T0, ..., TN`.
5046
+ // FIXME (pvdrz): what if these identifiers are already in use?
5047
+ let ( fields, params) : ( Vec < _ > , Vec < _ > ) = ( 0 ..max_len)
5048
+ . map ( |len| {
5049
+ (
5050
+ quote:: format_ident!( "t{}" , len) ,
5051
+ quote:: format_ident!( "T{}" , len) ,
5052
+ )
5053
+ } )
5054
+ . unzip ( ) ;
5055
+
5056
+ // This will hold the methods to be declared in the `VarArgs` trait as well as the
5057
+ // bodies of the implementations of such methods for each tuple length.
5058
+ let ( trait_method_decls, trait_method_impl_fns) : ( Vec < _ > , Vec < _ > ) =
5059
+ result
5060
+ . variadic_methods
5061
+ . drain ( )
5062
+ . map ( |( name, info) | {
5063
+ let super :: VariadicMethodInfo { args, ret, exprs } = info;
5064
+
5065
+ // The name of the `VarArgs` trait method associated with this method.
5066
+ // FIXME (pvdrz): what these identifiers are already in use?
5067
+ let trait_method_name =
5068
+ quote:: format_ident!( "call_{}" , name) ;
5069
+
5070
+ // The declaration of the `VarArgs` trait method associated with this method.
5071
+ let trait_method_decl = quote ! {
5072
+ unsafe fn #trait_method_name( self , #( #args) , * ) #ret
5073
+ } ;
5074
+
5075
+ // The implementations of the `VarArgs` trait method associated with this
5076
+ // method for each tuple length.
5077
+ let trait_method_impls = ( 0 ..=fields. len ( ) )
5078
+ . map ( |index| {
5079
+ let fields = & fields[ ..index] ;
5080
+ quote ! {
5081
+ #trait_method_decl {
5082
+ let ( #( #fields, ) * ) = self ;
5083
+ #name( #( #exprs) , * , #( #fields) , * )
5084
+ }
5085
+ }
5086
+ } )
5087
+ . collect :: < Vec < _ > > ( ) ;
5088
+
5089
+ ( trait_method_decl, trait_method_impls)
5090
+ } )
5091
+ . unzip ( ) ;
5092
+
5093
+ // Push the trait with the method declarations.
5094
+ result. items . push ( quote ! {
5095
+ pub trait VarArgs {
5096
+ #( #trait_method_decls; ) *
5097
+ }
5098
+ } ) ;
5099
+
5100
+ for index in 0 ..=params. len ( ) {
5101
+ let params = & params[ ..index] ;
5102
+ let methods =
5103
+ trait_method_impl_fns. iter ( ) . map ( |impls| & impls[ index] ) ;
5104
+
5105
+ // Push the implementation the trait for each tuple.
5106
+ result. items . push ( quote ! {
5107
+ impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
5108
+ #( #methods) *
5109
+ }
5110
+ } ) ;
5111
+ }
5112
+ }
5082
5113
}
0 commit comments