Skip to content

Commit e4f1143

Browse files
committed
refactor generate_varargs_trait
1 parent c473d28 commit e4f1143

File tree

1 file changed

+75
-44
lines changed

1 file changed

+75
-44
lines changed

src/codegen/mod.rs

Lines changed: 75 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4494,50 +4494,7 @@ pub(crate) fn codegen(
44944494
}
44954495

44964496
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);
45414498
}
45424499

45434500
result.items
@@ -5079,4 +5036,78 @@ pub mod utils {
50795036

50805037
true
50815038
}
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+
}
50825113
}

0 commit comments

Comments
 (0)