Terminology around unsafe, undefined behaviour, and invariants

I also think "undefined behavior" is a problematic term and we should try to find something clearer.

When I've written documentation that touches on these issues for C, I find it works best to talk in terms of assumptions made by different parts of the implementation. Here's a couple of examples.

bool occupies the same space as a u8, one byte, but the compiler generates code assuming that the numeric value of that byte is always either 0 or 1.

The following function [ed.: from this old thread] reads memory beyond the space allocated to the slice x. This is incorrect, even if x is a subslice of a larger allocation, because the compiler will assume that it does no such thing while generating code for its callers.

fn reach_beyond(x: &[i32]) -> i32 {
   unsafe {
       *x.as_ptr().add(x.len()+1)
   }
}

A hypothetical Rust language standard would, in these terms, say that "the compiler may assume that (not X)" where the C standard says "the behavior is undefined if (X)".

4 Likes