3 ms·
Rust is already most of the way there. The default math operators still do implicit underflow and overflow, but the behavior is actually well defined: debug bui
by kmeisthax 3y ago
Rust is already most of the way there. The default math operators still do implicit underflow and overflow, but the behavior is actually well defined: debug builds panic on overflow and release builds wrap on overflow. There is no way to get a C-style "demons fly out my nose" overflow.
There's also explicit arithmetic functions that let you choose your overflow behavior:
* Checked: return None on overflow
* Wrapping: two's compliment wrapped overflow (the "overflowing" variant gives you a carry bit)
* Saturating: return maximum value on overflow
- ryao 3y agoDo you mean the C compiler's optimization passes can do strange things to code paths that overflow? The last I checked, C would wrap on overflow too. Rust uses the same compiler backend as C, so it could very well have the same behavior emerge from compiler optimization passes.
- steveklabnik 3y ago> it could very well have the same behavior emerge from compiler optimization passes. It can not, because "compiler optimization passes" is not the root cause of this behavior: it is that it is undefined behavior in the language itself. This is what gives the compiler license to make those transformations. In Rust, it is not undefined behavior, and therefore the compiler does not have the right to make those transformations for Rust code. Just because Rust uses LLVM does not mean that suddenly it inherits C's semantics. This has actually happened (well, more specifically, C++'s semantics, C was accidentally inheriting them as well IIRC) at least one time before, but that is a bug in LLVM that was fixed. Now each language has the proper semantics here, and it all works just fine. (I am referring to the behavior with regards to infinite loops with no side effects.)
- dezgeg 3y agoTry something like this with optimization on: int would_increment_overflow(int a) { if (a + 1 < a) { return -1; return 0; } This gets turned to a function that always returns 0. 0000000000000000 <would_increment_overflow>: 0: f3 0f 1e fa endbr64 4: 31 c0 xor %eax,%eax 6: c3 retq Using unsigned int gives the wrapping semantics.