From 62bdb1a6e0011d6dbbcc552afebaffbd8fd26104 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Jul 2023 17:45:31 +0200 Subject: [PATCH 1/5] offset_from: docs improvements --- library/core/src/ptr/const_ptr.rs | 12 ++++++++++-- library/core/src/ptr/mut_ptr.rs | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ee69d89a4b720..b89e9e260e739 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,7 +607,9 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]. + /// This function is the inverse of [`offset`]: it is valid to call if and only if + /// `self` could have been computed as `origin.offset(n)` for some `n`, and it will + /// then return that `n`. /// /// [`offset`]: #method.offset /// @@ -646,6 +648,12 @@ impl *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: at compile-time, pointers into *different* allocated + /// object do not have a known distance to each other. However, the requirement also exists at + /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as + /// usize) / mem::size_of::()` to avoid this requirement. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -703,7 +711,7 @@ impl *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 6d623b82c1cfe..e7611c90344bf 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,7 +781,9 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]. + /// This function is the inverse of [`offset`]: it is valid to call if and only if + /// `self` could have been computed as `origin.offset(n)` for some `n`, and it will + /// then return that `n`. /// /// [`offset`]: pointer#method.offset-1 /// @@ -820,6 +822,12 @@ impl *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: at compile-time, pointers into *different* allocated + /// object do not have a known distance to each other. However, the requirement also exists at + /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as + /// usize) / mem::size_of::()` to avoid this requirement. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -875,7 +883,7 @@ impl *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, From 39b53dc204e944e37fef621d4799a561f423cfd3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Jul 2023 14:24:11 +0200 Subject: [PATCH 2/5] documentation tweaks --- library/core/src/ptr/const_ptr.rs | 12 ++++++------ library/core/src/ptr/mut_ptr.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b89e9e260e739..97aa3015bf1fc 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,9 +607,8 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]: it is valid to call if and only if - /// `self` could have been computed as `origin.offset(n)` for some `n`, and it will - /// then return that `n`. + /// This function is the inverse of [`offset`]: it is valid to call and will return + /// `n` if and only if `origin.offset(n)` is valid to call and will return `self`. /// /// [`offset`]: #method.offset /// @@ -650,9 +649,10 @@ impl *const T { /// /// The requirement for pointers to be derived from the same allocated object is primarily /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated - /// object do not have a known distance to each other. However, the requirement also exists at - /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as - /// usize) / mem::size_of::()` to avoid this requirement. + /// objects do not have a known distance to each other. 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 + /// usize).sub(origin as usize) / mem::size_of::()`. /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e7611c90344bf..2f21319d559dc 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,9 +781,8 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]: it is valid to call if and only if - /// `self` could have been computed as `origin.offset(n)` for some `n`, and it will - /// then return that `n`. + /// This function is the inverse of [`offset`]: it is valid to call and will return + /// `n` if and only if `origin.offset(n)` is valid to call and will return `self`. /// /// [`offset`]: pointer#method.offset-1 /// @@ -824,9 +823,10 @@ impl *mut T { /// /// The requirement for pointers to be derived from the same allocated object is primarily /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated - /// object do not have a known distance to each other. However, the requirement also exists at - /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as - /// usize) / mem::size_of::()` to avoid this requirement. + /// objects do not have a known distance to each other. 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 + /// usize).sub(origin as usize) / mem::size_of::()`. /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object From 14625f5b3ec9730bef12c63f7d4fb4c43d118d7a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Aug 2023 16:44:54 +0200 Subject: [PATCH 3/5] consistent wording --- library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 97aa3015bf1fc..0f589647a47fe 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -648,8 +648,8 @@ impl *const T { /// such large allocations either.) /// /// The requirement for pointers to be derived from the same allocated object is primarily - /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated - /// objects do not have a known distance to each other. However, the requirement also exists at + /// 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 /// usize).sub(origin as usize) / mem::size_of::()`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 2f21319d559dc..d395319b6f39d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -822,8 +822,8 @@ impl *mut T { /// such large allocations either.) /// /// The requirement for pointers to be derived from the same allocated object is primarily - /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated - /// objects do not have a known distance to each other. However, the requirement also exists at + /// 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 /// usize).sub(origin as usize) / mem::size_of::()`. From 6c73f254b977574a2e155dc18c4f96746071f4e0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 Sep 2023 08:31:16 +0200 Subject: [PATCH 4/5] avoid talking about inverses --- library/core/src/ptr/const_ptr.rs | 12 +++++++----- library/core/src/ptr/mut_ptr.rs | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0f589647a47fe..3e68216e40eda 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,8 +607,9 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]: it is valid to call and will return - /// `n` if and only if `origin.offset(n)` is valid to call and will return `self`. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. /// /// [`offset`]: #method.offset /// @@ -617,7 +618,7 @@ impl *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. @@ -651,8 +652,9 @@ impl *const T { /// 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 - /// usize).sub(origin as usize) / mem::size_of::()`. + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index d395319b6f39d..c89ce52292a3d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,8 +781,9 @@ impl *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::()`. /// - /// This function is the inverse of [`offset`]: it is valid to call and will return - /// `n` if and only if `origin.offset(n)` is valid to call and will return `self`. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. /// /// [`offset`]: pointer#method.offset-1 /// @@ -791,7 +792,7 @@ impl *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. @@ -825,8 +826,9 @@ impl *mut T { /// 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 - /// usize).sub(origin as usize) / mem::size_of::()`. + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object From 9b7f9c4328dde77396f815dc929de6cdbc700531 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Sep 2023 16:41:06 +0200 Subject: [PATCH 5/5] take more clarifying text from Gankra's PR original source: https://github.com/rust-lang/rust/pull/95851 --- library/core/src/ptr/const_ptr.rs | 7 +++++++ library/core/src/ptr/mut_ptr.rs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3e68216e40eda..9af8f1228f0b6 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -611,6 +611,13 @@ impl *const T { /// 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 /// /// # Safety diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index c89ce52292a3d..109c286929b4e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -785,6 +785,13 @@ impl *mut T { /// 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 /// /// # Safety