@@ -390,37 +390,26 @@ impl<T: ?Sized> *const T {
390390 if self . is_null ( ) { None } else { Some ( unsafe { & * ( self as * const MaybeUninit < T > ) } ) }
391391 }
392392
393- /// Calculates the offset from a pointer.
393+ /// Adds an offset to a pointer.
394394 ///
395395 /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
396396 /// offset of `3 * size_of::<T>()` bytes.
397397 ///
398398 /// # Safety
399399 ///
400- /// If any of the following conditions are violated, the result is Undefined
401- /// Behavior:
400+ /// If any of the following conditions are violated, the result is Undefined Behavior:
402401 ///
403- /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
404- /// pointer must be either in bounds or at the end of the same [allocated object].
405- /// (If it is zero, then the function is always well-defined.)
402+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
406403 ///
407- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
404+ /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
405+ /// [allocated object], and the entire memory range between `self` and the result must be in
406+ /// bounds of that allocated object. In particular, this range must not "wrap around" the edge
407+ /// of the address space.
408408 ///
409- /// * The offset being in bounds cannot rely on "wrapping around" the address
410- /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
411- ///
412- /// The compiler and standard library generally tries to ensure allocations
413- /// never reach a size where an offset is a concern. For instance, `Vec`
414- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
415- /// `vec.as_ptr().add(vec.len())` is always safe.
416- ///
417- /// Most platforms fundamentally can't even construct such an allocation.
418- /// For instance, no known 64-bit platform can ever serve a request
419- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
420- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
421- /// more than `isize::MAX` bytes with things like Physical Address
422- /// Extension. As such, memory acquired directly from allocators or memory
423- /// mapped files *may* be too large to handle with this function.
409+ /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
410+ /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
411+ /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
412+ /// safe.
424413 ///
425414 /// Consider using [`wrapping_offset`] instead if these constraints are
426415 /// difficult to satisfy. The only advantage of this method is that it
@@ -611,8 +600,7 @@ impl<T: ?Sized> *const T {
611600 ///
612601 /// # Safety
613602 ///
614- /// If any of the following conditions are violated, the result is Undefined
615- /// Behavior:
603+ /// If any of the following conditions are violated, the result is Undefined Behavior:
616604 ///
617605 /// * `self` and `origin` must either
618606 ///
@@ -623,26 +611,10 @@ impl<T: ?Sized> *const T {
623611 /// * The distance between the pointers, in bytes, must be an exact multiple
624612 /// of the size of `T`.
625613 ///
626- /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
627- ///
628- /// * The distance being in bounds cannot rely on "wrapping around" the address space.
629- ///
630- /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the
631- /// address space, so two pointers within some value of any Rust type `T` will always satisfy
632- /// the last two conditions. The standard library also generally ensures that allocations
633- /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they
634- /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())`
635- /// always satisfies the last two conditions.
636- ///
637- /// Most platforms fundamentally can't even construct such a large allocation.
638- /// For instance, no known 64-bit platform can ever serve a request
639- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
640- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
641- /// more than `isize::MAX` bytes with things like Physical Address
642- /// Extension. As such, memory acquired directly from allocators or memory
643- /// mapped files *may* be too large to handle with this function.
644- /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
645- /// such large allocations either.)
614+ /// As a consequence, the absolute distance between the pointers, in bytes, computed on
615+ /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
616+ /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
617+ /// than `isize::MAX` bytes.
646618 ///
647619 /// The requirement for pointers to be derived from the same allocated object is primarily
648620 /// needed for `const`-compatibility: the distance between pointers into *different* allocated
@@ -879,37 +851,26 @@ impl<T: ?Sized> *const T {
879851 }
880852 }
881853
882- /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
854+ /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
883855 ///
884856 /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
885857 /// offset of `3 * size_of::<T>()` bytes.
886858 ///
887859 /// # Safety
888860 ///
889- /// If any of the following conditions are violated, the result is Undefined
890- /// Behavior:
861+ /// If any of the following conditions are violated, the result is Undefined Behavior:
891862 ///
892- /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
893- /// pointer must be either in bounds or at the end of the same [allocated object].
894- /// (If it is zero, then the function is always well-defined.)
863+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
895864 ///
896- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
865+ /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
866+ /// [allocated object], and the entire memory range between `self` and the result must be in
867+ /// bounds of that allocated object. In particular, this range must not "wrap around" the edge
868+ /// of the address space.
897869 ///
898- /// * The offset being in bounds cannot rely on "wrapping around" the address
899- /// space. That is, the infinite-precision sum must fit in a `usize`.
900- ///
901- /// The compiler and standard library generally tries to ensure allocations
902- /// never reach a size where an offset is a concern. For instance, `Vec`
903- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
904- /// `vec.as_ptr().add(vec.len())` is always safe.
905- ///
906- /// Most platforms fundamentally can't even construct such an allocation.
907- /// For instance, no known 64-bit platform can ever serve a request
908- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
909- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
910- /// more than `isize::MAX` bytes with things like Physical Address
911- /// Extension. As such, memory acquired directly from allocators or memory
912- /// mapped files *may* be too large to handle with this function.
870+ /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
871+ /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
872+ /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
873+ /// safe.
913874 ///
914875 /// Consider using [`wrapping_add`] instead if these constraints are
915876 /// difficult to satisfy. The only advantage of this method is that it
@@ -963,38 +924,27 @@ impl<T: ?Sized> *const T {
963924 unsafe { self . cast :: < u8 > ( ) . add ( count) . with_metadata_of ( self ) }
964925 }
965926
966- /// Calculates the offset from a pointer (convenience for
927+ /// Subtracts an offset from a pointer (convenience for
967928 /// `.offset((count as isize).wrapping_neg())`).
968929 ///
969930 /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
970931 /// offset of `3 * size_of::<T>()` bytes.
971932 ///
972933 /// # Safety
973934 ///
974- /// If any of the following conditions are violated, the result is Undefined
975- /// Behavior:
976- ///
977- /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
978- /// pointer must be either in bounds or at the end of the same [allocated object].
979- /// (If it is zero, then the function is always well-defined.)
980- ///
981- /// * The computed offset cannot exceed `isize::MAX` **bytes**.
935+ /// If any of the following conditions are violated, the result is Undefined Behavior:
982936 ///
983- /// * The offset being in bounds cannot rely on "wrapping around" the address
984- /// space. That is, the infinite-precision sum must fit in a usize.
937+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
985938 ///
986- /// The compiler and standard library generally tries to ensure allocations
987- /// never reach a size where an offset is a concern. For instance, `Vec`
988- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
989- /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe .
939+ /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
940+ /// [allocated object], and the entire memory range between `self` and the result must be in
941+ /// bounds of that allocated object. In particular, this range must not "wrap around" the edge
942+ /// of the address space .
990943 ///
991- /// Most platforms fundamentally can't even construct such an allocation.
992- /// For instance, no known 64-bit platform can ever serve a request
993- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
994- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
995- /// more than `isize::MAX` bytes with things like Physical Address
996- /// Extension. As such, memory acquired directly from allocators or memory
997- /// mapped files *may* be too large to handle with this function.
944+ /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
945+ /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
946+ /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
947+ /// safe.
998948 ///
999949 /// Consider using [`wrapping_sub`] instead if these constraints are
1000950 /// difficult to satisfy. The only advantage of this method is that it
0 commit comments