@@ -232,23 +232,27 @@ impl<T: ?Sized> *const T {
232
232
///
233
233
/// # Safety
234
234
///
235
- /// The resulting pointer does not need to be in bounds, but it is
236
- /// potentially hazardous to dereference (which requires `unsafe`).
235
+ /// This operation itself is always safe, but using the resulting pointer is not.
237
236
///
238
- /// In particular, the resulting pointer remains attached to the same allocated
239
- /// object that `self` points to. It may *not* be used to access a
240
- /// different allocated object. Note that in Rust,
241
- /// every (stack-allocated) variable is considered a separate allocated object.
237
+ /// The resulting pointer remains attached to the same allocated object that `self` points to.
238
+ /// It may *not* be used to access a different allocated object. Note that in Rust, every
239
+ /// (stack-allocated) variable is considered a separate allocated object.
242
240
///
243
- /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
244
- /// is *not* the same as `y`, and dereferencing it is undefined behavior
245
- /// unless `x` and `y` point into the 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.
246
245
///
247
- /// Compared to [`offset`], this method basically delays the requirement of staying
248
- /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
249
- /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
250
- /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
251
- /// better and is thus preferable in performance-sensitive code.
246
+ /// Compared to [`offset`], this method basically delays the requirement of staying within the
247
+ /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
248
+ /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
249
+ /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
250
+ /// can be optimized better and is thus preferable in performance-sensitive code.
251
+ ///
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.
252
256
///
253
257
/// If you need to cross object boundaries, cast the pointer to an integer and
254
258
/// do the arithmetic there.
@@ -571,19 +575,27 @@ impl<T: ?Sized> *const T {
571
575
///
572
576
/// # Safety
573
577
///
574
- /// The resulting pointer does not need to be in bounds, but it is
575
- /// potentially hazardous to dereference (which requires `unsafe`).
578
+ /// This operation itself is always safe, but using the resulting pointer is not.
579
+ ///
580
+ /// The resulting pointer remains attached to the same allocated object that `self` points to.
581
+ /// It may *not* be used to access a different allocated object. Note that in Rust, every
582
+ /// (stack-allocated) variable is considered a separate allocated object.
583
+ ///
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.
576
588
///
577
- /// In particular, the resulting pointer remains attached to the same allocated
578
- /// object that `self` points to. It may *not* be used to access a
579
- /// different allocated object. Note that in Rust,
580
- /// every (stack-allocated) variable is considered a separate allocated object.
589
+ /// Compared to [`add`], this method basically delays the requirement of staying within the
590
+ /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
591
+ /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
592
+ /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
593
+ /// can be optimized better and is thus preferable in performance-sensitive code.
581
594
///
582
- /// Compared to [`add`], this method basically delays the requirement of staying
583
- /// within the same allocated object: [`add`] is immediate Undefined Behavior when
584
- /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
585
- /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
586
- /// better and is thus preferable in performance-sensitive code.
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,
597
+ /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
598
+ /// allocated object and then re-entering it later is permitted.
587
599
///
588
600
/// If you need to cross object boundaries, cast the pointer to an integer and
589
601
/// do the arithmetic there.
@@ -628,19 +640,27 @@ impl<T: ?Sized> *const T {
628
640
///
629
641
/// # Safety
630
642
///
631
- /// The resulting pointer does not need to be in bounds, but it is
632
- /// potentially hazardous to dereference (which requires `unsafe`).
643
+ /// This operation itself is always safe, but using the resulting pointer is not.
644
+ ///
645
+ /// The resulting pointer remains attached to the same allocated object that `self` points to.
646
+ /// It may *not* be used to access a different allocated object. Note that in Rust, every
647
+ /// (stack-allocated) variable is considered a separate allocated object.
648
+ ///
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.
633
653
///
634
- /// In particular, the resulting pointer remains attached to the same allocated
635
- /// object that `self` points to. It may *not* be used to access a
636
- /// different allocated object. Note that in Rust,
637
- /// every (stack-allocated) variable is considered a separate allocated object.
654
+ /// Compared to [`sub`], this method basically delays the requirement of staying within the
655
+ /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
656
+ /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
657
+ /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
658
+ /// can be optimized better and is thus preferable in performance-sensitive code.
638
659
///
639
- /// Compared to [`sub`], this method basically delays the requirement of staying
640
- /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
641
- /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
642
- /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
643
- /// better and is thus preferable in performance-sensitive code.
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,
662
+ /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
663
+ /// allocated object and then re-entering it later is permitted.
644
664
///
645
665
/// If you need to cross object boundaries, cast the pointer to an integer and
646
666
/// do the arithmetic there.
0 commit comments