Skip to content

Commit

Permalink
Rollup merge of rust-lang#63297 - RalfJung:ptr_offset, r=dtolnay
Browse files Browse the repository at this point in the history
Improve pointer offset method docs

Cc @rkruppe @gnzlbg
  • Loading branch information
Centril committed Aug 12, 2019
2 parents 4f1cc83 + 0dc9e2a commit 67de6ce
Showing 1 changed file with 128 additions and 34 deletions.
162 changes: 128 additions & 34 deletions src/libcore/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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`.
///
Expand Down Expand Up @@ -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`.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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**.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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`.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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`.
///
Expand Down Expand Up @@ -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`.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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**.
///
Expand All @@ -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:
Expand Down Expand Up @@ -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
///
Expand Down Expand Up @@ -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
///
Expand Down

0 comments on commit 67de6ce

Please sign in to comment.