@@ -2071,21 +2071,26 @@ impl<F: FnPtr> fmt::Debug for F {
2071
2071
/// as all other references. This macro can create a raw pointer *without* creating
2072
2072
/// a reference first.
2073
2073
///
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
+ /// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads from the
2075
+ /// place or requires the place to be dereferenceable. This means that `addr_of!((*ptr).field)`
2076
+ /// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2077
+ /// However, `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2079
2078
///
2080
2079
/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
2081
2080
/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or
2082
2081
/// `Index::index`, respectively. The statements above only apply when no such coercions are
2083
2082
/// applied.
2084
2083
///
2084
+ /// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
2085
+ /// Doing that with `addr_of` would not make much sense since one could only
2086
+ /// read the data, and that would be Undefined Behavior.
2087
+ ///
2085
2088
/// [`offset`]: pointer::offset
2086
2089
///
2087
2090
/// # Example
2088
2091
///
2092
+ /// **Correct usage: Creating a pointer to unaligned data**
2093
+ ///
2089
2094
/// ```
2090
2095
/// use std::ptr;
2091
2096
///
@@ -2101,9 +2106,24 @@ impl<F: FnPtr> fmt::Debug for F {
2101
2106
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
2102
2107
/// ```
2103
2108
///
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.
2109
+ /// **Incorrect usage: Out-of-bounds fields projection**
2110
+ ///
2111
+ /// ```rust,no_run
2112
+ /// use std::ptr;
2113
+ ///
2114
+ /// #[repr(C)]
2115
+ /// struct MyStruct {
2116
+ /// field1: i32,
2117
+ /// field2: i32,
2118
+ /// }
2119
+ ///
2120
+ /// let ptr: *const MyStruct = ptr::null();
2121
+ /// let fieldptr = unsafe { ptr::addr_of!((*ptr).field2) }; // Undefined Behavior ⚠️
2122
+ /// ```
2123
+ ///
2124
+ /// The field projection `.field2` would offset the pointer by 4 bytes,
2125
+ /// but the pointer is not in-bounds of an allocation for 4 bytes,
2126
+ /// so this offset is Undefined Behavior.
2107
2127
#[ stable( feature = "raw_ref_macros" , since = "1.51.0" ) ]
2108
2128
#[ rustc_macro_transparency = "semitransparent" ]
2109
2129
#[ allow_internal_unstable( raw_ref_op) ]
@@ -2120,11 +2140,10 @@ pub macro addr_of($place:expr) {
2120
2140
/// as all other references. This macro can create a raw pointer *without* creating
2121
2141
/// a reference first.
2122
2142
///
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`].
2143
+ /// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads from the
2144
+ /// place or requires the place to be dereferenceable. This means that `addr_of_mut!((*ptr).field)`
2145
+ /// still requires the projection to `field` to be in-bounds, using the same rules as [`offset`].
2146
+ /// However, `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
2128
2147
///
2129
2148
/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
2130
2149
/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref`
@@ -2135,7 +2154,7 @@ pub macro addr_of($place:expr) {
2135
2154
///
2136
2155
/// # Examples
2137
2156
///
2138
- /// **Creating a pointer to unaligned data: **
2157
+ /// **Correct usage: Creating a pointer to unaligned data**
2139
2158
///
2140
2159
/// ```
2141
2160
/// use std::ptr;
@@ -2153,7 +2172,7 @@ pub macro addr_of($place:expr) {
2153
2172
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
2154
2173
/// ```
2155
2174
///
2156
- /// **Creating a pointer to uninitialized data: **
2175
+ /// **Correct usage: Creating a pointer to uninitialized data**
2157
2176
///
2158
2177
/// ```rust
2159
2178
/// use std::{ptr, mem::MaybeUninit};
@@ -2169,6 +2188,25 @@ pub macro addr_of($place:expr) {
2169
2188
/// unsafe { f1_ptr.write(true); }
2170
2189
/// let init = unsafe { uninit.assume_init() };
2171
2190
/// ```
2191
+ ///
2192
+ /// **Incorrect usage: Out-of-bounds fields projection**
2193
+ ///
2194
+ /// ```rust,no_run
2195
+ /// use std::ptr;
2196
+ ///
2197
+ /// #[repr(C)]
2198
+ /// struct MyStruct {
2199
+ /// field1: i32,
2200
+ /// field2: i32,
2201
+ /// }
2202
+ ///
2203
+ /// let ptr: *mut MyStruct = ptr::null_mut();
2204
+ /// let fieldptr = unsafe { ptr::addr_of_mut!((*ptr).field2) }; // Undefined Behavior ⚠️
2205
+ /// ```
2206
+ ///
2207
+ /// The field projection `.field2` would offset the pointer by 4 bytes,
2208
+ /// but the pointer is not in-bounds of an allocation for 4 bytes,
2209
+ /// so this offset is Undefined Behavior.
2172
2210
#[ stable( feature = "raw_ref_macros" , since = "1.51.0" ) ]
2173
2211
#[ rustc_macro_transparency = "semitransparent" ]
2174
2212
#[ allow_internal_unstable( raw_ref_op) ]
0 commit comments