@@ -720,9 +720,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
720
720
///
721
721
/// ## On `packed` structs
722
722
///
723
- /// It is currently impossible to create raw pointers to unaligned fields
724
- /// of a packed struct.
725
- ///
726
723
/// Attempting to create a raw pointer to an `unaligned` struct field with
727
724
/// an expression such as `&packed.unaligned as *const FieldType` creates an
728
725
/// intermediate unaligned reference before converting that to a raw pointer.
@@ -731,9 +728,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
731
728
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
732
729
/// *undefined behavior* in your program.
733
730
///
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
+ ///
734
735
/// An example of what not to do and how this relates to `read_unaligned` is:
735
736
///
736
- /// ```no_run
737
+ /// ```
737
738
/// #[repr(packed, C)]
738
739
/// struct Packed {
739
740
/// _padding: u8,
@@ -745,24 +746,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
745
746
/// unaligned: 0x01020304,
746
747
/// };
747
748
///
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);
757
752
///
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);
762
755
/// ```
763
756
///
764
757
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
765
- // FIXME: Update docs based on outcome of RFC #2582 and friends.
766
758
///
767
759
/// # Examples
768
760
///
@@ -916,9 +908,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
916
908
///
917
909
/// ## On `packed` structs
918
910
///
919
- /// It is currently impossible to create raw pointers to unaligned fields
920
- /// of a packed struct.
921
- ///
922
911
/// Attempting to create a raw pointer to an `unaligned` struct field with
923
912
/// an expression such as `&packed.unaligned as *const FieldType` creates an
924
913
/// 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) {
927
916
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
928
917
/// *undefined behavior* in your program.
929
918
///
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:
931
924
///
932
- /// ```no_run
925
+ /// ```
933
926
/// #[repr(packed, C)]
934
927
/// struct Packed {
935
928
/// _padding: u8,
936
929
/// unaligned: u32,
937
930
/// }
938
931
///
939
- /// let v = 0x01020304;
940
932
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
941
933
///
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);
951
937
///
952
- /// std::ptr::write_unaligned(unaligned, v) ;
938
+ /// unsafe { std::ptr::write_unaligned(unaligned, 42) } ;
953
939
///
954
- /// v
955
- /// };
940
+ /// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
956
941
/// ```
957
942
///
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) .
960
945
///
961
946
/// # Examples
962
947
///
0 commit comments