1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
#![stable(feature = "core_hint", since = "1.27.0")]
//! 对编译器的提示,该提示会影响应如何发出或优化代码。
//! 提示可能是编译时或运行时。
use crate::intrinsics;
/// 通知编译器调用此函数的站点不可访问,可能会启用进一步优化。
///
/// # Safety
///
/// 达到这个函数是 *未定义的行为*。
///
/// 由于编译器假定所有形式的未定义行为永远不会发生,它将消除周围代码中的所有分支,它可以确定总是会导致调用 `unreachable_unchecked()`。
///
/// 如果使用这个函数的假设被证明是错误的 -- 也就是说,如果调用 `unreachable_unchecked()` 的站点在运行时实际上是可访问的 -- 编译器可能已经为这种情况生成了无意义的机器指令,包括看似不相关的代码,导致难以 - 调试问题。
///
///
/// 谨慎使用此功能。
/// 考虑使用 [`unreachable!`] 宏,这可能会阻止一些优化,但如果在运行时实际达到它会安全地 panic。对您的代码进行基准测试,以确定使用 `unreachable_unchecked()` 是否具有性能优势。
///
/// # Examples
///
/// `unreachable_unchecked()` 可用于编译器无法证明先前建立的不,变体,的情况。如果编译器无法分析的外部代码支持这些不,变体,则这种情况发生的可能性更高。
///
/// ```
/// fn prepare_inputs(divisors: &mut Vec<u32>) {
/// // 更改时,注意 future-self: 这里建立的不变量没有在 `do_computation()` 中检查; 如果这种情况发生变化,您必须更改 `do_computation()`。
/////
/////
/// divisors.retain(|divisor| *divisor != 0)
/// }
///
/// /// # Safety
/// /// `divisor` 的所有元素都必须非零。
/// unsafe fn do_computation(i: u32, divisors: &[u32]) -> u32 {
/// divisors.iter().fold(i, |acc, divisor| {
/// // 让编译器相信这里不会发生被零除,并且下面不需要检查。
/////
/// if *divisor == 0 {
/// // 安全性: 由于 `prepare_inputs`,`divisor` 不能为零,但编译器不知道这一点。
/// // 我们 *承诺* 我们总是调用 `prepare_inputs`。
/////
/// std::hint::unreachable_unchecked()
/// }
/// // 编译器通常会在此处引入一个检查,以防止被零除。
/// // 但是,如果 `divisor` 为零,则上面的分支将到达我们明确标记为不可达的地方。
/// // 编译器得出结论,此时 `divisor` 不能为零,并删除 - 现在证明无用 - 检查。
/////
/////
/// acc / divisor
/// })
/// }
///
/// let mut divisors = vec![2, 0, 4];
/// prepare_inputs(&mut divisors);
/// let result = unsafe {
/// // 安全性: prepare_inputs() 保证除数不为零
/// do_computation(100, &divisors)
/// };
/// assert_eq!(result, 12);
///
/// ```
///
/// 虽然在以下示例中使用 `unreachable_unchecked()` 是完美的,因为编译器能够证明除以零是不可能的,但基准测试显示 `unreachable_unchecked()` 与使用 [`unreachable!`] 相比没有任何好处,而后者不会引入未定义行为的可能性。
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
/// use std::hint::unreachable_unchecked;
///
/// // `b.saturating_add(1)` 始终为正 (非零),因此 `checked_div` 永远不会返回 `None`。
/////
/// // 因此,else 分支不可访问。
/// a.checked_div(b.saturating_add(1))
/// .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
///
///
///
///
///
///
///
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
#[cfg_attr(miri, track_caller)] // 即使没有 panic,这也有助于 Miri 回溯
pub const unsafe fn unreachable_unchecked() -> ! {
// SAFETY: 调用者必须遵守 `intrinsics::unreachable` 的安全保证。
//
unsafe {
intrinsics::assert_unsafe_precondition!("hint::unreachable_unchecked must never be reached", () => false);
intrinsics::unreachable()
}
}
/// 发出一条机器指令,以向处理器发送信号,指示其正在忙于等待的自旋循环 (自旋锁) 中运行。
///
/// 在接收到自旋环信号后,处理器可以通过例如节省功率或切换 hyper 线程来优化其行为。
///
/// 此函数不同于 [`thread::yield_now`],后者直接产生系统的调度程序,而 `spin_loop` 不与操作系统交互。
///
/// `spin_loop` 的一个常见用例是在同步原语的 CAS 循环中实现有界乐观旋转。
/// 为避免优先级倒置之类的问题,强烈建议在有限次数的迭代后终止旋转循环,并进行适当的阻塞系统调用。
///
///
/// **Note**: 在不支持接收自旋循环提示的平台上,此函数完全不执行任何操作。
///
/// # Examples
///
/// ```
/// use std::sync::atomic::{AtomicBool, Ordering};
/// use std::sync::Arc;
/// use std::{hint, thread};
///
/// // 线程将用于协调的共享原子值
/// let live = Arc::new(AtomicBool::new(false));
///
/// // 在后台线程中,我们最终将设置该值
/// let bg_work = {
/// let live = live.clone();
/// thread::spawn(move || {
/// // 做一些工作,然后创造值
/// do_some_work();
/// live.store(true, Ordering::Release);
/// })
/// };
///
/// // 回到我们当前的线程,我们等待该值被设置
/// while !live.load(Ordering::Acquire) {
/// // 自旋循环是对我们正在等待的 CPU 的提示,但可能不会持续很长时间
/////
/// hint::spin_loop();
/// }
///
/// // 现在设置该值
/// # fn do_some_work() {}
/// do_some_work();
/// bg_work.join()?;
/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
/// ```
///
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
///
///
///
///
///
///
///
#[inline(always)]
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
#[cfg(target_arch = "x86")]
{
// SAFETY: `cfg` 属性确保我们仅在 x86 目标上执行此操作。
unsafe { crate::arch::x86::_mm_pause() };
}
#[cfg(target_arch = "x86_64")]
{
// SAFETY: `cfg` 属性确保我们仅在 x86_64 目标上执行此操作。
unsafe { crate::arch::x86_64::_mm_pause() };
}
// RISC-V 平台自旋循环提示实现
{
// RISC-V RV32 和 RV64 共享相同的 PAUSE 指令,但它们位于 `core::arch` 中的不同模块中。
//
// 在这种情况下,我们在每个核心 arch 模块中调用 `pause` 函数。
#[cfg(target_arch = "riscv32")]
{
crate::arch::riscv32::pause();
}
#[cfg(target_arch = "riscv64")]
{
crate::arch::riscv64::pause();
}
}
#[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
{
#[cfg(target_arch = "aarch64")]
{
// SAFETY: `cfg` 属性确保我们仅在 aarch64 目标上执行此操作。
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
}
#[cfg(target_arch = "arm")]
{
// SAFETY: `cfg` 属性确保我们仅在支持 v6 特性的 arm 目标上执行此操作。
//
unsafe { crate::arch::arm::__yield() };
}
}
}
/// 一个标识函数,*__hints__* 编译器对 `black_box` 能做的事情保持最大限度的悲观。
///
/// 与 [`std::convert::identity`] 不同,鼓励 Rust 编译器假定 `black_box` 可以以允许 Rust 代码使用的任何可能有效方式使用 `dummy`,而不会在调用代码中引入未定义的行为。
///
/// 此属性使 `black_box` 可用于编写不需要进行某些优化 (例如基准测试) 的代码。
///
/// 但是请注意,`black_box` 仅 (并且只能) 以 "best-effort" 为基础提供。它可以阻止优化的程度可能会有所不同,具体取决于所使用的平台和代码源后端。
/// 程序不能依赖 `black_box` 的*正确性*,除了它作为身份函数。
/// 因此,**不得依赖它来控制关键程序行为。**这立即排除了将此函数直接用于加密或安全目的的任何可能性。
///
/// [`std::convert::identity`]: crate::convert::identity
///
/// # 这什么时候有用?
///
/// 虽然不适合那些关键任务的情况,但通常可以依赖 black_box 的功能进行基准测试,并且应该在那里使用。
/// 它将尝试确保编译器不会根据上下文优化部分预期的测试代码。
/// 例如:
///
/// ```
/// fn contains(haystack: &[&str], needle: &str) -> bool {
/// haystack.iter().any(|x| x == &needle)
/// }
///
/// pub fn benchmark() {
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
/// let needle = "ghi";
/// for _ in 0..10 {
/// contains(&haystack, needle);
/// }
/// }
/// ```
///
/// 编译器理论上可以进行如下优化:
///
/// - `needle` 和 `haystack` 一直一样,把调用移到循环外的 `contains`,删除循环
/// - Inline `contains`
/// - `needle` 和 `haystack` 的值在编译时已知,`contains` 始终为真。去掉调用,换成 `true`
/// - `contains` 的结果没有做任何事情: 完全删除这个函数调用
/// - `benchmark` 现在没有任何意义: 删除这个函数
///
/// 上述所有情况不太可能发生,但编译器肯定能够进行一些优化,这可能会导致基准测试非常不准确。这就是 `black_box` 的用武之地:
///
/// ```
/// use std::hint::black_box;
///
/// // 相同 `contains` 函数
/// fn contains(haystack: &[&str], needle: &str) -> bool {
/// haystack.iter().any(|x| x == &needle)
/// }
///
/// pub fn benchmark() {
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
/// let needle = "ghi";
/// for _ in 0..10 {
/// // 调整我们的基准循环内容
/// black_box(contains(black_box(&haystack), black_box(needle)));
/// }
/// }
/// ```
///
/// 这实质上告诉编译器阻止对 `black_box` 的任何调用的优化。
/// 所以,它现在:
///
/// - 将参数到 `contains` 都视为不可预测: `contains` 的主体不能再根据参数值进行优化
/// - 将调用 `contains` 及其结果视为易变的: `benchmark` 的主体无法优化它
///
/// 这使我们的基准测试更现实地了解函数如何在原位使用,其中函数通常在编译时未知,结果以某种方式使用。
///
///
///
///
///
///
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "bench_black_box", since = "1.66.0")]
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
pub const fn black_box<T>(dummy: T) -> T {
crate::intrinsics::black_box(dummy)
}
/// 如果调用者未使用给定值 (返回、存储在变量中等),则会触发 `unused_must_use` 警告的标识函数。
///
/// 这主要用于宏生成的代码,其中类型或函数上的 [`#[must_use]` 属性][must_use] 不方便。
///
/// [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
///
/// # Example
///
/// ```
/// #![feature(hint_must_use)]
///
/// use core::fmt;
///
/// pub struct Error(/* ... */);
///
/// #[macro_export]
/// macro_rules! make_error {
/// ($($args:expr),*) => {
/// core::hint::must_use({
/// let error = $crate::make_error(core::format_args!($($args),*));
/// error
/// })
/// };
/// }
///
/// // make_error 的实现细节! macro.
/// #[doc(hidden)]
/// pub fn make_error(args: fmt::Arguments<'_>) -> Error {
/// Error(/* ... */)
/// }
///
/// fn demo() -> Option<Error> {
/// if true {
/// // 哎呀,本来想写 `return Some(make_error!("..."));`
/// Some(make_error!("..."));
/// }
/// None
/// }
/// #
/// # // 使 rustdoc 不在 fn main 中包装整个片段,以便 $crate::make_error 工作
/// # fn main() {}
/// ```
///
/// 在上面的示例中,我们希望 `unused_must_use` lint 应用于 `make_error!` 创建的值。
/// 但是,结构体上的 `#[must_use]` 和函数上的 `#[must_use]` 都不适用于这里,因此宏使用 `core::hint::must_use` 进行扩展。
///
/// - 我们不希望在 `struct Error` 上使用 `#[must_use]`,因为这会使以下无问题的代码触发警告:
///
/// ```
/// # struct Error;
/// #
/// fn f(arg: &str) -> Result<(), Error>
/// # { Ok(()) }
///
/// #[test]
/// fn t() {
/// // 如果传递一个空字符串,则断言 `f` 将返回错误。
/// // 这里没有使用 `Error` 类型的值,但这不是问题。
/// f("").unwrap_err();
/// }
/// ```
///
/// - 在 `fn make_error` 上使用 `#[must_use]` 无济于事,因为返回值 *is* 被用作 `let` 语句的右侧。
/// `let` 语句看起来毫无用处,但实际上对于确保 `format_args` 扩展中的临时对象在创建 `Error` 之后不会保持活动状态是必要的,因为在创建 `Error` 之后保持它们活动可能会导致异步代码中的 autotrait 问题:
///
///
/// ```
/// # #![feature(hint_must_use)]
/// #
/// # struct Error;
/// #
/// # macro_rules! make_error {
/// # ($($args:expr),*) => {
/// # core::hint::must_use({
/// # // 如果不使用 `let`,则 `f()` 生成一个不发送的 future。
/// # let error = make_error(core::format_args!($($args),*));
/// # error
/// # })
/// # };
/// # }
/// #
/// # fn make_error(args: core::fmt::Arguments<'_>) -> Error {
/// # Error
/// # }
/// #
/// async fn f() {
/// // 在 make_error 扩展中使用 `let` 会导致诸如 `unsync()` 之类的临时变量在 `let` 语句的分号处,该分号位于 await 点之前。
/// // 否则它们会一直停留在 *this* 语句的分号上,也就是在 await 点之后,并且封闭的 Future 不会实现 Send。
/////
/////
/////
/// log(make_error!("look: {:p}", unsync())).await;
/// }
///
/// async fn log(error: Error) {/* ... */}
///
/// // 返回没有 Sync impl 的内容。
/// fn unsync() -> *const () {
/// 0 as *const ()
/// }
/// #
/// # fn test() {
/// # fn assert_send(_: impl Send) {}
/// # assert_send(f());
/// # }
/// ```
///
///
///
///
///
///
///
///
///
///
#[unstable(feature = "hint_must_use", issue = "94745")]
#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
#[must_use] // <-- :)
#[inline(always)]
pub const fn must_use<T>(value: T) -> T {
value
}