@@ -742,9 +742,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
742742///
743743/// ## On `packed` structs
744744///
745- /// It is currently impossible to create raw pointers to unaligned fields
746- /// of a packed struct.
747- ///
748745/// Attempting to create a raw pointer to an `unaligned` struct field with
749746/// an expression such as `&packed.unaligned as *const FieldType` creates an
750747/// intermediate unaligned reference before converting that to a raw pointer.
@@ -753,9 +750,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
753750/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
754751/// *undefined behavior* in your program.
755752///
753+ /// Instead you must use the [`ptr::addr_of!`](addr_of) macro to
754+ /// create the pointer. You may use that returned pointer together with this
755+ /// function.
756+ ///
756757/// An example of what not to do and how this relates to `read_unaligned` is:
757758///
758- /// ```no_run
759+ /// ```
759760/// #[repr(packed, C)]
760761/// struct Packed {
761762/// _padding: u8,
@@ -767,24 +768,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
767768/// unaligned: 0x01020304,
768769/// };
769770///
770- /// #[allow(unaligned_references)]
771- /// let v = unsafe {
772- /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
773- /// let unaligned =
774- /// // A temporary unaligned reference is created here which results in
775- /// // undefined behavior regardless of whether the reference is used or not.
776- /// &packed.unaligned
777- /// // Casting to a raw pointer doesn't help; the mistake already happened.
778- /// as *const u32;
771+ /// // Take the address of a 32-bit integer which is not aligned.
772+ /// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior.
773+ /// let unaligned = std::ptr::addr_of!(packed.unaligned);
779774///
780- /// let v = std::ptr::read_unaligned(unaligned);
781- ///
782- /// v
783- /// };
775+ /// let v = unsafe { std::ptr::read_unaligned(unaligned) };
776+ /// assert_eq!(v, 0x01020304);
784777/// ```
785778///
786779/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
787- // FIXME: Update docs based on outcome of RFC #2582 and friends.
788780///
789781/// # Examples
790782///
@@ -938,9 +930,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
938930///
939931/// ## On `packed` structs
940932///
941- /// It is currently impossible to create raw pointers to unaligned fields
942- /// of a packed struct.
943- ///
944933/// Attempting to create a raw pointer to an `unaligned` struct field with
945934/// an expression such as `&packed.unaligned as *const FieldType` creates an
946935/// intermediate unaligned reference before converting that to a raw pointer.
@@ -949,36 +938,32 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
949938/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
950939/// *undefined behavior* in your program.
951940///
952- /// An example of what not to do and how this relates to `write_unaligned` is:
941+ /// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut)
942+ /// macro to create the pointer. You may use that returned pointer together with
943+ /// this function.
944+ ///
945+ /// An example of how to do it and how this relates to `write_unaligned` is:
953946///
954- /// ```no_run
947+ /// ```
955948/// #[repr(packed, C)]
956949/// struct Packed {
957950/// _padding: u8,
958951/// unaligned: u32,
959952/// }
960953///
961- /// let v = 0x01020304;
962954/// let mut packed: Packed = unsafe { std::mem::zeroed() };
963955///
964- /// #[allow(unaligned_references)]
965- /// let v = unsafe {
966- /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
967- /// let unaligned =
968- /// // A temporary unaligned reference is created here which results in
969- /// // undefined behavior regardless of whether the reference is used or not.
970- /// &mut packed.unaligned
971- /// // Casting to a raw pointer doesn't help; the mistake already happened.
972- /// as *mut u32;
956+ /// // Take the address of a 32-bit integer which is not aligned.
957+ /// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior.
958+ /// let unaligned = std::ptr::addr_of_mut!(packed.unaligned);
973959///
974- /// std::ptr::write_unaligned(unaligned, v) ;
960+ /// unsafe { std::ptr::write_unaligned(unaligned, 42) } ;
975961///
976- /// v
977- /// };
962+ /// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
978963/// ```
979964///
980- /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
981- // FIXME: Update docs based on outcome of RFC #2582 and friends .
965+ /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however
966+ /// (as can be seen in the `assert_eq!` above) .
982967///
983968/// # Examples
984969///
0 commit comments