Skip to content

Commit

Permalink
Update documentation for hint::assert_unchecked
Browse files Browse the repository at this point in the history
Rearrange the sections and add an example to
`core::hint::assert_unchecked`.
  • Loading branch information
tgross35 committed Apr 7, 2024
1 parent 55e1775 commit 5ce23c1
Showing 1 changed file with 28 additions and 20 deletions.
48 changes: 28 additions & 20 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,35 +114,41 @@ pub const unsafe fn unreachable_unchecked() -> ! {
/// This may allow the optimizer to simplify things, but it might also make the generated code
/// slower. Either way, calling it will most likely make compilation take longer.
///
/// This is a situational tool for micro-optimization, and is allowed to do nothing.
/// Any use should come with a repeatable benchmark to show the value
/// and allow removing it later should the optimizer get smarter and no longer need it.
/// You may know this from other places as
/// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C,
/// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume).
///
/// The more complicated the condition the less likely this is to be fruitful.
/// For example, `assert_unchecked(foo.is_sorted())` is a complex enough value
/// that the compiler is unlikely to be able to take advantage of it.
/// This promotes a correctness requirement to a soundness requirement. Don't do that without
/// very good reason.
///
/// There's also no need to `assert_unchecked` basic properties of things. For
/// example, the compiler already knows the range of `count_ones`, so there's no
/// benefit to `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`.
/// # Usage
///
/// If ever you're tempted to write `assert_unchecked(false)`, then you're
/// actually looking for [`unreachable_unchecked()`].
/// This is a situational tool for micro-optimization, and is allowed to do nothing. Any use
/// should come with a repeatable benchmark to show the value, with the expectation to drop it
/// later should the optimizer get smarter and no longer need it.
///
/// You may know this from other places as
/// [`llvm.assume`](https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic) or, in C,
/// [`__builtin_assume`](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-assume).
/// The more complicated the condition, the less likely this is to be fruitful. For example,
/// `assert_unchecked(foo.is_sorted())` is a complex enough value that the compiler is unlikely
/// to be able to take advantage of it.
///
/// There's also no need to `assert_unchecked` basic properties of things. For example, the
/// compiler already knows the range of `count_ones`, so there is no benefit to
/// `let n = u32::count_ones(x); assert_unchecked(n <= u32::BITS);`.
///
/// This promotes a correctness requirement to a soundness requirement.
/// Don't do that without very good reason.
/// In release mode, the argument will most likely not actually be evaluated.
///
/// If ever you are tempted to write `assert_unchecked(false)`, then you are actually looking for
/// [`unreachable_unchecked()`].
///
/// # Safety
///
/// `cond` must be `true`. It's immediate UB to call this with `false`.
/// `cond` must be `true`. It is immediate UB to call this with `false`.
///
/// # Example
///
/// ```
/// #![feature(hint_assert_unchecked)]
///
/// use core::hint;
///
/// /// # Safety
Expand All @@ -161,7 +167,8 @@ pub const unsafe fn unreachable_unchecked() -> ! {
/// }
/// ```
///
/// Without the `assert_unchecked`, the above function produces the following with optimizations:
/// Without the `assert_unchecked`, the above function produces the following with optimizations
/// enabled:
///
/// ```asm
/// next_value:
Expand All @@ -186,8 +193,9 @@ pub const unsafe fn unreachable_unchecked() -> ! {
///
/// This example is quite unlike anything that would happen in the real world: it is redundant to
/// put an an assertion right next to code that checks the same thing, and dereferencing a
/// pointer already has the builtin assumption that it is nonnull. The optimizer can make use of
/// this information even when it isn't obvious, such as when checks happen in called functions.
/// pointer already has the builtin assumption that it is nonnull. However, the optimizer can
/// make use of this information even when it isn't as obvious, such as when checks happen in
/// called functions.
#[inline(always)]
#[doc(alias = "assume")]
#[track_caller]
Expand Down

0 comments on commit 5ce23c1

Please sign in to comment.