Rollup merge of #83553 - jfrimmel:addr-of, r=m-ou-se
Update `ptr` docs with regards to `ptr::addr_of!` This updates the documentation since `ptr::addr_of!` and `ptr::addr_of_mut!` are now stable. One might remove the distinction between the sections `# On packed structs` and `# Examples`, as the old section on packed structs was primarily to prevent users of doing undefined behavior, which is not necessary anymore. Technically there is now wrong/outdated documentation on stable, but I don't think this is worth a point release 😉 Fixes #83509. ``````````@rustbot`````````` modify labels: T-doc
This commit is contained in:
commit
722bebf163
2 changed files with 44 additions and 39 deletions
|
@ -720,9 +720,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
||||||
///
|
///
|
||||||
/// ## On `packed` structs
|
/// ## 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
|
/// Attempting to create a raw pointer to an `unaligned` struct field with
|
||||||
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
||||||
/// intermediate unaligned reference before converting that to a raw pointer.
|
/// intermediate unaligned reference before converting that to a raw pointer.
|
||||||
|
@ -731,9 +728,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
||||||
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
||||||
/// *undefined behavior* in your program.
|
/// *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:
|
/// An example of what not to do and how this relates to `read_unaligned` is:
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```
|
||||||
/// #[repr(packed, C)]
|
/// #[repr(packed, C)]
|
||||||
/// struct Packed {
|
/// struct Packed {
|
||||||
/// _padding: u8,
|
/// _padding: u8,
|
||||||
|
@ -745,24 +746,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
||||||
/// unaligned: 0x01020304,
|
/// unaligned: 0x01020304,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// #[allow(unaligned_references)]
|
/// // Take the address of a 32-bit integer which is not aligned.
|
||||||
/// let v = unsafe {
|
/// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior.
|
||||||
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
|
/// let unaligned = std::ptr::addr_of!(packed.unaligned);
|
||||||
/// 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;
|
|
||||||
///
|
///
|
||||||
/// let v = std::ptr::read_unaligned(unaligned);
|
/// let v = unsafe { std::ptr::read_unaligned(unaligned) };
|
||||||
///
|
/// assert_eq!(v, 0x01020304);
|
||||||
/// v
|
|
||||||
/// };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
||||||
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -916,9 +908,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
|
||||||
///
|
///
|
||||||
/// ## On `packed` structs
|
/// ## 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
|
/// Attempting to create a raw pointer to an `unaligned` struct field with
|
||||||
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
||||||
/// intermediate unaligned reference before converting that to a raw pointer.
|
/// intermediate unaligned reference before converting that to a raw pointer.
|
||||||
|
@ -927,36 +916,32 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
|
||||||
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
||||||
/// *undefined behavior* in your program.
|
/// *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.
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// An example of how to do it and how this relates to `write_unaligned` is:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
/// #[repr(packed, C)]
|
/// #[repr(packed, C)]
|
||||||
/// struct Packed {
|
/// struct Packed {
|
||||||
/// _padding: u8,
|
/// _padding: u8,
|
||||||
/// unaligned: u32,
|
/// unaligned: u32,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let v = 0x01020304;
|
|
||||||
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
|
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
|
||||||
///
|
///
|
||||||
/// #[allow(unaligned_references)]
|
/// // Take the address of a 32-bit integer which is not aligned.
|
||||||
/// let v = unsafe {
|
/// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior.
|
||||||
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
|
/// let unaligned = std::ptr::addr_of_mut!(packed.unaligned);
|
||||||
/// 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;
|
|
||||||
///
|
///
|
||||||
/// 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.
|
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however
|
||||||
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
/// (as can be seen in the `assert_eq!` above).
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -445,7 +445,27 @@ mod prim_unit {}
|
||||||
/// Note that here the call to [`drop`] is for clarity - it indicates
|
/// 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.
|
/// 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)]
|
/// # #![feature(rustc_private)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue