derive_more icon indicating copy to clipboard operation
derive_more copied to clipboard

Forward Add, AddAssign, Sub and so on should use generics

Open Luro02 opened this issue 5 years ago • 7 comments

#[derive(Add, AddAssign, Sub, SubAssign)]
struct Example(usize);

should generate

impl<T> Sub<T> for Example
where
    usize: Sub<T, Output = usize>,
{
    type Output = Self;

    #[must_use]
    #[inline]
    fn sub(self, rhs: T) -> Self::Output { Self(self.0.sub(rhs)) }
}

impl<T> SubAssign<T> for Example
where
    usize: SubAssign<T>,
{
    #[inline]
    fn sub_assign(&mut self, other: T) { self.0.sub_assign(other); }
}

impl<T> Add<T> for Example
where
    usize: Add<T, Output = usize>,
{
    type Output = Self;

    #[must_use]
    #[inline]
    fn add(self, rhs: T) -> Self::Output { Self(self.0.add(rhs)) }
}

impl<T> AddAssign<T> for Example
where
    usize: AddAssign<T>,
{
    #[inline]
    fn add_assign(&mut self, other: T) { self.0.add_assign(other); }
}

which would make the code a lot more flexible, than

impl ::core::ops::Add for Example {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Self(self.0.add(rhs.0), self.1.add(rhs.1))
    }
}

Luro02 avatar Feb 24 '20 11:02 Luro02

To be clear the goald of this request would be to allow for:

assert_eq(Example(1) + 3i32, Example(4))

I think it makes sense to have this feature, but definitely behind an attribute (e.g. #[add(forward)])

JelteF avatar Feb 24 '20 11:02 JelteF

To be clear the goal of this request would be to allow for

Yes

Luro02 avatar Feb 24 '20 13:02 Luro02

A similar addon can be useful for (Partial)Eq and (Partial)Ord.

z33ky avatar Apr 14 '20 14:04 z33ky

I think that I've hit an issue that is related to this. Mul and Add doesn't generate the same thing, and I'd like the Mul to ressemble the Add. Let me see if I can quickly amend this..

CGMossa avatar May 19 '21 22:05 CGMossa

Removing this from 1.0 milestone as this doesn't have to be a breaking change.

JelteF avatar Jun 10 '22 08:06 JelteF

Would this also be the solution for math operations not generating implementations that handle references?

let e = Example(3);
assert_eq(Example(1) + &e, Example(4))

Obviously non-sensical in the toy example but I had it come up & the workaround I have is to sprinkle clone all over the place or make the types trivially copyable and I'm worried about the performance of the generated code vs having an add defined to work with references (maybe I'm overthinking it and the optimizer elides it all anyway?).

vlovich avatar Dec 22 '23 19:12 vlovich

@vlovich I'm not sure that the proposal here would address that. But we do have a separate issue for specifically the usecase you're describing: #156

JelteF avatar Dec 25 '23 14:12 JelteF