@@ -605,7 +605,9 @@ impl<T: ?Sized> *const T {
605605 /// Calculates the distance between two pointers. The returned value is in
606606 /// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
607607 ///
608- /// This function is the inverse of [`offset`].
608+ /// This function is the inverse of [`offset`]: it is valid to call if and only if
609+ /// `self` could have been computed as `origin.offset(n)` for some `n`, and it will
610+ /// then return that `n`.
609611 ///
610612 /// [`offset`]: #method.offset
611613 ///
@@ -644,6 +646,12 @@ impl<T: ?Sized> *const T {
644646 /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
645647 /// such large allocations either.)
646648 ///
649+ /// The requirement for pointers to be derived from the same allocated object is primarily
650+ /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated
651+ /// object do not have a known distance to each other. However, the requirement also exists at
652+ /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as
653+ /// usize) / mem::size_of::<T>()` to avoid this requirement.
654+ ///
647655 /// [`add`]: #method.add
648656 /// [allocated object]: crate::ptr#allocated-object
649657 ///
@@ -701,7 +709,7 @@ impl<T: ?Sized> *const T {
701709 /// units of **bytes**.
702710 ///
703711 /// This is purely a convenience for casting to a `u8` pointer and
704- /// using [offset_from][pointer::offset_from] on it. See that method for
712+ /// using [` offset_from` ][pointer::offset_from] on it. See that method for
705713 /// documentation and safety requirements.
706714 ///
707715 /// For non-`Sized` pointees this operation considers only the data pointers,
@@ -799,6 +807,108 @@ impl<T: ?Sized> *const T {
799807 unsafe { intrinsics:: ptr_offset_from_unsigned ( self , origin) }
800808 }
801809
810+ /// Calculates the distance between two pointers using wrapping arithmetic. The returned value
811+ /// is in units of T: the distance in bytes divided by `mem::size_of::<T>()`.
812+ ///
813+ /// This function is the inverse of [`wrapping_offset`]: it is valid to call if and only if
814+ /// `self` could have been computed as `origin.wrapping_offset(n)` for some `n`, and it will
815+ /// then return that `n`.
816+ ///
817+ /// [`wrapping_offset`]: #method.wrapping_offset
818+ ///
819+ /// # Safety
820+ ///
821+ /// If any of the following conditions are violated, the result is Undefined
822+ /// Behavior:
823+ ///
824+ /// * Both pointers must be *derived from* a pointer to the same [allocated object].
825+ /// (See below for an example.)
826+ ///
827+ /// * The distance between the pointers, in bytes, must be an exact multiple
828+ /// of the size of `T`.
829+ ///
830+ /// Unlike [`offset_from`][pointer::offset_from], this method does *not* require the pointers to
831+ /// be in-bounds of the object they are derived from, nor does it impose any restrictions
832+ /// regarding the maximum distance or wrapping around the address space.
833+ ///
834+ /// The requirement for pointers to be derived from the same allocated object is primarily
835+ /// needed for `const`-compatibility: at compile-time, pointers into *different* allocated
836+ /// object do not have a known distance to each other. However, the requirement also exists at
837+ /// runtime, and may be exploited by optimizations. You can use `(self as usize).sub(origin as
838+ /// usize) / mem::size_of::<T>()` to avoid this requirement.
839+ ///
840+ /// [allocated object]: crate::ptr#allocated-object
841+ ///
842+ /// # Panics
843+ ///
844+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
845+ ///
846+ /// # Examples
847+ ///
848+ /// Basic usage:
849+ ///
850+ /// ```
851+ /// #![feature(ptr_wrapping_offset_from)]
852+ /// let a = [0; 2];
853+ /// let ptr1: *const i32 = &a[1];
854+ /// let ptr2: *const i32 = a.as_ptr().wrapping_offset(3); // out-of-bounds!
855+ /// unsafe {
856+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
857+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
858+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
859+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
860+ /// }
861+ /// ```
862+ ///
863+ /// *Incorrect* usage:
864+ ///
865+ /// ```rust,no_run
866+ /// #![feature(ptr_wrapping_offset_from)]
867+ /// let ptr1 = Box::into_raw(Box::new(0u8)) as *const u8;
868+ /// let ptr2 = Box::into_raw(Box::new(1u8)) as *const u8;
869+ /// let diff = (ptr2 as isize).wrapping_sub(ptr1 as isize);
870+ /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1.
871+ /// let ptr2_other = (ptr1 as *const u8).wrapping_offset(diff);
872+ /// assert_eq!(ptr2 as usize, ptr2_other as usize);
873+ /// // Since ptr2_other and ptr2 are derived from pointers to different objects,
874+ /// // computing their offset is undefined behavior, even though
875+ /// // they point to the same address!
876+ /// unsafe {
877+ /// let zero = ptr2_other.wrapping_offset_from(ptr2); // Undefined Behavior
878+ /// }
879+ /// ```
880+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "none" ) ]
881+ #[ rustc_const_unstable( feature = "ptr_wrapping_offset_from" , issue = "none" ) ]
882+ #[ inline]
883+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
884+ #[ cfg( not( bootstrap) ) ]
885+ pub const unsafe fn wrapping_offset_from ( self , origin : * const T ) -> isize
886+ where
887+ T : Sized ,
888+ {
889+ // SAFETY: the caller must uphold the safety contract for `ptr_offset_from`.
890+ unsafe { intrinsics:: ptr_wrapping_offset_from ( self , origin) }
891+ }
892+
893+ /// Calculates the distance between two pointers using wrapping arithmetic. The returned value
894+ /// is in units of **bytes**.
895+ ///
896+ /// This is purely a convenience for casting to a `u8` pointer and using
897+ /// [`wrapping_offset_from`][pointer::wrapping_offset_from] on it. See that method for
898+ /// documentation and safety requirements.
899+ ///
900+ /// For non-`Sized` pointees this operation considers only the data pointers,
901+ /// ignoring the metadata.
902+ #[ inline( always) ]
903+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "none" ) ]
904+ #[ rustc_const_unstable( feature = "ptr_wrapping_offset_from" , issue = "none" ) ]
905+ #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
906+ #[ cfg( not( bootstrap) ) ]
907+ pub const unsafe fn wrapping_byte_offset_from < U : ?Sized > ( self , origin : * const U ) -> isize {
908+ // SAFETY: the caller must uphold the safety contract for `wrapping_offset_from`.
909+ unsafe { self . cast :: < u8 > ( ) . wrapping_offset_from ( origin. cast :: < u8 > ( ) ) }
910+ }
911+
802912 /// Returns whether two pointers are guaranteed to be equal.
803913 ///
804914 /// At runtime this function behaves like `Some(self == other)`.
0 commit comments