From a4a6bdd33771ef4cf87fd1ffc6895ec7060ff898 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Apr 2021 19:25:11 +0200 Subject: [PATCH 1/4] addr_of_mut: add example for creating a pointer to uninit data --- library/core/src/mem/maybe_uninit.rs | 2 ++ library/core/src/ptr/mod.rs | 27 ++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 337f0e847bb56..64342de6341b0 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -190,6 +190,8 @@ use crate::ptr; /// let ptr = uninit.as_mut_ptr(); /// /// // Initializing the `name` field +/// // Using `write` instead of assignment via `=` to not call `drop` on the +/// // old, uninitialized value. /// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); } /// /// // Initializing the `list` field diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6412bd41a8c09..f8b124f581cce 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1540,6 +1540,12 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// let raw_f2 = ptr::addr_of!(packed.f2); /// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); /// ``` +/// +/// See [`addr_of_mut`] for how to create a pointer to ininitialized data. +/// Doing that with `addr_of` would not make much sense since one could only +/// read the data, and that would be Undefined Behavior. +/// +/// [`addr_of_mut`]: macro.addr_of_mut.html #[stable(feature = "raw_ref_macros", since = "1.51.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(raw_ref_op)] @@ -1556,7 +1562,9 @@ pub macro addr_of($place:expr) { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// # Example +/// # Examples +/// +/// **Creating a pointer to unaligned data:** /// /// ``` /// use std::ptr; @@ -1573,6 +1581,23 @@ pub macro addr_of($place:expr) { /// unsafe { raw_f2.write_unaligned(42); } /// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference. /// ``` +/// +/// **Creating a pointer to uninitialized data:** +/// +/// ```rust +/// use std::{ptr, mem::MaybeUninit}; +/// +/// struct Demo { +/// field: bool, +/// } +/// +/// let mut uninit = MaybeUninit::::uninit(); +/// // `&uninit.as_mut().field` would create a reference to an uninitialized `bool`, +/// // and thus be Undefined Behavior! +/// let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) }; +/// unsafe { f1_ptr.write(true); } +/// let init = unsafe { uninit.assume_init() }; +/// ``` #[stable(feature = "raw_ref_macros", since = "1.51.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(raw_ref_op)] From b93137a24e0de539293a99f6bfce9855cf13679d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Apr 2021 19:26:54 +0200 Subject: [PATCH 2/4] explain that even addr_of cannot deref a NULL ptr --- library/core/src/ptr/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f8b124f581cce..ba14b1abdb2e4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1524,6 +1524,10 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// +/// Note, however, that the `expr` in `addr_of!(expr)` is still subject to all +/// the usual rules. In particular, `addr_of!(*ptr::null())` is Undefined +/// Behavior because it dereferences a NULL pointer. +/// /// # Example /// /// ``` @@ -1562,6 +1566,10 @@ pub macro addr_of($place:expr) { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// +/// Note, however, that the `expr` in `addr_of_mut!(expr)` is still subject to all +/// the usual rules. In particular, `addr_of_mut!(*ptr::null_mut())` is Undefined +/// Behavior because it dereferences a NULL pointer. +/// /// # Examples /// /// **Creating a pointer to unaligned data:** From 5d1747bf07311f893829728c0e26e088794651e1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Apr 2021 11:24:25 +0200 Subject: [PATCH 3/4] rely on intra-doc links Co-authored-by: Yuki Okushi --- library/core/src/ptr/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ba14b1abdb2e4..bed5e0b899897 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1548,8 +1548,6 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// See [`addr_of_mut`] for how to create a pointer to ininitialized data. /// Doing that with `addr_of` would not make much sense since one could only /// read the data, and that would be Undefined Behavior. -/// -/// [`addr_of_mut`]: macro.addr_of_mut.html #[stable(feature = "raw_ref_macros", since = "1.51.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(raw_ref_op)] From b577d7ef259c159c8d74333c79a0540b954ba726 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Apr 2021 19:32:54 +0200 Subject: [PATCH 4/4] fix typo Co-authored-by: kennytm --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index bed5e0b899897..12fd4a36bd03d 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1545,7 +1545,7 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L } /// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); /// ``` /// -/// See [`addr_of_mut`] for how to create a pointer to ininitialized data. +/// See [`addr_of_mut`] for how to create a pointer to unininitialized data. /// Doing that with `addr_of` would not make much sense since one could only /// read the data, and that would be Undefined Behavior. #[stable(feature = "raw_ref_macros", since = "1.51.0")]