@@ -232,23 +232,27 @@ impl<T: ?Sized> *const T {
232232 ///
233233 /// # Safety
234234 ///
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.
237236 ///
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.
242240 ///
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.
246245 ///
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.
252256 ///
253257 /// If you need to cross object boundaries, cast the pointer to an integer and
254258 /// do the arithmetic there.
@@ -571,19 +575,27 @@ impl<T: ?Sized> *const T {
571575 ///
572576 /// # Safety
573577 ///
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.
576588 ///
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.
581594 ///
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.
587599 ///
588600 /// If you need to cross object boundaries, cast the pointer to an integer and
589601 /// do the arithmetic there.
@@ -628,19 +640,27 @@ impl<T: ?Sized> *const T {
628640 ///
629641 /// # Safety
630642 ///
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.
633653 ///
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.
638659 ///
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.
644664 ///
645665 /// If you need to cross object boundaries, cast the pointer to an integer and
646666 /// do the arithmetic there.
0 commit comments