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