Skip to content

Commit 0860a04

Browse files
committed
also remove redundant requirements from offset()
1 parent 6f80604 commit 0860a04

File tree

3 files changed

+100
-196
lines changed

3 files changed

+100
-196
lines changed

core/src/ptr/const_ptr.rs

+34-67
Original file line numberDiff line numberDiff line change
@@ -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:
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.)
406-
///
407-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
400+
/// If any of the following conditions are violated, the result is Undefined Behavior:
408401
///
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.
402+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
411403
///
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.
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.
416408
///
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
@@ -622,7 +611,7 @@ impl<T: ?Sized> *const T {
622611
/// * The distance between the pointers, in bytes, must be an exact multiple
623612
/// of the size of `T`.
624613
///
625-
/// As a consequence, the absolute distance between the pointers, **in bytes**, computed on
614+
/// As a consequence, the absolute distance between the pointers, in bytes, computed on
626615
/// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
627616
/// implied by the in-bounds requirement, and the fact that no allocated object can be larger
628617
/// than `isize::MAX` bytes.
@@ -862,37 +851,26 @@ impl<T: ?Sized> *const T {
862851
}
863852
}
864853

865-
/// 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)`).
866855
///
867856
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
868857
/// offset of `3 * size_of::<T>()` bytes.
869858
///
870859
/// # Safety
871860
///
872-
/// If any of the following conditions are violated, the result is Undefined
873-
/// Behavior:
874-
///
875-
/// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
876-
/// pointer must be either in bounds or at the end of the same [allocated object].
877-
/// (If it is zero, then the function is always well-defined.)
878-
///
879-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
861+
/// If any of the following conditions are violated, the result is Undefined Behavior:
880862
///
881-
/// * The offset being in bounds cannot rely on "wrapping around" the address
882-
/// space. That is, the infinite-precision sum must fit in a `usize`.
863+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
883864
///
884-
/// The compiler and standard library generally tries to ensure allocations
885-
/// never reach a size where an offset is a concern. For instance, `Vec`
886-
/// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
887-
/// `vec.as_ptr().add(vec.len())` is always safe.
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.
888869
///
889-
/// Most platforms fundamentally can't even construct such an allocation.
890-
/// For instance, no known 64-bit platform can ever serve a request
891-
/// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
892-
/// However, some 32-bit and 16-bit platforms may successfully serve a request for
893-
/// more than `isize::MAX` bytes with things like Physical Address
894-
/// Extension. As such, memory acquired directly from allocators or memory
895-
/// 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.
896874
///
897875
/// Consider using [`wrapping_add`] instead if these constraints are
898876
/// difficult to satisfy. The only advantage of this method is that it
@@ -946,38 +924,27 @@ impl<T: ?Sized> *const T {
946924
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
947925
}
948926

949-
/// Calculates the offset from a pointer (convenience for
927+
/// Subtracts an offset from a pointer (convenience for
950928
/// `.offset((count as isize).wrapping_neg())`).
951929
///
952930
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
953931
/// offset of `3 * size_of::<T>()` bytes.
954932
///
955933
/// # Safety
956934
///
957-
/// If any of the following conditions are violated, the result is Undefined
958-
/// Behavior:
959-
///
960-
/// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
961-
/// pointer must be either in bounds or at the end of the same [allocated object].
962-
/// (If it is zero, then the function is always well-defined.)
963-
///
964-
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
935+
/// If any of the following conditions are violated, the result is Undefined Behavior:
965936
///
966-
/// * The offset being in bounds cannot rely on "wrapping around" the address
967-
/// 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`.
968938
///
969-
/// The compiler and standard library generally tries to ensure allocations
970-
/// never reach a size where an offset is a concern. For instance, `Vec`
971-
/// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
972-
/// `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.
973943
///
974-
/// Most platforms fundamentally can't even construct such an allocation.
975-
/// For instance, no known 64-bit platform can ever serve a request
976-
/// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
977-
/// However, some 32-bit and 16-bit platforms may successfully serve a request for
978-
/// more than `isize::MAX` bytes with things like Physical Address
979-
/// Extension. As such, memory acquired directly from allocators or memory
980-
/// 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.
981948
///
982949
/// Consider using [`wrapping_sub`] instead if these constraints are
983950
/// difficult to satisfy. The only advantage of this method is that it

core/src/ptr/mut_ptr.rs

+33-66
Original file line numberDiff line numberDiff line change
@@ -404,37 +404,26 @@ impl<T: ?Sized> *mut T {
404404
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
405405
}
406406

407-
/// Calculates the offset from a pointer.
407+
/// Adds an offset to a pointer.
408408
///
409409
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
410410
/// offset of `3 * size_of::<T>()` bytes.
411411
///
412412
/// # Safety
413413
///
414-
/// If any of the following conditions are violated, the result is Undefined
415-
/// Behavior:
416-
///
417-
/// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
418-
/// pointer must be either in bounds or at the end of the same [allocated object].
419-
/// (If it is zero, then the function is always well-defined.)
420-
///
421-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
414+
/// If any of the following conditions are violated, the result is Undefined Behavior:
422415
///
423-
/// * The offset being in bounds cannot rely on "wrapping around" the address
424-
/// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
416+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
425417
///
426-
/// The compiler and standard library generally tries to ensure allocations
427-
/// never reach a size where an offset is a concern. For instance, `Vec`
428-
/// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
429-
/// `vec.as_ptr().add(vec.len())` is always safe.
418+
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
419+
/// [allocated object], and the entire memory range between `self` and the result must be in
420+
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
421+
/// of the address space.
430422
///
431-
/// Most platforms fundamentally can't even construct such an allocation.
432-
/// For instance, no known 64-bit platform can ever serve a request
433-
/// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
434-
/// However, some 32-bit and 16-bit platforms may successfully serve a request for
435-
/// more than `isize::MAX` bytes with things like Physical Address
436-
/// Extension. As such, memory acquired directly from allocators or memory
437-
/// mapped files *may* be too large to handle with this function.
423+
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
424+
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
425+
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
426+
/// safe.
438427
///
439428
/// Consider using [`wrapping_offset`] instead if these constraints are
440429
/// difficult to satisfy. The only advantage of this method is that it
@@ -1003,37 +992,26 @@ impl<T: ?Sized> *mut T {
1003992
unsafe { (self as *const T).sub_ptr(origin) }
1004993
}
1005994

1006-
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
995+
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
1007996
///
1008997
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
1009998
/// offset of `3 * size_of::<T>()` bytes.
1010999
///
10111000
/// # Safety
10121001
///
1013-
/// If any of the following conditions are violated, the result is Undefined
1014-
/// Behavior:
1015-
///
1016-
/// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
1017-
/// pointer must be either in bounds or at the end of the same [allocated object].
1018-
/// (If it is zero, then the function is always well-defined.)
1019-
///
1020-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
1002+
/// If any of the following conditions are violated, the result is Undefined Behavior:
10211003
///
1022-
/// * The offset being in bounds cannot rely on "wrapping around" the address
1023-
/// space. That is, the infinite-precision sum must fit in a `usize`.
1004+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
10241005
///
1025-
/// The compiler and standard library generally tries to ensure allocations
1026-
/// never reach a size where an offset is a concern. For instance, `Vec`
1027-
/// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
1028-
/// `vec.as_ptr().add(vec.len())` is always safe.
1006+
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
1007+
/// [allocated object], and the entire memory range between `self` and the result must be in
1008+
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
1009+
/// of the address space.
10291010
///
1030-
/// Most platforms fundamentally can't even construct such an allocation.
1031-
/// For instance, no known 64-bit platform can ever serve a request
1032-
/// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
1033-
/// However, some 32-bit and 16-bit platforms may successfully serve a request for
1034-
/// more than `isize::MAX` bytes with things like Physical Address
1035-
/// Extension. As such, memory acquired directly from allocators or memory
1036-
/// mapped files *may* be too large to handle with this function.
1011+
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
1012+
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
1013+
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
1014+
/// safe.
10371015
///
10381016
/// Consider using [`wrapping_add`] instead if these constraints are
10391017
/// difficult to satisfy. The only advantage of this method is that it
@@ -1087,38 +1065,27 @@ impl<T: ?Sized> *mut T {
10871065
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
10881066
}
10891067

1090-
/// Calculates the offset from a pointer (convenience for
1068+
/// Subtracts an offset from a pointer (convenience for
10911069
/// `.offset((count as isize).wrapping_neg())`).
10921070
///
10931071
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
10941072
/// offset of `3 * size_of::<T>()` bytes.
10951073
///
10961074
/// # Safety
10971075
///
1098-
/// If any of the following conditions are violated, the result is Undefined
1099-
/// Behavior:
1100-
///
1101-
/// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
1102-
/// pointer must be either in bounds or at the end of the same [allocated object].
1103-
/// (If it is zero, then the function is always well-defined.)
1104-
///
1105-
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
1076+
/// If any of the following conditions are violated, the result is Undefined Behavior:
11061077
///
1107-
/// * The offset being in bounds cannot rely on "wrapping around" the address
1108-
/// space. That is, the infinite-precision sum must fit in a usize.
1078+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
11091079
///
1110-
/// The compiler and standard library generally tries to ensure allocations
1111-
/// never reach a size where an offset is a concern. For instance, `Vec`
1112-
/// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
1113-
/// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
1080+
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
1081+
/// [allocated object], and the entire memory range between `self` and the result must be in
1082+
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
1083+
/// of the address space.
11141084
///
1115-
/// Most platforms fundamentally can't even construct such an allocation.
1116-
/// For instance, no known 64-bit platform can ever serve a request
1117-
/// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
1118-
/// However, some 32-bit and 16-bit platforms may successfully serve a request for
1119-
/// more than `isize::MAX` bytes with things like Physical Address
1120-
/// Extension. As such, memory acquired directly from allocators or memory
1121-
/// mapped files *may* be too large to handle with this function.
1085+
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
1086+
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
1087+
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
1088+
/// safe.
11221089
///
11231090
/// Consider using [`wrapping_sub`] instead if these constraints are
11241091
/// difficult to satisfy. The only advantage of this method is that it

0 commit comments

Comments
 (0)