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?