Rollup merge of #63297 - RalfJung:ptr_offset, r=dtolnay
Improve pointer offset method docs Cc @rkruppe @gnzlbg
This commit is contained in:
commit
e9615f2487
1 changed files with 128 additions and 34 deletions
|
@ -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
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue