Summary
This RFC proposes the inclusion of RAdd, RSub, … and RAddable, RSubtractable, … traits in the core library, that allow for the implementation of the Add trait from the RHS.
Motivation
There is currently no way to implement the Add/Sub/… trait for a type outside the module, leaving libraries that work with those traits with either ugly wrapper types or with just one side that can be any type, which is especially troubling for asymmetric operations like Sub or Div.
Detailed Design
There would be two new traits per operation, one that is used by the end user, and one that is used to allow said user to implement the traits from the other side.
Example for Add:
trait RAdd<T> {
type Output;
fn r_add(self, other: T) -> Self::Output;
}
trait RAddable {}
impl<T, U> Add<U> for T where T: RAddable, U: RAdd<T> {
type Output = U::Output;
fn add(self, other: U) -> U::Output {
other.r_add(self)
}
}
RAddable would be implemented for u8 - u128, i8 - i128, f32 and f64.
This allows library writers to implement Add for those types, without breaking any existing code.
Drawbacks
- only useful for libraries introducing some new types that interact with primitives, but would be around forever once stabilized
Alternatives
- Using methods on your own type (
subtracted_from, …)
- Implement the operator traits for primitives instead of using the
RAddable, … traits
Unresolved questions
- Should types like
Vec implement the RAddable, RSubtractable, … traits?
- Should types like
Option or Result implement RAddable, …? Maybe only if the encased type implements those traits?
- Should operations like
Index be supported?
- Should the
RAddable, RSubtractable, … traits be replaced with pnly one trait?