@@ -669,7 +669,7 @@ impl<T: ?Sized> *const T {
669669 /// `mem::size_of::<T>()` then the result of the division is rounded towards
670670 /// zero.
671671 ///
672- /// This function returns `None` if `T` is a zero-sized typed .
672+ /// This function returns `None` if `T` is a zero-sized type .
673673 ///
674674 /// # Examples
675675 ///
@@ -700,6 +700,124 @@ impl<T: ?Sized> *const T {
700700 }
701701 }
702702
703+ /// Calculates the distance between two pointers. The returned value is in
704+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
705+ ///
706+ /// This function is the inverse of [`offset`].
707+ ///
708+ /// [`offset`]: #method.offset
709+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from
710+ ///
711+ /// # Safety
712+ ///
713+ /// If any of the following conditions are violated, the result is Undefined
714+ /// Behavior:
715+ ///
716+ /// * Both the starting and other pointer must be either in bounds or one
717+ /// byte past the end of the same allocated object.
718+ ///
719+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
720+ ///
721+ /// * The distance between the pointers, in bytes, must be an exact multiple
722+ /// of the size of `T`.
723+ ///
724+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
725+ ///
726+ /// The compiler and standard library generally try to ensure allocations
727+ /// never reach a size where an offset is a concern. For instance, `Vec`
728+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
729+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
730+ ///
731+ /// Most platforms fundamentally can't even construct such an allocation.
732+ /// For instance, no known 64-bit platform can ever serve a request
733+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
734+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
735+ /// more than `isize::MAX` bytes with things like Physical Address
736+ /// Extension. As such, memory acquired directly from allocators or memory
737+ /// mapped files *may* be too large to handle with this function.
738+ ///
739+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
740+ /// difficult to satisfy. The only advantage of this method is that it
741+ /// enables more aggressive compiler optimizations.
742+ ///
743+ /// # Panics
744+ ///
745+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
746+ ///
747+ /// # Examples
748+ ///
749+ /// Basic usage:
750+ ///
751+ /// ```
752+ /// #![feature(ptr_offset_from)]
753+ ///
754+ /// let a = [0; 5];
755+ /// let ptr1: *const i32 = &a[1];
756+ /// let ptr2: *const i32 = &a[3];
757+ /// unsafe {
758+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
759+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
760+ /// assert_eq!(ptr1.offset(2), ptr2);
761+ /// assert_eq!(ptr2.offset(-2), ptr1);
762+ /// }
763+ /// ```
764+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
765+ #[ inline]
766+ pub unsafe fn offset_from ( self , origin : * const T ) -> isize where T : Sized {
767+ let pointee_size = mem:: size_of :: < T > ( ) ;
768+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
769+
770+ // This is the same sequence that Clang emits for pointer subtraction.
771+ // It can be neither `nsw` nor `nuw` because the input is treated as
772+ // unsigned but then the output is treated as signed, so neither works.
773+ let d = isize:: wrapping_sub ( self as _ , origin as _ ) ;
774+ intrinsics:: exact_div ( d, pointee_size as _ )
775+ }
776+
777+ /// Calculates the distance between two pointers. The returned value is in
778+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
779+ ///
780+ /// If the address different between the two pointers is not a multiple of
781+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
782+ /// zero.
783+ ///
784+ /// Though this method is safe for any two pointers, note that its result
785+ /// will be mostly useless if the two pointers aren't into the same allocated
786+ /// object, for example if they point to two different local variables.
787+ ///
788+ /// # Panics
789+ ///
790+ /// This function panics if `T` is a zero-sized type.
791+ ///
792+ /// # Examples
793+ ///
794+ /// Basic usage:
795+ ///
796+ /// ```
797+ /// #![feature(ptr_wrapping_offset_from)]
798+ ///
799+ /// let a = [0; 5];
800+ /// let ptr1: *const i32 = &a[1];
801+ /// let ptr2: *const i32 = &a[3];
802+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
803+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
804+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
805+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
806+ ///
807+ /// let ptr1: *const i32 = 3 as _;
808+ /// let ptr2: *const i32 = 13 as _;
809+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
810+ /// ```
811+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
812+ #[ inline]
813+ pub fn wrapping_offset_from ( self , origin : * const T ) -> isize where T : Sized {
814+ let pointee_size = mem:: size_of :: < T > ( ) ;
815+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
816+
817+ let d = isize:: wrapping_sub ( self as _ , origin as _ ) ;
818+ d. wrapping_div ( pointee_size as _ )
819+ }
820+
703821 /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
704822 ///
705823 /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
@@ -1316,7 +1434,7 @@ impl<T: ?Sized> *mut T {
13161434 /// `mem::size_of::<T>()` then the result of the division is rounded towards
13171435 /// zero.
13181436 ///
1319- /// This function returns `None` if `T` is a zero-sized typed .
1437+ /// This function returns `None` if `T` is a zero-sized type .
13201438 ///
13211439 /// # Examples
13221440 ///
@@ -1347,6 +1465,113 @@ impl<T: ?Sized> *mut T {
13471465 }
13481466 }
13491467
1468+ /// Calculates the distance between two pointers. The returned value is in
1469+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1470+ ///
1471+ /// This function is the inverse of [`offset`].
1472+ ///
1473+ /// [`offset`]: #method.offset-1
1474+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
1475+ ///
1476+ /// # Safety
1477+ ///
1478+ /// If any of the following conditions are violated, the result is Undefined
1479+ /// Behavior:
1480+ ///
1481+ /// * Both the starting and other pointer must be either in bounds or one
1482+ /// byte past the end of the same allocated object.
1483+ ///
1484+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
1485+ ///
1486+ /// * The distance between the pointers, in bytes, must be an exact multiple
1487+ /// of the size of `T`.
1488+ ///
1489+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
1490+ ///
1491+ /// The compiler and standard library generally try to ensure allocations
1492+ /// never reach a size where an offset is a concern. For instance, `Vec`
1493+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
1494+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
1495+ ///
1496+ /// Most platforms fundamentally can't even construct such an allocation.
1497+ /// For instance, no known 64-bit platform can ever serve a request
1498+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
1499+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
1500+ /// more than `isize::MAX` bytes with things like Physical Address
1501+ /// Extension. As such, memory acquired directly from allocators or memory
1502+ /// mapped files *may* be too large to handle with this function.
1503+ ///
1504+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
1505+ /// difficult to satisfy. The only advantage of this method is that it
1506+ /// enables more aggressive compiler optimizations.
1507+ ///
1508+ /// # Panics
1509+ ///
1510+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
1511+ ///
1512+ /// # Examples
1513+ ///
1514+ /// Basic usage:
1515+ ///
1516+ /// ```
1517+ /// #![feature(ptr_offset_from)]
1518+ ///
1519+ /// let mut a = [0; 5];
1520+ /// let ptr1: *mut i32 = &mut a[1];
1521+ /// let ptr2: *mut i32 = &mut a[3];
1522+ /// unsafe {
1523+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
1524+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
1525+ /// assert_eq!(ptr1.offset(2), ptr2);
1526+ /// assert_eq!(ptr2.offset(-2), ptr1);
1527+ /// }
1528+ /// ```
1529+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
1530+ #[ inline]
1531+ pub unsafe fn offset_from ( self , origin : * const T ) -> isize where T : Sized {
1532+ ( self as * const T ) . offset_from ( origin)
1533+ }
1534+
1535+ /// Calculates the distance between two pointers. The returned value is in
1536+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1537+ ///
1538+ /// If the address different between the two pointers is not a multiple of
1539+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
1540+ /// zero.
1541+ ///
1542+ /// Though this method is safe for any two pointers, note that its result
1543+ /// will be mostly useless if the two pointers aren't into the same allocated
1544+ /// object, for example if they point to two different local variables.
1545+ ///
1546+ /// # Panics
1547+ ///
1548+ /// This function panics if `T` is a zero-sized type.
1549+ ///
1550+ /// # Examples
1551+ ///
1552+ /// Basic usage:
1553+ ///
1554+ /// ```
1555+ /// #![feature(ptr_wrapping_offset_from)]
1556+ ///
1557+ /// let mut a = [0; 5];
1558+ /// let ptr1: *mut i32 = &mut a[1];
1559+ /// let ptr2: *mut i32 = &mut a[3];
1560+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1561+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
1562+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
1563+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
1564+ ///
1565+ /// let ptr1: *mut i32 = 3 as _;
1566+ /// let ptr2: *mut i32 = 13 as _;
1567+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1568+ /// ```
1569+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
1570+ #[ inline]
1571+ pub fn wrapping_offset_from ( self , origin : * const T ) -> isize where T : Sized {
1572+ ( self as * const T ) . wrapping_offset_from ( origin)
1573+ }
1574+
13501575 /// Computes the byte offset that needs to be applied in order to
13511576 /// make the pointer aligned to `align`.
13521577 /// If it is not possible to align the pointer, the implementation returns
0 commit comments