3 ms·
Arguably Rust does better for this particular example because, for debug builds and optionally release builds, overflows trigger an error. If you explicitly wan
by simias 4y ago
Arguably Rust does better for this particular example because, for debug builds and optionally release builds, overflows trigger an error. If you explicitly want wrapping arithmetic in Rust you should use b.wrapping_add(c) in this case, otherwise you'll get a runtime error.
So for instance the following code generates an error (I add to add the function call indirection otherwise rustc would even refuse to compile the straightforward `200u8 + 100u8`):
fn main() {
println!("{}", add(200, 100));
}
fn add(a: u8, b: u8) -> u8 {
a + b
}
// thread 'main' panicked at 'attempt to add with overflow', test.rs:6:5
// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
IMO that's a more robust and generic solution than hoping that `int` promotion will prevent the overflow. The drawback is that it incurs a performance hit and is therefore only enabled in debug builds by default.
- iFreilicht 4y agoI actually dislike this solution, because it relies on tests, while this could easily be a compile-time error. Not sure I like that D promotes implicitly and then complains about the result of the addition not being assignable to a `char`. But in theory, every integer could just have the maximum range of values encoded in its type, and for every arithmetic operation the compiler could check if the maximum range of the integer type is exceeded. You could set the range explicitly: fn mult_col(color:u8<0..31>, factor:u8<0..8>): u8<0..248> { color*factor } Or make the function generic over any range of inputs where the possible range of outputs provably fits the output type, which would be the default. There are crates that add ranged integers as types, but I haven’t found them satisfactory to work with.
- WalterBright 4y ago> The drawback is that it incurs a performance hit and is therefore only enabled in debug builds by default. D has core library functions to check for integer overflow. In my not-so-humble opinion, a targeted solution like this is better than a global switch to turn it on and off. Adding is deeply embedded into computation, and very very few are at any risk of overflowing.
- tga_d 4y agoRust also has checked operations (i.e., checked_add/sub/mul/etc. that return None when there's an over/underflow). You use wrapped operations when that's what's supposed to happen, checked operations when that's what's supposed to happen, debug builds to assert check all operations, and release builds to skip checks anywhere they're not explicit.