Defining range of valid values for a type

Continuing the discussion from Is there a way to emulate the following `ptr_metadata`-dependent code on stable Rust?:

Thank you! Would MaybeUninit<u8> then be described as having invalid values? Is that a compiler special case, or can I create types with invalid values, too?

There must've been a miscommunication; MaybeUninit has an unrestricted set of valid values i.e. whatever may be in the memory, is valid for that type. Other types are more restrictive/picky.


Now, let's imagine std had a type defined so:

/// A wrapper for a prime 32-bit integer.
#[rustc_layout_scalar_valid_range_start(2)]    // contents must be >= 2
struct Prime(u32);
  • trying to produce Prime(0) or Prime(1) is language UB;
    • alternatively speaking, [0x00, 0x00, 0x00, 0x00] or [0x00, 0x00, 0x00, 0x01] byte arrays aren't valid representations of a Prime;
  • trying to produce Prime(4) would be library UB;
    • nothing unsound happens while you're just moving one around[1], but UB is allowed to happen on invocation of any of Prime's methods (including Drop, if any);
  • {2, 3, 5, 7, 11, ...} are alright to have inside the struct.

So, in my understanding compiler (and LLVM) views the list of valid values as "[2, 3, 4, ..., usize::MAX]", while any processing functions inside the library will be defined to work on "[2, 3, 5, 7, 11, ...]" only.


  1. interpreting from MaybeUninit in std::mem - Rust, last paragraph ↩︎