I read that transmuting any random [u8] to anything, including u32, is not safe. That's because the [u8] may not be aligned properly, and u32 pointers need to be aligned to 4 bytes.
Browsing the source code for u32, I noticed the following transmute:
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
// SAFETY: integers are plain old datatypes so we can always transmute to them
unsafe { mem::transmute(bytes) }
}
So is casting a byte array to a plain old data type okay even if the byte array is not aligned to anything? Or is it safe because we are not actually transmuting the pointer but the data itself?
You've misunderstood what this does. It's transmuting an array (of type [u8; std::mem::size_of::<Self>()] aka [u8; 4]) not a pointer.
Transmuting the value is fine. What's not okay is transmuting the pointer since that need not be aligned adequately. Reading from a misaligned pointer is UB (unless you use the correct ptr operations, but those are slow).
Yes, it's safe to transmute a [u8; 8] to a [u32;2], however it is not safe to transmute a &[u8; 8] to a &[u32;2], because of alignment. Note how the introduction of references made alignment matter. Alignment only matters for pointers.
Based on the description of the MISALIGNED_LOADS counter in uProf, new Zen3 processors don't even bother reporting something as misaligned unless it crosses the 64 B cache line boundary or the 4 KiB page boundary.
But of course that's a big fat new desktop chip. The situation can be quite different on older or smaller chips.
And you do still need to use the correct operations to read & write unaligned things. Misaligned references are UB in Rust, no matter what your CPU does.