Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New name for hint::black_box: pretend_used #74853

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 13 additions & 11 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,25 @@ pub fn spin_loop() {
}
}

/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
/// An identity function that asks the compiler to pretend that the given value is used in some
/// arbitrary but valid way.
///
/// [`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 `pretend_used`
/// may use `x` in any possible valid way that Rust code is allowed to without introducing
/// undefined behavior in the calling code. This property makes `pretend_used` useful for writing
/// code in which certain optimizations are not desired, such as benchmarks. For example, if an
/// expression whose value is never used is passed through `pretend_used`, the compiler is
/// encouraged to compute the value of that expression rather than eliminate it as dead code.
///
/// 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 `pretend_used` 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 `pretend_used` for *correctness* in any way.
///
/// 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.
/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
#[inline]
#[unstable(feature = "test", issue = "50297")]
#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
pub fn black_box<T>(dummy: T) -> T {
pub fn pretend_used<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
Expand Down
2 changes: 1 addition & 1 deletion library/test/src/bench.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Benchmarking module.
pub use std::hint::black_box;
pub use std::hint::pretend_used as black_box;

use super::{
event::CompletedTest, helpers::sink::Sink, options::BenchMode, test_result::TestResult,
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/sanitize/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

#![feature(test)]

use std::hint::black_box;
use std::hint::pretend_used;

fn main() {
let xs = [0, 1, 2, 3];
// Avoid optimizing everything out.
let xs = black_box(xs.as_ptr());
let xs = pretend_used(xs.as_ptr());
let code = unsafe { *xs.offset(4) };
std::process::exit(code);
}
4 changes: 2 additions & 2 deletions src/test/ui/sanitize/leak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

#![feature(test)]

use std::hint::black_box;
use std::hint::pretend_used;
use std::mem;

fn main() {
for _ in 0..10 {
let xs = vec![1, 2, 3];
// Prevent compiler from removing the memory allocation.
let xs = black_box(xs);
let xs = pretend_used(xs);
mem::forget(xs);
}
}
4 changes: 2 additions & 2 deletions src/test/ui/sanitize/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
#![feature(start)]
#![feature(test)]

use std::hint::black_box;
use std::hint::pretend_used;
use std::mem::MaybeUninit;

#[inline(never)]
#[no_mangle]
fn random() -> [isize; 32] {
let r = unsafe { MaybeUninit::uninit().assume_init() };
// Avoid optimizing everything out.
black_box(r)
pretend_used(r)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretend_use / blackbox / ... is the completely wrong function to call here right? It doesn't help with correctness and this whole code relies on the black box hiding the fact that it's UB to read uninitialized memory from the compiler. (Same in the address sanitizer test)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I think what's going on here is actually that we want the code to be incorrect, but without pretend_used (as the comment implies) the r would be entirely optimized out by the compiler. pretend_used here causes the compiler to leave r in, which in turn means that the undefined behavior can be detected by the sanitizer.

}

#[inline(never)]
Expand Down