[rust-dev] Appeal for CORRECT, capable, future-proof math, pre-1.0

Daniel Micay danielmicay at gmail.com
Tue Jan 14 12:27:11 PST 2014


On Tue, Jan 14, 2014 at 3:16 PM, Tobias Müller <troplin at bluewin.ch> wrote:
> Lee Braiden <leebraid at gmail.com> wrote:
>> On 14/01/14 01:50, Palmer Cox wrote:
>>
>> On Mon, Jan 13, 2014 at 12:18 PM, Tobias Müller
>> <troplin at bluewin.ch
>> <mailto:troplin at bluewin.ch>> wrote:
>>
>>     Daniel Micay <danielmicay at gmail.com
>> <mailto:danielmicay at gmail.com>> wrote:
>> > Do you know what undefined behavior is? It doesn't mean unspecified.
>>
>>     True, but despite beeing so often cited it won't format your hard disk     (even in C).
>>
>> Actually, it's possible, at least on systems without MMU protection ---
>> some embedded systems, for example.  Ints are often used (not just in
>> your own code but in library code) to index a jump table. If that index
>> is a different number than you expected it to be, you could end up
>> executing calling random "functions" in memory.  Said "functions" could
>> (and probably would) crash within 1--2 instructions, but even then, it's
>> not INCONCEIVABLE that those instructions could equate to "1) load hard
>> drive device number into the first arg register; 2) call the OS  format_drive function".
>
> But this is just as likely with wrapping integers. _Any_ deviation from the
> expected behavior is as dangerous as UB.

That's not how undefined behaviour works in LLVM (and C). If you
perform an integer arithmetic operation with undefined behaviour, it
does not mean that you get an undefined result back. Undefined values
and undefined behaviour are not the same thing.

An arithmetic operation in LLVM can be marked as undefined on overflow
with `nsw` or `nuw` rather than wrapping. `clang` uses `nsw` on signed
integers when `-fwrapv` is not passed to communicate this guarantee.

LLVM can then assume that signed integers never overflow, enabling
more optimizations. It can become aware that makes loops must
terminate, and even gain the ability to count the number of
iterations. It can also glean information on the possible ranges of
values based on the invariants provided by most arithmetic operations.
If it sees `x + INT_MAX`, then `x` is less than or equal to zero.

Invoking undefined behaviour is always a safety issue. You would need
to look at the assembly for the whole program in detail to know
whether an optimization pass made an assumption that's not going to
hold. This will of course change across every compiler version, which
is why C programs so often break with a new `gcc` release.

Wrapping on overflow is a logic error and in rare cases may become a
safety issue if it's then used in a specific kind of `unsafe` code.
The `unsafe` code needs to make the assumption that the integer is in
some valid range, without checking it.

> And that's just why I want to help the programmer with those checks as much
> as possible. Lifetimes and non-nullable pointers do a great job ensuring
> this for memory management, int overflow is missing such a feature.

Rust has support for big integers. It also has support for
library-defined overflow checks via the LLVM overflow checking
intrinsics. A language feature is not necessary to support this.


More information about the Rust-dev mailing list