Skip to content

Commit d3299af

Browse files
committed
transmute: caution against int2ptr transmutation
1 parent a6d93ac commit d3299af

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

library/core/src/intrinsics.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -1169,14 +1169,6 @@ extern "rust-intrinsic" {
11691169
/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
11701170
/// unsafe**. `transmute` should be the absolute last resort.
11711171
///
1172-
/// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub],
1173-
/// unless the pointer was originally created *from* an integer.
1174-
/// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling],
1175-
/// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.)
1176-
/// Any attempt to use the resulting value for integer operations will abort const-evaluation.
1177-
/// (And even outside `const`, such transmutation is touching on many unspecified aspects of the
1178-
/// Rust memory model and should be avoided. See below for alternatives.)
1179-
///
11801172
/// Because `transmute` is a by-value operation, alignment of the *transmuted values
11811173
/// themselves* is not a concern. As with any other function, the compiler already ensures
11821174
/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
@@ -1187,6 +1179,35 @@ extern "rust-intrinsic" {
11871179
///
11881180
/// [ub]: ../../reference/behavior-considered-undefined.html
11891181
///
1182+
/// # Transmutation between pointers and integers
1183+
///
1184+
/// Special care has to be taken when transmuting between pointers and integers, e.g.
1185+
/// transmuting between `*const ()` and `usize`.
1186+
///
1187+
/// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless
1188+
/// the pointer was originally created *from* an integer. (That includes this function
1189+
/// specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling],
1190+
/// but also semantically-equivalent conversions such as punning through `repr(C)` union
1191+
/// fields.) Any attempt to use the resulting value for integer operations will abort
1192+
/// const-evaluation. (And even outside `const`, such transmutation is touching on many
1193+
/// unspecified aspects of the Rust memory model and should be avoided. See below for
1194+
/// alternatives.)
1195+
///
1196+
/// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not*
1197+
/// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed
1198+
/// this way is currently considered undefined behavior.
1199+
///
1200+
/// All this also applies when the integer is nested inside an array, tuple, struct, or enum.
1201+
/// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this
1202+
/// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling
1203+
/// `assume_init()` on that result is considered as completing the pointer-to-integer transmute
1204+
/// and thus runs into the issues discussed above.
1205+
///
1206+
/// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a
1207+
/// lossless process. If you want to round-trip a pointer through an integer in a way that you
1208+
/// can get back the original pointer, you need to use `as` casts, or replace the integer type
1209+
/// by `MaybeUninit<$int>` (and never call `assume_init()`).
1210+
///
11901211
/// # Examples
11911212
///
11921213
/// There are a few things that `transmute` is really useful for.

0 commit comments

Comments
 (0)