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