Rollup merge of #127275 - RalfJung:offset-from-isize-min, r=Amanieu · model-checking/verify-rust-std@5569ece (original) (raw)
`@@ -390,37 +390,26 @@ impl<T: ?Sized> *const T {
`
390
390
`if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) }
`
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 263 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 263 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 263 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::().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 263 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
`