use auto_impl_ops::*; use num_traits::*; use std::ops::*; #[derive(Clone, Default)] struct A(T); #[derive(Clone, Default)] struct B(i32); // from assign_ref #[auto_ops] impl<'a, M> AddAssign<&'a A> for A where M: Sized + Zero + for<'x> AddAssign<&'x M>, { fn add_assign(&mut self, other: &Self) { self.0 += &other.0; } } #[auto_ops] impl<'a, G> SubAssign<&'a A> for A where G: Sized + Zero + for<'x> SubAssign<&'x G>, { fn sub_assign(&mut self, other: &Self) { self.0 -= &other.0; } } #[auto_ops] impl<'a, K> RemAssign<&'a A> for A where K: Sized + Clone + Zero + for<'x> AddAssign<&'x K> + for<'x> SubAssign<&'x K> + for<'x> RemAssign<&'x K>, for<'x> &'x K: Mul + Div, { fn rem_assign(&mut self, other: &Self) { self.0 %= &other.0; } } #[auto_ops] impl<'a, R> MulAssign<&'a R> for A where R: Sized + Zero + for<'x> MulAssign<&'x R>, { fn mul_assign(&mut self, other: &R) { self.0 *= other; } } #[auto_ops] impl<'a, R> DivAssign<&'a R> for A where R: Sized + Zero + for<'x> DivAssign<&'x R>, { fn div_assign(&mut self, other: &R) { self.0 /= other; } } #[auto_ops] impl<'a> AddAssign<&'a B> for B { fn add_assign(&mut self, other: &Self) { self.0 += &other.0; } } // from ref_ref #[auto_ops] impl Mul for &A where M: Sized + Zero, for<'x> &'x M: Mul, { type Output = A; fn mul(self, other: Self) -> Self::Output { A(&self.0 * &other.0) } } // from val_ref #[auto_ops] impl Div<&A> for A where M: Sized + Zero, for<'x> &'x M: Div, { type Output = Self; fn div(self, other: &Self) -> Self::Output { A(&self.0 / &other.0) } } #[auto_ops] impl<'a, M> BitAndAssign<&'a A> for A where M: Sized + for<'x> BitAndAssign<&'x M>, { fn bitand_assign(&mut self, other: &Self) { self.0 &= &other.0; } } #[auto_ops] impl<'a, M> BitOrAssign<&'a A> for A where M: Sized + for<'x> BitOrAssign<&'x M>, { fn bitor_assign(&mut self, other: &Self) { self.0 |= &other.0; } } #[auto_ops] impl<'a, M> BitXorAssign<&'a A> for A where M: Sized + for<'x> BitXorAssign<&'x M>, { fn bitxor_assign(&mut self, other: &Self) { self.0 ^= &other.0; } } #[auto_ops] impl<'a, M> ShlAssign<&'a A> for A where M: Sized + for<'x> ShlAssign<&'x M>, { fn shl_assign(&mut self, other: &Self) { self.0 <<= &other.0; } } #[auto_ops] impl<'a, M> ShrAssign<&'a A> for A where M: Sized + for<'x> ShrAssign<&'x M>, { fn shr_assign(&mut self, other: &Self) { self.0 >>= &other.0; } } #[auto_ops] impl ShlAssign for A where M: Sized + ShlAssign, { fn shl_assign(&mut self, other: u8) { self.0 <<= other; } } #[auto_ops] impl ShrAssign for A where M: Sized + ShrAssign, { fn shr_assign(&mut self, other: u8) { self.0 >>= other; } } #[derive(Clone, Default)] struct C(T); #[auto_ops(val_val, ref_val)] impl AddAssign for C { fn add_assign(&mut self, other: Self) { self.0 += other.0; } } #[auto_ops(val_ref, ref_ref)] impl AddAssign<&C> for C where T: for<'x> AddAssign<&'x T>, { fn add_assign(&mut self, other: &Self) { self.0 += &other.0; } } #[derive(Clone, Default)] struct D(T); // from val_val #[auto_ops] impl Add for D where T: Add, { type Output = Self; fn add(self, other: Self) -> Self { D(self.0 + other.0) } } #[derive(Clone, Default)] struct E(T); // from assign_val #[auto_ops] impl AddAssign<&E> for E where T: for<'x> AddAssign<&'x T>, { fn add_assign(&mut self, other: &Self) { self.0 += &other.0; } } #[derive(Clone, Default)] struct F(T); // from ref_val #[auto_ops] impl<'a, T> Add> for &'a F where for<'x> &'x T: Add, { type Output = F; fn add(self, other: F) -> F { F(&self.0 + other.0) } } struct Vector2 { x: T, y: T, } struct Matrix2 { v00: T, v01: T, v10: T, v11: T, } #[auto_ops(ref_ref, ref_val, val_ref, val_val)] impl<'a, T> Mul<&'a Vector2> for &'a Matrix2 where T: Add, for<'x> &'x T: Mul, { type Output = Vector2; fn mul(self, other: &'a Vector2) -> Self::Output { Vector2 { x: &self.v00 * &other.x + &self.v01 * &other.y, y: &self.v10 * &other.x + &self.v11 * &other.y, } } } #[auto_ops(ref_ref, ref_val, val_ref, val_val)] impl Mul> for &A where for<'x> &'x M: Mul, { type Output = D; fn mul(self, other: C) -> Self::Output { D(&self.0 * &other.0) } } fn main() {}