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
6use crate::intrinsics;
7use 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
101pub 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")]
149pub 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")]
217pub 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")]
337pub 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)]
461pub const fn must_use<T>(value: T) -> T {
462 value
463}
464