Skip to content

Commutative multiplication and addition #2608

Open
@mqudsi

Description

@mqudsi

I was surprised to learn that the implementation of core::ops::{Add, Mul} (keywords: addition, multiplication) is not automatically (and exclusively) commutative. This is often not a problem for cases where it is possible to both impl Mul<X> for Y and impl Mul<Y> for X, but this is not an option when generics are involved.

For example, this implementation of Mul allows multiplying Size by any basic number type (from num_traits), as in Size(12) * 2 or Size(42) * 1.0:

impl<T, U> Mul<U> for &Size<T>
where
    T: ToPrimitive,
    U: ToPrimitive
{
    type Output = Size<u64>;

    fn mul(self, other: U) -> Self::Output {
        // omitted
    }
}

but it is not possible to define an ergonomic and efficient inverse to support the commutative variant of the same operations (2 * Size(12) or 3.0 * Size(7)), because the following is illegal:

impl<T> Mul<Size<T>> for ToPrimitive
where
    T: ToPrimitive,
{
    type Output = Size<u64>;

    fn mul(self, other: Size<T>) -> Self::Output {
        Size::Bytes((self as u64 * other.bytes()) as u64)
    }
}

as the self parameter to the mul function results in an attempt to define a non-generic parameter with unknown size.

I would like to use this issue to sound out ideas to support commutative operations, at the very least for operations that are typically (read: mathematically) commutative, but would appreciate any insight or commentary that sheds light on anything I'm missing here first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions