Summary
Add support for deriving Add
, Sub
, Mul
and Div
on structs whose fields implement them.
EDIT: Here we are talking about Rhs=Self
implementation.
Rationale
In Rust, implementing arithmetic traits like Add
, Sub
, Mul
, or Div
requires either manually writing implementation or dependency on third-party crates like derive_more even for trivial cases where the semantics are unambiguous (e.g. field-wise operations on numeric structs).
#[derive(Add)]
struct Point(u32, u32); // a + b == Point(a.0 + b.0, a.1 + b.1)
This is pointless busywork when the only sensible behavior is to perform the operation field by field. It would work the same way Clone
, Debug
and Copy
is resolved.
Generics?
For generic structs like:
#[derive(Add)]
struct Point<T> {
x: T,
y: T,
}
the derived implementation automatically requires T: Add
(exactly like #[derive(Clone)]
requires T: Clone
).
What about enums?
I noticed that enums rarely need arithmetic and when they do, manual impls are clearer so this proposal intentionally excludes support for deriving arithmetic traits on enums. While third-party crates like derive_more offer a solution for enums - wrap the output in Result<Self, Error>
.
impl Add for FooBar {
type Output = Result<Self, Error>;
fn add(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Foo(a), Foo(b)) => Ok(Foo(a + b)),
(Bar(a), Bar(b)) => Ok(Bar(a + b)),
_ => Err(Error::Mismatch),
}
}
}
Drawbacks
Adding a solution to the standard library that is necessarily more limited will create a small split in the ecosystem: "Should I use the standard derive
or the more powerful derive_more
?"
Nevertheless, I decided to propose it, especially since the #[derive(From)]
RFC has recently reached implementation so ÂŻ\_(ă)_/ÂŻ.
Unresolved Questions
Overflow behavior
Should derived implementations panic on overflow? The std's arithmetic traits provide no overflow control