Hacker News new | ask | show | jobs
by sshine 1251 days ago
Rust does have a fix for this:

  error: this arithmetic operation will overflow
   --> src/main.rs:2:18
    |
  2 |     let a: u64 = u64::MAX + 1;
    |                  ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
Rust also allows for overflowing arithmetic (preserving the default to fail):

https://doc.rust-lang.org/std/?search=overflowing

It's generally less ergonomic, e.g.

  let (zero, _did_overflow) = u64::MAX.overflowing_add(1);
3 comments

Slightly related, I wonder why the return type for `overflowing_add` isn't `Result<T>` and instead a tuple containing a boolean?
There are times when you want to know how much overflow occurred -- think of the way you learn to do multi-digit addition. There is a checked_add that returns an Option<T> if you only care about success/failure.
An example is efficient prime-field arithmetic:

https://cp4space.hatsya.com/2021/09/01/an-efficient-prime-fo...

> If A happened to be larger than C, and therefore the result of the subtraction underflowed, then we can correct for this by adding p to the result. [...] we can multiply B by 2^32 using a binary shift and a subtraction, and then add it to the result. We might encounter an overflow, but we can correct for that by subtracting p.

(Highlighting the parts that relate to reacting to overflow.)

My guess is:

The `(T, bool)` that gets returned is friendly towards optimization.

If you don't use the bool, the overflowing arithmetic is reduced to efficient arithmetic which is overflowing by default. If you do use the bool, the generated code contains one extra instruction.

Probably because you'd want to access the value in either case, depending on your application.
Could be a `Result<T, T>` which would seem to express the intent better.
Sometimes, sure. But an overflow doesn't have to be an error, it can be what you're after and you just want to know when it happens.
Binary search is similar and the return type there is already Result<usize, usize>: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.bin...
You'll get a compile error when rustc can statically prove that it'll overflow (as in your example above). That is generally not possible.

The correct answer is what shepmaster said in a sibling comment.

Edit: Gah, I'm a bit wrong too. There's the compiler error (this), and the runtime error (what I'm talking about below.)

Here's a link to the runtime variant: https://play.rust-lang.org/?version=stable&mode=debug&editio...

As a sibling notes, currently, this is for debug builds. So, if you change that playground to "Release", you'll see it wrap.

(I love this feature, and I wish they had done it in release mode too. The sibling comment has some notes on that, too.)

(But, e.g., were `git` written in Rust, presumably the end product would be a release build. Now, you can enable the check there, but that is something you have to do, today.)

(But also note, that, in all cases, it's well-defined. Vs. C, where some overflows are UB.)