Ergonomics of wrapping operations

FWIW, one of the major pain-points with Wrapping<T> is that heterogeneous operations - e.g. T + Wrapping<T> - are not permitted. This is because it’s not obvious whether such an operation should wrap or not. In different words, one of the operands essentially needs to be casted before performing the operation, and it’s not clear which one.

I’m now kind of leaning towards saying that Wrapping<T> should “win”: in other words, that we should have impl Add<u32> for Wrapping<u32> { type Output = Wrapping<u32>; ... } (and vice versa), and likewise for the other types. The intuition is this: the reason why “plain” T (e.g. u32) panics on over/underflow is not because this is well-known to be the behavior that’s desired by users of u32; rather, the reason is precisely that we don’t have any information about the programmer’s intent, so our only reasonable option is to signal the unhandled circumstance by panicking. (This is also underscored by the fact that panicking only happens in debug builds: if we knew that panicking is what the programmer explicitly wants, then we would do it always.)

Now in the case of u32 + Wrapping<u32>, if we think of it as a unification problem, then “no available information” unifies with “it should wrap” to yield “it should wrap”.

(Incidentally, for completeness’s sake, we should presumably also have Saturating<T>, Checked<T>, and Overflowing<T> for the other possible policies, with analogous impls. And see also.)