I came across this post which presents an example using rust's transmute and it's incorrect behavior when the alignment is different. https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-ru...
Is this issue still present? I tried to figure it out the other day using latest rust's nightly but the llvm ir output has so much going on that I didn't _really_ understand what was going on
> Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values.
The post you've linked transmutes a reference, and as the caller fails to explicitly ensure proper alignment, it explicitly risks invoking undefined behavior - I would consider the code buggy. The easiest way to prove it's broken would be to create an reference that's more likely to be unaligned (&array[1] instead of &array[0]?) and run the code on a less misalignment-tolerant platform (ARM?).
Here are some 100% sound alternatives using bytemuck (no unsafe required!) and core::ptr::{read,write}_unaligned (unsafe required):
https://play.rust-lang.org/?version=stable&mode=debug&editio...
> Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values.
This code is doing the latter incorrectly, and therefore invokes UB, as far as I can tell. To be honest, I don't use transmute very often and so I don't have every single last corner case about it memorized.
It's not so much an "issue" as it is "Here's an API that's extremely sharp in Rust, and a similar, but less sharp API in Zig."
For this reason, we never reach the question of alignment because we know neither i32, u8, nor any other type has the same layout as Foo (undefined layout).
It is certainly true that unsafe Rust is veeeeery unsafe, as perhaps evidenced by me being the first person to point out the repr issue. On the other hand this scheme has a lot of advantages for writing safe Rust.
#[repr(u16)]
enum Foo { A = 0, B }
#[repr(u16)]
enum Bar { A = 3200, B }
struct FooOrBar(u16);
And then proceeding to violate all of the unwritten rules of Rust by wrangling casts across these types like a goddamn wizardI'm not proud of this...
I still feel like this trick has it's place though, as an example take a look at where I stole this trick from, by matklad [0] and tell me what you think :)
[0] https://github.com/rust-analyzer/rowan/blob/d2c7843858da9d9e...
If you have a byte array that you've received over a network connection that represents an array of floats, or you need to convert a 32bit RGBA pixel buffer that you got from some clang ffi binding to a byte pixel buffer without having to split/copy to a new vector.