about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-12 10:58:13 +0200
committerGitHub <noreply@github.com>2019-08-12 10:58:13 +0200
commite9615f2487dc2acdad2d1dd7668808728f99e310 (patch)
tree0eb16276ced8ea4daa946536040be667cb465792 /src
parent0b4823de23ea6af70f49bd7fb8e811fc6dffe006 (diff)
parent0dc9e2a56502c1138c6faf021888844905e64cf3 (diff)
downloadrust-e9615f2487dc2acdad2d1dd7668808728f99e310.tar.gz
rust-e9615f2487dc2acdad2d1dd7668808728f99e310.zip
Rollup merge of #63297 - RalfJung:ptr_offset, r=dtolnay
Improve pointer offset method docs

Cc @rkruppe @gnzlbg
Diffstat (limited to 'src')
-rw-r--r--src/libcore/ptr/mod.rs162
1 files changed, 128 insertions, 34 deletions
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index fa55bbf9c16..f5fbd1a6b13 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1120,7 +1120,8 @@ impl<T: ?Sized> *const T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset, **in bytes**, cannot overflow an `isize`.
     ///
@@ -1140,10 +1141,12 @@ impl<T: ?Sized> *const T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_offset`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_offset`]: #method.wrapping_offset
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1172,15 +1175,26 @@ impl<T: ?Sized> *const T {
     ///
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
-    /// In particular, the resulting pointer may *not* be used to access a
-    /// different allocated object than the one `self` points to. In other
-    /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+    ///
+    /// 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.
+    ///
+    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
     /// *not* the same as `y`, and dereferencing it is undefined behavior
     /// unless `x` and `y` point into the same allocated object.
     ///
-    /// Always use `.offset(count)` instead when possible, because `offset`
-    /// allows the compiler to optimize better. If you need to cross object
-    /// boundaries, cast the pointer to an integer and do the arithmetic there.
+    /// 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 preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`offset`]: #method.offset
     ///
     /// # Examples
     ///
@@ -1223,7 +1237,8 @@ impl<T: ?Sized> *const T {
     /// Behavior:
     ///
     /// * Both the starting and other pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
     ///
@@ -1338,7 +1353,8 @@ impl<T: ?Sized> *const T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset, **in bytes**, cannot overflow an `isize`.
     ///
@@ -1358,10 +1374,12 @@ impl<T: ?Sized> *const T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_add`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_add`]: #method.wrapping_add
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1395,7 +1413,8 @@ impl<T: ?Sized> *const T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset cannot exceed `isize::MAX` **bytes**.
     ///
@@ -1415,10 +1434,12 @@ impl<T: ?Sized> *const T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_sub`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_sub`]: #method.wrapping_sub
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1451,8 +1472,21 @@ impl<T: ?Sized> *const T {
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
     ///
-    /// Always use `.add(count)` instead when possible, because `add`
-    /// allows the compiler to optimize better.
+    /// 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 that pointer is dereferenced. [`add`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`add`]: #method.add
     ///
     /// # Examples
     ///
@@ -1492,8 +1526,21 @@ impl<T: ?Sized> *const T {
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
     ///
-    /// Always use `.sub(count)` instead when possible, because `sub`
-    /// allows the compiler to optimize better.
+    /// 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 that pointer is dereferenced. [`sub`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`sub`]: #method.sub
     ///
     /// # Examples
     ///
@@ -1757,7 +1804,8 @@ impl<T: ?Sized> *mut T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset, **in bytes**, cannot overflow an `isize`.
     ///
@@ -1777,10 +1825,12 @@ impl<T: ?Sized> *mut T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_offset`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_offset`]: #method.wrapping_offset
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1808,15 +1858,26 @@ impl<T: ?Sized> *mut T {
     ///
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
-    /// In particular, the resulting pointer may *not* be used to access a
-    /// different allocated object than the one `self` points to. In other
-    /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+    ///
+    /// 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.
+    ///
+    /// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
     /// *not* the same as `y`, and dereferencing it is undefined behavior
     /// unless `x` and `y` point into the same allocated object.
     ///
-    /// Always use `.offset(count)` instead when possible, because `offset`
-    /// allows the compiler to optimize better. If you need to cross object
-    /// boundaries, cast the pointer to an integer and do the arithmetic there.
+    /// 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 preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`offset`]: #method.offset
     ///
     /// # Examples
     ///
@@ -1903,7 +1964,8 @@ impl<T: ?Sized> *mut T {
     /// Behavior:
     ///
     /// * Both the starting and other pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
     ///
@@ -2007,7 +2069,8 @@ impl<T: ?Sized> *mut T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset, **in bytes**, cannot overflow an `isize`.
     ///
@@ -2027,10 +2090,12 @@ impl<T: ?Sized> *mut T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_add`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_add`]: #method.wrapping_add
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -2064,7 +2129,8 @@ impl<T: ?Sized> *mut T {
     /// Behavior:
     ///
     /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same allocated object.
+    ///   byte past the end of the same allocated object. Note that in Rust,
+    ///   every (stack-allocated) variable is considered a separate allocated object.
     ///
     /// * The computed offset cannot exceed `isize::MAX` **bytes**.
     ///
@@ -2084,10 +2150,12 @@ impl<T: ?Sized> *mut T {
     /// Extension. As such, memory acquired directly from allocators or memory
     /// mapped files *may* be too large to handle with this function.
     ///
-    /// Consider using `wrapping_offset` instead if these constraints are
+    /// Consider using [`wrapping_sub`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
     /// enables more aggressive compiler optimizations.
     ///
+    /// [`wrapping_sub`]: #method.wrapping_sub
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -2120,8 +2188,21 @@ impl<T: ?Sized> *mut T {
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
     ///
-    /// Always use `.add(count)` instead when possible, because `add`
-    /// allows the compiler to optimize better.
+    /// 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 that pointer is dereferenced. [`add`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`add`]: #method.add
     ///
     /// # Examples
     ///
@@ -2161,8 +2242,21 @@ impl<T: ?Sized> *mut T {
     /// The resulting pointer does not need to be in bounds, but it is
     /// potentially hazardous to dereference (which requires `unsafe`).
     ///
-    /// Always use `.sub(count)` instead when possible, because `sub`
-    /// allows the compiler to optimize better.
+    /// 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 that pointer is dereferenced. [`sub`] can be optimized
+    /// better and is thus preferrable in performance-sensitive code.
+    ///
+    /// If you need to cross object boundaries, cast the pointer to an integer and
+    /// do the arithmetic there.
+    ///
+    /// [`sub`]: #method.sub
     ///
     /// # Examples
     ///