diff options
| author | bors <bors@rust-lang.org> | 2023-09-29 13:53:11 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-29 13:53:11 +0000 |
| commit | a6dfd89fa76e5dda36d07463d0e54268d6240b49 (patch) | |
| tree | c687590b80d1883c33ccbbd6fcd605bfed3968ea | |
| parent | c5450191f313658d206dc7539311f665a274947f (diff) | |
| parent | 9b7f9c4328dde77396f815dc929de6cdbc700531 (diff) | |
| download | rust-a6dfd89fa76e5dda36d07463d0e54268d6240b49.tar.gz rust-a6dfd89fa76e5dda36d07463d0e54268d6240b49.zip | |
Auto merge of #113797 - RalfJung:offset_from_docs, r=workingjubilee
offset_from: docs improvements This is the part of https://github.com/rust-lang/rust/pull/112837 that doesn't add a new function, just tweaks the existing docs.
| -rw-r--r-- | library/core/src/ptr/const_ptr.rs | 23 | ||||
| -rw-r--r-- | library/core/src/ptr/mut_ptr.rs | 23 |
2 files changed, 40 insertions, 6 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ee69d89a4b7..9af8f1228f0 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,7 +607,16 @@ impl<T: ?Sized> *const T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::<T>()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: #method.offset /// @@ -616,7 +625,7 @@ impl<T: ?Sized> *const T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -646,6 +655,14 @@ impl<T: ?Sized> *const T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::<T>()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -703,7 +720,7 @@ impl<T: ?Sized> *const T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6d623b82c1c..109c286929b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,7 +781,16 @@ impl<T: ?Sized> *mut T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::<T>()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: pointer#method.offset-1 /// @@ -790,7 +799,7 @@ impl<T: ?Sized> *mut T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -820,6 +829,14 @@ impl<T: ?Sized> *mut T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::<T>()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -875,7 +892,7 @@ impl<T: ?Sized> *mut T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, |
