Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ptr docs with regards to ptr::addr_of! #83553

Merged
merged 1 commit into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 23 additions & 38 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,9 +742,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
///
/// ## On `packed` structs
///
/// It is currently impossible to create raw pointers to unaligned fields
/// of a packed struct.
///
/// Attempting to create a raw pointer to an `unaligned` struct field with
/// an expression such as `&packed.unaligned as *const FieldType` creates an
/// intermediate unaligned reference before converting that to a raw pointer.
Expand All @@ -753,9 +750,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
/// *undefined behavior* in your program.
///
/// Instead you must use the [`ptr::addr_of!`](addr_of) macro to
/// create the pointer. You may use that returned pointer together with this
/// function.
///
/// An example of what not to do and how this relates to `read_unaligned` is:
///
/// ```no_run
/// ```
/// #[repr(packed, C)]
/// struct Packed {
/// _padding: u8,
Expand All @@ -767,24 +768,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
/// unaligned: 0x01020304,
/// };
///
/// #[allow(unaligned_references)]
/// let v = unsafe {
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
/// let unaligned =
/// // A temporary unaligned reference is created here which results in
/// // undefined behavior regardless of whether the reference is used or not.
/// &packed.unaligned
/// // Casting to a raw pointer doesn't help; the mistake already happened.
/// as *const u32;
/// // Take the address of a 32-bit integer which is not aligned.
/// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior.
/// let unaligned = std::ptr::addr_of!(packed.unaligned);
///
/// let v = std::ptr::read_unaligned(unaligned);
///
/// v
/// };
/// let v = unsafe { std::ptr::read_unaligned(unaligned) };
/// assert_eq!(v, 0x01020304);
/// ```
///
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
// FIXME: Update docs based on outcome of RFC #2582 and friends.
///
/// # Examples
///
Expand Down Expand Up @@ -938,9 +930,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
///
/// ## On `packed` structs
///
/// It is currently impossible to create raw pointers to unaligned fields
/// of a packed struct.
///
/// Attempting to create a raw pointer to an `unaligned` struct field with
/// an expression such as `&packed.unaligned as *const FieldType` creates an
/// intermediate unaligned reference before converting that to a raw pointer.
Expand All @@ -949,36 +938,32 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
/// *undefined behavior* in your program.
///
/// An example of what not to do and how this relates to `write_unaligned` is:
/// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut)
/// macro to create the pointer. You may use that returned pointer together with
/// this function.
///
/// An example of how to do it and how this relates to `write_unaligned` is:
///
/// ```no_run
/// ```
/// #[repr(packed, C)]
/// struct Packed {
/// _padding: u8,
/// unaligned: u32,
/// }
///
/// let v = 0x01020304;
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
///
/// #[allow(unaligned_references)]
/// let v = unsafe {
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
/// let unaligned =
/// // A temporary unaligned reference is created here which results in
/// // undefined behavior regardless of whether the reference is used or not.
/// &mut packed.unaligned
/// // Casting to a raw pointer doesn't help; the mistake already happened.
/// as *mut u32;
/// // Take the address of a 32-bit integer which is not aligned.
/// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior.
/// let unaligned = std::ptr::addr_of_mut!(packed.unaligned);
///
/// std::ptr::write_unaligned(unaligned, v);
/// unsafe { std::ptr::write_unaligned(unaligned, 42) };
///
/// v
/// };
/// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
/// ```
///
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
// FIXME: Update docs based on outcome of RFC #2582 and friends.
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however
/// (as can be seen in the `assert_eq!` above).
///
/// # Examples
///
Expand Down
22 changes: 21 additions & 1 deletion library/std/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,27 @@ mod prim_unit {}
/// Note that here the call to [`drop`] is for clarity - it indicates
/// that we are done with the given value and it should be destroyed.
///
/// ## 3. Get it from C.
/// ## 3. Create it using `ptr::addr_of!`
///
/// Instead of coercing a reference to a raw pointer, you can use the macros
/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
/// These macros allow you to create raw pointers to fields to which you cannot
/// create a reference (without causing undefined behaviour), such as an
/// unaligned field. This might be necessary if packed structs or uninitialized
/// memory is involved.
///
/// ```
/// #[derive(Debug, Default, Copy, Clone)]
/// #[repr(C, packed)]
/// struct S {
/// aligned: u8,
/// unaligned: u32,
/// }
/// let s = S::default();
/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
/// ```
///
/// ## 4. Get it from C.
///
/// ```
/// # #![feature(rustc_private)]
Expand Down