hint.rs.html -- source
Description: Source to the Rust file `src\libcore\hint.rs`.
Keywords: rust, rustlang, rust-lang

      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

    #![stable(feature = "core_hint", since = "1.27.0")]

    //! Hints to compiler that affects how code should be emitted or optimized.

    use crate::intrinsics;

    /// Informs the compiler that this point in the code is not reachable, enabling
    /// further optimizations.
    ///
    /// # Safety
    ///
    /// Reaching this function is completely *undefined behavior* (UB). In
    /// particular, the compiler assumes that all UB must never happen, and
    /// therefore will eliminate all branches that reach to a call to
    /// `unreachable_unchecked()`.
    ///
    /// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
    /// `unreachable_unchecked()` call is actually reachable among all possible
    /// control flow, the compiler will apply the wrong optimization strategy, and
    /// may sometimes even corrupt seemingly unrelated code, causing
    /// difficult-to-debug problems.
    ///
    /// Use this function only when you can prove that the code will never call it.
    /// Otherwise, consider using the [`unreachable!`] macro, which does not allow
    /// optimizations but will panic when executed.
    ///
    /// [`unreachable!`]: ../macro.unreachable.html
    ///
    /// # Example
    ///
    /// ```
    /// fn div_1(a: u32, b: u32) -> u32 {
    ///     use std::hint::unreachable_unchecked;
    ///
    ///     // `b.saturating_add(1)` is always positive (not zero),
    ///     // hence `checked_div` will never return `None`.
    ///     // Therefore, the else branch is unreachable.
    ///     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")]
    pub unsafe fn unreachable_unchecked() -> ! {
        // SAFETY: the safety contract for `intrinsics::unreachable` must
        // be upheld by the caller.
        unsafe { intrinsics::unreachable() }
    }

    /// Emits a machine instruction hinting to the processor that it is running in busy-wait
    /// spin-loop ("spin lock").
    ///
    /// For a discussion of different locking strategies and their trade-offs, see
    /// [`core::sync::atomic::spin_loop_hint`].
    ///
    /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
    /// do anything at all.
    ///
    /// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
    #[inline]
    #[unstable(feature = "renamed_spin_loop", issue = "55002")]
    pub fn spin_loop() {
        #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
        {
            #[cfg(target_arch = "x86")]
            {
                // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
                unsafe { crate::arch::x86::_mm_pause() };
            }

            #[cfg(target_arch = "x86_64")]
            {
                // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
                unsafe { crate::arch::x86_64::_mm_pause() };
            }
        }

        #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
        {
            #[cfg(target_arch = "aarch64")]
            {
                // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
                unsafe { crate::arch::aarch64::__yield() };
            }
            #[cfg(target_arch = "arm")]
            {
                // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
                // with support for the v6 feature.
                unsafe { crate::arch::arm::__yield() };
            }
        }
    }

    /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
    /// `black_box` could do.
    ///
    /// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
    ///
    /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
    /// use `x` in any possible valid way that Rust code is allowed to without introducing undefined
    /// behavior in the calling code. This property makes `black_box` useful for writing code in which
    /// certain optimizations are not desired, such as benchmarks.
    ///
    /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
    /// extent to which it can block optimisations may vary depending upon the platform and code-gen
    /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
    #[inline]
    #[unstable(feature = "test", issue = "50297")]
    #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
    pub fn black_box<T>(dummy: T) -> T {
        // We need to "use" the argument in some way LLVM can't introspect, and on
        // targets that support it we can typically leverage inline assembly to do
        // this. LLVM's interpretation of inline assembly is that it's, well, a black
        // box. This isn't the greatest implementation since it probably deoptimizes
        // more than we want, but it's so far good enough.

        // SAFETY: the inline assembly is a no-op.
        unsafe {
            llvm_asm!("" : : "r"(&dummy));
            dummy
        }
    }