@@ -111,9 +111,8 @@ pub const unsafe fn unreachable_unchecked() -> ! {
111
111
112
112
/// Makes a *soundness* promise to the compiler that `cond` holds.
113
113
///
114
- /// This may allow the optimizer to simplify things,
115
- /// but it might also make the generated code slower.
116
- /// Either way, calling it will most likely make compilation take longer.
114
+ /// This may allow the optimizer to simplify things, but it might also make the generated code
115
+ /// slower. Either way, calling it will most likely make compilation take longer.
117
116
///
118
117
/// This is a situational tool for micro-optimization, and is allowed to do nothing.
119
118
/// Any use should come with a repeatable benchmark to show the value
@@ -130,9 +129,9 @@ pub const unsafe fn unreachable_unchecked() -> ! {
130
129
/// If ever you're tempted to write `assert_unchecked(false)`, then you're
131
130
/// actually looking for [`unreachable_unchecked()`].
132
131
///
133
- /// You may know this from other places
134
- /// as [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic)
135
- /// or [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume).
132
+ /// You may know this from other places as
133
+ /// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C,
134
+ /// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume).
136
135
///
137
136
/// This promotes a correctness requirement to a soundness requirement.
138
137
/// Don't do that without very good reason.
@@ -141,6 +140,54 @@ pub const unsafe fn unreachable_unchecked() -> ! {
141
140
///
142
141
/// `cond` must be `true`. It's immediate UB to call this with `false`.
143
142
///
143
+ /// # Example
144
+ ///
145
+ /// ```
146
+ /// use core::hint;
147
+ ///
148
+ /// /// # Safety
149
+ /// ///
150
+ /// /// `p` must be nonnull and valid
151
+ /// pub unsafe fn next_value(p: *const i32) -> i32 {
152
+ /// // SAFETY: caller invariants guarantee that `p` is not null
153
+ /// unsafe { hint::assert_unchecked(!p.is_null()) }
154
+ ///
155
+ /// if p.is_null() {
156
+ /// return -1;
157
+ /// } else {
158
+ /// // SAFETY: caller invariants guarantee that `p` is valid
159
+ /// unsafe { *p + 1 }
160
+ /// }
161
+ /// }
162
+ /// ```
163
+ ///
164
+ /// Without the `assert_unchecked`, the above function produces the following with optimizations:
165
+ ///
166
+ /// ```asm
167
+ /// next_value:
168
+ /// test rdi, rdi
169
+ /// je .LBB0_1
170
+ /// mov eax, dword ptr [rdi]
171
+ /// inc eax
172
+ /// ret
173
+ /// .LBB0_1:
174
+ /// mov eax, -1
175
+ /// ret
176
+ /// ```
177
+ ///
178
+ /// Adding the assertion allows the optimizer to remove the extra check:
179
+ ///
180
+ /// ```asm
181
+ /// next_value:
182
+ /// mov eax, dword ptr [rdi]
183
+ /// inc eax
184
+ /// ret
185
+ /// ```
186
+ ///
187
+ /// This example is quite unlike anything that would happen in the real world: it is redundant to
188
+ /// put an an assertion right next to code that checks the same thing, and dereferencing a
189
+ /// pointer already has the builtin assumption that it is nonnull. The optimizer can make use of
190
+ /// this information even when it isn't obvious, such as when checks happen in called functions.
144
191
#[ inline( always) ]
145
192
#[ doc( alias = "assume" ) ]
146
193
#[ track_caller]
0 commit comments