Skip to content

Commit 9ed2862

Browse files
committed
core: begin deduplicating pointer docs
this also cleans up two inconsistancies: 1. both doctests on the ::add methods were actually calling the const version. 2. on of the ::offset methods was missing a line of clarification. part of #139190
1 parent 038d599 commit 9ed2862

File tree

4 files changed

+70
-123
lines changed

4 files changed

+70
-123
lines changed

library/core/src/ptr/const_ptr.rs

Lines changed: 3 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -397,35 +397,7 @@ impl<T: ?Sized> *const T {
397397
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
398398
}
399399

400-
/// Adds a signed offset to a pointer.
401-
///
402-
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
403-
/// offset of `3 * size_of::<T>()` bytes.
404-
///
405-
/// # Safety
406-
///
407-
/// If any of the following conditions are violated, the result is Undefined Behavior:
408-
///
409-
/// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
410-
/// "wrapping around"), must fit in an `isize`.
411-
///
412-
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
413-
/// [allocated object], and the entire memory range between `self` and the result must be in
414-
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
415-
/// of the address space. Note that "range" here refers to a half-open range as usual in Rust,
416-
/// i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
417-
///
418-
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
419-
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
420-
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
421-
/// safe.
422-
///
423-
/// Consider using [`wrapping_offset`] instead if these constraints are
424-
/// difficult to satisfy. The only advantage of this method is that it
425-
/// enables more aggressive compiler optimizations.
426-
///
427-
/// [`wrapping_offset`]: #method.wrapping_offset
428-
/// [allocated object]: crate::ptr#allocated-object
400+
#[doc = include_str!("./docs/offset.md")]
429401
///
430402
/// # Examples
431403
///
@@ -905,38 +877,7 @@ impl<T: ?Sized> *const T {
905877
}
906878
}
907879

908-
/// Adds an unsigned offset to a pointer.
909-
///
910-
/// This can only move the pointer forward (or not move it). If you need to move forward or
911-
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
912-
/// which takes a signed offset.
913-
///
914-
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
915-
/// offset of `3 * size_of::<T>()` bytes.
916-
///
917-
/// # Safety
918-
///
919-
/// If any of the following conditions are violated, the result is Undefined Behavior:
920-
///
921-
/// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
922-
/// "wrapping around"), must fit in an `isize`.
923-
///
924-
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
925-
/// [allocated object], and the entire memory range between `self` and the result must be in
926-
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
927-
/// of the address space.
928-
///
929-
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
930-
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
931-
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
932-
/// safe.
933-
///
934-
/// Consider using [`wrapping_add`] instead if these constraints are
935-
/// difficult to satisfy. The only advantage of this method is that it
936-
/// enables more aggressive compiler optimizations.
937-
///
938-
/// [`wrapping_add`]: #method.wrapping_add
939-
/// [allocated object]: crate::ptr#allocated-object
880+
#[doc = include_str!("./docs/add.md")]
940881
///
941882
/// # Examples
942883
///
@@ -1609,6 +1550,7 @@ impl<T> *const [T] {
16091550
unsafe { index.get_unchecked(self) }
16101551
}
16111552

1553+
16121554
/// Returns `None` if the pointer is null, or else returns a shared slice to
16131555
/// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
16141556
/// that the value has to be initialized.

library/core/src/ptr/docs/add.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Adds an unsigned offset to a pointer.
2+
3+
This can only move the pointer forward (or not move it). If you need to move forward or
4+
backward depending on the value, then you might want [`offset`](#method.offset) instead
5+
which takes a signed offset.
6+
7+
`count` is in units of T; e.g., a `count` of 3 represents a pointer
8+
offset of `3 * size_of::<T>()` bytes.
9+
10+
# Safety
11+
12+
If any of the following conditions are violated, the result is Undefined Behavior:
13+
14+
* The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
15+
"wrapping around"), must fit in an `isize`.
16+
17+
* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
18+
[allocated object], and the entire memory range between `self` and the result must be in
19+
bounds of that allocated object. In particular, this range must not "wrap around" the edge
20+
of the address space.
21+
22+
Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
23+
stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
24+
This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
25+
safe.
26+
27+
Consider using [`wrapping_add`] instead if these constraints are
28+
difficult to satisfy. The only advantage of this method is that it
29+
enables more aggressive compiler optimizations.
30+
31+
[`wrapping_add`]: #method.wrapping_add
32+
[allocated object]: crate::ptr#allocated-object
33+

library/core/src/ptr/docs/offset.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Adds a signed offset to a pointer.
2+
3+
`count` is in units of T; e.g., a `count` of 3 represents a pointer
4+
offset of `3 * size_of::<T>()` bytes.
5+
6+
# Safety
7+
8+
If any of the following conditions are violated, the result is Undefined Behavior:
9+
10+
* The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
11+
"wrapping around"), must fit in an `isize`.
12+
13+
* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
14+
[allocated object], and the entire memory range between `self` and the result must be in
15+
bounds of that allocated object. In particular, this range must not "wrap around" the edge
16+
of the address space. Note that "range" here refers to a half-open range as usual in Rust,
17+
i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
18+
19+
Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
20+
stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
21+
This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
22+
safe.
23+
24+
Consider using [`wrapping_offset`] instead if these constraints are
25+
difficult to satisfy. The only advantage of this method is that it
26+
enables more aggressive compiler optimizations.
27+
28+
[`wrapping_offset`]: #method.wrapping_offset
29+
[allocated object]: crate::ptr#allocated-object
30+

library/core/src/ptr/mut_ptr.rs

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -394,34 +394,7 @@ impl<T: ?Sized> *mut T {
394394
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
395395
}
396396

397-
/// Adds a signed offset to a pointer.
398-
///
399-
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
400-
/// offset of `3 * size_of::<T>()` bytes.
401-
///
402-
/// # Safety
403-
///
404-
/// If any of the following conditions are violated, the result is Undefined Behavior:
405-
///
406-
/// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
407-
/// "wrapping around"), must fit in an `isize`.
408-
///
409-
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
410-
/// [allocated object], and the entire memory range between `self` and the result must be in
411-
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
412-
/// of the address space.
413-
///
414-
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
415-
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
416-
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
417-
/// safe.
418-
///
419-
/// Consider using [`wrapping_offset`] instead if these constraints are
420-
/// difficult to satisfy. The only advantage of this method is that it
421-
/// enables more aggressive compiler optimizations.
422-
///
423-
/// [`wrapping_offset`]: #method.wrapping_offset
424-
/// [allocated object]: crate::ptr#allocated-object
397+
#[doc = include_str!("./docs/offset.md")]
425398
///
426399
/// # Examples
427400
///
@@ -996,44 +969,13 @@ impl<T: ?Sized> *mut T {
996969
unsafe { (self as *const T).byte_offset_from_unsigned(origin) }
997970
}
998971

999-
/// Adds an unsigned offset to a pointer.
1000-
///
1001-
/// This can only move the pointer forward (or not move it). If you need to move forward or
1002-
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
1003-
/// which takes a signed offset.
1004-
///
1005-
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer
1006-
/// offset of `3 * size_of::<T>()` bytes.
1007-
///
1008-
/// # Safety
1009-
///
1010-
/// If any of the following conditions are violated, the result is Undefined Behavior:
1011-
///
1012-
/// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
1013-
/// "wrapping around"), must fit in an `isize`.
1014-
///
1015-
/// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
1016-
/// [allocated object], and the entire memory range between `self` and the result must be in
1017-
/// bounds of that allocated object. In particular, this range must not "wrap around" the edge
1018-
/// of the address space.
1019-
///
1020-
/// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
1021-
/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
1022-
/// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
1023-
/// safe.
1024-
///
1025-
/// Consider using [`wrapping_add`] instead if these constraints are
1026-
/// difficult to satisfy. The only advantage of this method is that it
1027-
/// enables more aggressive compiler optimizations.
1028-
///
1029-
/// [`wrapping_add`]: #method.wrapping_add
1030-
/// [allocated object]: crate::ptr#allocated-object
972+
#[doc = include_str!("./docs/add.md")]
1031973
///
1032974
/// # Examples
1033975
///
1034976
/// ```
1035-
/// let s: &str = "123";
1036-
/// let ptr: *const u8 = s.as_ptr();
977+
/// let mut s: &str = "123".to_string();
978+
/// let ptr: *mut u8 = s.as_mut_ptr();
1037979
///
1038980
/// unsafe {
1039981
/// assert_eq!('2', *ptr.add(1) as char);

0 commit comments

Comments
 (0)