@@ -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