Actually, your comments do not match the behavior you observe:
- in your first example: you get a compilation warning that you ignore, and thus the compiler outputs that you want the transfer behavior.
- in your second example: you get a runtime error
The Go example is similar to the first Rust example (except that Go, by design, has no warnings).
In Rust, underflow, or overflow, an unspecified value is obtained, which can be ! or lower in computer science, a special value indicating that the control flow diverges, which generally means either abortion or an exception.
This specification allows you to:
- applying debug mode to catch all overflows the moment they happen.
- 1 release mode is not used (and wrapping arithmetic is used there)
and nevertheless, both modes are compatible with the specification.
1 Without using the default, you can, if you choose for relatively modest performance, outside of the heavy numeric code, activate the overflow check in Release with a simple flag.
About the cost of overflow checks: the current situation with Rust / LLVM is useful for debugging, but is not really optimized. Thus, in this framework, the cost of overflow is worth it. If the situation improves, then rustc can decide, one fine day, to activate the default overflow check even in Release.
In Midori (a Microsoft experimental OS developed in a language similar to C #), overflow checking was enabled even in Release versions:
In Midori, we compiled with the default overflow check. This is different from C # stock, where you must explicitly pass the / checked flag for this behavior. In our experience, the amount of unexpected overflows that were caught and unintentionally was worth the inconvenience and expense. But this meant that our compiler needed to understand very well how to eliminate unnecessary ones.
Apparently, they improved their compiler to:
- he will talk about ranges of variables and statically eliminate boundary checks and overflow checks whenever possible.
- it will aggregate checks as much as possible (one check for several potentially overflowing operations)
The latter should only be executed in Release (you lose accuracy), but it reduces the number of branches.
So what is the cost?
Potentially different arithmetic rules that interfere with optimization:
- in regular arithmetic,
64 + x - 128 can be optimized to x - 64 ; with overflow checks, the compiler may not be able to perform this optimization. - vectorization may also be difficult if the compiler does not have built-in overflow checking tools.
- ...
However, if the code is not very numerical (for example, scientific modeling or graphics), this can affect it.