Skip to content

Commit 35e24a6

Browse files
committed
refactor generate_varargs_trait
1 parent d91a4d0 commit 35e24a6

File tree

1 file changed

+75
-44
lines changed

1 file changed

+75
-44
lines changed

src/codegen/mod.rs

+75-44
Original file line numberDiff line numberDiff line change
@@ -4434,50 +4434,7 @@ pub(crate) fn codegen(
44344434
}
44354435

44364436
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);
44814438
}
44824439

44834440
result.items
@@ -5015,4 +4972,78 @@ pub mod utils {
50154972

50164973
true
50174974
}
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+
}
50185049
}

0 commit comments

Comments
 (0)