diff options
| author | Ralf Jung <post@ralfj.de> | 2025-05-23 22:48:50 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2025-06-06 22:34:10 +0200 |
| commit | 910a59dfae6c60bae36a1c0eb478f46c624512ba (patch) | |
| tree | 8dcbfd1a473943519a874f384fa9e72e5a3a3307 | |
| parent | d00435f223dc3a88d8c5f472b10ba948b7959cc6 (diff) | |
| download | rust-910a59dfae6c60bae36a1c0eb478f46c624512ba.tar.gz rust-910a59dfae6c60bae36a1c0eb478f46c624512ba.zip | |
unsafe keyword docs: emphasize that an unsafe fn in a trait does not get to choose its safety contract
| -rw-r--r-- | library/std/src/keyword_docs.rs | 27 |
1 files changed, 11 insertions, 16 deletions
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 79b25040ef6..1c55824ab90 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1916,10 +1916,6 @@ mod type_keyword {} /// - and to declare that a programmer has checked that these contracts have been upheld (`unsafe /// {}` and `unsafe impl`, but also `unsafe fn` -- see below). /// -/// They are not mutually exclusive, as can be seen in `unsafe fn`: the body of an `unsafe fn` is, -/// by default, treated like an unsafe block. The `unsafe_op_in_unsafe_fn` lint can be enabled to -/// change that. -/// /// # Unsafe abilities /// /// **No matter what, Safe Rust can't cause Undefined Behavior**. This is @@ -1961,13 +1957,6 @@ mod type_keyword {} /// - `unsafe impl`: the contract necessary to implement the trait has been /// checked by the programmer and is guaranteed to be respected. /// -/// By default, `unsafe fn` also acts like an `unsafe {}` block -/// around the code inside the function. This means it is not just a signal to -/// the caller, but also promises that the preconditions for the operations -/// inside the function are upheld. Mixing these two meanings can be confusing, so the -/// `unsafe_op_in_unsafe_fn` lint can be enabled to warn against that and require explicit unsafe -/// blocks even inside `unsafe fn`. -/// /// See the [Rustonomicon] and the [Reference] for more information. /// /// # Examples @@ -2109,6 +2098,7 @@ mod type_keyword {} /// impl Indexable for i32 { /// const LEN: usize = 1; /// +/// /// See `Indexable` for the safety contract. /// unsafe fn idx_unchecked(&self, idx: usize) -> i32 { /// debug_assert_eq!(idx, 0); /// *self @@ -2120,6 +2110,7 @@ mod type_keyword {} /// impl Indexable for [i32; 42] { /// const LEN: usize = 42; /// +/// /// See `Indexable` for the safety contract. /// unsafe fn idx_unchecked(&self, idx: usize) -> i32 { /// // SAFETY: As per this trait's documentation, the caller ensures /// // that `idx < 42`. @@ -2132,6 +2123,7 @@ mod type_keyword {} /// impl Indexable for ! { /// const LEN: usize = 0; /// +/// /// See `Indexable` for the safety contract. /// unsafe fn idx_unchecked(&self, idx: usize) -> i32 { /// // SAFETY: As per this trait's documentation, the caller ensures /// // that `idx < 0`, which is impossible, so this is dead code. @@ -2153,11 +2145,14 @@ mod type_keyword {} /// contract of `idx_unchecked`. Implementing `Indexable` is safe because when writing /// `idx_unchecked`, we don't have to worry: our *callers* need to discharge a proof obligation /// (like `use_indexable` does), but the *implementation* of `get_unchecked` has no proof obligation -/// to contend with. Of course, the implementation of `Indexable` may choose to call other unsafe -/// operations, and then it needs an `unsafe` *block* to indicate it discharged the proof -/// obligations of its callees. (We enabled `unsafe_op_in_unsafe_fn`, so the body of `idx_unchecked` -/// is not implicitly an unsafe block.) For that purpose it can make use of the contract that all -/// its callers must uphold -- the fact that `idx < LEN`. +/// to contend with. Of course, the implementation may choose to call other unsafe operations, and +/// then it needs an `unsafe` *block* to indicate it discharged the proof obligations of its +/// callees. For that purpose it can make use of the contract that all its callers must uphold -- +/// the fact that `idx < LEN`. +/// +/// Note that unlike normal `unsafe fn`, an `unsafe fn` in a trait implementation does not get to +/// just pick an arbitrary safety contract! It *has* to use the safety contract defined by the trait +/// (or one with weaker preconditions). /// /// Formally speaking, an `unsafe fn` in a trait is a function with *preconditions* that go beyond /// those encoded by the argument types (such as `idx < LEN`), whereas an `unsafe trait` can declare |
