I'm implementing a math library and keep finding a common issue: I want users to be able to pass any combination of T and &T for lhs and rhs to std::ops binary traits (or ones that look like them).
I made a macro that given a user impl for &T, &T, it will generate (T, T), (&T, T), (T, &T) to solve the impl side of things.
From the consumption side, I'm stuck with writing out a bunch of nasty bounds.
use std::ops::Mul;
pub trait RhsMul<T>: Mul<T, Output=T> + for<'a> Mul<&'a T, Output=T> {}
pub struct Foo<T> where
T: RhsMul<T>,
for <'a> &'a T: RhsMul<T>
{
data: T
}
impl<T> Foo<T> where
T: RhsMul<T>,
for <'a> &'a T: RhsMul<T>
{
pub fn mul_1(self, rhs: Self) -> Self {
Foo { data: self.data * rhs.data }
}
pub fn mul_2(self, rhs: &Self) -> Self {
Foo { data: self.data * &rhs.data }
}
pub fn mul_3(&self, rhs: Self) -> Self {
Foo { data: &self.data * rhs.data }
}
pub fn mul_4(&self, rhs: &Self) -> Self {
Foo { data: &self.data * &rhs.data }
}
}
I'm able to wrap the rhs into T
and &T
just fine with the RhsMul
supertrait, but I'd like to join the where clauses into one alias. Something like:
alias clause Nasty<T> =
T: Mul<T, Output=T> + for <'a> Mul<&'a T, Output=T>,
for <'a> &'a T: Mul<T, Output=T> + Mul<&'a T, Output=T>;
struct Foo<T> where Nasty<T>, T: Debug {
data: T
}
impl<T> Foo<T> where Nasty<T>, T: Debug {
fn mul_1(self, rhs: Self) -> Self {
Foo { data: self.data * rhs.data }
}
fn mul_2(self, rhs: &Self) -> Self {
Foo { data: self.data * &rhs.data }
}
fn mul_3(&self, rhs: Self) -> Self {
Foo { data: &self.data * rhs.data }
}
fn mul_4(&self, rhs: &Self) -> Self {
Foo { data: &self.data * &rhs.data }
}
}
Is there anything like this in stable or even nightly Rust that addresses this?