@@ -625,42 +625,50 @@ pub unsafe fn read<T>(src: *const T) -> T {
625
625
/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
626
626
/// [valid]: ../ptr/index.html#safety
627
627
///
628
- /// # Examples
628
+ /// ## On `packed` structs
629
629
///
630
- /// Access members of a packed struct by reference:
630
+ /// It is currently impossible to create raw pointers to unaligned fields
631
+ /// of a packed struct.
631
632
///
632
- /// ```
633
- /// use std::ptr;
633
+ /// Attempting to create a raw pointer to an `unaligned` struct field with
634
+ /// an expression such as `&packed.unaligned as *const FieldType` creates an
635
+ /// intermediate unaligned reference before converting that to a raw pointer.
636
+ /// That this reference is temporary and immediately cast is inconsequential
637
+ /// as the compiler always expects references to be properly aligned.
638
+ /// As a result, using `&packed.unaligned as *const FieldType` causes immediate
639
+ /// *undefined behavior* in your program.
634
640
///
641
+ /// An example of what not to do and how this relates to `read_unaligned` is:
642
+ ///
643
+ /// ```no_run
635
644
/// #[repr(packed, C)]
636
645
/// struct Packed {
637
646
/// _padding: u8,
638
647
/// unaligned: u32,
639
648
/// }
640
649
///
641
- /// let x = Packed {
650
+ /// let packed = Packed {
642
651
/// _padding: 0x00,
643
652
/// unaligned: 0x01020304,
644
653
/// };
645
654
///
646
655
/// let v = unsafe {
647
- /// // Take the address of a 32-bit integer which is not aligned.
648
- /// // This must be done as a raw pointer; unaligned references are invalid.
649
- /// let unaligned = &x. unaligned as *const u32;
650
- ///
651
- /// // Dereferencing normally will emit an aligned load instruction,
652
- /// // causing undefined behavior .
653
- /// // let v = *unaligned; // ERROR
656
+ /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
657
+ /// let unaligned =
658
+ /// // A temporary unaligned reference is created here which results in
659
+ /// // undefined behavior regardless of whether the reference is used or not.
660
+ /// &packed.unaligned
661
+ /// // Casting to a raw pointer doesn't help; the mistake already happened .
662
+ /// as *const u32;
654
663
///
655
- /// // Instead, use `read_unaligned` to read improperly aligned values.
656
- /// let v = ptr::read_unaligned(unaligned);
664
+ /// let v = std::ptr::read_unaligned(unaligned);
657
665
///
658
666
/// v
659
667
/// };
660
- ///
661
- /// // Accessing unaligned values directly is safe.
662
- /// assert!(x.unaligned == v);
663
668
/// ```
669
+ ///
670
+ /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
671
+ // FIXME: Update docs based on outcome of RFC #2582 and friends.
664
672
#[ inline]
665
673
#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
666
674
pub unsafe fn read_unaligned < T > ( src : * const T ) -> T {
@@ -789,38 +797,48 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
789
797
///
790
798
/// [valid]: ../ptr/index.html#safety
791
799
///
792
- /// # Examples
800
+ /// ## On `packed` structs
793
801
///
794
- /// Access fields in a packed struct:
802
+ /// It is currently impossible to create raw pointers to unaligned fields
803
+ /// of a packed struct.
795
804
///
796
- /// ```
797
- /// use std::{mem, ptr};
805
+ /// Attempting to create a raw pointer to an `unaligned` struct field with
806
+ /// an expression such as `&packed.unaligned as *const FieldType` creates an
807
+ /// intermediate unaligned reference before converting that to a raw pointer.
808
+ /// That this reference is temporary and immediately cast is inconsequential
809
+ /// as the compiler always expects references to be properly aligned.
810
+ /// As a result, using `&packed.unaligned as *const FieldType` causes immediate
811
+ /// *undefined behavior* in your program.
798
812
///
813
+ /// An example of what not to do and how this relates to `write_unaligned` is:
814
+ ///
815
+ /// ```no_run
799
816
/// #[repr(packed, C)]
800
- /// #[derive(Default)]
801
817
/// struct Packed {
802
818
/// _padding: u8,
803
819
/// unaligned: u32,
804
820
/// }
805
821
///
806
822
/// let v = 0x01020304;
807
- /// let mut x: Packed = unsafe { mem::zeroed() };
808
- ///
809
- /// unsafe {
810
- /// // Take a reference to a 32-bit integer which is not aligned.
811
- /// let unaligned = &mut x.unaligned as *mut u32;
823
+ /// let mut packed: Packed = unsafe { std::mem::zeroed() };
812
824
///
813
- /// // Dereferencing normally will emit an aligned store instruction,
814
- /// // causing undefined behavior because the pointer is not aligned.
815
- /// // *unaligned = v; // ERROR
825
+ /// let v = unsafe {
826
+ /// // Here we attempt to take the address of a 32-bit integer which is not aligned.
827
+ /// let unaligned =
828
+ /// // A temporary unaligned reference is created here which results in
829
+ /// // undefined behavior regardless of whether the reference is used or not.
830
+ /// &mut packed.unaligned
831
+ /// // Casting to a raw pointer doesn't help; the mistake already happened.
832
+ /// as *mut u32;
816
833
///
817
- /// // Instead, use `write_unaligned` to write improperly aligned values.
818
- /// ptr::write_unaligned(unaligned, v);
819
- /// }
834
+ /// std::ptr::write_unaligned(unaligned, v);
820
835
///
821
- /// // Accessing unaligned values directly is safe.
822
- /// assert!(x.unaligned == v) ;
836
+ /// v
837
+ /// } ;
823
838
/// ```
839
+ ///
840
+ /// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
841
+ // FIXME: Update docs based on outcome of RFC #2582 and friends.
824
842
#[ inline]
825
843
#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
826
844
pub unsafe fn write_unaligned < T > ( dst : * mut T , src : T ) {
0 commit comments