Skip to content

Commit 389333a

Browse files
jfrimmelJoshua Nelsonm-ou-seSoveuRalfJung
committed
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 unde- fined behavior, which is not necessary anymore. There is also a new section in "how to obtain a pointer", which referen- ces the `ptr::addr_of!` macros. This commit contains squashed commits from code review. Co-authored-by: Joshua Nelson <joshua@yottadb.com> Co-authored-by: Mara Bos <m-ou.se@m-ou.se> Co-authored-by: Soveu <marx.tomasz@gmail.com> Co-authored-by: Ralf Jung <post@ralfj.de>
1 parent 5208f63 commit 389333a

File tree

2 files changed

+44
-39
lines changed

2 files changed

+44
-39
lines changed

library/core/src/ptr/mod.rs

+23-38
Original file line numberDiff line numberDiff line change
@@ -742,9 +742,6 @@ pub const unsafe fn read<T>(src: *const T) -> T {
742742
///
743743
/// ## On `packed` structs
744744
///
745-
/// It is currently impossible to create raw pointers to unaligned fields
746-
/// of a packed struct.
747-
///
748745
/// Attempting to create a raw pointer to an `unaligned` struct field with
749746
/// an expression such as `&packed.unaligned as *const FieldType` creates an
750747
/// intermediate unaligned reference before converting that to a raw pointer.
@@ -753,9 +750,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
753750
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
754751
/// *undefined behavior* in your program.
755752
///
753+
/// Instead you must use the [`ptr::addr_of!`](addr_of) macro to
754+
/// create the pointer. You may use that returned pointer together with this
755+
/// function.
756+
///
756757
/// An example of what not to do and how this relates to `read_unaligned` is:
757758
///
758-
/// ```no_run
759+
/// ```
759760
/// #[repr(packed, C)]
760761
/// struct Packed {
761762
/// _padding: u8,
@@ -767,24 +768,15 @@ pub const unsafe fn read<T>(src: *const T) -> T {
767768
/// unaligned: 0x01020304,
768769
/// };
769770
///
770-
/// #[allow(unaligned_references)]
771-
/// let v = unsafe {
772-
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
773-
/// let unaligned =
774-
/// // A temporary unaligned reference is created here which results in
775-
/// // undefined behavior regardless of whether the reference is used or not.
776-
/// &packed.unaligned
777-
/// // Casting to a raw pointer doesn't help; the mistake already happened.
778-
/// as *const u32;
771+
/// // Take the address of a 32-bit integer which is not aligned.
772+
/// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior.
773+
/// let unaligned = std::ptr::addr_of!(packed.unaligned);
779774
///
780-
/// let v = std::ptr::read_unaligned(unaligned);
781-
///
782-
/// v
783-
/// };
775+
/// let v = unsafe { std::ptr::read_unaligned(unaligned) };
776+
/// assert_eq!(v, 0x01020304);
784777
/// ```
785778
///
786779
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
787-
// FIXME: Update docs based on outcome of RFC #2582 and friends.
788780
///
789781
/// # Examples
790782
///
@@ -938,9 +930,6 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
938930
///
939931
/// ## On `packed` structs
940932
///
941-
/// It is currently impossible to create raw pointers to unaligned fields
942-
/// of a packed struct.
943-
///
944933
/// Attempting to create a raw pointer to an `unaligned` struct field with
945934
/// an expression such as `&packed.unaligned as *const FieldType` creates an
946935
/// intermediate unaligned reference before converting that to a raw pointer.
@@ -949,36 +938,32 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
949938
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
950939
/// *undefined behavior* in your program.
951940
///
952-
/// An example of what not to do and how this relates to `write_unaligned` is:
941+
/// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut)
942+
/// macro to create the pointer. You may use that returned pointer together with
943+
/// this function.
944+
///
945+
/// An example of how to do it and how this relates to `write_unaligned` is:
953946
///
954-
/// ```no_run
947+
/// ```
955948
/// #[repr(packed, C)]
956949
/// struct Packed {
957950
/// _padding: u8,
958951
/// unaligned: u32,
959952
/// }
960953
///
961-
/// let v = 0x01020304;
962954
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
963955
///
964-
/// #[allow(unaligned_references)]
965-
/// let v = unsafe {
966-
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
967-
/// let unaligned =
968-
/// // A temporary unaligned reference is created here which results in
969-
/// // undefined behavior regardless of whether the reference is used or not.
970-
/// &mut packed.unaligned
971-
/// // Casting to a raw pointer doesn't help; the mistake already happened.
972-
/// as *mut u32;
956+
/// // Take the address of a 32-bit integer which is not aligned.
957+
/// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior.
958+
/// let unaligned = std::ptr::addr_of_mut!(packed.unaligned);
973959
///
974-
/// std::ptr::write_unaligned(unaligned, v);
960+
/// unsafe { std::ptr::write_unaligned(unaligned, 42) };
975961
///
976-
/// v
977-
/// };
962+
/// assert_eq!({packed.unaligned}, 42); // `{...}` forces copying the field instead of creating a reference.
978963
/// ```
979964
///
980-
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
981-
// FIXME: Update docs based on outcome of RFC #2582 and friends.
965+
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however
966+
/// (as can be seen in the `assert_eq!` above).
982967
///
983968
/// # Examples
984969
///

library/std/src/primitive_docs.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,27 @@ mod prim_unit {}
445445
/// Note that here the call to [`drop`] is for clarity - it indicates
446446
/// that we are done with the given value and it should be destroyed.
447447
///
448-
/// ## 3. Get it from C.
448+
/// ## 3. Create it using `ptr::addr_of!`
449+
///
450+
/// Instead of coercing a reference to a raw pointer, you can use the macros
451+
/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
452+
/// These macros allow you to create raw pointers to fields to which you cannot
453+
/// create a reference (without causing undefined behaviour), such as an
454+
/// unaligned field. This might be necessary if packed structs or uninitialized
455+
/// memory is involved.
456+
///
457+
/// ```
458+
/// #[derive(Debug, Default, Copy, Clone)]
459+
/// #[repr(C, packed)]
460+
/// struct S {
461+
/// aligned: u8,
462+
/// unaligned: u32,
463+
/// }
464+
/// let s = S::default();
465+
/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
466+
/// ```
467+
///
468+
/// ## 4. Get it from C.
449469
///
450470
/// ```
451471
/// # #![feature(rustc_private)]

0 commit comments

Comments
 (0)