@@ -742,9 +742,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
742
742
///
743
743
/// ## On `packed` structs
744
744
///
745
- /// It is currently impossible to create raw pointers to unaligned fields
746
- /// of a packed struct.
747
- ///
748
745
/// Attempting to create a raw pointer to an `unaligned` struct field with
749
746
/// an expression such as `&packed.unaligned as *const FieldType` creates an
750
747
/// intermediate unaligned reference before converting that to a raw pointer.
@@ -753,9 +750,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
753
750
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
754
751
/// *undefined behavior* in your program.
755
752
///
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
+ ///
756
757
/// An example of what not to do and how this relates to `read_unaligned` is:
757
758
///
758
- /// ```no_run
759
+ /// ```
759
760
/// #[repr(packed, C)]
760
761
/// struct Packed {
761
762
/// _padding: u8,
@@ -767,24 +768,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
767
768
/// unaligned: 0x01020304,
768
769
/// };
769
770
///
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);
779
774
///
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);
784
777
/// ```
785
778
///
786
779
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
787
- // FIXME: Update docs based on outcome of RFC #2582 and friends.
788
780
///
789
781
/// # Examples
790
782
///
@@ -938,9 +930,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
938
930
///
939
931
/// ## On `packed` structs
940
932
///
941
- /// It is currently impossible to create raw pointers to unaligned fields
942
- /// of a packed struct.
943
- ///
944
933
/// Attempting to create a raw pointer to an `unaligned` struct field with
945
934
/// an expression such as `&packed.unaligned as *const FieldType` creates an
946
935
/// 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) {
949
938
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
950
939
/// *undefined behavior* in your program.
951
940
///
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:
953
946
///
954
- /// ```no_run
947
+ /// ```
955
948
/// #[repr(packed, C)]
956
949
/// struct Packed {
957
950
/// _padding: u8,
958
951
/// unaligned: u32,
959
952
/// }
960
953
///
961
- /// let v = 0x01020304;
962
954
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
963
955
///
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);
973
959
///
974
- /// std::ptr::write_unaligned(unaligned, v) ;
960
+ /// unsafe { std::ptr::write_unaligned(unaligned, 42) } ;
975
961
///
976
- /// v
977
- /// };
962
+ /// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
978
963
/// ```
979
964
///
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) .
982
967
///
983
968
/// # Examples
984
969
///
0 commit comments