Why even unused data needs to be valid

@Aloso good questions :slight_smile:

@Ixrec already answered this: it is impossible to cause UB by dereferencing an unaligned or dangling reference, because even constructing that reference is already UB.

This is an interesting one. First of all let me notice that some reads of uninitialized memory are fine. For example:

let uninit_mem = MaybeUninit::<u32>::uninit();
let ptr_to_uninit = &uninit_mem as *const _ as *const MaybeUninit<u8>;
let _val: MaybeUninit<u8> = ptr::read(ptr_to_uninit);

In other words, there is no general principle in Rust that says that reading uninit memory is disallowed. (This is a common confusion and indeed even the reference was wrong here for a long time.)

Whether or not reading uninit memory is allowed depends on the type---this is part of the "though shall not construct invalid values" system. As you noted, for integers and floats we state it explicitly. For bool, char and enum I consider this rule to be implied by saying things like "the tag needs to match an existing variant of the enum"; uniinitialized memory cannot match any tag. Thus these may not be uninitialized either. Structs, arrays and similar types inherit this property from their fields (but the padding between the fields, if any, may indeed be uninitialized). That leaves only unions, and those, too, may be uninitialized under the current rules (but also see this discussion). That's why the above read of an uninitialized MaybeUninit<u8> is allowed.

6 Likes