core/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//! Hints may be compile time or runtime.
6
7use crate::mem::MaybeUninit;
8use crate::{intrinsics, ub_checks};
9
10/// Informs the compiler that the site which is calling this function is not
11/// reachable, possibly enabling further optimizations.
12///
13/// # Safety
14///
15/// Reaching this function is *Undefined Behavior*.
16///
17/// As the compiler assumes that all forms of Undefined Behavior can never
18/// happen, it will eliminate all branches in the surrounding code that it can
19/// determine will invariably lead to a call to `unreachable_unchecked()`.
20///
21/// If the assumptions embedded in using this function turn out to be wrong -
22/// that is, if the site which is calling `unreachable_unchecked()` is actually
23/// reachable at runtime - the compiler may have generated nonsensical machine
24/// instructions for this situation, including in seemingly unrelated code,
25/// causing difficult-to-debug problems.
26///
27/// Use this function sparingly. Consider using the [`unreachable!`] macro,
28/// which may prevent some optimizations but will safely panic in case it is
29/// actually reached at runtime. Benchmark your code to find out if using
30/// `unreachable_unchecked()` comes with a performance benefit.
31///
32/// # Examples
33///
34/// `unreachable_unchecked()` can be used in situations where the compiler
35/// can't prove invariants that were previously established. Such situations
36/// have a higher chance of occurring if those invariants are upheld by
37/// external code that the compiler can't analyze.
38/// ```
39/// fn prepare_inputs(divisors: &mut Vec<u32>) {
40/// // Note to future-self when making changes: The invariant established
41/// // here is NOT checked in `do_computation()`; if this changes, you HAVE
42/// // to change `do_computation()`.
43/// divisors.retain(|divisor| *divisor != 0)
44/// }
45///
46/// /// # Safety
47/// /// All elements of `divisor` must be non-zero.
48/// unsafe fn do_computation(i: u32, divisors: &[u32]) -> u32 {
49/// divisors.iter().fold(i, |acc, divisor| {
50/// // Convince the compiler that a division by zero can't happen here
51/// // and a check is not needed below.
52/// if *divisor == 0 {
53/// // Safety: `divisor` can't be zero because of `prepare_inputs`,
54/// // but the compiler does not know about this. We *promise*
55/// // that we always call `prepare_inputs`.
56/// unsafe { std::hint::unreachable_unchecked() }
57/// }
58/// // The compiler would normally introduce a check here that prevents
59/// // a division by zero. However, if `divisor` was zero, the branch
60/// // above would reach what we explicitly marked as unreachable.
61/// // The compiler concludes that `divisor` can't be zero at this point
62/// // and removes the - now proven useless - check.
63/// acc / divisor
64/// })
65/// }
66///
67/// let mut divisors = vec![2, 0, 4];
68/// prepare_inputs(&mut divisors);
69/// let result = unsafe {
70/// // Safety: prepare_inputs() guarantees that divisors is non-zero
71/// do_computation(100, &divisors)
72/// };
73/// assert_eq!(result, 12);
74///
75/// ```
76///
77/// While using `unreachable_unchecked()` is perfectly sound in the following
78/// example, as the compiler is able to prove that a division by zero is not
79/// possible, benchmarking reveals that `unreachable_unchecked()` provides
80/// no benefit over using [`unreachable!`], while the latter does not introduce
81/// the possibility of Undefined Behavior.
82///
83/// ```
84/// fn div_1(a: u32, b: u32) -> u32 {
85/// use std::hint::unreachable_unchecked;
86///
87/// // `b.saturating_add(1)` is always positive (not zero),
88/// // hence `checked_div` will never return `None`.
89/// // Therefore, the else branch is unreachable.
90/// a.checked_div(b.saturating_add(1))
91/// .unwrap_or_else(|| unsafe { unreachable_unchecked() })
92/// }
93///
94/// assert_eq!(div_1(7, 0), 7);
95/// assert_eq!(div_1(9, 1), 4);
96/// assert_eq!(div_1(11, u32::MAX), 0);
97/// ```
98#[inline]
99#[stable(feature = "unreachable", since = "1.27.0")]
100#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
101#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
102pub const unsafe fn unreachable_unchecked() -> ! {
103 ub_checks::assert_unsafe_precondition!(
104 check_language_ub,
105 "hint::unreachable_unchecked must never be reached",
106 () => false
107 );
108 // SAFETY: the safety contract for `intrinsics::unreachable` must
109 // be upheld by the caller.
110 unsafe { intrinsics::unreachable() }
111}
112
113/// Makes a *soundness* promise to the compiler that `cond` holds.
114///
115/// This may allow the optimizer to simplify things, but it might also make the generated code
116/// slower. Either way, calling it will most likely make compilation take longer.
117///
118/// You may know this from other places as
119/// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C,
120/// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume).
121///
122/// This promotes a correctness requirement to a soundness requirement. Don't do that without
123/// very good reason.
124///
125/// # Usage
126///
127/// This is a situational tool for micro-optimization, and is allowed to do nothing. Any use
128/// should come with a repeatable benchmark to show the value, with the expectation to drop it
129/// later should the optimizer get smarter and no longer need it.
130///
131/// The more complicated the condition, the less likely this is to be useful. For example,
132/// `assert_unchecked(foo.is_sorted())` is a complex enough value that the compiler is unlikely
133/// to be able to take advantage of it.
134///
135/// There's also no need to `assert_unchecked` basic properties of things. For example, the
136/// compiler already knows the range of `count_ones`, so there is no benefit to
137/// `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`.
138///
139/// `assert_unchecked` is logically equivalent to `if !cond { unreachable_unchecked(); }`. If
140/// ever you are tempted to write `assert_unchecked(false)`, you should instead use
141/// [`unreachable_unchecked()`] directly.
142///
143/// # Safety
144///
145/// `cond` must be `true`. It is immediate UB to call this with `false`.
146///
147/// # Example
148///
149/// ```
150/// use core::hint;
151///
152/// /// # Safety
153/// ///
154/// /// `p` must be nonnull and valid
155/// pub unsafe fn next_value(p: *const i32) -> i32 {
156/// // SAFETY: caller invariants guarantee that `p` is not null
157/// unsafe { hint::assert_unchecked(!p.is_null()) }
158///
159/// if p.is_null() {
160/// return -1;
161/// } else {
162/// // SAFETY: caller invariants guarantee that `p` is valid
163/// unsafe { *p + 1 }
164/// }
165/// }
166/// ```
167///
168/// Without the `assert_unchecked`, the above function produces the following with optimizations
169/// enabled:
170///
171/// ```asm
172/// next_value:
173/// test rdi, rdi
174/// je .LBB0_1
175/// mov eax, dword ptr [rdi]
176/// inc eax
177/// ret
178/// .LBB0_1:
179/// mov eax, -1
180/// ret
181/// ```
182///
183/// Adding the assertion allows the optimizer to remove the extra check:
184///
185/// ```asm
186/// next_value:
187/// mov eax, dword ptr [rdi]
188/// inc eax
189/// ret
190/// ```
191///
192/// This example is quite unlike anything that would be used in the real world: it is redundant
193/// to put an assertion right next to code that checks the same thing, and dereferencing a
194/// pointer already has the builtin assumption that it is nonnull. However, it illustrates the
195/// kind of changes the optimizer can make even when the behavior is less obviously related.
196#[track_caller]
197#[inline(always)]
198#[doc(alias = "assume")]
199#[stable(feature = "hint_assert_unchecked", since = "1.81.0")]
200#[rustc_const_stable(feature = "hint_assert_unchecked", since = "1.81.0")]
201pub const unsafe fn assert_unchecked(cond: bool) {
202 // SAFETY: The caller promised `cond` is true.
203 unsafe {
204 ub_checks::assert_unsafe_precondition!(
205 check_language_ub,
206 "hint::assert_unchecked must never be called when the condition is false",
207 (cond: bool = cond) => cond,
208 );
209 crate::intrinsics::assume(cond);
210 }
211}
212
213/// Emits a machine instruction to signal the processor that it is running in
214/// a busy-wait spin-loop ("spin lock").
215///
216/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
217/// for example, saving power or switching hyper-threads.
218///
219/// This function is different from [`thread::yield_now`] which directly
220/// yields to the system's scheduler, whereas `spin_loop` does not interact
221/// with the operating system.
222///
223/// A common use case for `spin_loop` is implementing bounded optimistic
224/// spinning in a CAS loop in synchronization primitives. To avoid problems
225/// like priority inversion, it is strongly recommended that the spin loop is
226/// terminated after a finite amount of iterations and an appropriate blocking
227/// syscall is made.
228///
229/// **Note**: On platforms that do not support receiving spin-loop hints this
230/// function does not do anything at all.
231///
232/// # Examples
233///
234/// ```ignore-wasm
235/// use std::sync::atomic::{AtomicBool, Ordering};
236/// use std::sync::Arc;
237/// use std::{hint, thread};
238///
239/// // A shared atomic value that threads will use to coordinate
240/// let live = Arc::new(AtomicBool::new(false));
241///
242/// // In a background thread we'll eventually set the value
243/// let bg_work = {
244/// let live = live.clone();
245/// thread::spawn(move || {
246/// // Do some work, then make the value live
247/// do_some_work();
248/// live.store(true, Ordering::Release);
249/// })
250/// };
251///
252/// // Back on our current thread, we wait for the value to be set
253/// while !live.load(Ordering::Acquire) {
254/// // The spin loop is a hint to the CPU that we're waiting, but probably
255/// // not for very long
256/// hint::spin_loop();
257/// }
258///
259/// // The value is now set
260/// # fn do_some_work() {}
261/// do_some_work();
262/// bg_work.join()?;
263/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
264/// ```
265///
266/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
267#[inline(always)]
268#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
269pub fn spin_loop() {
270 #[cfg(target_arch = "x86")]
271 {
272 // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
273 unsafe { crate::arch::x86::_mm_pause() };
274 }
275
276 #[cfg(target_arch = "x86_64")]
277 {
278 // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
279 unsafe { crate::arch::x86_64::_mm_pause() };
280 }
281
282 #[cfg(target_arch = "riscv32")]
283 {
284 crate::arch::riscv32::pause();
285 }
286
287 #[cfg(target_arch = "riscv64")]
288 {
289 crate::arch::riscv64::pause();
290 }
291
292 #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
293 {
294 // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
295 unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
296 }
297
298 #[cfg(all(target_arch = "arm", target_feature = "v6"))]
299 {
300 // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
301 // with support for the v6 feature.
302 unsafe { crate::arch::arm::__yield() };
303 }
304}
305
306/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
307/// `black_box` could do.
308///
309/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
310/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
311/// behavior in the calling code. This property makes `black_box` useful for writing code in which
312/// certain optimizations are not desired, such as benchmarks.
313///
314/// <div class="warning">
315///
316/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
317/// extent to which it can block optimisations may vary depending upon the platform and code-gen
318/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
319/// identity function. As such, it **must not be relied upon to control critical program behavior.**
320/// This also means that this function does not offer any guarantees for cryptographic or security
321/// purposes.
322///
323/// This limitation is not specific to `black_box`; there is no mechanism in the entire Rust
324/// language that can provide the guarantees required for constant-time cryptography.
325/// (There is also no such mechanism in LLVM, so the same is true for every other LLVM-based compiler.)
326///
327/// </div>
328///
329/// [`std::convert::identity`]: crate::convert::identity
330///
331/// # When is this useful?
332///
333/// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be
334/// relied upon for benchmarking, and should be used there. It will try to ensure that the
335/// compiler doesn't optimize away part of the intended test code based on context. For
336/// example:
337///
338/// ```
339/// fn contains(haystack: &[&str], needle: &str) -> bool {
340/// haystack.iter().any(|x| x == &needle)
341/// }
342///
343/// pub fn benchmark() {
344/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
345/// let needle = "ghi";
346/// for _ in 0..10 {
347/// contains(&haystack, needle);
348/// }
349/// }
350/// ```
351///
352/// The compiler could theoretically make optimizations like the following:
353///
354/// - The `needle` and `haystack` do not change, move the call to `contains` outside the loop and
355/// delete the loop
356/// - Inline `contains`
357/// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove
358/// the call and replace with `true`
359/// - Nothing is done with the result of `contains`: delete this function call entirely
360/// - `benchmark` now has no purpose: delete this function
361///
362/// It is not likely that all of the above happens, but the compiler is definitely able to make some
363/// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes
364/// in:
365///
366/// ```
367/// use std::hint::black_box;
368///
369/// // Same `contains` function.
370/// fn contains(haystack: &[&str], needle: &str) -> bool {
371/// haystack.iter().any(|x| x == &needle)
372/// }
373///
374/// pub fn benchmark() {
375/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
376/// let needle = "ghi";
377/// for _ in 0..10 {
378/// // Force the compiler to run `contains`, even though it is a pure function whose
379/// // results are unused.
380/// black_box(contains(
381/// // Prevent the compiler from making assumptions about the input.
382/// black_box(&haystack),
383/// black_box(needle),
384/// ));
385/// }
386/// }
387/// ```
388///
389/// This essentially tells the compiler to block optimizations across any calls to `black_box`. So,
390/// it now:
391///
392/// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be
393/// optimized based on argument values
394/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
395/// optimize this away
396///
397/// This makes our benchmark much more realistic to how the function would actually be used, where
398/// arguments are usually not known at compile time and the result is used in some way.
399///
400/// # How to use this
401///
402/// In practice, `black_box` serves two purposes:
403///
404/// 1. It prevents the compiler from making optimizations related to the value returned by `black_box`
405/// 2. It forces the value passed to `black_box` to be calculated, even if the return value of `black_box` is unused
406///
407/// ```
408/// use std::hint::black_box;
409///
410/// let zero = 0;
411/// let five = 5;
412///
413/// // The compiler will see this and remove the `* five` call, because it knows that multiplying
414/// // any integer by 0 will result in 0.
415/// let c = zero * five;
416///
417/// // Adding `black_box` here disables the compiler's ability to reason about the first operand in the multiplication.
418/// // It is forced to assume that it can be any possible number, so it cannot remove the `* five`
419/// // operation.
420/// let c = black_box(zero) * five;
421/// ```
422///
423/// While most cases will not be as clear-cut as the above example, it still illustrates how
424/// `black_box` can be used. When benchmarking a function, you usually want to wrap its inputs in
425/// `black_box` so the compiler cannot make optimizations that would be unrealistic in real-life
426/// use.
427///
428/// ```
429/// use std::hint::black_box;
430///
431/// // This is a simple function that increments its input by 1. Note that it is pure, meaning it
432/// // has no side-effects. This function has no effect if its result is unused. (An example of a
433/// // function *with* side-effects is `println!()`.)
434/// fn increment(x: u8) -> u8 {
435/// x + 1
436/// }
437///
438/// // Here, we call `increment` but discard its result. The compiler, seeing this and knowing that
439/// // `increment` is pure, will eliminate this function call entirely. This may not be desired,
440/// // though, especially if we're trying to track how much time `increment` takes to execute.
441/// let _ = increment(black_box(5));
442///
443/// // Here, we force `increment` to be executed. This is because the compiler treats `black_box`
444/// // as if it has side-effects, and thus must compute its input.
445/// let _ = black_box(increment(black_box(5)));
446/// ```
447///
448/// There may be additional situations where you want to wrap the result of a function in
449/// `black_box` to force its execution. This is situational though, and may not have any effect
450/// (such as when the function returns a zero-sized type such as [`()` unit][unit]).
451///
452/// Note that `black_box` has no effect on how its input is treated, only its output. As such,
453/// expressions passed to `black_box` may still be optimized:
454///
455/// ```
456/// use std::hint::black_box;
457///
458/// // The compiler sees this...
459/// let y = black_box(5 * 10);
460///
461/// // ...as this. As such, it will likely simplify `5 * 10` to just `50`.
462/// let _0 = 5 * 10;
463/// let y = black_box(_0);
464/// ```
465///
466/// In the above example, the `5 * 10` expression is considered distinct from the `black_box` call,
467/// and thus is still optimized by the compiler. You can prevent this by moving the multiplication
468/// operation outside of `black_box`:
469///
470/// ```
471/// use std::hint::black_box;
472///
473/// // No assumptions can be made about either operand, so the multiplication is not optimized out.
474/// let y = black_box(5) * black_box(10);
475/// ```
476///
477/// During constant evaluation, `black_box` is treated as a no-op.
478#[inline]
479#[stable(feature = "bench_black_box", since = "1.66.0")]
480#[rustc_const_stable(feature = "const_black_box", since = "1.86.0")]
481pub const fn black_box<T>(dummy: T) -> T {
482 crate::intrinsics::black_box(dummy)
483}
484
485/// An identity function that causes an `unused_must_use` warning to be
486/// triggered if the given value is not used (returned, stored in a variable,
487/// etc) by the caller.
488///
489/// This is primarily intended for use in macro-generated code, in which a
490/// [`#[must_use]` attribute][must_use] either on a type or a function would not
491/// be convenient.
492///
493/// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
494///
495/// # Example
496///
497/// ```
498/// #![feature(hint_must_use)]
499///
500/// use core::fmt;
501///
502/// pub struct Error(/* ... */);
503///
504/// #[macro_export]
505/// macro_rules! make_error {
506/// ($($args:expr),*) => {
507/// core::hint::must_use({
508/// let error = $crate::make_error(core::format_args!($($args),*));
509/// error
510/// })
511/// };
512/// }
513///
514/// // Implementation detail of make_error! macro.
515/// #[doc(hidden)]
516/// pub fn make_error(args: fmt::Arguments<'_>) -> Error {
517/// Error(/* ... */)
518/// }
519///
520/// fn demo() -> Option<Error> {
521/// if true {
522/// // Oops, meant to write `return Some(make_error!("..."));`
523/// Some(make_error!("..."));
524/// }
525/// None
526/// }
527/// #
528/// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works
529/// # fn main() {}
530/// ```
531///
532/// In the above example, we'd like an `unused_must_use` lint to apply to the
533/// value created by `make_error!`. However, neither `#[must_use]` on a struct
534/// nor `#[must_use]` on a function is appropriate here, so the macro expands
535/// using `core::hint::must_use` instead.
536///
537/// - We wouldn't want `#[must_use]` on the `struct Error` because that would
538/// make the following unproblematic code trigger a warning:
539///
540/// ```
541/// # struct Error;
542/// #
543/// fn f(arg: &str) -> Result<(), Error>
544/// # { Ok(()) }
545///
546/// #[test]
547/// fn t() {
548/// // Assert that `f` returns error if passed an empty string.
549/// // A value of type `Error` is unused here but that's not a problem.
550/// f("").unwrap_err();
551/// }
552/// ```
553///
554/// - Using `#[must_use]` on `fn make_error` can't help because the return value
555/// *is* used, as the right-hand side of a `let` statement. The `let`
556/// statement looks useless but is in fact necessary for ensuring that
557/// temporaries within the `format_args` expansion are not kept alive past the
558/// creation of the `Error`, as keeping them alive past that point can cause
559/// autotrait issues in async code:
560///
561/// ```
562/// # #![feature(hint_must_use)]
563/// #
564/// # struct Error;
565/// #
566/// # macro_rules! make_error {
567/// # ($($args:expr),*) => {
568/// # core::hint::must_use({
569/// # // If `let` isn't used, then `f()` produces a non-Send future.
570/// # let error = make_error(core::format_args!($($args),*));
571/// # error
572/// # })
573/// # };
574/// # }
575/// #
576/// # fn make_error(args: core::fmt::Arguments<'_>) -> Error {
577/// # Error
578/// # }
579/// #
580/// async fn f() {
581/// // Using `let` inside the make_error expansion causes temporaries like
582/// // `unsync()` to drop at the semicolon of that `let` statement, which
583/// // is prior to the await point. They would otherwise stay around until
584/// // the semicolon on *this* statement, which is after the await point,
585/// // and the enclosing Future would not implement Send.
586/// log(make_error!("look: {:p}", unsync())).await;
587/// }
588///
589/// async fn log(error: Error) {/* ... */}
590///
591/// // Returns something without a Sync impl.
592/// fn unsync() -> *const () {
593/// 0 as *const ()
594/// }
595/// #
596/// # fn test() {
597/// # fn assert_send(_: impl Send) {}
598/// # assert_send(f());
599/// # }
600/// ```
601#[unstable(feature = "hint_must_use", issue = "94745")]
602#[must_use] // <-- :)
603#[inline(always)]
604pub const fn must_use<T>(value: T) -> T {
605 value
606}
607
608/// Hints to the compiler that a branch condition is likely to be true.
609/// Returns the value passed to it.
610///
611/// It can be used with `if` or boolean `match` expressions.
612///
613/// When used outside of a branch condition, it may still influence a nearby branch, but
614/// probably will not have any effect.
615///
616/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to
617/// compound expressions, such as `likely(a && b)`. When applied to compound expressions, it has
618/// the following effect:
619/// ```text
620/// likely(!a) => !unlikely(a)
621/// likely(a && b) => likely(a) && likely(b)
622/// likely(a || b) => a || likely(b)
623/// ```
624///
625/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code.
626///
627/// # Examples
628///
629/// ```
630/// #![feature(likely_unlikely)]
631/// use core::hint::likely;
632///
633/// fn foo(x: i32) {
634/// if likely(x > 0) {
635/// println!("this branch is likely to be taken");
636/// } else {
637/// println!("this branch is unlikely to be taken");
638/// }
639///
640/// match likely(x > 0) {
641/// true => println!("this branch is likely to be taken"),
642/// false => println!("this branch is unlikely to be taken"),
643/// }
644///
645/// // Use outside of a branch condition may still influence a nearby branch
646/// let cond = likely(x != 0);
647/// if cond {
648/// println!("this branch is likely to be taken");
649/// }
650/// }
651/// ```
652///
653///
654#[unstable(feature = "likely_unlikely", issue = "136873")]
655#[inline(always)]
656pub const fn likely(b: bool) -> bool {
657 crate::intrinsics::likely(b)
658}
659
660/// Hints to the compiler that a branch condition is unlikely to be true.
661/// Returns the value passed to it.
662///
663/// It can be used with `if` or boolean `match` expressions.
664///
665/// When used outside of a branch condition, it may still influence a nearby branch, but
666/// probably will not have any effect.
667///
668/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to
669/// compound expressions, such as `unlikely(a && b)`. When applied to compound expressions, it has
670/// the following effect:
671/// ```text
672/// unlikely(!a) => !likely(a)
673/// unlikely(a && b) => a && unlikely(b)
674/// unlikely(a || b) => unlikely(a) || unlikely(b)
675/// ```
676///
677/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code.
678///
679/// # Examples
680///
681/// ```
682/// #![feature(likely_unlikely)]
683/// use core::hint::unlikely;
684///
685/// fn foo(x: i32) {
686/// if unlikely(x > 0) {
687/// println!("this branch is unlikely to be taken");
688/// } else {
689/// println!("this branch is likely to be taken");
690/// }
691///
692/// match unlikely(x > 0) {
693/// true => println!("this branch is unlikely to be taken"),
694/// false => println!("this branch is likely to be taken"),
695/// }
696///
697/// // Use outside of a branch condition may still influence a nearby branch
698/// let cond = unlikely(x != 0);
699/// if cond {
700/// println!("this branch is likely to be taken");
701/// }
702/// }
703/// ```
704#[unstable(feature = "likely_unlikely", issue = "136873")]
705#[inline(always)]
706pub const fn unlikely(b: bool) -> bool {
707 crate::intrinsics::unlikely(b)
708}
709
710/// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may
711/// choose to optimize paths that are not cold at the expense of paths that are cold.
712///
713/// # Examples
714///
715/// ```
716/// #![feature(cold_path)]
717/// use core::hint::cold_path;
718///
719/// fn foo(x: &[i32]) {
720/// if let Some(first) = x.get(0) {
721/// // this is the fast path
722/// } else {
723/// // this path is unlikely
724/// cold_path();
725/// }
726/// }
727///
728/// fn bar(x: i32) -> i32 {
729/// match x {
730/// 1 => 10,
731/// 2 => 100,
732/// 3 => { cold_path(); 1000 }, // this branch is unlikely
733/// _ => { cold_path(); 10000 }, // this is also unlikely
734/// }
735/// }
736/// ```
737#[unstable(feature = "cold_path", issue = "136873")]
738#[inline(always)]
739pub const fn cold_path() {
740 crate::intrinsics::cold_path()
741}
742
743/// Returns either `true_val` or `false_val` depending on the value of
744/// `condition`, with a hint to the compiler that `condition` is unlikely to be
745/// correctly predicted by a CPU’s branch predictor.
746///
747/// This method is functionally equivalent to
748/// ```ignore (this is just for illustrative purposes)
749/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
750/// if b { true_val } else { false_val }
751/// }
752/// ```
753/// but might generate different assembly. In particular, on platforms with
754/// a conditional move or select instruction (like `cmov` on x86 or `csel`
755/// on ARM) the optimizer might use these instructions to avoid branches,
756/// which can benefit performance if the branch predictor is struggling
757/// with predicting `condition`, such as in an implementation of binary
758/// search.
759///
760/// Note however that this lowering is not guaranteed (on any platform) and
761/// should not be relied upon when trying to write cryptographic constant-time
762/// code. Also be aware that this lowering might *decrease* performance if
763/// `condition` is well-predictable. It is advisable to perform benchmarks to
764/// tell if this function is useful.
765///
766/// # Examples
767///
768/// Distribute values evenly between two buckets:
769/// ```
770/// use std::hash::BuildHasher;
771/// use std::hint;
772///
773/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
774/// let hash = hasher.hash_one(&v);
775/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two);
776/// bucket.push(v);
777/// }
778/// # let hasher = std::collections::hash_map::RandomState::new();
779/// # let mut bucket_one = Vec::new();
780/// # let mut bucket_two = Vec::new();
781/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
782/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
783/// ```
784#[inline(always)]
785#[stable(feature = "select_unpredictable", since = "1.88.0")]
786pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T {
787 // FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
788 // Change this to use ManuallyDrop instead.
789 let mut true_val = MaybeUninit::new(true_val);
790 let mut false_val = MaybeUninit::new(false_val);
791 // SAFETY: The value that is not selected is dropped, and the selected one
792 // is returned. This is necessary because the intrinsic doesn't drop the
793 // value that is not selected.
794 unsafe {
795 crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
796 .assume_init_drop();
797 crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
798 }
799}