@@ -390,37 +390,26 @@ impl<T: ?Sized> *const T {
390
390
if self . is_null ( ) { None } else { Some ( unsafe { & * ( self as * const MaybeUninit < T > ) } ) }
391
391
}
392
392
393
- /// Calculates the offset from a pointer.
393
+ /// Adds an offset to a pointer.
394
394
///
395
395
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
396
396
/// offset of `3 * size_of::<T>()` bytes.
397
397
///
398
398
/// # Safety
399
399
///
400
- /// If any of the following conditions are violated, the result is Undefined
401
- /// Behavior:
402
- ///
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.)
400
+ /// If any of the following conditions are violated, the result is Undefined Behavior:
406
401
///
407
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
402
+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
408
403
///
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.
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 egde
407
+ /// of the address space.
411
408
///
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`, so if the computed offset stays in
410
+ /// bounds of the allocated object, it is guaranteed to satisfy the first requirement. This
411
+ /// implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
412
+ /// safe.
424
413
///
425
414
/// Consider using [`wrapping_offset`] instead if these constraints are
426
415
/// difficult to satisfy. The only advantage of this method is that it
@@ -623,7 +612,7 @@ impl<T: ?Sized> *const T {
623
612
/// * The distance between the pointers, in bytes, must be an exact multiple
624
613
/// of the size of `T`.
625
614
///
626
- /// As a consequence, the absolute distance between the pointers, ** in bytes** , computed on
615
+ /// As a consequence, the absolute distance between the pointers, in bytes, computed on
627
616
/// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
628
617
/// implied by the in-bounds requirement, and the fact that no allocated object can be larger
629
618
/// than `isize::MAX`.
@@ -863,37 +852,26 @@ impl<T: ?Sized> *const T {
863
852
}
864
853
}
865
854
866
- /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
855
+ /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
867
856
///
868
857
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
869
858
/// offset of `3 * size_of::<T>()` bytes.
870
859
///
871
860
/// # Safety
872
861
///
873
- /// If any of the following conditions are violated, the result is Undefined
874
- /// Behavior:
875
- ///
876
- /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
877
- /// pointer must be either in bounds or at the end of the same [allocated object].
878
- /// (If it is zero, then the function is always well-defined.)
879
- ///
880
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
862
+ /// If any of the following conditions are violated, the result is Undefined Behavior:
881
863
///
882
- /// * The offset being in bounds cannot rely on "wrapping around" the address
883
- /// space. That is, the infinite-precision sum must fit in a `usize`.
864
+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
884
865
///
885
- /// The compiler and standard library generally tries to ensure allocations
886
- /// never reach a size where an offset is a concern. For instance, `Vec`
887
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
888
- /// `vec.as_ptr().add(vec.len())` is always safe .
866
+ /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
867
+ /// [allocated object], and the entire memory range between `self` and the result must be in
868
+ /// bounds of that allocated object. In particular, this range must not "wrap around" the egde
869
+ /// of the address space .
889
870
///
890
- /// Most platforms fundamentally can't even construct such an allocation.
891
- /// For instance, no known 64-bit platform can ever serve a request
892
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
893
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
894
- /// more than `isize::MAX` bytes with things like Physical Address
895
- /// Extension. As such, memory acquired directly from allocators or memory
896
- /// mapped files *may* be too large to handle with this function.
871
+ /// Allocated objects can never be larger than `isize::MAX`, so if the computed offset stays in
872
+ /// bounds of the allocated object, it is guaranteed to satisfy the first requirement. This
873
+ /// implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
874
+ /// safe.
897
875
///
898
876
/// Consider using [`wrapping_add`] instead if these constraints are
899
877
/// difficult to satisfy. The only advantage of this method is that it
@@ -947,38 +925,27 @@ impl<T: ?Sized> *const T {
947
925
unsafe { self . cast :: < u8 > ( ) . add ( count) . with_metadata_of ( self ) }
948
926
}
949
927
950
- /// Calculates the offset from a pointer (convenience for
928
+ /// Subtracts an offset from a pointer (convenience for
951
929
/// `.offset((count as isize).wrapping_neg())`).
952
930
///
953
931
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
954
932
/// offset of `3 * size_of::<T>()` bytes.
955
933
///
956
934
/// # Safety
957
935
///
958
- /// If any of the following conditions are violated, the result is Undefined
959
- /// Behavior:
960
- ///
961
- /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
962
- /// pointer must be either in bounds or at the end of the same [allocated object].
963
- /// (If it is zero, then the function is always well-defined.)
964
- ///
965
- /// * The computed offset cannot exceed `isize::MAX` **bytes**.
936
+ /// If any of the following conditions are violated, the result is Undefined Behavior:
966
937
///
967
- /// * The offset being in bounds cannot rely on "wrapping around" the address
968
- /// space. That is, the infinite-precision sum must fit in a usize.
938
+ /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
969
939
///
970
- /// The compiler and standard library generally tries to ensure allocations
971
- /// never reach a size where an offset is a concern. For instance, `Vec`
972
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
973
- /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe .
940
+ /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
941
+ /// [allocated object], and the entire memory range between `self` and the result must be in
942
+ /// bounds of that allocated object. In particular, this range must not "wrap around" the egde
943
+ /// of the address space .
974
944
///
975
- /// Most platforms fundamentally can't even construct such an allocation.
976
- /// For instance, no known 64-bit platform can ever serve a request
977
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
978
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
979
- /// more than `isize::MAX` bytes with things like Physical Address
980
- /// Extension. As such, memory acquired directly from allocators or memory
981
- /// mapped files *may* be too large to handle with this function.
945
+ /// Allocated objects can never be larger than `isize::MAX`, so if the computed offset stays in
946
+ /// bounds of the allocated object, it is guaranteed to satisfy the first requirement. This
947
+ /// implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
948
+ /// safe.
982
949
///
983
950
/// Consider using [`wrapping_sub`] instead if these constraints are
984
951
/// difficult to satisfy. The only advantage of this method is that it
0 commit comments