]> git.lizzy.rs Git - rust.git/blob - library/core/src/hint.rs
Auto merge of #94598 - scottmcm:prefix-free-hasher-methods, r=Amanieu
[rust.git] / library / core / src / 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 //! Hints may be compile time or runtime.
5
6 use crate::intrinsics;
7
8 /// Informs the compiler that this point in the code is not reachable, enabling
9 /// further optimizations.
10 ///
11 /// # Safety
12 ///
13 /// Reaching this function is completely *undefined behavior* (UB). In
14 /// particular, the compiler assumes that all UB must never happen, and
15 /// therefore will eliminate all branches that reach to a call to
16 /// `unreachable_unchecked()`.
17 ///
18 /// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
19 /// `unreachable_unchecked()` call is actually reachable among all possible
20 /// control flow, the compiler will apply the wrong optimization strategy, and
21 /// may sometimes even corrupt seemingly unrelated code, causing
22 /// difficult-to-debug problems.
23 ///
24 /// Use this function only when you can prove that the code will never call it.
25 /// Otherwise, consider using the [`unreachable!`] macro, which does not allow
26 /// optimizations but will panic when executed.
27 ///
28 /// # Example
29 ///
30 /// ```
31 /// fn div_1(a: u32, b: u32) -> u32 {
32 ///     use std::hint::unreachable_unchecked;
33 ///
34 ///     // `b.saturating_add(1)` is always positive (not zero),
35 ///     // hence `checked_div` will never return `None`.
36 ///     // Therefore, the else branch is unreachable.
37 ///     a.checked_div(b.saturating_add(1))
38 ///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
39 /// }
40 ///
41 /// assert_eq!(div_1(7, 0), 7);
42 /// assert_eq!(div_1(9, 1), 4);
43 /// assert_eq!(div_1(11, u32::MAX), 0);
44 /// ```
45 #[inline]
46 #[stable(feature = "unreachable", since = "1.27.0")]
47 #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
48 pub const unsafe fn unreachable_unchecked() -> ! {
49     // SAFETY: the safety contract for `intrinsics::unreachable` must
50     // be upheld by the caller.
51     unsafe { intrinsics::unreachable() }
52 }
53
54 /// Emits a machine instruction to signal the processor that it is running in
55 /// a busy-wait spin-loop ("spin lock").
56 ///
57 /// Upon receiving the spin-loop signal the processor can optimize its behavior by,
58 /// for example, saving power or switching hyper-threads.
59 ///
60 /// This function is different from [`thread::yield_now`] which directly
61 /// yields to the system's scheduler, whereas `spin_loop` does not interact
62 /// with the operating system.
63 ///
64 /// A common use case for `spin_loop` is implementing bounded optimistic
65 /// spinning in a CAS loop in synchronization primitives. To avoid problems
66 /// like priority inversion, it is strongly recommended that the spin loop is
67 /// terminated after a finite amount of iterations and an appropriate blocking
68 /// syscall is made.
69 ///
70 /// **Note**: On platforms that do not support receiving spin-loop hints this
71 /// function does not do anything at all.
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// use std::sync::atomic::{AtomicBool, Ordering};
77 /// use std::sync::Arc;
78 /// use std::{hint, thread};
79 ///
80 /// // A shared atomic value that threads will use to coordinate
81 /// let live = Arc::new(AtomicBool::new(false));
82 ///
83 /// // In a background thread we'll eventually set the value
84 /// let bg_work = {
85 ///     let live = live.clone();
86 ///     thread::spawn(move || {
87 ///         // Do some work, then make the value live
88 ///         do_some_work();
89 ///         live.store(true, Ordering::Release);
90 ///     })
91 /// };
92 ///
93 /// // Back on our current thread, we wait for the value to be set
94 /// while !live.load(Ordering::Acquire) {
95 ///     // The spin loop is a hint to the CPU that we're waiting, but probably
96 ///     // not for very long
97 ///     hint::spin_loop();
98 /// }
99 ///
100 /// // The value is now set
101 /// # fn do_some_work() {}
102 /// do_some_work();
103 /// bg_work.join()?;
104 /// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
105 /// ```
106 ///
107 /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
108 #[inline]
109 #[stable(feature = "renamed_spin_loop", since = "1.49.0")]
110 pub fn spin_loop() {
111     #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
112     {
113         #[cfg(target_arch = "x86")]
114         {
115             // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
116             unsafe { crate::arch::x86::_mm_pause() };
117         }
118
119         #[cfg(target_arch = "x86_64")]
120         {
121             // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
122             unsafe { crate::arch::x86_64::_mm_pause() };
123         }
124     }
125
126     // RISC-V platform spin loop hint implementation
127     {
128         // RISC-V RV32 and RV64 share the same PAUSE instruction, but they are located in different
129         // modules in `core::arch`.
130         // In this case, here we call `pause` function in each core arch module.
131         #[cfg(target_arch = "riscv32")]
132         {
133             crate::arch::riscv32::pause();
134         }
135         #[cfg(target_arch = "riscv64")]
136         {
137             crate::arch::riscv64::pause();
138         }
139     }
140
141     #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
142     {
143         #[cfg(target_arch = "aarch64")]
144         {
145             // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
146             unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
147         }
148         #[cfg(target_arch = "arm")]
149         {
150             // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
151             // with support for the v6 feature.
152             unsafe { crate::arch::arm::__yield() };
153         }
154     }
155 }
156
157 /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
158 /// `black_box` could do.
159 ///
160 /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
161 /// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
162 /// behavior in the calling code. This property makes `black_box` useful for writing code in which
163 /// certain optimizations are not desired, such as benchmarks.
164 ///
165 /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
166 /// extent to which it can block optimisations may vary depending upon the platform and code-gen
167 /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
168 ///
169 /// [`std::convert::identity`]: crate::convert::identity
170 #[inline]
171 #[unstable(feature = "bench_black_box", issue = "64102")]
172 #[rustc_const_unstable(feature = "const_black_box", issue = "none")]
173 pub const fn black_box<T>(dummy: T) -> T {
174     crate::intrinsics::black_box(dummy)
175 }
176
177 /// An identity function that causes an `unused_must_use` warning to be
178 /// triggered if the given value is not used (returned, stored in a variable,
179 /// etc) by the caller.
180 ///
181 /// This is primarily intended for use in macro-generated code, in which a
182 /// [`#[must_use]` attribute][must_use] either on a type or a function would not
183 /// be convenient.
184 ///
185 /// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
186 ///
187 /// # Example
188 ///
189 /// ```
190 /// #![feature(hint_must_use)]
191 ///
192 /// use core::fmt;
193 ///
194 /// pub struct Error(/* ... */);
195 ///
196 /// #[macro_export]
197 /// macro_rules! make_error {
198 ///     ($($args:expr),*) => {
199 ///         core::hint::must_use({
200 ///             let error = $crate::make_error(core::format_args!($($args),*));
201 ///             error
202 ///         })
203 ///     };
204 /// }
205 ///
206 /// // Implementation detail of make_error! macro.
207 /// #[doc(hidden)]
208 /// pub fn make_error(args: fmt::Arguments<'_>) -> Error {
209 ///     Error(/* ... */)
210 /// }
211 ///
212 /// fn demo() -> Option<Error> {
213 ///     if true {
214 ///         // Oops, meant to write `return Some(make_error!("..."));`
215 ///         Some(make_error!("..."));
216 ///     }
217 ///     None
218 /// }
219 /// #
220 /// # // Make rustdoc not wrap the whole snippet in fn main, so that $crate::make_error works
221 /// # fn main() {}
222 /// ```
223 ///
224 /// In the above example, we'd like an `unused_must_use` lint to apply to the
225 /// value created by `make_error!`. However, neither `#[must_use]` on a struct
226 /// nor `#[must_use]` on a function is appropriate here, so the macro expands
227 /// using `core::hint::must_use` instead.
228 ///
229 /// - We wouldn't want `#[must_use]` on the `struct Error` because that would
230 ///   make the following unproblematic code trigger a warning:
231 ///
232 ///   ```
233 ///   # struct Error;
234 ///   #
235 ///   fn f(arg: &str) -> Result<(), Error>
236 ///   # { Ok(()) }
237 ///
238 ///   #[test]
239 ///   fn t() {
240 ///       // Assert that `f` returns error if passed an empty string.
241 ///       // A value of type `Error` is unused here but that's not a problem.
242 ///       f("").unwrap_err();
243 ///   }
244 ///   ```
245 ///
246 /// - Using `#[must_use]` on `fn make_error` can't help because the return value
247 ///   *is* used, as the right-hand side of a `let` statement. The `let`
248 ///   statement looks useless but is in fact necessary for ensuring that
249 ///   temporaries within the `format_args` expansion are not kept alive past the
250 ///   creation of the `Error`, as keeping them alive past that point can cause
251 ///   autotrait issues in async code:
252 ///
253 ///   ```
254 ///   # #![feature(hint_must_use)]
255 ///   #
256 ///   # struct Error;
257 ///   #
258 ///   # macro_rules! make_error {
259 ///   #     ($($args:expr),*) => {
260 ///   #         core::hint::must_use({
261 ///   #             // If `let` isn't used, then `f()` produces a non-Send future.
262 ///   #             let error = make_error(core::format_args!($($args),*));
263 ///   #             error
264 ///   #         })
265 ///   #     };
266 ///   # }
267 ///   #
268 ///   # fn make_error(args: core::fmt::Arguments<'_>) -> Error {
269 ///   #     Error
270 ///   # }
271 ///   #
272 ///   async fn f() {
273 ///       // Using `let` inside the make_error expansion causes temporaries like
274 ///       // `unsync()` to drop at the semicolon of that `let` statement, which
275 ///       // is prior to the await point. They would otherwise stay around until
276 ///       // the semicolon on *this* statement, which is after the await point,
277 ///       // and the enclosing Future would not implement Send.
278 ///       log(make_error!("look: {:p}", unsync())).await;
279 ///   }
280 ///
281 ///   async fn log(error: Error) {/* ... */}
282 ///
283 ///   // Returns something without a Sync impl.
284 ///   fn unsync() -> *const () {
285 ///       0 as *const ()
286 ///   }
287 ///   #
288 ///   # fn test() {
289 ///   #     fn assert_send(_: impl Send) {}
290 ///   #     assert_send(f());
291 ///   # }
292 ///   ```
293 #[unstable(feature = "hint_must_use", issue = "94745")]
294 #[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
295 #[must_use] // <-- :)
296 pub const fn must_use<T>(value: T) -> T {
297     value
298 }