1.Wha is the use of transmute.
2.how it works.
3.when it needed.
4.as vs transmute
For unsafe
code in general, you should read the Rustonomicon.
There’s a page about it. Also the documentation of transmute
itself does some explaining.
As a beginner or even intermediate Rust
programmer you usually don’t really need to use transmute
, or any unsafe
code. Rust’s memory safety guarantees are easily circumvented when using transmute
, i.e. it’s really easy to make mistakes that result in bad program crashes or misbehavior.
The as
casting is a totally different story. It is safe to use. All the details about as
can be found in the Reference, one of its most common usage is for casting between different numeric types (though you can get unexpected results from truncation on overflows).
So,
it’s an advanced tool that can be used in unsafe
Rust code,
it converts between different types by just “reinterpreting the bytes”, kind-of just like “disabling the type-checker” somewhat (if “disabling the type-checker” sounds bad, that’s because it is pretty bad),
It’s needed less often than one might think. One common use is if you have some references/pointers to types that are repr(transparent)
struct to convert from the inner type to the struct. Though there are crates that abstract the unsafety away, so it might be preferrable to use those instead if need be. In particular bytemuck offers a lot of abstractions over things that could be archieved with transmute
.
I already said some things about as
before. One key difference is that as
does some intelligent/smart casts. E.g. converting between floating point and integer numbers does try to get the closest numerical value, using as
for explicitly coercing to trait objects, e.g. Box<T>
to Box<dyn Any>
adds the vtable
, etc. On the other hand transmute
does nothing smart at all. There are a few sanity checks in the compiler, e.g. that the converted types have the same size, but that’s it.
There's another one: it warns if the type you're casting to is uninhabited in the case of zero sized types (ZST).
#![feature(never_type)]
enum Empty {}
fn main() {
unsafe { std::mem::transmute::<(), ! >(()) };
unsafe { std::mem::transmute::<(), Empty>(()) };
}
Results in
Compiling playground v0.0.1 (/playground)
warning: the type `!` does not permit zero-initialization
--> src/main.rs:6:14
|
6 | unsafe { std::mem::transmute::<(), ! >(()) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: `#[warn(invalid_value)]` on by default
= note: the `!` type has no valid value
warning: the type `Empty` does not permit zero-initialization
--> src/main.rs:7:14
|
7 | unsafe { std::mem::transmute::<(), Empty>(()) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: enums with no variants have no valid value
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.