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