@@ -720,9 +720,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
720720///
721721/// ## On `packed` structs
722722///
723- /// It is currently impossible to create raw pointers to unaligned fields
724- /// of a packed struct.
725- ///
726723/// Attempting to create a raw pointer to an `unaligned` struct field with
727724/// an expression such as `&packed.unaligned as *const FieldType` creates an
728725/// intermediate unaligned reference before converting that to a raw pointer.
@@ -731,9 +728,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
731728/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
732729/// *undefined behavior* in your program.
733730///
731+ /// Instead you must use the [`ptr::addr_of!`](addr_of) macro to
732+ /// create the pointer. You may use that returned pointer together with this
733+ /// function.
734+ ///
734735/// An example of what not to do and how this relates to `read_unaligned` is:
735736///
736- /// ```no_run
737+ /// ```
737738/// #[repr(packed, C)]
738739/// struct Packed {
739740/// _padding: u8,
@@ -745,24 +746,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
745746/// unaligned: 0x01020304,
746747/// };
747748///
748- /// #[allow(unaligned_references)]
749- /// let v = unsafe {
750- /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
751- /// let unaligned =
752- /// // A temporary unaligned reference is created here which results in
753- /// // undefined behavior regardless of whether the reference is used or not.
754- /// &packed.unaligned
755- /// // Casting to a raw pointer doesn't help; the mistake already happened.
756- /// as *const u32;
749+ /// // Take the address of a 32-bit integer which is not aligned.
750+ /// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior.
751+ /// let unaligned = std::ptr::addr_of!(packed.unaligned);
757752///
758- /// let v = std::ptr::read_unaligned(unaligned);
759- ///
760- /// v
761- /// };
753+ /// let v = unsafe { std::ptr::read_unaligned(unaligned) };
754+ /// assert_eq!(v, 0x01020304);
762755/// ```
763756///
764757/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
765- // FIXME: Update docs based on outcome of RFC #2582 and friends.
766758///
767759/// # Examples
768760///
@@ -916,9 +908,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
916908///
917909/// ## On `packed` structs
918910///
919- /// It is currently impossible to create raw pointers to unaligned fields
920- /// of a packed struct.
921- ///
922911/// Attempting to create a raw pointer to an `unaligned` struct field with
923912/// an expression such as `&packed.unaligned as *const FieldType` creates an
924913/// intermediate unaligned reference before converting that to a raw pointer.
@@ -927,36 +916,32 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
927916/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
928917/// *undefined behavior* in your program.
929918///
930- /// An example of what not to do and how this relates to `write_unaligned` is:
919+ /// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut)
920+ /// macro to create the pointer. You may use that returned pointer together with
921+ /// this function.
922+ ///
923+ /// An example of how to do it and how this relates to `write_unaligned` is:
931924///
932- /// ```no_run
925+ /// ```
933926/// #[repr(packed, C)]
934927/// struct Packed {
935928/// _padding: u8,
936929/// unaligned: u32,
937930/// }
938931///
939- /// let v = 0x01020304;
940932/// let mut packed: Packed = unsafe { std::mem::zeroed() };
941933///
942- /// #[allow(unaligned_references)]
943- /// let v = unsafe {
944- /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
945- /// let unaligned =
946- /// // A temporary unaligned reference is created here which results in
947- /// // undefined behavior regardless of whether the reference is used or not.
948- /// &mut packed.unaligned
949- /// // Casting to a raw pointer doesn't help; the mistake already happened.
950- /// as *mut u32;
934+ /// // Take the address of a 32-bit integer which is not aligned.
935+ /// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior.
936+ /// let unaligned = std::ptr::addr_of_mut!(packed.unaligned);
951937///
952- /// std::ptr::write_unaligned(unaligned, v) ;
938+ /// unsafe { std::ptr::write_unaligned(unaligned, 42) } ;
953939///
954- /// v
955- /// };
940+ /// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
956941/// ```
957942///
958- /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
959- // FIXME: Update docs based on outcome of RFC #2582 and friends .
943+ /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however
944+ /// (as can be seen in the `assert_eq!` above) .
960945///
961946/// # Examples
962947///
0 commit comments