Is `align_of` guaranteed to be non-zero?

Does anyone know where I might find documentation that core::mem::align_of is guaranteed (or not guaranteed) to never return 0? If it is (currently) guaranteed, is there a particular reason the devs decided to go with usize instead of NonZeroUsize?

I think it is guaranteed to be at least 1. quoting the type layout section of the reference:

...
Alignment is measured in bytes, and must be at least 1, and always a power of 2. The alignment of a value can be checked with the align_of_val function.
...
Types where all values have the same size and alignment, and both are known at compile time, implement the Sized trait and can be checked with the size_of and align_of functions.

I don't know the reason why it uses usize instead of NonZeroUsize.

NonZeroUsize came with Rust 1.28.0, while align_of was around since 1.6.0.

Good news, we can do better than NonZero<usize>, and it's already proposed for stabilization:

That's interesting, and provides a lot of nice guarantees. Is there much advantage to this as opposed to just a u8 representing the exponent (2^n), aside from the fact that 2^255 is a nonsensically large alignment? Would there be an argument for waiting for (possibly forever-unstable) pattern types, such that we could define alignment as type Alignment = u8 is 0..32;? (or make a new u5 integer type for this specific purpose, or arbitrary-width integers, etc.)

Depends what you're using it for. The version stored by its log is useful too -- the rust compiler has one, for example: Align in rustc_abi - Rust (And there's an ilog2 method on mem::Alignment to get that exponent.)

But things like https://en.cppreference.com/c/memory/aligned_alloc want the alignment, not its logarithm, so this form is common too :person_shrugging: