diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 19ed7599a5101..4d86d3ffcb8ed 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -397,35 +397,7 @@ impl *const T { if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } } - /// Adds a signed offset to a pointer. - /// - /// `count` is in units of T; e.g., a `count` of 3 represents a pointer - /// offset of `3 * size_of::()` bytes. - /// - /// # Safety - /// - /// If any of the following conditions are violated, the result is Undefined Behavior: - /// - /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without - /// "wrapping around"), must fit in an `isize`. - /// - /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some - /// [allocated object], and the entire memory range between `self` and the result must be in - /// bounds of that allocated object. In particular, this range must not "wrap around" the edge - /// of the address space. Note that "range" here refers to a half-open range as usual in Rust, - /// i.e., `self..result` for non-negative offsets and `result..self` for negative offsets. - /// - /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset - /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. - /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always - /// safe. - /// - /// Consider using [`wrapping_offset`] instead if these constraints are - /// difficult to satisfy. The only advantage of this method is that it - /// enables more aggressive compiler optimizations. - /// - /// [`wrapping_offset`]: #method.wrapping_offset - /// [allocated object]: crate::ptr#allocated-object + #[doc = include_str!("./docs/offset.md")] /// /// # Examples /// @@ -905,38 +877,7 @@ impl *const T { } } - /// Adds an unsigned offset to a pointer. - /// - /// This can only move the pointer forward (or not move it). If you need to move forward or - /// backward depending on the value, then you might want [`offset`](#method.offset) instead - /// which takes a signed offset. - /// - /// `count` is in units of T; e.g., a `count` of 3 represents a pointer - /// offset of `3 * size_of::()` bytes. - /// - /// # Safety - /// - /// If any of the following conditions are violated, the result is Undefined Behavior: - /// - /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without - /// "wrapping around"), must fit in an `isize`. - /// - /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some - /// [allocated object], and the entire memory range between `self` and the result must be in - /// bounds of that allocated object. In particular, this range must not "wrap around" the edge - /// of the address space. - /// - /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset - /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. - /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always - /// safe. - /// - /// Consider using [`wrapping_add`] instead if these constraints are - /// difficult to satisfy. The only advantage of this method is that it - /// enables more aggressive compiler optimizations. - /// - /// [`wrapping_add`]: #method.wrapping_add - /// [allocated object]: crate::ptr#allocated-object + #[doc = include_str!("./docs/add.md")] /// /// # Examples /// diff --git a/library/core/src/ptr/docs/add.md b/library/core/src/ptr/docs/add.md new file mode 100644 index 0000000000000..555dc11c1bb40 --- /dev/null +++ b/library/core/src/ptr/docs/add.md @@ -0,0 +1,32 @@ +Adds an unsigned offset to a pointer. + +This can only move the pointer forward (or not move it). If you need to move forward or +backward depending on the value, then you might want [`offset`](#method.offset) instead +which takes a signed offset. + +`count` is in units of T; e.g., a `count` of 3 represents a pointer +offset of `3 * size_of::()` bytes. + +# Safety + +If any of the following conditions are violated, the result is Undefined Behavior: + +* The offset in bytes, `count * size_of::()`, computed on mathematical integers (without +"wrapping around"), must fit in an `isize`. + +* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some +[allocated object], and the entire memory range between `self` and the result must be in +bounds of that allocated object. In particular, this range must not "wrap around" the edge +of the address space. + +Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset +stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. +This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always +safe. + +Consider using [`wrapping_add`] instead if these constraints are +difficult to satisfy. The only advantage of this method is that it +enables more aggressive compiler optimizations. + +[`wrapping_add`]: #method.wrapping_add +[allocated object]: crate::ptr#allocated-object diff --git a/library/core/src/ptr/docs/offset.md b/library/core/src/ptr/docs/offset.md new file mode 100644 index 0000000000000..6e431e054b052 --- /dev/null +++ b/library/core/src/ptr/docs/offset.md @@ -0,0 +1,29 @@ +Adds a signed offset to a pointer. + +`count` is in units of T; e.g., a `count` of 3 represents a pointer +offset of `3 * size_of::()` bytes. + +# Safety + +If any of the following conditions are violated, the result is Undefined Behavior: + +* The offset in bytes, `count * size_of::()`, computed on mathematical integers (without +"wrapping around"), must fit in an `isize`. + +* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some +[allocated object], and the entire memory range between `self` and the result must be in +bounds of that allocated object. In particular, this range must not "wrap around" the edge +of the address space. Note that "range" here refers to a half-open range as usual in Rust, +i.e., `self..result` for non-negative offsets and `result..self` for negative offsets. + +Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset +stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. +This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always +safe. + +Consider using [`wrapping_offset`] instead if these constraints are +difficult to satisfy. The only advantage of this method is that it +enables more aggressive compiler optimizations. + +[`wrapping_offset`]: #method.wrapping_offset +[allocated object]: crate::ptr#allocated-object diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 53aa3ab49388f..9f75d77e0db88 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -394,34 +394,7 @@ impl *mut T { if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } } - /// Adds a signed offset to a pointer. - /// - /// `count` is in units of T; e.g., a `count` of 3 represents a pointer - /// offset of `3 * size_of::()` bytes. - /// - /// # Safety - /// - /// If any of the following conditions are violated, the result is Undefined Behavior: - /// - /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without - /// "wrapping around"), must fit in an `isize`. - /// - /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some - /// [allocated object], and the entire memory range between `self` and the result must be in - /// bounds of that allocated object. In particular, this range must not "wrap around" the edge - /// of the address space. - /// - /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset - /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. - /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always - /// safe. - /// - /// Consider using [`wrapping_offset`] instead if these constraints are - /// difficult to satisfy. The only advantage of this method is that it - /// enables more aggressive compiler optimizations. - /// - /// [`wrapping_offset`]: #method.wrapping_offset - /// [allocated object]: crate::ptr#allocated-object + #[doc = include_str!("./docs/offset.md")] /// /// # Examples /// @@ -996,44 +969,13 @@ impl *mut T { unsafe { (self as *const T).byte_offset_from_unsigned(origin) } } - /// Adds an unsigned offset to a pointer. - /// - /// This can only move the pointer forward (or not move it). If you need to move forward or - /// backward depending on the value, then you might want [`offset`](#method.offset) instead - /// which takes a signed offset. - /// - /// `count` is in units of T; e.g., a `count` of 3 represents a pointer - /// offset of `3 * size_of::()` bytes. - /// - /// # Safety - /// - /// If any of the following conditions are violated, the result is Undefined Behavior: - /// - /// * The offset in bytes, `count * size_of::()`, computed on mathematical integers (without - /// "wrapping around"), must fit in an `isize`. - /// - /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some - /// [allocated object], and the entire memory range between `self` and the result must be in - /// bounds of that allocated object. In particular, this range must not "wrap around" the edge - /// of the address space. - /// - /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset - /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement. - /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec`) is always - /// safe. - /// - /// Consider using [`wrapping_add`] instead if these constraints are - /// difficult to satisfy. The only advantage of this method is that it - /// enables more aggressive compiler optimizations. - /// - /// [`wrapping_add`]: #method.wrapping_add - /// [allocated object]: crate::ptr#allocated-object + #[doc = include_str!("./docs/add.md")] /// /// # Examples /// /// ``` - /// let s: &str = "123"; - /// let ptr: *const u8 = s.as_ptr(); + /// let mut s: String = "123".to_string(); + /// let ptr: *mut u8 = s.as_mut_ptr(); /// /// unsafe { /// assert_eq!('2', *ptr.add(1) as char);