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 |
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 | /// Makes a *soundness* promise to the compiler that `cond` holds. |
110 | /// |
111 | /// This may allow the optimizer to simplify things, |
112 | /// but it might also make the generated code slower. |
113 | /// Either way, calling it will most likely make compilation take longer. |
114 | /// |
115 | /// This is a situational tool for micro-optimization, and is allowed to do nothing. |
116 | /// Any use should come with a repeatable benchmark to show the value |
117 | /// and allow removing it later should the optimizer get smarter and no longer need it. |
118 | /// |
119 | /// The more complicated the condition the less likely this is to be fruitful. |
120 | /// For example, `assert_unchecked(foo.is_sorted())` is a complex enough value |
121 | /// that the compiler is unlikely to be able to take advantage of it. |
122 | /// |
123 | /// There's also no need to `assert_unchecked` basic properties of things. For |
124 | /// example, the compiler already knows the range of `count_ones`, so there's no |
125 | /// benefit to `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`. |
126 | /// |
127 | /// If ever you're tempted to write `assert_unchecked(false)`, then you're |
128 | /// actually looking for [`unreachable_unchecked()`]. |
129 | /// |
130 | /// You may know this from other places |
131 | /// as [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) |
132 | /// or [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume). |
133 | /// |
134 | /// This promotes a correctness requirement to a soundness requirement. |
135 | /// Don't do that without very good reason. |
136 | /// |
137 | /// # Safety |
138 | /// |
139 | /// `cond` must be `true`. It's immediate UB to call this with `false`. |
140 | /// |
141 | #[inline (always)] |
142 | #[doc (alias = "assume" )] |
143 | #[track_caller ] |
144 | #[unstable (feature = "hint_assert_unchecked" , issue = "119131" )] |
145 | #[rustc_const_unstable (feature = "const_hint_assert_unchecked" , issue = "119131" )] |
146 | pub const unsafe fn assert_unchecked(cond: bool) { |
147 | // SAFETY: The caller promised `cond` is true. |
148 | unsafe { |
149 | intrinsics::assert_unsafe_precondition!( |
150 | "hint::assert_unchecked must never be called when the condition is false" , |
151 | (cond: bool) => cond, |
152 | ); |
153 | crate::intrinsics::assume(cond); |
154 | } |
155 | } |
156 | |
157 | /// Emits a machine instruction to signal the processor that it is running in |
158 | /// a busy-wait spin-loop ("spin lock"). |
159 | /// |
160 | /// Upon receiving the spin-loop signal the processor can optimize its behavior by, |
161 | /// for example, saving power or switching hyper-threads. |
162 | /// |
163 | /// This function is different from [`thread::yield_now`] which directly |
164 | /// yields to the system's scheduler, whereas `spin_loop` does not interact |
165 | /// with the operating system. |
166 | /// |
167 | /// A common use case for `spin_loop` is implementing bounded optimistic |
168 | /// spinning in a CAS loop in synchronization primitives. To avoid problems |
169 | /// like priority inversion, it is strongly recommended that the spin loop is |
170 | /// terminated after a finite amount of iterations and an appropriate blocking |
171 | /// syscall is made. |
172 | /// |
173 | /// **Note**: On platforms that do not support receiving spin-loop hints this |
174 | /// function does not do anything at all. |
175 | /// |
176 | /// # Examples |
177 | /// |
178 | /// ``` |
179 | /// use std::sync::atomic::{AtomicBool, Ordering}; |
180 | /// use std::sync::Arc; |
181 | /// use std::{hint, thread}; |
182 | /// |
183 | /// // A shared atomic value that threads will use to coordinate |
184 | /// let live = Arc::new(AtomicBool::new(false)); |
185 | /// |
186 | /// // In a background thread we'll eventually set the value |
187 | /// let bg_work = { |
188 | /// let live = live.clone(); |
189 | /// thread::spawn(move || { |
190 | /// // Do some work, then make the value live |
191 | /// do_some_work(); |
192 | /// live.store(true, Ordering::Release); |
193 | /// }) |
194 | /// }; |
195 | /// |
196 | /// // Back on our current thread, we wait for the value to be set |
197 | /// while !live.load(Ordering::Acquire) { |
198 | /// // The spin loop is a hint to the CPU that we're waiting, but probably |
199 | /// // not for very long |
200 | /// hint::spin_loop(); |
201 | /// } |
202 | /// |
203 | /// // The value is now set |
204 | /// # fn do_some_work() {} |
205 | /// do_some_work(); |
206 | /// bg_work.join()?; |
207 | /// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(()) |
208 | /// ``` |
209 | /// |
210 | /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html |
211 | #[inline (always)] |
212 | #[stable (feature = "renamed_spin_loop" , since = "1.49.0" )] |
213 | pub fn spin_loop() { |
214 | #[cfg (target_arch = "x86" )] |
215 | { |
216 | // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. |
217 | unsafe { crate::arch::x86::_mm_pause() }; |
218 | } |
219 | |
220 | #[cfg (target_arch = "x86_64" )] |
221 | { |
222 | // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. |
223 | unsafe { crate::arch::x86_64::_mm_pause() }; |
224 | } |
225 | |
226 | #[cfg (target_arch = "riscv32" )] |
227 | { |
228 | crate::arch::riscv32::pause(); |
229 | } |
230 | |
231 | #[cfg (target_arch = "riscv64" )] |
232 | { |
233 | crate::arch::riscv64::pause(); |
234 | } |
235 | |
236 | #[cfg (target_arch = "aarch64" )] |
237 | { |
238 | // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. |
239 | unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; |
240 | } |
241 | |
242 | #[cfg (all(target_arch = "arm" , target_feature = "v6" ))] |
243 | { |
244 | // SAFETY: the `cfg` attr ensures that we only execute this on arm targets |
245 | // with support for the v6 feature. |
246 | unsafe { crate::arch::arm::__yield() }; |
247 | } |
248 | } |
249 | |
250 | /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what |
251 | /// `black_box` could do. |
252 | /// |
253 | /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can |
254 | /// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined |
255 | /// behavior in the calling code. This property makes `black_box` useful for writing code in which |
256 | /// certain optimizations are not desired, such as benchmarks. |
257 | /// |
258 | /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The |
259 | /// extent to which it can block optimisations may vary depending upon the platform and code-gen |
260 | /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the |
261 | /// identity function. As such, it **must not be relied upon to control critical program behavior.** |
262 | /// This _immediately_ precludes any direct use of this function for cryptographic or security |
263 | /// purposes. |
264 | /// |
265 | /// [`std::convert::identity`]: crate::convert::identity |
266 | /// |
267 | /// # When is this useful? |
268 | /// |
269 | /// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be |
270 | /// relied upon for benchmarking, and should be used there. It will try to ensure that the |
271 | /// compiler doesn't optimize away part of the intended test code based on context. For |
272 | /// example: |
273 | /// |
274 | /// ``` |
275 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
276 | /// haystack.iter().any(|x| x == &needle) |
277 | /// } |
278 | /// |
279 | /// pub fn benchmark() { |
280 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
281 | /// let needle = "ghi" ; |
282 | /// for _ in 0..10 { |
283 | /// contains(&haystack, needle); |
284 | /// } |
285 | /// } |
286 | /// ``` |
287 | /// |
288 | /// The compiler could theoretically make optimizations like the following: |
289 | /// |
290 | /// - The `needle` and `haystack` do not change, move the call to `contains` outside the loop and |
291 | /// delete the loop |
292 | /// - Inline `contains` |
293 | /// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove |
294 | /// the call and replace with `true` |
295 | /// - Nothing is done with the result of `contains`: delete this function call entirely |
296 | /// - `benchmark` now has no purpose: delete this function |
297 | /// |
298 | /// It is not likely that all of the above happens, but the compiler is definitely able to make some |
299 | /// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes |
300 | /// in: |
301 | /// |
302 | /// ``` |
303 | /// use std::hint::black_box; |
304 | /// |
305 | /// // Same `contains` function |
306 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
307 | /// haystack.iter().any(|x| x == &needle) |
308 | /// } |
309 | /// |
310 | /// pub fn benchmark() { |
311 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
312 | /// let needle = "ghi" ; |
313 | /// for _ in 0..10 { |
314 | /// // Adjust our benchmark loop contents |
315 | /// black_box(contains(black_box(&haystack), black_box(needle))); |
316 | /// } |
317 | /// } |
318 | /// ``` |
319 | /// |
320 | /// This essentially tells the compiler to block optimizations across any calls to `black_box`. So, |
321 | /// it now: |
322 | /// |
323 | /// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be |
324 | /// optimized based on argument values |
325 | /// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot |
326 | /// optimize this away |
327 | /// |
328 | /// This makes our benchmark much more realistic to how the function would actually be used, where |
329 | /// arguments are usually not known at compile time and the result is used in some way. |
330 | #[inline ] |
331 | #[stable (feature = "bench_black_box" , since = "1.66.0" )] |
332 | #[rustc_const_unstable (feature = "const_black_box" , issue = "none" )] |
333 | pub const fn black_box<T>(dummy: T) -> T { |
334 | crate::intrinsics::black_box(dummy) |
335 | } |
336 | |
337 | /// An identity function that causes an `unused_must_use` warning to be |
338 | /// triggered if the given value is not used (returned, stored in a variable, |
339 | /// etc) by the caller. |
340 | /// |
341 | /// This is primarily intended for use in macro-generated code, in which a |
342 | /// [`#[must_use]` attribute][must_use] either on a type or a function would not |
343 | /// be convenient. |
344 | /// |
345 | /// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute |
346 | /// |
347 | /// # Example |
348 | /// |
349 | /// ``` |
350 | /// #![feature(hint_must_use)] |
351 | /// |
352 | /// use core::fmt; |
353 | /// |
354 | /// pub struct Error(/* ... */); |
355 | /// |
356 | /// #[macro_export] |
357 | /// macro_rules! make_error { |
358 | /// ($($args:expr),*) => { |
359 | /// core::hint::must_use({ |
360 | /// let error = $crate::make_error(core::format_args!($($args),*)); |
361 | /// error |
362 | /// }) |
363 | /// }; |
364 | /// } |
365 | /// |
366 | /// // Implementation detail of make_error! macro. |
367 | /// #[doc(hidden)] |
368 | /// pub fn make_error(args: fmt::Arguments<'_>) -> Error { |
369 | /// Error(/* ... */) |
370 | /// } |
371 | /// |
372 | /// fn demo() -> Option<Error> { |
373 | /// if true { |
374 | /// // Oops, meant to write `return Some(make_error!("..."));` |
375 | /// Some(make_error!("..." )); |
376 | /// } |
377 | /// None |
378 | /// } |
379 | /// # |
380 | /// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works |
381 | /// # fn main() {} |
382 | /// ``` |
383 | /// |
384 | /// In the above example, we'd like an `unused_must_use` lint to apply to the |
385 | /// value created by `make_error!`. However, neither `#[must_use]` on a struct |
386 | /// nor `#[must_use]` on a function is appropriate here, so the macro expands |
387 | /// using `core::hint::must_use` instead. |
388 | /// |
389 | /// - We wouldn't want `#[must_use]` on the `struct Error` because that would |
390 | /// make the following unproblematic code trigger a warning: |
391 | /// |
392 | /// ``` |
393 | /// # struct Error; |
394 | /// # |
395 | /// fn f(arg: &str) -> Result<(), Error> |
396 | /// # { Ok(()) } |
397 | /// |
398 | /// #[test] |
399 | /// fn t() { |
400 | /// // Assert that `f` returns error if passed an empty string. |
401 | /// // A value of type `Error` is unused here but that's not a problem. |
402 | /// f("" ).unwrap_err(); |
403 | /// } |
404 | /// ``` |
405 | /// |
406 | /// - Using `#[must_use]` on `fn make_error` can't help because the return value |
407 | /// *is* used, as the right-hand side of a `let` statement. The `let` |
408 | /// statement looks useless but is in fact necessary for ensuring that |
409 | /// temporaries within the `format_args` expansion are not kept alive past the |
410 | /// creation of the `Error`, as keeping them alive past that point can cause |
411 | /// autotrait issues in async code: |
412 | /// |
413 | /// ``` |
414 | /// # #![feature(hint_must_use)] |
415 | /// # |
416 | /// # struct Error; |
417 | /// # |
418 | /// # macro_rules! make_error { |
419 | /// # ($($args:expr),*) => { |
420 | /// # core::hint::must_use({ |
421 | /// # // If `let` isn't used, then `f()` produces a non-Send future. |
422 | /// # let error = make_error(core::format_args!($($args),*)); |
423 | /// # error |
424 | /// # }) |
425 | /// # }; |
426 | /// # } |
427 | /// # |
428 | /// # fn make_error(args: core::fmt::Arguments<'_>) -> Error { |
429 | /// # Error |
430 | /// # } |
431 | /// # |
432 | /// async fn f() { |
433 | /// // Using `let` inside the make_error expansion causes temporaries like |
434 | /// // `unsync()` to drop at the semicolon of that `let` statement, which |
435 | /// // is prior to the await point. They would otherwise stay around until |
436 | /// // the semicolon on *this* statement, which is after the await point, |
437 | /// // and the enclosing Future would not implement Send. |
438 | /// log(make_error!("look: {:p}" , unsync())).await; |
439 | /// } |
440 | /// |
441 | /// async fn log(error: Error) {/* ... */} |
442 | /// |
443 | /// // Returns something without a Sync impl. |
444 | /// fn unsync() -> *const () { |
445 | /// 0 as *const () |
446 | /// } |
447 | /// # |
448 | /// # fn test() { |
449 | /// # fn assert_send(_: impl Send) {} |
450 | /// # assert_send(f()); |
451 | /// # } |
452 | /// ``` |
453 | #[unstable (feature = "hint_must_use" , issue = "94745" )] |
454 | #[rustc_const_unstable (feature = "hint_must_use" , issue = "94745" )] |
455 | #[must_use ] // <-- :) |
456 | #[inline (always)] |
457 | pub const fn must_use<T>(value: T) -> T { |
458 | value |
459 | } |
460 | |