@@ -4434,50 +4434,7 @@ pub(crate) fn codegen(
4434
4434
}
4435
4435
4436
4436
if let Some ( max_len) = context. options ( ) . tuple_varargs_len {
4437
- let mut methods = Vec :: with_capacity ( result. variadic_methods . len ( ) ) ;
4438
- let mut impls = ( 0 ..=max_len)
4439
- . map ( |len| {
4440
- (
4441
- ( 0 ..len)
4442
- . map ( |len| quote:: format_ident!( "t{}" , len) )
4443
- . collect :: < Vec < _ > > ( ) ,
4444
- vec ! [ ] ,
4445
- )
4446
- } )
4447
- . collect :: < Vec < _ > > ( ) ;
4448
- for ( name, VariadicMethodInfo { args, ret, exprs } ) in
4449
- result. variadic_methods . drain ( )
4450
- {
4451
- let call_name = quote:: format_ident!( "call_{}" , name) ;
4452
- methods. push ( quote ! {
4453
- unsafe fn #call_name( self , #( #args) , * ) #ret
4454
- } ) ;
4455
-
4456
- for ( fields, methods) in & mut impls {
4457
- methods. push ( quote ! {
4458
- unsafe fn #call_name( self , #( #args) , * ) #ret {
4459
- let ( #( #fields, ) * ) = self ;
4460
- #name( #( #exprs) , * , #( #fields) , * )
4461
- }
4462
- } ) ;
4463
- }
4464
- }
4465
- result. items . push ( quote ! {
4466
- pub trait VarArgs {
4467
- #( #methods; ) *
4468
- }
4469
- } ) ;
4470
-
4471
- for ( fields, methods) in impls {
4472
- let params = ( 0 ..fields. len ( ) )
4473
- . map ( |len| quote:: format_ident!( "T{}" , len) )
4474
- . collect :: < Vec < _ > > ( ) ;
4475
- result. items . push ( quote ! {
4476
- impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
4477
- #( #methods) *
4478
- }
4479
- } ) ;
4480
- }
4437
+ utils:: generate_varargs_trait ( max_len, & mut result) ;
4481
4438
}
4482
4439
4483
4440
result. items
@@ -5015,4 +4972,78 @@ pub mod utils {
5015
4972
5016
4973
true
5017
4974
}
4975
+
4976
+ pub ( super ) fn generate_varargs_trait (
4977
+ max_len : usize ,
4978
+ result : & mut super :: CodegenResult ,
4979
+ ) {
4980
+ // This will hold the identifiers to be used for the fields of the tuples `t0, ..., tn` as
4981
+ // well as the identifiers of the type parameters for each field type of the tuples `T0, ..., TN`.
4982
+ // FIXME (pvdrz): what if these identifiers are already in use?
4983
+ let ( fields, params) : ( Vec < _ > , Vec < _ > ) = ( 0 ..max_len)
4984
+ . map ( |len| {
4985
+ (
4986
+ quote:: format_ident!( "t{}" , len) ,
4987
+ quote:: format_ident!( "T{}" , len) ,
4988
+ )
4989
+ } )
4990
+ . unzip ( ) ;
4991
+
4992
+ // This will hold the methods to be declared in the `VarArgs` trait as well as the
4993
+ // bodies of the implementations of such methods for each tuple length.
4994
+ let ( trait_method_decls, trait_method_impl_fns) : ( Vec < _ > , Vec < _ > ) =
4995
+ result
4996
+ . variadic_methods
4997
+ . drain ( )
4998
+ . map ( |( name, info) | {
4999
+ let super :: VariadicMethodInfo { args, ret, exprs } = info;
5000
+
5001
+ // The name of the `VarArgs` trait method associated with this method.
5002
+ // FIXME (pvdrz): what these identifiers are already in use?
5003
+ let trait_method_name =
5004
+ quote:: format_ident!( "call_{}" , name) ;
5005
+
5006
+ // The declaration of the `VarArgs` trait method associated with this method.
5007
+ let trait_method_decl = quote ! {
5008
+ unsafe fn #trait_method_name( self , #( #args) , * ) #ret
5009
+ } ;
5010
+
5011
+ // The implementations of the `VarArgs` trait method associated with this
5012
+ // method for each tuple length.
5013
+ let trait_method_impls = ( 0 ..=fields. len ( ) )
5014
+ . map ( |index| {
5015
+ let fields = & fields[ ..index] ;
5016
+ quote ! {
5017
+ #trait_method_decl {
5018
+ let ( #( #fields, ) * ) = self ;
5019
+ #name( #( #exprs) , * , #( #fields) , * )
5020
+ }
5021
+ }
5022
+ } )
5023
+ . collect :: < Vec < _ > > ( ) ;
5024
+
5025
+ ( trait_method_decl, trait_method_impls)
5026
+ } )
5027
+ . unzip ( ) ;
5028
+
5029
+ // Push the trait with the method declarations.
5030
+ result. items . push ( quote ! {
5031
+ pub trait VarArgs {
5032
+ #( #trait_method_decls; ) *
5033
+ }
5034
+ } ) ;
5035
+
5036
+ for index in 0 ..=params. len ( ) {
5037
+ let params = & params[ ..index] ;
5038
+ let methods =
5039
+ trait_method_impl_fns. iter ( ) . map ( |impls| & impls[ index] ) ;
5040
+
5041
+ // Push the implementation the trait for each tuple.
5042
+ result. items . push ( quote ! {
5043
+ impl <#( #params) , * > VarArgs for ( #( #params, ) * ) {
5044
+ #( #methods) *
5045
+ }
5046
+ } ) ;
5047
+ }
5048
+ }
5018
5049
}
0 commit comments