As a possible point of discussion, here is a trait that I wrote in one of my own projects to abstract over the primitive integer types…
pub trait Integer:
'static
+ num::PrimInt
+ num::Integer
+ num::FromPrimitive
+ num::bigint::ToBigInt
+ AddAssign<Self>
+ SubAssign<Self>
+ MulAssign<Self>
+ WrappingAdd
+ WrappingSub
+ WrappingMul
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ CheckedShl
+ CheckedShr
+ Shl<u32, Output = Self>
+ Shr<u32, Output = Self>
+ ShlAssign<u32>
+ ShrAssign<u32>
+ std::iter::Sum
+ Debug
+ Display
+ Default
+ Send
+ Sync
{
fn saturating_mul(self, other: Self) -> Self;
fn total_bits() -> u32 {
mem::size_of::<Self>() as u32 * 8
}
fn nonsign_bits() -> u32;
fn to_big_rational(&self) -> BigRational {
BigRational::from(self.to_bigint().unwrap())
}
fn squared(self) -> Self {
self * self
}
}
Obviously, the collection of stuff I dumped in there is pretty ad-hoc, but it would definitely be nice if I didn't have to write down all that stuff to make the other parts of my code be more convenient. And it doesn't even have everything I'd like it to (since you can't express &'a Self: for<'a> Add<&'a Self, Output = Self>
as a supertrait, can't write numeric literals with them, etc.)