Skip to content

Commit 80d0f14

Browse files
committed
also remove redundant requirements from offset()
1 parent 8e31c9a commit 80d0f14

File tree

2 files changed

+67
-133
lines changed

2 files changed

+67
-133
lines changed

library/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.)
400+
/// If any of the following conditions are violated, the result is Undefined Behavior:
406401
///
407-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
402+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
408403
///
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.
411408
///
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.
424413
///
425414
/// Consider using [`wrapping_offset`] instead if these constraints are
426415
/// difficult to satisfy. The only advantage of this method is that it
@@ -623,7 +612,7 @@ impl<T: ?Sized> *const T {
623612
/// * The distance between the pointers, in bytes, must be an exact multiple
624613
/// of the size of `T`.
625614
///
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
627616
/// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
628617
/// implied by the in-bounds requirement, and the fact that no allocated object can be larger
629618
/// than `isize::MAX`.
@@ -863,37 +852,26 @@ impl<T: ?Sized> *const T {
863852
}
864853
}
865854

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)`).
867856
///
868857
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
869858
/// offset of `3 * size_of::<T>()` bytes.
870859
///
871860
/// # Safety
872861
///
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:
881863
///
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`.
884865
///
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.
889870
///
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.
897875
///
898876
/// Consider using [`wrapping_add`] instead if these constraints are
899877
/// difficult to satisfy. The only advantage of this method is that it
@@ -947,38 +925,27 @@ impl<T: ?Sized> *const T {
947925
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
948926
}
949927

950-
/// Calculates the offset from a pointer (convenience for
928+
/// Subtracts an offset from a pointer (convenience for
951929
/// `.offset((count as isize).wrapping_neg())`).
952930
///
953931
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
954932
/// offset of `3 * size_of::<T>()` bytes.
955933
///
956934
/// # Safety
957935
///
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:
966937
///
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`.
969939
///
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.
974944
///
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.
982949
///
983950
/// Consider using [`wrapping_sub`] instead if these constraints are
984951
/// difficult to satisfy. The only advantage of this method is that it

library/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.)
414+
/// If any of the following conditions are violated, the result is Undefined Behavior:
420415
///
421-
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
416+
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
422417
///
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.
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 egde
421+
/// of the address space.
425422
///
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.
430-
///
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`, so if the computed offset stays in
424+
/// bounds of the allocated object, it is guaranteed to satisfy the first requirement. This
425+
/// 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
@@ -1004,37 +993,26 @@ impl<T: ?Sized> *mut T {
1004993
unsafe { (self as *const T).sub_ptr(origin) }
1005994
}
1006995

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

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

0 commit comments

Comments
 (0)