]> git.lizzy.rs Git - rust.git/blob - src/libcore/hint.rs
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
[rust.git] / src / libcore / hint.rs
1 #![stable(feature = "core_hint", since = "1.27.0")]
2
3 //! Hints to compiler that affects how code should be emitted or optimized.
4
5 use intrinsics;
6
7 /// Informs the compiler that this point in the code is not reachable, enabling
8 /// further optimizations.
9 ///
10 /// # Safety
11 ///
12 /// Reaching this function is completely *undefined behavior* (UB). In
13 /// particular, the compiler assumes that all UB must never happen, and
14 /// therefore will eliminate all branches that reach to a call to
15 /// `unreachable_unchecked()`.
16 ///
17 /// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
18 /// `unreachable_unchecked()` call is actually reachable among all possible
19 /// control flow, the compiler will apply the wrong optimization strategy, and
20 /// may sometimes even corrupt seemingly unrelated code, causing
21 /// difficult-to-debug problems.
22 ///
23 /// Use this function only when you can prove that the code will never call it.
24 ///
25 /// The [`unreachable!()`] macro is the safe counterpart of this function, which
26 /// will panic instead when executed.
27 ///
28 /// [`unreachable!()`]: ../macro.unreachable.html
29 ///
30 /// # Example
31 ///
32 /// ```
33 /// fn div_1(a: u32, b: u32) -> u32 {
34 ///     use std::hint::unreachable_unchecked;
35 ///
36 ///     // `b.saturating_add(1)` is always positive (not zero),
37 ///     // hence `checked_div` will never return None.
38 ///     // Therefore, the else branch is unreachable.
39 ///     a.checked_div(b.saturating_add(1))
40 ///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
41 /// }
42 ///
43 /// assert_eq!(div_1(7, 0), 7);
44 /// assert_eq!(div_1(9, 1), 4);
45 /// assert_eq!(div_1(11, std::u32::MAX), 0);
46 /// ```
47 #[inline]
48 #[stable(feature = "unreachable", since = "1.27.0")]
49 pub unsafe fn unreachable_unchecked() -> ! {
50     intrinsics::unreachable()
51 }
52
53 /// Save power or switch hyperthreads in a busy-wait spin-loop.
54 ///
55 /// This function is deliberately more primitive than
56 /// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
57 /// does not directly yield to the system's scheduler.
58 /// In some cases it might be useful to use a combination of both functions.
59 /// Careful benchmarking is advised.
60 ///
61 /// On some platforms this function may not do anything at all.
62 #[inline]
63 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
64 pub fn spin_loop() {
65     #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
66     unsafe {
67         asm!("pause" ::: "memory" : "volatile");
68     }
69
70     #[cfg(target_arch = "aarch64")]
71     unsafe {
72         asm!("yield" ::: "memory" : "volatile");
73     }
74 }