@@ -238,20 +238,21 @@ impl<T: ?Sized> *const T {
238
238
/// It may *not* be used to access a different allocated object. Note that in Rust, every
239
239
/// (stack-allocated) variable is considered a separate allocated object.
240
240
///
241
- /// In other words, `let z = x.wrapping_add ((y as usize).wrapping_sub (x as usize) /
242
- /// size_of::<T>())` does *not* make `z` the same as `y`: `z` is still attached to the object `x ` is
243
- /// attached to, and dereferencing it is Undefined Behavior unless `x` and `y` point into the
244
- /// same allocated object.
241
+ /// In other words, `let z = x.wrapping_offset ((y as isize) - (x as isize))` does *not* make `z`
242
+ /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z ` is still
243
+ /// attached to the object `x` is attached to , and dereferencing it is Undefined Behavior unless
244
+ /// `x` and `y` point into the same allocated object.
245
245
///
246
246
/// Compared to [`offset`], this method basically delays the requirement of staying within the
247
247
/// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
248
248
/// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
249
249
/// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
250
250
/// can be optimized better and is thus preferable in performance-sensitive code.
251
251
///
252
- /// `x.wrapping_offset(o).wrapping_offset(-o)` is always the same as `x` (if `-o` does not
253
- /// overflow). In other words, leaving the allocated object and then re-entering it later is
254
- /// permitted.
252
+ /// The delayed check only considers the value of the pointer that was dereferenced, not the
253
+ /// intermediate values used during the computation of the final result. For example,
254
+ /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
255
+ /// words, leaving the allocated object and then re-entering it later is permitted.
255
256
///
256
257
/// If you need to cross object boundaries, cast the pointer to an integer and
257
258
/// do the arithmetic there.
@@ -580,17 +581,19 @@ impl<T: ?Sized> *const T {
580
581
/// It may *not* be used to access a different allocated object. Note that in Rust, every
581
582
/// (stack-allocated) variable is considered a separate allocated object.
582
583
///
583
- /// In other words, `let z = x.wrapping_add((y as usize).wrapping_sub (x as usize) /
584
- /// size_of::<T>())` does *not* make `z` the same as `y`: `z` is still attached to the object `x ` is
585
- /// attached to, and dereferencing it is Undefined Behavior unless `x` and `y` point into the
586
- /// same allocated object.
584
+ /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
585
+ /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z ` is still
586
+ /// attached to the object `x` is attached to , and dereferencing it is Undefined Behavior unless
587
+ /// `x` and `y` point into the same allocated object.
587
588
///
588
589
/// Compared to [`add`], this method basically delays the requirement of staying within the
589
590
/// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
590
591
/// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
591
592
/// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
592
593
/// can be optimized better and is thus preferable in performance-sensitive code.
593
594
///
595
+ /// The delayed check only considers the value of the pointer that was dereferenced, not the
596
+ /// intermediate values used during the computation of the final result. For example,
594
597
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
595
598
/// allocated object and then re-entering it later is permitted.
596
599
///
@@ -643,17 +646,19 @@ impl<T: ?Sized> *const T {
643
646
/// It may *not* be used to access a different allocated object. Note that in Rust, every
644
647
/// (stack-allocated) variable is considered a separate allocated object.
645
648
///
646
- /// In other words, `let z = x.wrapping_add((y as usize).wrapping_sub(x as usize) /
647
- /// size_of::<T>())` does *not* make `z` the same as `y`: `z` is still attached to the object `x ` is
648
- /// attached to, and dereferencing it is Undefined Behavior unless `x` and `y` point into the
649
- /// same allocated object.
649
+ /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
650
+ /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z ` is still
651
+ /// attached to the object `x` is attached to , and dereferencing it is Undefined Behavior unless
652
+ /// `x` and `y` point into the same allocated object.
650
653
///
651
654
/// Compared to [`sub`], this method basically delays the requirement of staying within the
652
655
/// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
653
656
/// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
654
657
/// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
655
658
/// can be optimized better and is thus preferable in performance-sensitive code.
656
659
///
660
+ /// The delayed check only considers the value of the pointer that was dereferenced, not the
661
+ /// intermediate values used during the computation of the final result. For example,
657
662
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
658
663
/// allocated object and then re-entering it later is permitted.
659
664
///
0 commit comments