AddAssign<i32> for Wrapping<u32> etc

If you're using x = x.wrapping_add_signed(y), it likely makes sense for x to be of type Wrapping<u32> instead of just u32, but then as things stand you have to perform some gymnastics like x = Wrapping(x.0.wrapping_add_signed(y)), whereas x += y would be simpler and unambiguous. The types u32 and i32 are for example, ideally this would be for all the instances of wrapping_add_signed.

1 Like

For the _signed case, I think it'd be more consistent to have Wrapping::add_signed methods, maybe?

x += Wrapping(1) would fail for x: Wrapping<u16> if you have Wrapping<u16>: AddAssign<Wrapping<i16>> because of details of how type inference for literals works.

Actually I suggest Wrapping<u16>: AddAssign<i16>, not AddAssign<Wrapping<i16>>, so you would do x += 1 directly. But I don't understand how type inference for literals works so maybe that would have the same issue?

1 Like

It would.

Here's a simple example:

trait MyTrait {}
impl MyTrait for i16 {}

fn foo(x: impl MyTrait) {}

fn main() {
    foo(1); // This compiles
    
    // But it stops working if you uncomment the below
    // impl MyTrait for u16 {}
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e98df2dc3784162f8d87d7a9519025a0

If there's exactly one possible integer type, the literal gets that type. But as soon as there's a second possibility the literal becomes i32 because of integer literal fallback, and then it no longer works.

It's long been a wish to have a way to let things like this work somehow, but no such feature has been designed yet.

5 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.