@@ -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:
400
+ /// If any of the following conditions are violated, the result is Undefined Behavior:
402
401
///
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`.
406
403
///
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.
408
408
///
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.
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
@@ -611,8 +600,7 @@ impl<T: ?Sized> *const T {
611
600
///
612
601
/// # Safety
613
602
///
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:
616
604
///
617
605
/// * `self` and `origin` must either
618
606
///
@@ -623,26 +611,10 @@ impl<T: ?Sized> *const T {
623
611
/// * The distance between the pointers, in bytes, must be an exact multiple
624
612
/// of the size of `T`.
625
613
///
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.
646
618
///
647
619
/// The requirement for pointers to be derived from the same allocated object is primarily
648
620
/// needed for `const`-compatibility: the distance between pointers into *different* allocated
@@ -879,37 +851,26 @@ impl<T: ?Sized> *const T {
879
851
}
880
852
}
881
853
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)`).
883
855
///
884
856
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
885
857
/// offset of `3 * size_of::<T>()` bytes.
886
858
///
887
859
/// # Safety
888
860
///
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:
891
862
///
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`.
895
864
///
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.
897
869
///
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.
913
874
///
914
875
/// Consider using [`wrapping_add`] instead if these constraints are
915
876
/// difficult to satisfy. The only advantage of this method is that it
@@ -963,38 +924,27 @@ impl<T: ?Sized> *const T {
963
924
unsafe { self . cast :: < u8 > ( ) . add ( count) . with_metadata_of ( self ) }
964
925
}
965
926
966
- /// Calculates the offset from a pointer (convenience for
927
+ /// Subtracts an offset from a pointer (convenience for
967
928
/// `.offset((count as isize).wrapping_neg())`).
968
929
///
969
930
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
970
931
/// offset of `3 * size_of::<T>()` bytes.
971
932
///
972
933
/// # Safety
973
934
///
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:
982
936
///
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`.
985
938
///
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 .
990
943
///
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.
998
948
///
999
949
/// Consider using [`wrapping_sub`] instead if these constraints are
1000
950
/// difficult to satisfy. The only advantage of this method is that it
0 commit comments