@@ -625,42 +625,50 @@ pub unsafe fn read<T>(src: *const T) -> T {
625625/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
626626/// [valid]: ../ptr/index.html#safety
627627///
628- /// # Examples
628+ /// ## On `packed` structs
629629///
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.
631632///
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.
634640///
641+ /// An example of what not to do and how this relates to `read_unaligned` is:
642+ ///
643+ /// ```no_run
635644/// #[repr(packed, C)]
636645/// struct Packed {
637646/// _padding: u8,
638647/// unaligned: u32,
639648/// }
640649///
641- /// let x = Packed {
650+ /// let packed = Packed {
642651/// _padding: 0x00,
643652/// unaligned: 0x01020304,
644653/// };
645654///
646655/// 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;
654663///
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);
657665///
658666/// v
659667/// };
660- ///
661- /// // Accessing unaligned values directly is safe.
662- /// assert!(x.unaligned == v);
663668/// ```
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.
664672#[ inline]
665673#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
666674pub unsafe fn read_unaligned < T > ( src : * const T ) -> T {
@@ -789,38 +797,48 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
789797///
790798/// [valid]: ../ptr/index.html#safety
791799///
792- /// # Examples
800+ /// ## On `packed` structs
793801///
794- /// Access fields in a packed struct:
802+ /// It is currently impossible to create raw pointers to unaligned fields
803+ /// of a packed struct.
795804///
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.
798812///
813+ /// An example of what not to do and how this relates to `write_unaligned` is:
814+ ///
815+ /// ```no_run
799816/// #[repr(packed, C)]
800- /// #[derive(Default)]
801817/// struct Packed {
802818/// _padding: u8,
803819/// unaligned: u32,
804820/// }
805821///
806822/// 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() };
812824///
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;
816833///
817- /// // Instead, use `write_unaligned` to write improperly aligned values.
818- /// ptr::write_unaligned(unaligned, v);
819- /// }
834+ /// std::ptr::write_unaligned(unaligned, v);
820835///
821- /// // Accessing unaligned values directly is safe.
822- /// assert!(x.unaligned == v) ;
836+ /// v
837+ /// } ;
823838/// ```
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.
824842#[ inline]
825843#[ stable( feature = "ptr_unaligned" , since = "1.17.0" ) ]
826844pub unsafe fn write_unaligned < T > ( dst : * mut T , src : T ) {
0 commit comments