mem::transmute¶
Level: 301 · deep dive
One line: transmute::<A, B> reinterprets the bits of an A as a B and checks one thing at compile time — that the two sizes match — so validity, the alignment of anything a pointer points at, and lifetimes are all yours, which is why nearly every use has a safer replacement.
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
What it has to cover¶
- What rustc checks: size only.
transmute::<u64, u32>isE0512, "cannot transmute between types of different sizes, or dependently-sized types", with both bit widths in the notes.transmute::<u8, bool>(2)compiles. - What the docs ↗ demand instead: "Both the argument and the result must be valid at their given type"; padding "is not guaranteed to be preserved"; and for pointers, references and boxes "the caller has to ensure proper alignment of the pointed-to values".
- The safer tools, each for one job:
asfor numeric and pointer casts;f32::from_bitsandto_bits;u32::from_ne_bytes,from_le_bytes,to_be_bytes;char::from_u32. rustc'sunnecessary_transmuteslint (warn) now points at them —transmute::<u32, char>draws "consider usingchar::from_u32(…).unwrap()". bytemuck↗:cast,cast_ref,cast_mut,cast_slice,cast_slice_mut, gated on theNoUninitandAnyBitPatterntraits (its docs' historical note says the crate started out with a singlePodtrait). The proof moves from a comment to a trait bound — which conversions from this page can it not express?- The lints, as
clippy-driver -Whelplists them for 1.98. Warn:transmute_ptr_to_ref,transmute_int_to_bool,transmute_int_to_non_zero,transmute_bytes_to_str,useless_transmute,crosspointer_transmute,transmutes_expressible_as_ptr_casts,missing_transmute_annotations. Deny:wrong_transmute,unsound_collection_transmute,transmuting_null,transmute_null_to_fn,eager_transmute. Allow:transmute_ptr_to_ptr,transmute_undefined_repr. And rustc's ownmutable_transmutes(deny) andinteger_to_ptr_transmutes(warn). Which of them fires on each example the finished page shows? - Lifetimes: transmuting
&'a Tinto&'static Tcompiles, and hands back the same unbounded lifetimeCStr::from_ptrdoes. Vec<A>intoVec<B>withsize_of::<A>() == size_of::<B>(): why isunsound_collection_transmutedeny-by-default even then?- Safe transmutation as a language feature:
std::mem::TransmuteFromexists in 1.98 and is nightly-only (transmutability).
The trap it exists for¶
transmute reached for because a C tutorial used a cast, on a conversion as, from_bits or from_ne_bytes already does without unsafe. Or two repr(Rust) structs with "the same fields" transmuted into each other — the sizes match, the compiler is satisfied, and the field order was never promised.
Where this sits¶
- Casting with
ascoversas; Validity invariants covers which bit patterns are undefined behaviour to produce; What a union is covers the other way to read bits as another type; Type layout covers why same-fields is not same-layout. This page covers onlytransmuteand its replacements.
See also¶
- Casting with
as— the conversion that is never undefined behaviour, and what it does instead - Validity invariants — the rule "valid at both types" refers to
- What a union is —
f32::to_bitsas the safe answer to the same question - Type layout —
repr(Rust), and whatrepr(C)promises instead - What a float actually stores — the bits
from_bitshands back - Why a
charis 32 bits wide — whytransmuteinto acharis undefined behaviour - Clippy: the groups, the settings, the commands — how the lints above are enabled
- Books — the
socket20.3.9 dependency that transmuted a std type into a C struct and stopped compiling
If you are coming from another language¶
- C. A cast between pointer types, a
union, ormemcpyinto a variable of another type are C's three spellings, and strict aliasing makes reading through the cast pointer undefined.memcpyis the portable one, and it corresponds tofrom_ne_bytes. Rust has no strict-aliasing rule; its equivalent danger is the validity of the result. - C++.
reinterpret_castis the unchecked pointer version, and C++20'sstd::bit_castis the closest match totransmute: it requires equal sizes and trivially copyable types, and leaves whether the result is a meaningful value to you. - Go.
unsafe.Pointerconversions do the same job with the same absence of checks, andmath.Float64bits/math.Float64frombitsare the safe path, liketo_bitsandfrom_bits. - Python. Every reinterpretation goes through bytes explicitly —
struct.unpack("<f", data)orint.from_bytes— so thetransmuteshortcut does not exist;ctypes.castis the unsafe exception and can crash the interpreter.
Po polsku¶
mem::transmute reinterpretuje bity jednej wartości jako inny typ i sprawdza przy kompilacji dokładnie jedno: czy rozmiary są równe (inaczej E0512). Poprawność wyniku, wyrównanie tego, na co wskazuje wskaźnik, i czasy życia (lifetimes) są na twojej głowie. Prawie zawsze istnieje bezpieczniejsze narzędzie — as, f32::from_bits, u32::from_ne_bytes, char::from_u32 — a rustc sam je podpowiada lintem unnecessary_transmutes. Skrzynka bytemuck zamienia komentarz z uzasadnieniem na ograniczenie cechy (trait bound).
Szukaj po polsku: reinterpretacja bitów · rzutowanie typów w Ruscie · rust transmute alternatives · rust bytemuck cast_slice · clippy transmute lints