diff options
| author | Ralf Jung <post@ralfj.de> | 2020-12-26 18:07:52 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2020-12-26 18:07:52 +0100 |
| commit | 8543388beb52785897b87e3f0a5ffd3c8560f956 (patch) | |
| tree | cdb1fcdfee072d3893e6e530390446c59ab5c609 | |
| parent | 3533204e999cf70378131c63e1abbfe812109792 (diff) | |
| download | rust-8543388beb52785897b87e3f0a5ffd3c8560f956.tar.gz rust-8543388beb52785897b87e3f0a5ffd3c8560f956.zip | |
address review feedback
| -rw-r--r-- | library/core/src/ptr/const_ptr.rs | 35 | ||||
| -rw-r--r-- | library/core/src/ptr/mut_ptr.rs | 35 |
2 files changed, 40 insertions, 30 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 6638033566f..38519f759ae 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -238,10 +238,10 @@ 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 @@ -249,9 +249,10 @@ impl<T: ?Sized> *const T { /// 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. @@ -580,10 +581,10 @@ 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 @@ -591,6 +592,8 @@ impl<T: ?Sized> *const T { /// 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. /// @@ -643,10 +646,10 @@ 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 @@ -654,6 +657,8 @@ impl<T: ?Sized> *const T { /// 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. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index a0edb036c25..92f4e431de4 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -244,10 +244,10 @@ 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 @@ -255,9 +255,10 @@ impl<T: ?Sized> *mut T { /// 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. @@ -687,10 +688,10 @@ 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 @@ -698,6 +699,8 @@ impl<T: ?Sized> *mut T { /// 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. /// @@ -750,10 +753,10 @@ 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 @@ -761,6 +764,8 @@ impl<T: ?Sized> *mut T { /// 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. /// |
