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 | use crate::{intrinsics, 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 | /// unsafe { 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 |
101 | pub 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, but it might also make the generated code |
115 | /// slower. Either way, calling it will most likely make compilation take longer. |
116 | /// |
117 | /// You may know this from other places as |
118 | /// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C, |
119 | /// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume). |
120 | /// |
121 | /// This promotes a correctness requirement to a soundness requirement. Don't do that without |
122 | /// very good reason. |
123 | /// |
124 | /// # Usage |
125 | /// |
126 | /// This is a situational tool for micro-optimization, and is allowed to do nothing. Any use |
127 | /// should come with a repeatable benchmark to show the value, with the expectation to drop it |
128 | /// later should the optimizer get smarter and no longer need it. |
129 | /// |
130 | /// The more complicated the condition, the less likely this is to be useful. For example, |
131 | /// `assert_unchecked(foo.is_sorted())` is a complex enough value that the compiler is unlikely |
132 | /// to be able to take advantage of it. |
133 | /// |
134 | /// There's also no need to `assert_unchecked` basic properties of things. For example, the |
135 | /// compiler already knows the range of `count_ones`, so there is no benefit to |
136 | /// `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`. |
137 | /// |
138 | /// `assert_unchecked` is logically equivalent to `if !cond { unreachable_unchecked(); }`. If |
139 | /// ever you are tempted to write `assert_unchecked(false)`, you should instead use |
140 | /// [`unreachable_unchecked()`] directly. |
141 | /// |
142 | /// # Safety |
143 | /// |
144 | /// `cond` must be `true`. It is immediate UB to call this with `false`. |
145 | /// |
146 | /// # Example |
147 | /// |
148 | /// ``` |
149 | /// use core::hint; |
150 | /// |
151 | /// /// # Safety |
152 | /// /// |
153 | /// /// `p` must be nonnull and valid |
154 | /// pub unsafe fn next_value(p: *const i32) -> i32 { |
155 | /// // SAFETY: caller invariants guarantee that `p` is not null |
156 | /// unsafe { hint::assert_unchecked(!p.is_null()) } |
157 | /// |
158 | /// if p.is_null() { |
159 | /// return -1; |
160 | /// } else { |
161 | /// // SAFETY: caller invariants guarantee that `p` is valid |
162 | /// unsafe { *p + 1 } |
163 | /// } |
164 | /// } |
165 | /// ``` |
166 | /// |
167 | /// Without the `assert_unchecked`, the above function produces the following with optimizations |
168 | /// enabled: |
169 | /// |
170 | /// ```asm |
171 | /// next_value: |
172 | /// test rdi, rdi |
173 | /// je .LBB0_1 |
174 | /// mov eax, dword ptr [rdi] |
175 | /// inc eax |
176 | /// ret |
177 | /// .LBB0_1: |
178 | /// mov eax, -1 |
179 | /// ret |
180 | /// ``` |
181 | /// |
182 | /// Adding the assertion allows the optimizer to remove the extra check: |
183 | /// |
184 | /// ```asm |
185 | /// next_value: |
186 | /// mov eax, dword ptr [rdi] |
187 | /// inc eax |
188 | /// ret |
189 | /// ``` |
190 | /// |
191 | /// This example is quite unlike anything that would be used in the real world: it is redundant |
192 | /// to put an assertion right next to code that checks the same thing, and dereferencing a |
193 | /// pointer already has the builtin assumption that it is nonnull. However, it illustrates the |
194 | /// kind of changes the optimizer can make even when the behavior is less obviously related. |
195 | #[track_caller ] |
196 | #[inline (always)] |
197 | #[doc (alias = "assume" )] |
198 | #[stable (feature = "hint_assert_unchecked" , since = "1.81.0" )] |
199 | #[rustc_const_stable (feature = "hint_assert_unchecked" , since = "1.81.0" )] |
200 | pub const unsafe fn assert_unchecked(cond: bool) { |
201 | // SAFETY: The caller promised `cond` is true. |
202 | unsafe { |
203 | ub_checks::assert_unsafe_precondition!( |
204 | check_language_ub, |
205 | "hint::assert_unchecked must never be called when the condition is false" , |
206 | (cond: bool = cond) => cond, |
207 | ); |
208 | crate::intrinsics::assume(cond); |
209 | } |
210 | } |
211 | |
212 | /// Emits a machine instruction to signal the processor that it is running in |
213 | /// a busy-wait spin-loop ("spin lock"). |
214 | /// |
215 | /// Upon receiving the spin-loop signal the processor can optimize its behavior by, |
216 | /// for example, saving power or switching hyper-threads. |
217 | /// |
218 | /// This function is different from [`thread::yield_now`] which directly |
219 | /// yields to the system's scheduler, whereas `spin_loop` does not interact |
220 | /// with the operating system. |
221 | /// |
222 | /// A common use case for `spin_loop` is implementing bounded optimistic |
223 | /// spinning in a CAS loop in synchronization primitives. To avoid problems |
224 | /// like priority inversion, it is strongly recommended that the spin loop is |
225 | /// terminated after a finite amount of iterations and an appropriate blocking |
226 | /// syscall is made. |
227 | /// |
228 | /// **Note**: On platforms that do not support receiving spin-loop hints this |
229 | /// function does not do anything at all. |
230 | /// |
231 | /// # Examples |
232 | /// |
233 | /// ``` |
234 | /// use std::sync::atomic::{AtomicBool, Ordering}; |
235 | /// use std::sync::Arc; |
236 | /// use std::{hint, thread}; |
237 | /// |
238 | /// // A shared atomic value that threads will use to coordinate |
239 | /// let live = Arc::new(AtomicBool::new(false)); |
240 | /// |
241 | /// // In a background thread we'll eventually set the value |
242 | /// let bg_work = { |
243 | /// let live = live.clone(); |
244 | /// thread::spawn(move || { |
245 | /// // Do some work, then make the value live |
246 | /// do_some_work(); |
247 | /// live.store(true, Ordering::Release); |
248 | /// }) |
249 | /// }; |
250 | /// |
251 | /// // Back on our current thread, we wait for the value to be set |
252 | /// while !live.load(Ordering::Acquire) { |
253 | /// // The spin loop is a hint to the CPU that we're waiting, but probably |
254 | /// // not for very long |
255 | /// hint::spin_loop(); |
256 | /// } |
257 | /// |
258 | /// // The value is now set |
259 | /// # fn do_some_work() {} |
260 | /// do_some_work(); |
261 | /// bg_work.join()?; |
262 | /// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(()) |
263 | /// ``` |
264 | /// |
265 | /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html |
266 | #[inline (always)] |
267 | #[stable (feature = "renamed_spin_loop" , since = "1.49.0" )] |
268 | pub fn spin_loop() { |
269 | #[cfg (target_arch = "x86" )] |
270 | { |
271 | // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets. |
272 | unsafe { crate::arch::x86::_mm_pause() }; |
273 | } |
274 | |
275 | #[cfg (target_arch = "x86_64" )] |
276 | { |
277 | // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets. |
278 | unsafe { crate::arch::x86_64::_mm_pause() }; |
279 | } |
280 | |
281 | #[cfg (target_arch = "riscv32" )] |
282 | { |
283 | crate::arch::riscv32::pause(); |
284 | } |
285 | |
286 | #[cfg (target_arch = "riscv64" )] |
287 | { |
288 | crate::arch::riscv64::pause(); |
289 | } |
290 | |
291 | #[cfg (any(target_arch = "aarch64" , target_arch = "arm64ec" ))] |
292 | { |
293 | // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets. |
294 | unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }; |
295 | } |
296 | |
297 | #[cfg (all(target_arch = "arm" , target_feature = "v6" ))] |
298 | { |
299 | // SAFETY: the `cfg` attr ensures that we only execute this on arm targets |
300 | // with support for the v6 feature. |
301 | unsafe { crate::arch::arm::__yield() }; |
302 | } |
303 | } |
304 | |
305 | /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what |
306 | /// `black_box` could do. |
307 | /// |
308 | /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can |
309 | /// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined |
310 | /// behavior in the calling code. This property makes `black_box` useful for writing code in which |
311 | /// certain optimizations are not desired, such as benchmarks. |
312 | /// |
313 | /// <div class="warning"> |
314 | /// |
315 | /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The |
316 | /// extent to which it can block optimisations may vary depending upon the platform and code-gen |
317 | /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the |
318 | /// identity function. As such, it **must not be relied upon to control critical program behavior.** |
319 | /// This also means that this function does not offer any guarantees for cryptographic or security |
320 | /// purposes. |
321 | /// |
322 | /// </div> |
323 | /// |
324 | /// [`std::convert::identity`]: crate::convert::identity |
325 | /// |
326 | /// # When is this useful? |
327 | /// |
328 | /// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be |
329 | /// relied upon for benchmarking, and should be used there. It will try to ensure that the |
330 | /// compiler doesn't optimize away part of the intended test code based on context. For |
331 | /// example: |
332 | /// |
333 | /// ``` |
334 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
335 | /// haystack.iter().any(|x| x == &needle) |
336 | /// } |
337 | /// |
338 | /// pub fn benchmark() { |
339 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
340 | /// let needle = "ghi" ; |
341 | /// for _ in 0..10 { |
342 | /// contains(&haystack, needle); |
343 | /// } |
344 | /// } |
345 | /// ``` |
346 | /// |
347 | /// The compiler could theoretically make optimizations like the following: |
348 | /// |
349 | /// - The `needle` and `haystack` do not change, move the call to `contains` outside the loop and |
350 | /// delete the loop |
351 | /// - Inline `contains` |
352 | /// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove |
353 | /// the call and replace with `true` |
354 | /// - Nothing is done with the result of `contains`: delete this function call entirely |
355 | /// - `benchmark` now has no purpose: delete this function |
356 | /// |
357 | /// It is not likely that all of the above happens, but the compiler is definitely able to make some |
358 | /// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes |
359 | /// in: |
360 | /// |
361 | /// ``` |
362 | /// use std::hint::black_box; |
363 | /// |
364 | /// // Same `contains` function. |
365 | /// fn contains(haystack: &[&str], needle: &str) -> bool { |
366 | /// haystack.iter().any(|x| x == &needle) |
367 | /// } |
368 | /// |
369 | /// pub fn benchmark() { |
370 | /// let haystack = vec!["abc" , "def" , "ghi" , "jkl" , "mno" ]; |
371 | /// let needle = "ghi" ; |
372 | /// for _ in 0..10 { |
373 | /// // Force the compiler to run `contains`, even though it is a pure function whose |
374 | /// // results are unused. |
375 | /// black_box(contains( |
376 | /// // Prevent the compiler from making assumptions about the input. |
377 | /// black_box(&haystack), |
378 | /// black_box(needle), |
379 | /// )); |
380 | /// } |
381 | /// } |
382 | /// ``` |
383 | /// |
384 | /// This essentially tells the compiler to block optimizations across any calls to `black_box`. So, |
385 | /// it now: |
386 | /// |
387 | /// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be |
388 | /// optimized based on argument values |
389 | /// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot |
390 | /// optimize this away |
391 | /// |
392 | /// This makes our benchmark much more realistic to how the function would actually be used, where |
393 | /// arguments are usually not known at compile time and the result is used in some way. |
394 | /// |
395 | /// # How to use this |
396 | /// |
397 | /// In practice, `black_box` serves two purposes: |
398 | /// |
399 | /// 1. It prevents the compiler from making optimizations related to the value returned by `black_box` |
400 | /// 2. It forces the value passed to `black_box` to be calculated, even if the return value of `black_box` is unused |
401 | /// |
402 | /// ``` |
403 | /// use std::hint::black_box; |
404 | /// |
405 | /// let zero = 0; |
406 | /// let five = 5; |
407 | /// |
408 | /// // The compiler will see this and remove the `* five` call, because it knows that multiplying |
409 | /// // any integer by 0 will result in 0. |
410 | /// let c = zero * five; |
411 | /// |
412 | /// // Adding `black_box` here disables the compiler's ability to reason about the first operand in the multiplication. |
413 | /// // It is forced to assume that it can be any possible number, so it cannot remove the `* five` |
414 | /// // operation. |
415 | /// let c = black_box(zero) * five; |
416 | /// ``` |
417 | /// |
418 | /// While most cases will not be as clear-cut as the above example, it still illustrates how |
419 | /// `black_box` can be used. When benchmarking a function, you usually want to wrap its inputs in |
420 | /// `black_box` so the compiler cannot make optimizations that would be unrealistic in real-life |
421 | /// use. |
422 | /// |
423 | /// ``` |
424 | /// use std::hint::black_box; |
425 | /// |
426 | /// // This is a simple function that increments its input by 1. Note that it is pure, meaning it |
427 | /// // has no side-effects. This function has no effect if its result is unused. (An example of a |
428 | /// // function *with* side-effects is `println!()`.) |
429 | /// fn increment(x: u8) -> u8 { |
430 | /// x + 1 |
431 | /// } |
432 | /// |
433 | /// // Here, we call `increment` but discard its result. The compiler, seeing this and knowing that |
434 | /// // `increment` is pure, will eliminate this function call entirely. This may not be desired, |
435 | /// // though, especially if we're trying to track how much time `increment` takes to execute. |
436 | /// let _ = increment(black_box(5)); |
437 | /// |
438 | /// // Here, we force `increment` to be executed. This is because the compiler treats `black_box` |
439 | /// // as if it has side-effects, and thus must compute its input. |
440 | /// let _ = black_box(increment(black_box(5))); |
441 | /// ``` |
442 | /// |
443 | /// There may be additional situations where you want to wrap the result of a function in |
444 | /// `black_box` to force its execution. This is situational though, and may not have any effect |
445 | /// (such as when the function returns a zero-sized type such as [`()` unit][unit]). |
446 | /// |
447 | /// Note that `black_box` has no effect on how its input is treated, only its output. As such, |
448 | /// expressions passed to `black_box` may still be optimized: |
449 | /// |
450 | /// ``` |
451 | /// use std::hint::black_box; |
452 | /// |
453 | /// // The compiler sees this... |
454 | /// let y = black_box(5 * 10); |
455 | /// |
456 | /// // ...as this. As such, it will likely simplify `5 * 10` to just `50`. |
457 | /// let _0 = 5 * 10; |
458 | /// let y = black_box(_0); |
459 | /// ``` |
460 | /// |
461 | /// In the above example, the `5 * 10` expression is considered distinct from the `black_box` call, |
462 | /// and thus is still optimized by the compiler. You can prevent this by moving the multiplication |
463 | /// operation outside of `black_box`: |
464 | /// |
465 | /// ``` |
466 | /// use std::hint::black_box; |
467 | /// |
468 | /// // No assumptions can be made about either operand, so the multiplication is not optimized out. |
469 | /// let y = black_box(5) * black_box(10); |
470 | /// ``` |
471 | /// |
472 | /// During constant evaluation, `black_box` is treated as a no-op. |
473 | #[inline ] |
474 | #[stable (feature = "bench_black_box" , since = "1.66.0" )] |
475 | #[rustc_const_stable (feature = "const_black_box" , since = "1.86.0" )] |
476 | pub const fn black_box<T>(dummy: T) -> T { |
477 | crate::intrinsics::black_box(dummy) |
478 | } |
479 | |
480 | /// An identity function that causes an `unused_must_use` warning to be |
481 | /// triggered if the given value is not used (returned, stored in a variable, |
482 | /// etc) by the caller. |
483 | /// |
484 | /// This is primarily intended for use in macro-generated code, in which a |
485 | /// [`#[must_use]` attribute][must_use] either on a type or a function would not |
486 | /// be convenient. |
487 | /// |
488 | /// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute |
489 | /// |
490 | /// # Example |
491 | /// |
492 | /// ``` |
493 | /// #![feature(hint_must_use)] |
494 | /// |
495 | /// use core::fmt; |
496 | /// |
497 | /// pub struct Error(/* ... */); |
498 | /// |
499 | /// #[macro_export] |
500 | /// macro_rules! make_error { |
501 | /// ($($args:expr),*) => { |
502 | /// core::hint::must_use({ |
503 | /// let error = $crate::make_error(core::format_args!($($args),*)); |
504 | /// error |
505 | /// }) |
506 | /// }; |
507 | /// } |
508 | /// |
509 | /// // Implementation detail of make_error! macro. |
510 | /// #[doc(hidden)] |
511 | /// pub fn make_error(args: fmt::Arguments<'_>) -> Error { |
512 | /// Error(/* ... */) |
513 | /// } |
514 | /// |
515 | /// fn demo() -> Option<Error> { |
516 | /// if true { |
517 | /// // Oops, meant to write `return Some(make_error!("..."));` |
518 | /// Some(make_error!("..." )); |
519 | /// } |
520 | /// None |
521 | /// } |
522 | /// # |
523 | /// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works |
524 | /// # fn main() {} |
525 | /// ``` |
526 | /// |
527 | /// In the above example, we'd like an `unused_must_use` lint to apply to the |
528 | /// value created by `make_error!`. However, neither `#[must_use]` on a struct |
529 | /// nor `#[must_use]` on a function is appropriate here, so the macro expands |
530 | /// using `core::hint::must_use` instead. |
531 | /// |
532 | /// - We wouldn't want `#[must_use]` on the `struct Error` because that would |
533 | /// make the following unproblematic code trigger a warning: |
534 | /// |
535 | /// ``` |
536 | /// # struct Error; |
537 | /// # |
538 | /// fn f(arg: &str) -> Result<(), Error> |
539 | /// # { Ok(()) } |
540 | /// |
541 | /// #[test] |
542 | /// fn t() { |
543 | /// // Assert that `f` returns error if passed an empty string. |
544 | /// // A value of type `Error` is unused here but that's not a problem. |
545 | /// f("" ).unwrap_err(); |
546 | /// } |
547 | /// ``` |
548 | /// |
549 | /// - Using `#[must_use]` on `fn make_error` can't help because the return value |
550 | /// *is* used, as the right-hand side of a `let` statement. The `let` |
551 | /// statement looks useless but is in fact necessary for ensuring that |
552 | /// temporaries within the `format_args` expansion are not kept alive past the |
553 | /// creation of the `Error`, as keeping them alive past that point can cause |
554 | /// autotrait issues in async code: |
555 | /// |
556 | /// ``` |
557 | /// # #![feature(hint_must_use)] |
558 | /// # |
559 | /// # struct Error; |
560 | /// # |
561 | /// # macro_rules! make_error { |
562 | /// # ($($args:expr),*) => { |
563 | /// # core::hint::must_use({ |
564 | /// # // If `let` isn't used, then `f()` produces a non-Send future. |
565 | /// # let error = make_error(core::format_args!($($args),*)); |
566 | /// # error |
567 | /// # }) |
568 | /// # }; |
569 | /// # } |
570 | /// # |
571 | /// # fn make_error(args: core::fmt::Arguments<'_>) -> Error { |
572 | /// # Error |
573 | /// # } |
574 | /// # |
575 | /// async fn f() { |
576 | /// // Using `let` inside the make_error expansion causes temporaries like |
577 | /// // `unsync()` to drop at the semicolon of that `let` statement, which |
578 | /// // is prior to the await point. They would otherwise stay around until |
579 | /// // the semicolon on *this* statement, which is after the await point, |
580 | /// // and the enclosing Future would not implement Send. |
581 | /// log(make_error!("look: {:p}" , unsync())).await; |
582 | /// } |
583 | /// |
584 | /// async fn log(error: Error) {/* ... */} |
585 | /// |
586 | /// // Returns something without a Sync impl. |
587 | /// fn unsync() -> *const () { |
588 | /// 0 as *const () |
589 | /// } |
590 | /// # |
591 | /// # fn test() { |
592 | /// # fn assert_send(_: impl Send) {} |
593 | /// # assert_send(f()); |
594 | /// # } |
595 | /// ``` |
596 | #[unstable (feature = "hint_must_use" , issue = "94745" )] |
597 | #[must_use ] // <-- :) |
598 | #[inline (always)] |
599 | pub const fn must_use<T>(value: T) -> T { |
600 | value |
601 | } |
602 | |
603 | /// Hints to the compiler that a branch condition is likely to be true. |
604 | /// Returns the value passed to it. |
605 | /// |
606 | /// It can be used with `if` or boolean `match` expressions. |
607 | /// |
608 | /// When used outside of a branch condition, it may still influence a nearby branch, but |
609 | /// probably will not have any effect. |
610 | /// |
611 | /// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to |
612 | /// compound expressions, such as `likely(a && b)`. When applied to compound expressions, it has |
613 | /// the following effect: |
614 | /// ```text |
615 | /// likely(!a) => !unlikely(a) |
616 | /// likely(a && b) => likely(a) && likely(b) |
617 | /// likely(a || b) => a || likely(b) |
618 | /// ``` |
619 | /// |
620 | /// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code. |
621 | /// |
622 | /// # Examples |
623 | /// |
624 | /// ``` |
625 | /// #![feature(likely_unlikely)] |
626 | /// use core::hint::likely; |
627 | /// |
628 | /// fn foo(x: i32) { |
629 | /// if likely(x > 0) { |
630 | /// println!("this branch is likely to be taken" ); |
631 | /// } else { |
632 | /// println!("this branch is unlikely to be taken" ); |
633 | /// } |
634 | /// |
635 | /// match likely(x > 0) { |
636 | /// true => println!("this branch is likely to be taken" ), |
637 | /// false => println!("this branch is unlikely to be taken" ), |
638 | /// } |
639 | /// |
640 | /// // Use outside of a branch condition may still influence a nearby branch |
641 | /// let cond = likely(x != 0); |
642 | /// if cond { |
643 | /// println!("this branch is likely to be taken" ); |
644 | /// } |
645 | /// } |
646 | /// ``` |
647 | /// |
648 | /// |
649 | #[unstable (feature = "likely_unlikely" , issue = "136873" )] |
650 | #[inline (always)] |
651 | pub const fn likely(b: bool) -> bool { |
652 | crate::intrinsics::likely(b) |
653 | } |
654 | |
655 | /// Hints to the compiler that a branch condition is unlikely to be true. |
656 | /// Returns the value passed to it. |
657 | /// |
658 | /// It can be used with `if` or boolean `match` expressions. |
659 | /// |
660 | /// When used outside of a branch condition, it may still influence a nearby branch, but |
661 | /// probably will not have any effect. |
662 | /// |
663 | /// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to |
664 | /// compound expressions, such as `unlikely(a && b)`. When applied to compound expressions, it has |
665 | /// the following effect: |
666 | /// ```text |
667 | /// unlikely(!a) => !likely(a) |
668 | /// unlikely(a && b) => a && unlikely(b) |
669 | /// unlikely(a || b) => unlikely(a) || unlikely(b) |
670 | /// ``` |
671 | /// |
672 | /// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code. |
673 | /// |
674 | /// # Examples |
675 | /// |
676 | /// ``` |
677 | /// #![feature(likely_unlikely)] |
678 | /// use core::hint::unlikely; |
679 | /// |
680 | /// fn foo(x: i32) { |
681 | /// if unlikely(x > 0) { |
682 | /// println!("this branch is unlikely to be taken" ); |
683 | /// } else { |
684 | /// println!("this branch is likely to be taken" ); |
685 | /// } |
686 | /// |
687 | /// match unlikely(x > 0) { |
688 | /// true => println!("this branch is unlikely to be taken" ), |
689 | /// false => println!("this branch is likely to be taken" ), |
690 | /// } |
691 | /// |
692 | /// // Use outside of a branch condition may still influence a nearby branch |
693 | /// let cond = unlikely(x != 0); |
694 | /// if cond { |
695 | /// println!("this branch is likely to be taken" ); |
696 | /// } |
697 | /// } |
698 | /// ``` |
699 | #[unstable (feature = "likely_unlikely" , issue = "136873" )] |
700 | #[inline (always)] |
701 | pub const fn unlikely(b: bool) -> bool { |
702 | crate::intrinsics::unlikely(b) |
703 | } |
704 | |
705 | /// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may |
706 | /// choose to optimize paths that are not cold at the expense of paths that are cold. |
707 | /// |
708 | /// # Examples |
709 | /// |
710 | /// ``` |
711 | /// #![feature(cold_path)] |
712 | /// use core::hint::cold_path; |
713 | /// |
714 | /// fn foo(x: &[i32]) { |
715 | /// if let Some(first) = x.get(0) { |
716 | /// // this is the fast path |
717 | /// } else { |
718 | /// // this path is unlikely |
719 | /// cold_path(); |
720 | /// } |
721 | /// } |
722 | /// |
723 | /// fn bar(x: i32) -> i32 { |
724 | /// match x { |
725 | /// 1 => 10, |
726 | /// 2 => 100, |
727 | /// 3 => { cold_path(); 1000 }, // this branch is unlikely |
728 | /// _ => { cold_path(); 10000 }, // this is also unlikely |
729 | /// } |
730 | /// } |
731 | /// ``` |
732 | #[unstable (feature = "cold_path" , issue = "136873" )] |
733 | #[inline (always)] |
734 | pub const fn cold_path() { |
735 | crate::intrinsics::cold_path() |
736 | } |
737 | |