@@ -2071,11 +2071,16 @@ impl<F: FnPtr> fmt::Debug for F {
20712071/// as all other references. This macro can create a raw pointer *without* creating
20722072/// a reference first.
20732073///
2074- /// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads
2075- /// from the place or requires the place to be dereferenceable. This means that
2076- /// `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2077- /// Note however that `addr_of!((*ptr).field)` still requires the projection to
2078- /// `field` to be in-bounds, using the same rules as [`offset`].
2074+ /// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
2075+ /// Doing that with `addr_of` would not make much sense since one could only
2076+ /// read the data, and that would be Undefined Behavior.
2077+ ///
2078+ /// # Safety
2079+ ///
2080+ /// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads from the
2081+ /// place or requires the place to be dereferenceable. This means that `addr_of!((*ptr).field)`
2082+ /// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2083+ /// However, `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
20792084///
20802085/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
20812086/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or
@@ -2086,6 +2091,8 @@ impl<F: FnPtr> fmt::Debug for F {
20862091///
20872092/// # Example
20882093///
2094+ /// **Correct usage: Creating a pointer to unaligned data**
2095+ ///
20892096/// ```
20902097/// use std::ptr;
20912098///
@@ -2101,9 +2108,27 @@ impl<F: FnPtr> fmt::Debug for F {
21012108/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
21022109/// ```
21032110///
2104- /// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
2105- /// Doing that with `addr_of` would not make much sense since one could only
2106- /// read the data, and that would be Undefined Behavior.
2111+ /// **Incorrect usage: Out-of-bounds fields projection**
2112+ ///
2113+ /// ```rust,no_run
2114+ /// use std::ptr;
2115+ ///
2116+ /// #[repr(C)]
2117+ /// struct MyStruct {
2118+ /// field1: i32,
2119+ /// field2: i32,
2120+ /// }
2121+ ///
2122+ /// let ptr: *const MyStruct = ptr::null();
2123+ /// let fieldptr = unsafe { ptr::addr_of!((*ptr).field2) }; // Undefined Behavior ⚠️
2124+ /// ```
2125+ ///
2126+ /// The field projection `.field2` would offset the pointer by 4 bytes,
2127+ /// but the pointer is not in-bounds of an allocation for 4 bytes,
2128+ /// so this offset is Undefined Behavior.
2129+ /// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the
2130+ /// same requirements apply to field projections, even inside `addr_of!`. (In particular, it makes
2131+ /// no difference whether the pointer is null or dangling.)
21072132#[ stable( feature = "raw_ref_macros" , since = "1.51.0" ) ]
21082133#[ rustc_macro_transparency = "semitransparent" ]
21092134#[ allow_internal_unstable( raw_ref_op) ]
@@ -2120,11 +2145,12 @@ pub macro addr_of($place:expr) {
21202145/// as all other references. This macro can create a raw pointer *without* creating
21212146/// a reference first.
21222147///
2123- /// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads
2124- /// from the place or requires the place to be dereferenceable. This means that
2125- /// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2126- /// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to
2127- /// `field` to be in-bounds, using the same rules as [`offset`].
2148+ /// # Safety
2149+ ///
2150+ /// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads from the
2151+ /// place or requires the place to be dereferenceable. This means that `addr_of_mut!((*ptr).field)`
2152+ /// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2153+ /// However, `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
21282154///
21292155/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
21302156/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref`
@@ -2135,7 +2161,7 @@ pub macro addr_of($place:expr) {
21352161///
21362162/// # Examples
21372163///
2138- /// **Creating a pointer to unaligned data: **
2164+ /// **Correct usage: Creating a pointer to unaligned data**
21392165///
21402166/// ```
21412167/// use std::ptr;
@@ -2153,7 +2179,7 @@ pub macro addr_of($place:expr) {
21532179/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
21542180/// ```
21552181///
2156- /// **Creating a pointer to uninitialized data: **
2182+ /// **Correct usage: Creating a pointer to uninitialized data**
21572183///
21582184/// ```rust
21592185/// use std::{ptr, mem::MaybeUninit};
@@ -2169,6 +2195,28 @@ pub macro addr_of($place:expr) {
21692195/// unsafe { f1_ptr.write(true); }
21702196/// let init = unsafe { uninit.assume_init() };
21712197/// ```
2198+ ///
2199+ /// **Incorrect usage: Out-of-bounds fields projection**
2200+ ///
2201+ /// ```rust,no_run
2202+ /// use std::ptr;
2203+ ///
2204+ /// #[repr(C)]
2205+ /// struct MyStruct {
2206+ /// field1: i32,
2207+ /// field2: i32,
2208+ /// }
2209+ ///
2210+ /// let ptr: *mut MyStruct = ptr::null_mut();
2211+ /// let fieldptr = unsafe { ptr::addr_of_mut!((*ptr).field2) }; // Undefined Behavior ⚠️
2212+ /// ```
2213+ ///
2214+ /// The field projection `.field2` would offset the pointer by 4 bytes,
2215+ /// but the pointer is not in-bounds of an allocation for 4 bytes,
2216+ /// so this offset is Undefined Behavior.
2217+ /// See the [`offset`] docs for a full list of requirements for inbounds pointer arithmetic; the
2218+ /// same requirements apply to field projections, even inside `addr_of_mut!`. (In particular, it
2219+ /// makes no difference whether the pointer is null or dangling.)
21722220#[ stable( feature = "raw_ref_macros" , since = "1.51.0" ) ]
21732221#[ rustc_macro_transparency = "semitransparent" ]
21742222#[ allow_internal_unstable( raw_ref_op) ]
0 commit comments