Skip to content

Commit 1f13be2

Browse files
committed
feat: clarify how to use black_box()
1 parent c94848c commit 1f13be2

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

library/core/src/hint.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,41 @@ pub fn spin_loop() {
310310
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
311311
/// certain optimizations are not desired, such as benchmarks.
312312
///
313+
/// In practice, `black_box` serves two purposes:
314+
///
315+
/// 1. It forces the input to be calculated, even if its results are never used
316+
/// 2. It prevents the compiler from making optimizations related to the value of the returned
317+
/// type
318+
///
319+
/// Note that `black_box` does not prevent its inputs from being optimized before they are passed
320+
/// to the function, though.
321+
///
322+
/// ```
323+
/// // This...
324+
/// let y = black_box(5 * 10);
325+
/// // ...will still be optimized to this:
326+
/// let y = black_box(50);
327+
/// ```
328+
///
329+
/// In the above example, `5 * 10` is replaced with `50` by the compiler. You can prevent this by
330+
/// moving the multiplication outside of `black_box`:
331+
///
332+
/// ```
333+
/// // No assumptions can be made about either number, so the multiplication is kept.
334+
/// let y = black_box(5) * black_box(10);
335+
/// ```
336+
///
337+
/// <div class="warning">
338+
///
313339
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
314340
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
315341
/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
316342
/// identity function. As such, it **must not be relied upon to control critical program behavior.**
317343
/// This also means that this function does not offer any guarantees for cryptographic or security
318344
/// purposes.
319345
///
346+
/// </div>
347+
///
320348
/// [`std::convert::identity`]: crate::convert::identity
321349
///
322350
/// # When is this useful?
@@ -357,7 +385,7 @@ pub fn spin_loop() {
357385
/// ```
358386
/// use std::hint::black_box;
359387
///
360-
/// // Same `contains` function
388+
/// // Same `contains` function.
361389
/// fn contains(haystack: &[&str], needle: &str) -> bool {
362390
/// haystack.iter().any(|x| x == &needle)
363391
/// }
@@ -366,8 +394,13 @@ pub fn spin_loop() {
366394
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
367395
/// let needle = "ghi";
368396
/// for _ in 0..10 {
369-
/// // Adjust our benchmark loop contents
370-
/// black_box(contains(black_box(&haystack), black_box(needle)));
397+
/// // Force the compiler to run `contains`, even though it is a pure function whose
398+
/// // results are unused.
399+
/// black_box(contains(
400+
/// // Prevent the compiler from making assumptions about the input.
401+
/// black_box(&haystack),
402+
/// black_box(needle),
403+
/// ));
371404
/// }
372405
/// }
373406
/// ```

0 commit comments

Comments
 (0)