Currently, just looking at Add
and u32
, the macro-expanded impls are:
// core::ops::arith::add_impl!
impl Add for u32 {
type Output = u32;
fn add(self, other: u32) -> u32 { self + other }
}
// core::internal_macros::forward_ref_binop!
impl Add<u32> for &'_ u32 {
type Output = <u32 as Add<u32>>::Output;
fn add(self, other: u32) -> <u32 as Add<u32>>::Output {
Add::add(*self, other)
}
}
impl Add<&'_ u32> for u32 {
type Output = <u32 as Add<u32>>::Output;
fn add(self, other: &u32) -> <u32 as Add<u32>>::Output {
Add::add(self, *other)
}
}
impl Add<&'_ u32> for &'_ u32 {
type Output = <u32 as Add<u32>>::Output;
fn add(self, other: u32) -> <u32 as Add<u32>>::Output {
Add::add(*self, *other)
}
}
// core::ops::arith::add_assign_impl!
impl AddAssign for u32 {
fn add_assign(&mut self, other: u32) { *self += other }
}
// core::internal_macros::forward_ref_op_assign!
impl AddAssign<&'_ u32> for u32 {
fn add_assign(&mut self, other: &u32) {
AddAssign::add_assign(self, *other);
}
}
// core::iter::traits::accum::integer_sum_product!
impl Sum for u32 {
fn sum<I: Iterator<Item=u32>>(iter: I) -> u32 {
iter.fold(0, Add::add)
}
}
impl<'a> Sum<&'a u32> for u32 {
fn sum<I: Iterator<Item=&'a u32>>(iter: I) -> u32 {
iter.fold(0, Add::add)
}
}
These can be (overly?) reduced to use generics rather than simply copy-pasting the cross product of all the combinations:
// Base case
impl Add for u32 {
type Output = u32;
fn add(self, other: u32) -> u32 { self + other }
}
// remove right-ref
impl Add<&'_ u32> for u32 {
type Output = u32;
fn add(self, other: &u32) -> u32 { self + *other }
}
// remove left-ref
impl<T> Add<T> for &'_ u32
where
u32: Add<T, Output=u32>,
{
type Output = u32;
fn add(self, other: T) -> u32 { *self + other }
}
// add assign
impl<A> AddAssign<A> for u32
where
u32: Add<A, Output=u32>,
{
fn add_assign(&mut self, rhs: A) { *self = *self + rhs }
}
// iter sum
impl<A> Sum<A> for u32
where
u32: Add<A, Output=u32>,
{
fn sum<I: Iterator<Item = A>>(iter: I) -> u32 {
iter.fold(0, Add::add)
}
}
The right-ref case can be generalized further, but this probably is too far
impl<A: Copy> Add<&'_ A> for u32
where
u32: Add<A, Output=u32>,
{
type Output = u32;
fn add(self, other: &T) -> u32 { self + *other }
}
Is there a reason that core doesn't use the generic versions of AddAssign
/Sum
? Should crates providing "primitive-integer-like" types prefer imitating core's macro-pasted impls or the generic versions?