Skip to content

Commit ad34174

Browse files
authored
Rollup merge of rust-lang#82592 - Lonami:patch-1, r=RalfJung
Improve transmute docs with further clarifications Closes rust-lang#82493. Please let me know if any of the new wording sounds off, English is not my mother tongue.
2 parents 0005a16 + fbc1741 commit ad34174

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

library/core/src/intrinsics.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,12 @@ extern "rust-intrinsic" {
846846
/// destination value, then forgets the original. It's equivalent to C's
847847
/// `memcpy` under the hood, just like `transmute_copy`.
848848
///
849+
/// Because `transmute` is a by-value operation, alignment of the *transmuted values
850+
/// themselves* is not a concern. As with any other function, the compiler already ensures
851+
/// both `T` and `U` are properly aligned. However, when transmuting values that *point
852+
/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
853+
/// alignment of the pointed-to values.
854+
///
849855
/// `transmute` is **incredibly** unsafe. There are a vast number of ways to
850856
/// cause [undefined behavior][ub] with this function. `transmute` should be
851857
/// the absolute last resort.
@@ -965,7 +971,13 @@ extern "rust-intrinsic" {
965971
/// assert_eq!(b"Rust", &[82, 117, 115, 116]);
966972
/// ```
967973
///
968-
/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
974+
/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`.
975+
///
976+
/// To transmute the inner type of the contents of a container, you must make sure to not
977+
/// violate any of the container's invariants. For `Vec`, this means that both the size
978+
/// *and alignment* of the inner types have to match. Other containers might rely on the
979+
/// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't
980+
/// be possible at all without violating the container invariants.
969981
///
970982
/// ```
971983
/// let store = [0, 1, 2, 3];
@@ -991,14 +1003,11 @@ extern "rust-intrinsic" {
9911003
///
9921004
/// let v_clone = v_orig.clone();
9931005
///
994-
/// // The no-copy, unsafe way, still using transmute, but not relying on the data layout.
995-
/// // Like the first approach, this reuses the `Vec` internals.
996-
/// // Therefore, the new inner type must have the
997-
/// // exact same size, *and the same alignment*, as the old type.
998-
/// // The same caveats exist for this method as transmute, for
999-
/// // the original inner type (`&i32`) to the converted inner type
1000-
/// // (`Option<&i32>`), so read the nomicon pages linked above and also
1001-
/// // consult the [`from_raw_parts`] documentation.
1006+
/// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the
1007+
/// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but
1008+
/// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`),
1009+
/// // this has all the same caveats. Besides the information provided above, also consult the
1010+
/// // [`from_raw_parts`] documentation.
10021011
/// let v_from_raw = unsafe {
10031012
// FIXME Update this when vec_into_raw_parts is stabilized
10041013
/// // Ensure the original vector is not dropped.

0 commit comments

Comments
 (0)