@@ -647,42 +647,50 @@ pub unsafe fn read<T>(src: *const T) -> T {
647
647
/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
648
648
/// [valid]: ../ptr/index.html#safety
649
649
///
650
- /// # Examples
650
+ /// ## On `packed` structs
651
651
///
652
- /// Access members of a packed struct by reference:
652
+ /// It is currently impossible to create raw pointers to unaligned fields
653
+ /// of a packed struct.
653
654
///
654
- /// ```
655
- /// use std::ptr;
655
+ /// Attempting to create a raw pointer to an `unaligned` struct field with
656
+ /// an expression such as `&packed.unaligned as *const FieldType` creates an
657
+ /// intermediate unaligned reference before converting that to a raw pointer.
658
+ /// That this reference is temporary and immediately cast is inconsequential
659
+ /// as the compiler always expects references to be properly aligned.
660
+ /// As a result, using `&packed.unaligned as *const FieldType` causes immediate
661
+ /// *undefined behavior* in your program.
656
662
///
663
+ /// An example of what not to do and how this relates to `read_unaligned` is:
664
+ ///
665
+ /// ```
657
666
/// #[repr(packed, C)]
658
667
/// struct Packed {
659
668
/// _padding: u8,
660
669
/// unaligned: u32,
661
670
/// }
662
671
///
663
- /// let x = Packed {
672
+ /// let packed = Packed {
664
673
/// _padding: 0x00,
665
674
/// unaligned: 0x01020304,
666
675
/// };
667
676
///
668
677
/// let v = unsafe {
669
- /// // Take the address of a 32-bit integer which is not aligned.
670
- /// // This must be done as a raw pointer; unaligned references are invalid.
671
- /// let unaligned = &x.unaligned as *const u32;
678
+ /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
679
+ /// let unaligned =
680
+ /// // A temporary unaligned reference is created here which results in
681
+ /// // undefined behavior regardless of whether the reference is used or not.
682
+ /// &packed.unaligned
683
+ /// // Casting to a raw pointer doesn't help; the mistake already happened.
684
+ /// as *const u32;
672
685
///
673
- /// // Dereferencing normally will emit an aligned load instruction,
674
- /// // causing undefined behavior.
675
- /// // let v = *unaligned; // ERROR
676
- ///
677
- /// // Instead, use `read_unaligned` to read improperly aligned values.
678
- /// let v = ptr::read_unaligned(unaligned);
686
+ /// let v = std::ptr::read_unaligned(unaligned);
679
687
///
680
688
/// v
681
689
/// };
682
- ///
683
- /// // Accessing unaligned values directly is safe.
684
- /// assert!(x.unaligned == v);
685
690
/// ```
691
+ ///
692
+ /// Accessing unaligned values directly with e.g. `packed.unaligned` is safe however.
693
+ // FIXME: Update docs based on outcome of RFC #2582 and friends.
686
694
#[ inline]
687
695
#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
688
696
pub unsafe fn read_unaligned < T > ( src : * const T ) -> T {
@@ -811,38 +819,48 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
811
819
///
812
820
/// [valid]: ../ptr/index.html#safety
813
821
///
814
- /// # Examples
822
+ /// ## On `packed` structs
815
823
///
816
- /// Access fields in a packed struct:
824
+ /// It is currently impossible to create raw pointers to unaligned fields
825
+ /// of a packed struct.
817
826
///
818
- /// ```
819
- /// use std::{mem, ptr};
827
+ /// Attempting to create a raw pointer to an `unaligned` struct field with
828
+ /// an expression such as `&packed.unaligned as *const FieldType` creates an
829
+ /// intermediate unaligned reference before converting that to a raw pointer.
830
+ /// That this reference is temporary and immediately cast is inconsequential
831
+ /// as the compiler always expects references to be properly aligned.
832
+ /// As a result, using `&packed.unaligned as *const FieldType` causes immediate
833
+ /// *undefined behavior* in your program.
820
834
///
835
+ /// An example of what not to do and how this relates to `write_unaligned` is:
836
+ ///
837
+ /// ```
821
838
/// #[repr(packed, C)]
822
- /// #[derive(Default)]
823
839
/// struct Packed {
824
840
/// _padding: u8,
825
841
/// unaligned: u32,
826
842
/// }
827
843
///
828
844
/// let v = 0x01020304;
829
- /// let mut x : Packed = unsafe { mem::zeroed() };
845
+ /// let mut packed : Packed = unsafe { std:: mem::zeroed() };
830
846
///
831
- /// unsafe {
832
- /// // Take a reference to a 32-bit integer which is not aligned.
833
- /// let unaligned = &mut x.unaligned as *mut u32;
847
+ /// let v = unsafe {
848
+ /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
849
+ /// let unaligned =
850
+ /// // A temporary unaligned reference is created here which results in
851
+ /// // undefined behavior regardless of whether the reference is used or not.
852
+ /// &mut packed.unaligned
853
+ /// // Casting to a raw pointer doesn't help; the mistake already happened.
854
+ /// as *mut u32;
834
855
///
835
- /// // Dereferencing normally will emit an aligned store instruction,
836
- /// // causing undefined behavior because the pointer is not aligned.
837
- /// // *unaligned = v; // ERROR
856
+ /// std::ptr::write_unaligned(unaligned, v);
838
857
///
839
- /// // Instead, use `write_unaligned` to write improperly aligned values.
840
- /// ptr::write_unaligned(unaligned, v);
841
- /// }
842
- ///
843
- /// // Accessing unaligned values directly is safe.
844
- /// assert!(x.unaligned == v);
858
+ /// v
859
+ /// };
845
860
/// ```
861
+ ///
862
+ /// Accessing unaligned values directly with e.g. `packed.unaligned` is safe however.
863
+ // FIXME: Update docs based on outcome of RFC #2582 and friends.
846
864
#[ inline]
847
865
#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
848
866
pub unsafe fn write_unaligned < T > ( dst : * mut T , src : T ) {
0 commit comments