about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-04-05 00:24:32 +0200
committerGitHub <noreply@github.com>2021-04-05 00:24:32 +0200
commitfbe89e20e83bd726b34ee0462ac96f2515f5945d (patch)
tree2d5ab5d6925bbdb09242b8ac8667fc11c41629d6
parentad776fdba8b862b43cbde3cec31d1a16c3e4d4d9 (diff)
parentb577d7ef259c159c8d74333c79a0540b954ba726 (diff)
downloadrust-fbe89e20e83bd726b34ee0462ac96f2515f5945d.tar.gz
rust-fbe89e20e83bd726b34ee0462ac96f2515f5945d.zip
Rollup merge of #83815 - RalfJung:addr_of, r=kennytm
ptr::addr_of documentation improvements

While writing https://github.com/rust-lang/reference/pull/1001 I figured I could also improve the docs here a bit.
-rw-r--r--library/core/src/mem/maybe_uninit.rs2
-rw-r--r--library/core/src/ptr/mod.rs33
2 files changed, 34 insertions, 1 deletions
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 337f0e847bb..64342de6341 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 f673a6fd178..c19eb642e22 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1537,6 +1537,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
 ///
 /// ```
@@ -1553,6 +1557,10 @@ 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 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")]
 #[rustc_macro_transparency = "semitransparent"]
 #[allow_internal_unstable(raw_ref_op)]
@@ -1569,7 +1577,13 @@ pub macro addr_of($place:expr) {
 /// as all other references. This macro can create a raw pointer *without* creating
 /// a reference first.
 ///
-/// # Example
+/// 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:**
 ///
 /// ```
 /// use std::ptr;
@@ -1586,6 +1600,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::<Demo>::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)]