Skip to content
Closed
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
799fa60
llvm-wrapper: adapt for LLVM API change
krasimirgg Dec 24, 2022
13e25b8
Improve the documentation of `black_box`
tgross35 Dec 25, 2022
b467547
Update cc to 1.0.77
glandium Jan 12, 2023
f6d8abf
Re-enable building rust-analyzer on riscv64
cuviper Jan 18, 2023
fa7d17d
Create new bootstrap team
albertlarsan68 Jan 19, 2023
134b2d0
Remove duplicated debug call
spastorino Nov 24, 2022
ee4a4c9
Store relationships on Inherent
spastorino Nov 25, 2022
dc90fb3
Move relationships::update to Inherited::update_infer_var_info
spastorino Jan 20, 2023
3733844
Rename relationships to infer_var_info
spastorino Jan 20, 2023
8742fd9
Label closure captures/generator locals that make opaque types recursive
compiler-errors Jan 8, 2023
dc88761
Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report
Aaron1011 Oct 22, 2022
7a2b5c8
Rollup merge of #103418 - Aaron1011:macro-semicolon-future-incompat, …
compiler-errors Jan 22, 2023
3c10728
Rollup merge of #104926 - spastorino:calculate_diverging_fallback-cle…
compiler-errors Jan 22, 2023
6472f31
Rollup merge of #106113 - krasimirgg:llvm-16-ext-tyid, r=nikic
compiler-errors Jan 22, 2023
03a069c
Rollup merge of #106144 - tgross35:patch-1, r=Mark-Simulacrum
compiler-errors Jan 22, 2023
f8b287d
Rollup merge of #106578 - compiler-errors:recursive-opaque-closure, r…
compiler-errors Jan 22, 2023
cfc1738
Rollup merge of #106749 - glandium:dwarf, r=Mark-Simulacrum
compiler-errors Jan 22, 2023
65e946b
Rollup merge of #107015 - cuviper:ra-riscv64, r=Mark-Simulacrum
compiler-errors Jan 22, 2023
0f1dca8
Rollup merge of #107029 - albertlarsan68:patch-2, r=Mark-Simulacrum
compiler-errors Jan 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,75 @@ pub fn spin_loop() {
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: crate::convert::identity
///
/// # When is this useful?
///
/// First and foremost: `black_box` does _not_ guarantee any exact behavior and, in some cases, may
/// do nothing at all. As such, it **must not be relied upon to control critical program behavior.**
/// This _immediately_ precludes any direct use of this function for cryptographic or security
/// purposes.
///
/// While not suitable in those mission-critical cases, `back_box`'s functionality can generally be
/// relied upon for benchmarking, and should be used there. It will try to ensure that the
/// compiler doesn't optimize away part of the intended test code based on context. For
/// example:
///
/// ```
/// 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);
/// }
/// }
/// ```
///
/// The compiler could theoretically make optimizations like the following:
///
/// - `needle` and `haystack` are always the same, move the call to `contains` outside the loop and
/// delete the loop
/// - Inline `contains`
/// - `needle` and `haystack` have values known at compile time, `contains` is always true. Remove
/// the call and replace with `true`
/// - Nothing is done with the result of `contains`: delete this function call entirely
/// - `benchmark` now has no purpose: delete this function
///
/// It is not likely that all of the above happens, but the compiler is definitely able to make some
/// optimizations that could result in a very inaccurate benchmark. This is where `black_box` comes
/// in:
///
/// ```
/// use std::hint::black_box;
///
/// // Same `contains` function
/// 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 {
/// // Adjust our benchmark loop contents
/// black_box(contains(black_box(&haystack), black_box(needle)));
/// }
/// }
/// ```
///
/// This essentially tells the compiler to block optimizations across any calls to `black_box`. So,
/// it now:
///
/// - Treats both arguments to `contains` as unpredictable: the body of `contains` can no longer be
/// optimized based on argument values
/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
/// optimize this away
///
/// This makes our benchmark much more realistic to how the function would be used in situ, where
/// arguments are usually not known at compile time and the result is used in some way.
#[inline]
#[stable(feature = "bench_black_box", since = "1.66.0")]
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
Expand Down