about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/ptr/const_ptr.rs92
-rw-r--r--library/core/src/ptr/mut_ptr.rs92
2 files changed, 112 insertions, 72 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 8fd9ff768c4..38519f759ae 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -232,23 +232,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
-    /// is *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
+    /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// Compared to [`offset`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
+    ///
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
+    /// words, leaving the allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -571,19 +575,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`add`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -628,19 +640,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`sub`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 5f94c2393ae..92f4e431de4 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -238,23 +238,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
-    /// is *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
+    /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// Compared to [`offset`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
+    ///
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
+    /// words, leaving the allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -678,19 +682,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`add`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -735,19 +747,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`sub`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.