From e32c69ae668f8ebd96acb32b6ded1d6e117bd876 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 18 May 2025 14:40:49 +0200 Subject: [PATCH] =?UTF-8?q?terminology:=20allocated=20object=20=E2=86=92?= =?UTF-8?q?=20allocation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/core/src/ffi/c_str.rs | 2 +- library/core/src/intrinsics/mod.rs | 2 +- library/core/src/primitive_docs.rs | 4 +- library/core/src/ptr/const_ptr.rs | 80 +++++++++++------------ library/core/src/ptr/mod.rs | 62 +++++++++--------- library/core/src/ptr/mut_ptr.rs | 95 ++++++++++++++-------------- library/core/src/ptr/non_null.rs | 46 +++++++------- library/core/src/slice/raw.rs | 20 +++--- tests/ui/const-ptr/allowed_slices.rs | 2 +- 9 files changed, 158 insertions(+), 155 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index ac07c645c0195..6e9d984893e0d 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -207,7 +207,7 @@ impl CStr { /// * `ptr` must be [valid] for reads of bytes up to and including the nul terminator. /// This means in particular: /// - /// * The entire memory range of this `CStr` must be contained within a single allocated object! + /// * The entire memory range of this `CStr` must be contained within a single allocation! /// * `ptr` must be non-null even for a zero-length cstr. /// /// * The memory referenced by the returned `CStr` must not be mutated for diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index effdc3c63eeaa..eaec849b38930 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1708,7 +1708,7 @@ pub const fn needs_drop() -> bool; /// # Safety /// /// If the computed offset is non-zero, then both the starting and resulting pointer must be -/// either in bounds or at the end of an allocated object. If either pointer is out +/// either in bounds or at the end of an allocation. If either pointer is out /// of bounds or arithmetic overflow occurs then this operation is undefined behavior. /// /// The stabilized version of this intrinsic is [`pointer::offset`]. diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 17c4b48836134..10b11613f90fa 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1623,7 +1623,7 @@ mod prim_usize {} /// * if `size_of_val(t) > 0`, then `t` is dereferenceable for `size_of_val(t)` many bytes /// /// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range -/// `[a, a + N)` is all contained within a single [allocated object]. +/// `[a, a + N)` is all contained within a single [allocation]. /// /// For instance, this means that unsafe code in a safe function may assume these invariants are /// ensured of arguments passed by the caller, and it may assume that these invariants are ensured @@ -1639,7 +1639,7 @@ mod prim_usize {} /// may be unsound or become unsound in future versions of Rust depending on how this question is /// decided. /// -/// [allocated object]: ptr#allocated-object +/// [allocation]: ptr#allocation #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 35089b4853d7f..aab0ec01d86e5 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -384,13 +384,13 @@ impl *const T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -399,7 +399,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_offset`]: #method.wrapping_offset - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -484,17 +484,17 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to + /// The resulting pointer "remembers" the [allocation] that `self` points to /// (this is called "[Provenance](ptr/index.html#provenance)"). - /// The pointer must not be used to read or write other allocated objects. + /// The pointer must not be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`offset`], this method basically delays the requirement of staying within the - /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// same allocation: [`offset`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -502,10 +502,10 @@ impl *const T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other - /// words, leaving the allocated object and then re-entering it later is permitted. + /// words, leaving the allocation and then re-entering it later is permitted. /// /// [`offset`]: #method.offset - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -618,7 +618,7 @@ impl *const T { /// * `self` and `origin` must either /// /// * point to the same address, or - /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocation], and the memory range between /// the two pointers must be in bounds of that object. (See below for an example.) /// /// * The distance between the pointers, in bytes, must be an exact multiple @@ -626,10 +626,10 @@ impl *const T { /// /// As a consequence, the absolute distance between the pointers, in bytes, computed on /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is - /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// implied by the in-bounds requirement, and the fact that no allocation can be larger /// than `isize::MAX` bytes. /// - /// The requirement for pointers to be derived from the same allocated object is primarily + /// The requirement for pointers to be derived from the same allocation is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated /// objects is not known at compile-time. However, the requirement also exists at /// runtime and may be exploited by optimizations. If you wish to compute the difference between @@ -638,7 +638,7 @@ impl *const T { // FIXME: recommend `addr()` instead of `as usize` once that is stable. /// /// [`add`]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics /// @@ -896,12 +896,12 @@ impl *const T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -910,7 +910,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_add`]: #method.wrapping_add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1002,12 +1002,12 @@ impl *const T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -1016,7 +1016,7 @@ impl *const T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_sub`]: #method.wrapping_sub - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1106,16 +1106,16 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not - /// be used to read or write other allocated objects. + /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not + /// be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`add`], this method basically delays the requirement of staying within the - /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// same allocation: [`add`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -1123,10 +1123,10 @@ impl *const T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the - /// allocated object and then re-entering it later is permitted. + /// allocation and then re-entering it later is permitted. /// /// [`add`]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1185,16 +1185,16 @@ impl *const T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not - /// be used to read or write other allocated objects. + /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not + /// be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`sub`], this method basically delays the requirement of staying within the - /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// same allocation: [`sub`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -1202,10 +1202,10 @@ impl *const T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the - /// allocated object and then re-entering it later is permitted. + /// allocation and then re-entering it later is permitted. /// /// [`sub`]: #method.sub - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1597,8 +1597,8 @@ impl *const [T] { /// * The pointer must be [valid] for reads for `ptr.len() * size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single [allocated object]! - /// Slices can never span across multiple allocated objects. + /// * The entire memory range of this slice must be contained within a single [allocation]! + /// Slices can never span across multiple allocations. /// /// * The pointer must be aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references @@ -1619,7 +1619,7 @@ impl *const [T] { /// See also [`slice::from_raw_parts`][]. /// /// [valid]: crate::ptr#safety - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics during const evaluation /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index bd6c4daa509d9..f16fdc8ef8522 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -19,10 +19,10 @@ //! pointer. The following points are only concerned with non-zero-sized accesses. //! * A [null] pointer is *never* valid. //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer be -//! *dereferenceable*. The [provenance] of the pointer is used to determine which [allocated -//! object] it is derived from; a pointer is dereferenceable if the memory range of the given size -//! starting at the pointer is entirely contained within the bounds of that allocated object. Note -//! that in Rust, every (stack-allocated) variable is considered a separate allocated object. +//! *dereferenceable*. The [provenance] of the pointer is used to determine which [allocation] +//! it is derived from; a pointer is dereferenceable if the memory range of the given size +//! starting at the pointer is entirely contained within the bounds of that allocation. Note +//! that in Rust, every (stack-allocated) variable is considered a separate allocation. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different @@ -30,7 +30,7 @@ //! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot //! be used for inter-thread synchronization. //! * The result of casting a reference to a pointer is valid for as long as the -//! underlying object is live and no reference (just raw pointers) is used to +//! underlying allocation is live and no reference (just raw pointers) is used to //! access the same memory. That is, reference and pointer accesses cannot be //! interleaved. //! @@ -95,24 +95,26 @@ //! //! [valid value]: ../../reference/behavior-considered-undefined.html#invalid-values //! -//! ## Allocated object +//! ## Allocation //! -//! An *allocated object* is a subset of program memory which is addressable +//! +//! +//! An *allocation* is a subset of program memory which is addressable //! from Rust, and within which pointer arithmetic is possible. Examples of -//! allocated objects include heap allocations, stack-allocated variables, +//! allocations include heap allocations, stack-allocated variables, //! statics, and consts. The safety preconditions of some Rust operations - //! such as `offset` and field projections (`expr.field`) - are defined in -//! terms of the allocated objects on which they operate. +//! terms of the allocations on which they operate. //! -//! An allocated object has a base address, a size, and a set of memory -//! addresses. It is possible for an allocated object to have zero size, but -//! such an allocated object will still have a base address. The base address -//! of an allocated object is not necessarily unique. While it is currently the -//! case that an allocated object always has a set of memory addresses which is +//! An allocation has a base address, a size, and a set of memory +//! addresses. It is possible for an allocation to have zero size, but +//! such an allocation will still have a base address. The base address +//! of an allocation is not necessarily unique. While it is currently the +//! case that an allocation always has a set of memory addresses which is //! fully contiguous (i.e., has no "holes"), there is no guarantee that this //! will not change in the future. //! -//! For any allocated object with `base` address, `size`, and a set of +//! For any allocation with `base` address, `size`, and a set of //! `addresses`, the following are guaranteed: //! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base + //! size)` (note that this requires `a < base + size`, not `a <= base + size`) @@ -122,11 +124,11 @@ //! - `size <= isize::MAX` //! //! As a consequence of these guarantees, given any address `a` within the set -//! of addresses of an allocated object: +//! of addresses of an allocation: //! - It is guaranteed that `a - base` does not overflow `isize` //! - It is guaranteed that `a - base` is non-negative //! - It is guaranteed that, given `o = a - base` (i.e., the offset of `a` within -//! the allocated object), `base + o` will not wrap around the address space (in +//! the allocation), `base + o` will not wrap around the address space (in //! other words, will not overflow `usize`) //! //! [`null()`]: null @@ -138,8 +140,8 @@ //! and the freed memory gets reallocated before your read/write (in fact this is the //! worst-case scenario, UAFs would be much less concerning if this didn't happen!). //! As another example, consider that [`wrapping_offset`] is documented to "remember" -//! the allocated object that the original pointer points to, even if it is offset far -//! outside the memory range occupied by that allocated object. +//! the allocation that the original pointer points to, even if it is offset far +//! outside the memory range occupied by that allocation. //! To rationalize claims like this, pointers need to somehow be *more* than just their addresses: //! they must have **provenance**. //! @@ -159,12 +161,12 @@ //! writes. Note that this can interact with the other components, e.g. a pointer might permit //! mutation only for a subset of addresses, or only for a subset of its maximal timespan. //! -//! When an [allocated object] is created, it has a unique Original Pointer. For alloc +//! When an [allocation] is created, it has a unique Original Pointer. For alloc //! APIs this is literally the pointer the call returns, and for local variables and statics, //! this is the name of the variable/static. (This is mildly overloading the term "pointer" //! for the sake of brevity/exposition.) //! -//! The Original Pointer for an allocated object has provenance that constrains the *spatial* +//! The Original Pointer for an allocation has provenance that constrains the *spatial* //! permissions of this pointer to the memory range of the allocation, and the *temporal* //! permissions to the lifetime of the allocation. Provenance is implicitly inherited by all //! pointers transitively derived from the Original Pointer through operations like [`offset`], @@ -192,10 +194,10 @@ //! provenance since they access an empty range of memory. //! //! * It is undefined behavior to [`offset`] a pointer across a memory range that is not contained -//! in the allocated object it is derived from, or to [`offset_from`] two pointers not derived -//! from the same allocated object. Provenance is used to say what exactly "derived from" even +//! in the allocation it is derived from, or to [`offset_from`] two pointers not derived +//! from the same allocation. Provenance is used to say what exactly "derived from" even //! means: the lineage of a pointer is traced back to the Original Pointer it descends from, and -//! that identifies the relevant allocated object. In particular, it's always UB to offset a +//! that identifies the relevant allocation. In particular, it's always UB to offset a //! pointer derived from something that is now deallocated, except if the offset is 0. //! //! But it *is* still sound to: @@ -216,7 +218,7 @@ //! * Compare arbitrary pointers by address. Pointer comparison ignores provenance and addresses //! *are* just integers, so there is always a coherent answer, even if the pointers are dangling //! or from different provenances. Note that if you get "lucky" and notice that a pointer at the -//! end of one allocated object is the "same" address as the start of another allocated object, +//! end of one allocation is the "same" address as the start of another allocation, //! anything you do with that fact is *probably* going to be gibberish. The scope of that //! gibberish is kept under control by the fact that the two pointers *still* aren't allowed to //! access the other's allocation (bytes), because they still have different provenance. @@ -369,7 +371,7 @@ //! integer-to-pointer casts. //! //! [aliasing]: ../../nomicon/aliasing.html -//! [allocated object]: #allocated-object +//! [allocation]: #allocation //! [provenance]: #provenance //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer //! [ub]: ../../reference/behavior-considered-undefined.html @@ -1016,7 +1018,7 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { // SAFETY: the caller must guarantee that `x` and `y` are // valid for writes and properly aligned. `tmp` cannot be // overlapping either `x` or `y` because `tmp` was just allocated - // on the stack as a separate allocated object. + // on the stack as a separate allocation. unsafe { copy_nonoverlapping(x, tmp.as_mut_ptr(), 1); copy(y, x, 1); // `x` and `y` may overlap @@ -1135,7 +1137,7 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { // Going though a slice here helps codegen know the size fits in `isize` let slice = slice_from_raw_parts_mut(x, count); // SAFETY: This is all readable from the pointer, meaning it's one - // allocated object, and thus cannot be more than isize::MAX bytes. + // allocation, and thus cannot be more than isize::MAX bytes. let bytes = unsafe { mem::size_of_val_raw::<[T]>(slice) }; if let Some(bytes) = NonZero::new(bytes) { // SAFETY: These are the same ranges, just expressed in a different @@ -1288,7 +1290,7 @@ pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be // cast to a mutable reference (valid for writes, aligned, initialized), // and cannot overlap `src` since `dst` must point to a distinct - // allocated object. + // allocation. unsafe { ub_checks::assert_unsafe_precondition!( check_language_ub, @@ -1535,7 +1537,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { let mut tmp = MaybeUninit::::uninit(); // SAFETY: the caller must guarantee that `src` is valid for reads. // `src` cannot overlap `tmp` because `tmp` was just allocated on - // the stack as a separate allocated object. + // the stack as a separate allocation. // // Also, since we just wrote a valid value into `tmp`, it is guaranteed // to be properly initialized. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 9cf251742d427..3f57496a1ff58 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -381,12 +381,12 @@ impl *mut T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -395,7 +395,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_offset`]: #method.wrapping_offset - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -449,7 +449,7 @@ impl *mut T { // SAFETY: the caller must uphold the safety contract for `offset`. // The obtained pointer is valid for writes since the caller must - // guarantee that it points to the same allocated object as `self`. + // guarantee that it points to the same allocation as `self`. unsafe { intrinsics::offset(self, count) } } @@ -482,17 +482,17 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to + /// The resulting pointer "remembers" the [allocation] that `self` points to /// (this is called "[Provenance](ptr/index.html#provenance)"). - /// The pointer must not be used to read or write other allocated objects. + /// The pointer must not be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`offset`], this method basically delays the requirement of staying within the - /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object + /// same allocation: [`offset`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -500,10 +500,10 @@ impl *mut T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other - /// words, leaving the allocated object and then re-entering it later is permitted. + /// words, leaving the allocation and then re-entering it later is permitted. /// /// [`offset`]: #method.offset - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -792,7 +792,7 @@ impl *mut T { /// * `self` and `origin` must either /// /// * point to the same address, or - /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between + /// * both be [derived from][crate::ptr#provenance] a pointer to the same [allocation], and the memory range between /// the two pointers must be in bounds of that object. (See below for an example.) /// /// * The distance between the pointers, in bytes, must be an exact multiple @@ -800,10 +800,10 @@ impl *mut T { /// /// As a consequence, the absolute distance between the pointers, in bytes, computed on /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is - /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// implied by the in-bounds requirement, and the fact that no allocation can be larger /// than `isize::MAX` bytes. /// - /// The requirement for pointers to be derived from the same allocated object is primarily + /// The requirement for pointers to be derived from the same allocation is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated /// objects is not known at compile-time. However, the requirement also exists at /// runtime and may be exploited by optimizations. If you wish to compute the difference between @@ -812,7 +812,7 @@ impl *mut T { // FIXME: recommend `addr()` instead of `as usize` once that is stable. /// /// [`add`]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics /// @@ -987,12 +987,12 @@ impl *mut T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -1001,7 +1001,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_add`]: #method.wrapping_add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1093,12 +1093,12 @@ impl *mut T { /// "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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// @@ -1107,7 +1107,7 @@ impl *mut T { /// enables more aggressive compiler optimizations. /// /// [`wrapping_sub`]: #method.wrapping_sub - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1197,16 +1197,16 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not - /// be used to read or write other allocated objects. + /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not + /// be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`add`], this method basically delays the requirement of staying within the - /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object + /// same allocation: [`add`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -1214,10 +1214,10 @@ impl *mut T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the - /// allocated object and then re-entering it later is permitted. + /// allocation and then re-entering it later is permitted. /// /// [`add`]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1273,16 +1273,16 @@ impl *mut T { /// /// This operation itself is always safe, but using the resulting pointer is not. /// - /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not - /// be used to read or write other allocated objects. + /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not + /// be used to read or write other allocations. /// /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z` /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless - /// `x` and `y` point into the same allocated object. + /// `x` and `y` point into the same allocation. /// /// Compared to [`sub`], this method basically delays the requirement of staying within the - /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object + /// same allocation: [`sub`] is immediate Undefined Behavior when crossing object /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`] /// can be optimized better and is thus preferable in performance-sensitive code. @@ -1290,10 +1290,10 @@ impl *mut T { /// The delayed check only considers the value of the pointer that was dereferenced, not the /// intermediate values used during the computation of the final result. For example, /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the - /// allocated object and then re-entering it later is permitted. + /// allocation and then re-entering it later is permitted. /// /// [`sub`]: #method.sub - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -1802,7 +1802,7 @@ impl *mut [T] { /// /// # Safety /// - /// `mid` must be [in-bounds] of the underlying [allocated object]. + /// `mid` must be [in-bounds] of the underlying [allocation]. /// Which means `self` must be dereferenceable and span a single allocation /// that is at least `mid * size_of::()` bytes long. Not upholding these /// requirements is *[undefined behavior]* even if the resulting pointers are not used. @@ -1813,7 +1813,7 @@ impl *mut [T] { /// /// [`split_at_mut_unchecked`]: #method.split_at_mut_unchecked /// [in-bounds]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// /// # Examples @@ -1848,13 +1848,14 @@ impl *mut [T] { /// /// # Safety /// - /// `mid` must be [in-bounds] of the underlying [allocated object]. + /// `mid` must be [in-bounds] of the underlying [allocation]. /// Which means `self` must be dereferenceable and span a single allocation /// that is at least `mid * size_of::()` bytes long. Not upholding these /// requirements is *[undefined behavior]* even if the resulting pointers are not used. /// /// [in-bounds]: #method.add /// [out-of-bounds index]: #method.add + /// [allocation]: crate::ptr#allocation /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// /// # Examples @@ -1954,8 +1955,8 @@ impl *mut [T] { /// * The pointer must be [valid] for reads for `ptr.len() * size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single [allocated object]! - /// Slices can never span across multiple allocated objects. + /// * The entire memory range of this slice must be contained within a single [allocation]! + /// Slices can never span across multiple allocations. /// /// * The pointer must be aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references @@ -1976,7 +1977,7 @@ impl *mut [T] { /// See also [`slice::from_raw_parts`][]. /// /// [valid]: crate::ptr#safety - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics during const evaluation /// @@ -2012,8 +2013,8 @@ impl *mut [T] { /// * The pointer must be [valid] for reads and writes for `ptr.len() * size_of::()` /// many bytes, and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single [allocated object]! - /// Slices can never span across multiple allocated objects. + /// * The entire memory range of this slice must be contained within a single [allocation]! + /// Slices can never span across multiple allocations. /// /// * The pointer must be aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references @@ -2034,7 +2035,7 @@ impl *mut [T] { /// See also [`slice::from_raw_parts_mut`][]. /// /// [valid]: crate::ptr#safety - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics during const evaluation /// diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d05fb6a6d3199..1c35f96790919 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -500,16 +500,16 @@ impl NonNull { /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// /// * If the computed offset is non-zero, then `self` must be derived from 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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -576,16 +576,16 @@ impl NonNull { /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// /// * If the computed offset is non-zero, then `self` must be derived from 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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -653,16 +653,16 @@ impl NonNull { /// * The computed offset, `count * size_of::()` bytes, must not overflow `isize`. /// /// * If the computed offset is non-zero, then `self` must be derived from 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 + /// [allocation], and the entire memory range between `self` and the result must be in + /// bounds of that allocation. 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. + /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset + /// stays in bounds of the allocation, 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. /// - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Examples /// @@ -745,7 +745,7 @@ impl NonNull { /// * `self` and `origin` must either /// /// * point to the same address, or - /// * both be *derived from* a pointer to the same [allocated object], and the memory range between + /// * both be *derived from* a pointer to the same [allocation], and the memory range between /// the two pointers must be in bounds of that object. (See below for an example.) /// /// * The distance between the pointers, in bytes, must be an exact multiple @@ -753,10 +753,10 @@ impl NonNull { /// /// As a consequence, the absolute distance between the pointers, in bytes, computed on /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is - /// implied by the in-bounds requirement, and the fact that no allocated object can be larger + /// implied by the in-bounds requirement, and the fact that no allocation can be larger /// than `isize::MAX` bytes. /// - /// The requirement for pointers to be derived from the same allocated object is primarily + /// The requirement for pointers to be derived from the same allocation is primarily /// needed for `const`-compatibility: the distance between pointers into *different* allocated /// objects is not known at compile-time. However, the requirement also exists at /// runtime and may be exploited by optimizations. If you wish to compute the difference between @@ -765,7 +765,7 @@ impl NonNull { // FIXME: recommend `addr()` instead of `as usize` once that is stable. /// /// [`add`]: #method.add - /// [allocated object]: crate::ptr#allocated-object + /// [allocation]: crate::ptr#allocation /// /// # Panics /// @@ -1445,8 +1445,8 @@ impl NonNull<[T]> { /// * The pointer must be [valid] for reads for `ptr.len() * size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single allocated object! - /// Slices can never span across multiple allocated objects. + /// * The entire memory range of this slice must be contained within a single allocation! + /// Slices can never span across multiple allocations. /// /// * The pointer must be aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references @@ -1490,8 +1490,8 @@ impl NonNull<[T]> { /// * The pointer must be [valid] for reads and writes for `ptr.len() * size_of::()` /// many bytes, and it must be properly aligned. This means in particular: /// - /// * The entire memory range of this slice must be contained within a single allocated object! - /// Slices can never span across multiple allocated objects. + /// * The entire memory range of this slice must be contained within a single allocation! + /// Slices can never span across multiple allocations. /// /// * The pointer must be aligned even for zero-length slices. One /// reason for this is that enum layout optimizations may rely on references diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 3582c7e8b3f38..bc1c06c287a94 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -14,8 +14,8 @@ use crate::{array, ptr, ub_checks}; /// * `data` must be non-null, [valid] for reads for `len * size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. See [below](#incorrect-usage) +/// * The entire memory range of this slice must be contained within a single allocation! +/// Slices can never span across multiple allocations. See [below](#incorrect-usage) /// for an example incorrectly not taking this into account. /// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One /// reason for this is that enum layout optimizations may rely on references @@ -65,14 +65,14 @@ use crate::{array, ptr, ub_checks}; /// assert_eq!(fst_end, snd_start, "Slices must be contiguous!"); /// unsafe { /// // The assertion above ensures `fst` and `snd` are contiguous, but they might -/// // still be contained within _different allocated objects_, in which case +/// // still be contained within _different allocations_, in which case /// // creating this slice is undefined behavior. /// slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len()) /// } /// } /// /// fn main() { -/// // `a` and `b` are different allocated objects... +/// // `a` and `b` are different allocations... /// let a = 42; /// let b = 27; /// // ... which may nevertheless be laid out contiguously in memory: | a | b | @@ -149,8 +149,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// * `data` must be non-null, [valid] for both reads and writes for `len * size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// * The entire memory range of this slice must be contained within a single allocation! +/// Slices can never span across multiple allocations. /// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One /// reason for this is that enum layout optimizations may rely on references /// (including slices of any length) being aligned and non-null to distinguish @@ -226,8 +226,8 @@ pub const fn from_mut(s: &mut T) -> &mut [T] { /// the last element, such that the offset from the end to the start pointer is /// the length of the slice. /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// * The entire memory range of this slice must be contained within a single allocation! +/// Slices can never span across multiple allocations. /// /// * The range must contain `N` consecutive properly initialized values of type `T`. /// @@ -295,8 +295,8 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { /// the last element, such that the offset from the end to the start pointer is /// the length of the slice. /// -/// * The entire memory range of this slice must be contained within a single allocated object! -/// Slices can never span across multiple allocated objects. +/// * The entire memory range of this slice must be contained within a single allocation! +/// Slices can never span across multiple allocations. /// /// * The range must contain `N` consecutive properly initialized values of type `T`. /// diff --git a/tests/ui/const-ptr/allowed_slices.rs b/tests/ui/const-ptr/allowed_slices.rs index e5b9966c60930..23f63ff5febf7 100644 --- a/tests/ui/const-ptr/allowed_slices.rs +++ b/tests/ui/const-ptr/allowed_slices.rs @@ -26,7 +26,7 @@ pub static S5: &[MaybeUninit] = unsafe { from_raw_parts((&D1) as *const _ as // is valid as [bool; 4], so this is not UB (it's basically a transmute) pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; -// Structs are considered single allocated objects, +// Structs are considered single allocations, // as long as you don't reinterpret padding as initialized // data everything is ok. pub static S7: &[u16] = unsafe {