I have a Module
trait and I would like to write a procedural macro that implements Add
, Sub
, and Mul
for any implementation of the Module
trait.
Given a struct Foo<S>
that implements Module
, the resulting code should look like this
impl <S, RHS: Module> std::ops::Add<RHS> for Foo<S> {
type Output = crate::modules::Add<Foo<S>, RHS>;
fn add(self, rhs: RHS) -> Self::Output {
crate::modules::Add::new(self, rhs)
}
}
The problem is that both the struct and the Add
trait have their own generic types.
If this weren't the case, the macro code could look something like this
let name = &ast.ident;
let generics = &ast.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
quote! {
impl #impl_generics std::ops::Add<RHS> for #name #ty_generics #where_clause {
type Output = crate::modules::Add<#name, RHS>;
fn add(self, rhs: RHS) -> Self::Output {
crate::modules::Add::new(self, rhs)
}
}
}
but then the RHS
type is never defined.
I have tried variations on <#impl_generics, RHS: Module>
and the like, but none of them work.
Obviously a blanket implementation of Add
for T: Module
would be better, but this is impossible to do because foreign traits can't be implemented for type parameters. See here. A workaround for this would also solve my problem in this specific case, but it seems like what I'm asking about should be possible.
Is there any way to do this?