Skip to content

Commit

Permalink
address review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Dec 26, 2020
1 parent 3533204 commit 8543388
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 30 deletions.
35 changes: 20 additions & 15 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,21 @@ impl<T: ?Sized> *const T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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 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.
///
/// `x.wrapping_offset(o).wrapping_offset(-o)` is always the same as `x` (if `-o` does not
/// overflow). In other words, leaving the allocated object and then re-entering it later is
/// permitted.
/// 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.
Expand Down Expand Up @@ -580,17 +581,19 @@ impl<T: ?Sized> *const T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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.
///
/// 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.
///
/// 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.
///
Expand Down Expand Up @@ -643,17 +646,19 @@ impl<T: ?Sized> *const T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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.
///
/// 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.
///
/// 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.
///
Expand Down
35 changes: 20 additions & 15 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,20 +244,21 @@ impl<T: ?Sized> *mut T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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 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.
///
/// `x.wrapping_offset(o).wrapping_offset(-o)` is always the same as `x` (if `-o` does not
/// overflow). In other words, leaving the allocated object and then re-entering it later is
/// permitted.
/// 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.
Expand Down Expand Up @@ -687,17 +688,19 @@ impl<T: ?Sized> *mut T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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.
///
/// 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.
///
/// 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.
///
Expand Down Expand Up @@ -750,17 +753,19 @@ impl<T: ?Sized> *mut T {
/// 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).wrapping_sub(x as usize) /
/// size_of::<T>())` does *not* make `z` the same as `y`: `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 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.
///
/// 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.
///
/// 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.
///
Expand Down

0 comments on commit 8543388

Please sign in to comment.