Get out of our way type system! We're going to reinterpret these bits or die trying! Even though this book is all about doing things that are unsafe, I really can't emphasize that you should deeply think about finding Another Way than the operations covered in this section. This is really, truly, the most horribly unsafe thing you can do in Rust. The guardrails here are dental floss.
mem::transmute<T, U> takes a value of type
T and reinterprets
it to have type
U. The only restriction is that the
U are verified
to have the same size. The ways to cause Undefined Behavior with this are mind
First and foremost, creating an instance of any type with an invalid state is going to cause arbitrary chaos that can't really be predicted. Do not transmute
bool. Even if you never do anything with the
bool. Just don't.
Transmute has an overloaded return type. If you do not specify the return type it may produce a surprising type to satisfy inference.
&mutis Undefined Behavior. While certain usages may appear safe, note that the Rust optimizer is free to assume that a shared reference won't change through its lifetime and thus such transmutation will run afoul of those assumptions. So:
- Transmuting an
&mutis always Undefined Behavior.
- No you can't do it.
- No you're not special.
- Transmuting an
Transmuting to a reference without an explicitly provided lifetime produces an unbounded lifetime.
When transmuting between different compound types, you have to make sure they are laid out the same way! If layouts differ, the wrong fields are going to get filled with the wrong data, which will make you unhappy and can also be Undefined Behavior (see above).
So how do you know if the layouts are the same? For
repr(transparent)types, layout is precisely defined. But for your run-of-the-mill
repr(Rust), it is not. Even different instances of the same generic type can have wildly different layout.
Vec<u32>might have their fields in the same order, or they might not. The details of what exactly is and is not guaranteed for data layout are still being worked out over at the UCG WG.
mem::transmute_copy<T, U> somehow manages to be even more
wildly unsafe than this. It copies
size_of<U> bytes out of an
interprets them as a
U. The size check that
mem::transmute has is gone (as
it may be valid to copy out a prefix), though it is Undefined Behavior for
to be larger than
Also of course you can get all of the functionality of these functions using raw
pointer casts or
unions, but without any of the lints or other basic sanity
checks. Raw pointer casts and
unions do not magically avoid the above rules.