@@ -310,13 +310,41 @@ pub fn spin_loop() {
310
310
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
311
311
/// certain optimizations are not desired, such as benchmarks.
312
312
///
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
+ ///
313
339
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
314
340
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
315
341
/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
316
342
/// identity function. As such, it **must not be relied upon to control critical program behavior.**
317
343
/// This also means that this function does not offer any guarantees for cryptographic or security
318
344
/// purposes.
319
345
///
346
+ /// </div>
347
+ ///
320
348
/// [`std::convert::identity`]: crate::convert::identity
321
349
///
322
350
/// # When is this useful?
@@ -357,7 +385,7 @@ pub fn spin_loop() {
357
385
/// ```
358
386
/// use std::hint::black_box;
359
387
///
360
- /// // Same `contains` function
388
+ /// // Same `contains` function.
361
389
/// fn contains(haystack: &[&str], needle: &str) -> bool {
362
390
/// haystack.iter().any(|x| x == &needle)
363
391
/// }
@@ -366,8 +394,13 @@ pub fn spin_loop() {
366
394
/// let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
367
395
/// let needle = "ghi";
368
396
/// 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
+ /// ));
371
404
/// }
372
405
/// }
373
406
/// ```
0 commit comments