1 | #![stable (feature = "core_hint" , since = "1.27.0" )] |
2 | |
3 | //! Hints to compiler that affects how code should be emitted or optimized. |
4 | //! Hints may be compile time or runtime. |
5 | |
6 | use crate::intrinsics; |
7 | use crate::ub_checks; |
8 | |
9 | /// Informs the compiler that the site which is calling this function is not |
10 | /// reachable, possibly enabling further optimizations. |
11 | /// |
12 | /// # Safety |
13 | /// |
14 | /// Reaching this function is *Undefined Behavior*. |
15 | /// |
16 | /// As the compiler assumes that all forms of Undefined Behavior can never |
17 | /// happen, it will eliminate all branches in the surrounding code that it can |
18 | /// determine will invariably lead to a call to `unreachable_unchecked()`. |
19 | /// |
20 | /// If the assumptions embedded in using this function turn out to be wrong - |
21 | /// that is, if the site which is calling `unreachable_unchecked()` is actually |
22 | /// reachable at runtime - the compiler may have generated nonsensical machine |
23 | /// instructions for this situation, including in seemingly unrelated code, |
24 | /// causing difficult-to-debug problems. |
25 | /// |
26 | /// Use this function sparingly. Consider using the [`unreachable!`] macro, |
27 | /// which may prevent some optimizations but will safely panic in case it is |
28 | /// actually reached at runtime. Benchmark your code to find out if using |
29 | /// `unreachable_unchecked()` comes with a performance benefit. |
30 | /// |
31 | /// # Examples |
32 | /// |
33 | /// `unreachable_unchecked()` can be used in situations where the compiler |
34 | /// can't prove invariants that were previously established. Such situations |
35 | /// have a higher chance of occurring if those invariants are upheld by |
36 | /// external code that the compiler can't analyze. |
37 | /// ``` |
38 | /// fn prepare_inputs(divisors: &mut Vec<u32>) { |
39 | /// // Note to future-self when making changes: The invariant established |
40 | /// // here is NOT checked in `do_computation()`; if this changes, you HAVE |
41 | /// // to change `do_computation()`. |
42 | /// divisors.retain(|divisor| *divisor != 0) |
43 | /// } |
44 | /// |
45 | /// /// # Safety |
46 | /// /// All elements of `divisor` must be non-zero. |
47 | /// unsafe fn do_computation(i: u32, divisors: &[u32]) -> u32 { |
48 | /// divisors.iter().fold(i, |acc, divisor| { |
49 | /// // Convince the compiler that a division by zero can't happen here |
50 | /// // and a check is not needed below. |
51 | /// if *divisor == 0 { |
52 | /// // Safety: `divisor` can't be zero because of `prepare_inputs`, |
53 | /// // but the compiler does not know about this. We *promise* |
54 | /// // that we always call `prepare_inputs`. |
55 | /// std::hint::unreachable_unchecked() |
56 | /// } |
57 | /// // The compiler would normally introduce a check here that prevents |
58 | /// // a division by zero. However, if `divisor` was zero, the branch |
59 | /// // above would reach what we explicitly marked as unreachable. |
60 | /// // The compiler concludes that `divisor` can't be zero at this point |
61 | /// // and removes the - now proven useless - check. |
62 | /// acc / divisor |
63 | /// }) |
64 | /// } |
65 | /// |
66 | /// let mut divisors = vec![2, 0, 4]; |
67 | /// prepare_inputs(&mut divisors); |
68 | /// let result = unsafe { |
69 | /// // Safety: prepare_inputs() guarantees that divisors is non-zero |
70 | /// do_computation(100, &divisors) |
71 | /// }; |
72 | /// assert_eq!(result, 12); |
73 | /// |
74 | /// ``` |
75 | /// |
76 | /// While using `unreachable_unchecked()` is perfectly sound in the following |
77 | /// example, as the compiler is able to prove that a division by zero is not |
78 | /// possible, benchmarking reveals that `unreachable_unchecked()` provides |
79 | /// no benefit over using [`unreachable!`], while the latter does not introduce |
80 | /// the possibility of Undefined Behavior. |
81 | /// |
82 | /// ``` |
83 | /// fn div_1(a: u32, b: u32) -> u32 { |
84 | /// use std::hint::unreachable_unchecked; |
85 | /// |
86 | /// // `b.saturating_add(1)` is always positive (not zero), |
87 | /// // hence `checked_div` will never return `None`. |
88 | /// // Therefore, the else branch is unreachable. |
89 | /// a.checked_div(b.saturating_add(1)) |
90 | /// .unwrap_or_else(|| unsafe { unreachable_unchecked() }) |
91 | /// } |
92 | /// |
93 | /// assert_eq!(div_1(7, 0), 7); |
94 | /// assert_eq!(div_1(9, 1), 4); |
95 | /// assert_eq!(div_1(11, u32::MAX), 0); |
96 | /// ``` |
97 | #[inline ] |
98 | #[stable (feature = "unreachable" , since = "1.27.0" )] |
99 | #[rustc_const_stable (feature = "const_unreachable_unchecked" , since = "1.57.0" )] |
100 | #[cfg_attr (miri, track_caller)] // even without panics, this helps for Miri backtraces |
101 | pub const unsafe fn unreachable_unchecked() -> ! { |
102 | ub_checks::assert_unsafe_precondition!( |
103 | check_language_ub, |
104 | "hint::unreachable_unchecked must never be reached" , |
105 | () => false |
106 | ); |
107 | // SAFETY: the safety contract for `intrinsics::unreachable` must |
108 | // be upheld by the caller. |
109 | unsafe { intrinsics::unreachable() } |
110 | } |
111 | |
112 | /// Makes a *soundness* promise to the compiler that `cond` holds. |
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. |
117 | /// |
118 | /// This is a situational tool for micro-optimization, and is allowed to do nothing. |
119 | /// Any use should come with a repeatable benchmark to show the value |
120 | /// and allow removing it later should the optimizer get smarter and no longer need it. |
121 | /// |
122 | /// The more complicated the condition the less likely this is to be fruitful. |
123 | /// For example, `assert_unchecked(foo.is_sorted())` is a complex enough value |
124 | /// that the compiler is unlikely to be able to take advantage of it. |
125 | /// |
126 | /// There's also no need to `assert_unchecked` basic properties of things. For |
127 | /// example, the compiler already knows the range of `count_ones`, so there's no |
128 | /// benefit to `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`. |
129 | /// |
130 | /// If ever you're tempted to write `assert_unchecked(false)`, then you're |
131 | /// actually looking for [`unreachable_unchecked()`]. |
132 | /// |
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). |
136 | /// |
137 | /// This promotes a correctness requirement to a soundness requirement. |
138 | /// Don't do that without very good reason. |
139 | /// |
140 | /// # Safety |
141 | /// |
142 | /// `cond` must be `true`. It's immediate UB to call this with `false`. |
143 | /// |
144 | #[inline (always)] |
145 | #[doc (alias = "assume" )] |
146 | #[track_caller ] |
147 | #[unstable (feature = "hint_assert_unchecked" , issue = "119131" )] |
148 | #[rustc_const_unstable (feature = "const_hint_assert_unchecked" , issue = "119131" )] |
149 | pub const unsafe fn assert_unchecked(cond: bool) { |
150 | // SAFETY: The caller promised `cond` is true. |
151 | unsafe { |
152 | ub_checks::assert_unsafe_precondition!( |
153 | check_language_ub, |
154 | "hint::assert_unchecked must never be called when the condition is false" , |
155 | (cond: bool = cond) => cond, |
156 | ); |
157 | crate::intrinsics::assume(cond); |
158 | } |
159 | } |
160 | |
161 | /// Emits a machine instruction to signal the processor that it is running in |
162 | /// a busy-wait spin-loop ("spin lock"). |
163 | /// |
164 | /// Upon receiving the spin-loop signal the processor can optimize its behavior by, |
165 | /// for example, saving power or switching hyper-threads. |
166 | /// |
167 | /// This function is different from [`thread::yield_now`] which directly |
168 | /// yields to the system's scheduler, whereas `spin_loop` does not interact |
169 | /// with the operating system. |
170 | /// |
171 | /// A common use case for `spin_loop` is implementing bounded optimistic |
172 | /// spinning in a CAS loop in synchronization primitives. To avoid problems |
173 | /// like priority inversion, it is strongly recommended that the spin loop is |
174 | /// terminated after a finite amount of iterations and an appropriate blocking |
175 | /// syscall is made. |
176 | /// |
177 | /// **Note**: On platforms that do not support receiving spin-loop hints this |
178 | /// function does not do anything at all. |
179 | /// |
180 | /// # Examples |
181 | /// |
182 | /// ``` |
183 | /// use std::sync::atomic::{AtomicBool, Ordering}; |
184 | /// use std::sync::Arc; |
185 | /// use std::{hint, thread}; |
186 | /// |
187 | /// // A shared atomic value that threads will use to coordinate |
188 | /// let live = Arc::new(AtomicBool::new(false)); |
189 | /// |
190 | /// // In a background thread we'll eventually set the value |
191 | /// let bg_work = { |
192 | /// let live = live.clone(); |
193 | /// thread::spawn(move || { |
194 | /// // Do some work, then make the value live |
195 | /// do_some_work(); |
196 | /// live.store(true, Ordering::Release); |
197 | /// }) |
198 | /// }; |
199 | /// |
200 | /// // Back on our current thread, we wait for the value to be set |
201 | /// while !live.load(Ordering::Acquire) { |
202 | /// // The spin loop is a hint to the CPU that we're waiting, but probably |
203 | /// // not for very long |
204 | /// hint::spin_loop(); |
205 | /// } |
206 | /// |
207 | /// // The value is now set |
208 | /// # fn do_some_work() {} |
209 | /// do_some_work(); |
210 | /// bg_work.join()?; |
211 | /// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(()) |
212 | /// ``` |
213 | /// |
214 | /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html |
215 | #[inline (always)] |
216 | #[stable (feature = "renamed_spin_loop" , since = "1.49.0" )] |
217 | pub fn spin_loop() { |
218 | #[cfg (target_arch = "x86" )] |
219 | { |
220 | // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. |
221 | unsafe { crate::arch::x86::_mm_pause() }; |
222 | } |
223 | |
224 | #[cfg (target_arch = "x86_64" )] |
225 | { |
226 | // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. |
227 | unsafe { crate::arch::x86_64::_mm_pause() }; |
228 | } |
229 | |
230 | #[cfg (target_arch = "riscv32" )] |
231 | { |
232 | crate::arch::riscv32::pause(); |
233 | } |
234 | |
235 | #[cfg (target_arch = "riscv64" )] |
236 | { |
237 | crate::arch::riscv64::pause(); |
238 | } |
239 | |
240 | #[cfg (any(target_arch = "aarch64" , target_arch = "arm64ec" ))] |
241 | { |
242 | // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. |
243 | unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; |
244 | } |
245 | |
246 | #[cfg (all(target_arch = "arm" , target_feature = "v6" ))] |
247 | { |
248 | // SAFETY: the `cfg` attr ensures that we only execute this on arm targets |
249 | // with support for the v6 feature. |
250 | unsafe { crate::arch::arm::__yield() }; |
251 | } |
252 | } |
253 | |
254 | /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what |
255 | /// `black_box` could do. |
256 | /// |
257 | /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can |
258 | /// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined |
259 | /// behavior in the calling code. This property makes `black_box` useful for writing code in which |
260 | /// certain optimizations are not desired, such as benchmarks. |
261 | /// |
262 | /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The |
263 | /// extent to which it can block optimisations may vary depending upon the platform and code-gen |
264 | /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the |
265 | /// identity function. As such, it **must not be relied upon to control critical program behavior.** |
266 | /// This _immediately_ precludes any direct use of this function for cryptographic or security |
267 | /// purposes. |
268 | /// |
269 | /// [`std::convert::identity`]: crate::convert::identity |
270 | /// |
271 | /// # When is this useful? |
272 | /// |
273 | /// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be |
274 | /// relied upon for benchmarking, and should be used there. It will try to ensure that the |
275 | /// compiler doesn't optimize away part of the intended test code based on context. For |
276 | /// example: |
277 | /// |
278 | /// ``` |
279 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
280 | /// haystack.iter().any(|x| x == &needle) |
281 | /// } |
282 | /// |
283 | /// pub fn benchmark() { |
284 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
285 | /// let needle = "ghi" ; |
286 | /// for _ in 0..10 { |
287 | /// contains(&haystack, needle); |
288 | /// } |
289 | /// } |
290 | /// ``` |
291 | /// |
292 | /// The compiler could theoretically make optimizations like the following: |
293 | /// |
294 | /// - The `needle` and `haystack` do not change, move the call to `contains` outside the loop and |
295 | /// delete the loop |
296 | /// - Inline `contains` |
297 | /// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove |
298 | /// the call and replace with `true` |
299 | /// - Nothing is done with the result of `contains`: delete this function call entirely |
300 | /// - `benchmark` now has no purpose: delete this function |
301 | /// |
302 | /// It is not likely that all of the above happens, but the compiler is definitely able to make some |
303 | /// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes |
304 | /// in: |
305 | /// |
306 | /// ``` |
307 | /// use std::hint::black_box; |
308 | /// |
309 | /// // Same `contains` function |
310 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
311 | /// haystack.iter().any(|x| x == &needle) |
312 | /// } |
313 | /// |
314 | /// pub fn benchmark() { |
315 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
316 | /// let needle = "ghi" ; |
317 | /// for _ in 0..10 { |
318 | /// // Adjust our benchmark loop contents |
319 | /// black_box(contains(black_box(&haystack), black_box(needle))); |
320 | /// } |
321 | /// } |
322 | /// ``` |
323 | /// |
324 | /// This essentially tells the compiler to block optimizations across any calls to `black_box`. So, |
325 | /// it now: |
326 | /// |
327 | /// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be |
328 | /// optimized based on argument values |
329 | /// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot |
330 | /// optimize this away |
331 | /// |
332 | /// This makes our benchmark much more realistic to how the function would actually be used, where |
333 | /// arguments are usually not known at compile time and the result is used in some way. |
334 | #[inline ] |
335 | #[stable (feature = "bench_black_box" , since = "1.66.0" )] |
336 | #[rustc_const_unstable (feature = "const_black_box" , issue = "none" )] |
337 | pub const fn black_box<T>(dummy: T) -> T { |
338 | crate::intrinsics::black_box(dummy) |
339 | } |
340 | |
341 | /// An identity function that causes an `unused_must_use` warning to be |
342 | /// triggered if the given value is not used (returned, stored in a variable, |
343 | /// etc) by the caller. |
344 | /// |
345 | /// This is primarily intended for use in macro-generated code, in which a |
346 | /// [`#[must_use]` attribute][must_use] either on a type or a function would not |
347 | /// be convenient. |
348 | /// |
349 | /// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute |
350 | /// |
351 | /// # Example |
352 | /// |
353 | /// ``` |
354 | /// #![feature(hint_must_use)] |
355 | /// |
356 | /// use core::fmt; |
357 | /// |
358 | /// pub struct Error(/* ... */); |
359 | /// |
360 | /// #[macro_export] |
361 | /// macro_rules! make_error { |
362 | /// ($($args:expr),*) => { |
363 | /// core::hint::must_use({ |
364 | /// let error = $crate::make_error(core::format_args!($($args),*)); |
365 | /// error |
366 | /// }) |
367 | /// }; |
368 | /// } |
369 | /// |
370 | /// // Implementation detail of make_error! macro. |
371 | /// #[doc(hidden)] |
372 | /// pub fn make_error(args: fmt::Arguments<'_>) -> Error { |
373 | /// Error(/* ... */) |
374 | /// } |
375 | /// |
376 | /// fn demo() -> Option<Error> { |
377 | /// if true { |
378 | /// // Oops, meant to write `return Some(make_error!("..."));` |
379 | /// Some(make_error!("..." )); |
380 | /// } |
381 | /// None |
382 | /// } |
383 | /// # |
384 | /// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works |
385 | /// # fn main() {} |
386 | /// ``` |
387 | /// |
388 | /// In the above example, we'd like an `unused_must_use` lint to apply to the |
389 | /// value created by `make_error!`. However, neither `#[must_use]` on a struct |
390 | /// nor `#[must_use]` on a function is appropriate here, so the macro expands |
391 | /// using `core::hint::must_use` instead. |
392 | /// |
393 | /// - We wouldn't want `#[must_use]` on the `struct Error` because that would |
394 | /// make the following unproblematic code trigger a warning: |
395 | /// |
396 | /// ``` |
397 | /// # struct Error; |
398 | /// # |
399 | /// fn f(arg: &str) -> Result<(), Error> |
400 | /// # { Ok(()) } |
401 | /// |
402 | /// #[test] |
403 | /// fn t() { |
404 | /// // Assert that `f` returns error if passed an empty string. |
405 | /// // A value of type `Error` is unused here but that's not a problem. |
406 | /// f("" ).unwrap_err(); |
407 | /// } |
408 | /// ``` |
409 | /// |
410 | /// - Using `#[must_use]` on `fn make_error` can't help because the return value |
411 | /// *is* used, as the right-hand side of a `let` statement. The `let` |
412 | /// statement looks useless but is in fact necessary for ensuring that |
413 | /// temporaries within the `format_args` expansion are not kept alive past the |
414 | /// creation of the `Error`, as keeping them alive past that point can cause |
415 | /// autotrait issues in async code: |
416 | /// |
417 | /// ``` |
418 | /// # #![feature(hint_must_use)] |
419 | /// # |
420 | /// # struct Error; |
421 | /// # |
422 | /// # macro_rules! make_error { |
423 | /// # ($($args:expr),*) => { |
424 | /// # core::hint::must_use({ |
425 | /// # // If `let` isn't used, then `f()` produces a non-Send future. |
426 | /// # let error = make_error(core::format_args!($($args),*)); |
427 | /// # error |
428 | /// # }) |
429 | /// # }; |
430 | /// # } |
431 | /// # |
432 | /// # fn make_error(args: core::fmt::Arguments<'_>) -> Error { |
433 | /// # Error |
434 | /// # } |
435 | /// # |
436 | /// async fn f() { |
437 | /// // Using `let` inside the make_error expansion causes temporaries like |
438 | /// // `unsync()` to drop at the semicolon of that `let` statement, which |
439 | /// // is prior to the await point. They would otherwise stay around until |
440 | /// // the semicolon on *this* statement, which is after the await point, |
441 | /// // and the enclosing Future would not implement Send. |
442 | /// log(make_error!("look: {:p}" , unsync())).await; |
443 | /// } |
444 | /// |
445 | /// async fn log(error: Error) {/* ... */} |
446 | /// |
447 | /// // Returns something without a Sync impl. |
448 | /// fn unsync() -> *const () { |
449 | /// 0 as *const () |
450 | /// } |
451 | /// # |
452 | /// # fn test() { |
453 | /// # fn assert_send(_: impl Send) {} |
454 | /// # assert_send(f()); |
455 | /// # } |
456 | /// ``` |
457 | #[unstable (feature = "hint_must_use" , issue = "94745" )] |
458 | #[rustc_const_unstable (feature = "hint_must_use" , issue = "94745" )] |
459 | #[must_use ] // <-- :) |
460 | #[inline (always)] |
461 | pub const fn must_use<T>(value: T) -> T { |
462 | value |
463 | } |
464 | |