Rollup merge of #99216 - duarten:master, r=joshtriplett
docs: be less harsh in wording for Vec::from_raw_parts In particular, be clear that it is sound to specify memory not originating from a previous `Vec` allocation. That is already suggested in other parts of the documentation about zero-alloc conversions to Box<[T]>. Incorporate a constraint from `slice::from_raw_parts` that was missing but needs to be fulfilled, since a `Vec` can be converted into a slice. Fixes https://github.com/rust-lang/rust/issues/98780.
This commit is contained in:
commit
2110d2de5a
@ -483,15 +483,13 @@ impl<T> Vec<T> {
|
||||
Self::with_capacity_in(capacity, Global)
|
||||
}
|
||||
|
||||
/// Creates a `Vec<T>` directly from the raw components of another vector.
|
||||
/// Creates a `Vec<T>` directly from a pointer, a capacity, and a length.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is highly unsafe, due to the number of invariants that aren't
|
||||
/// checked:
|
||||
///
|
||||
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
|
||||
/// (at least, it's highly likely to be incorrect if it wasn't).
|
||||
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
|
||||
/// (`T` having a less strict alignment is not sufficient, the alignment really
|
||||
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
|
||||
@ -500,6 +498,14 @@ impl<T> Vec<T> {
|
||||
/// to be the same size as the pointer was allocated with. (Because similar to
|
||||
/// alignment, [`dealloc`] must be called with the same layout `size`.)
|
||||
/// * `length` needs to be less than or equal to `capacity`.
|
||||
/// * The first `length` values must be properly initialized values of type `T`.
|
||||
/// * `capacity` needs to be the capacity that the pointer was allocated with.
|
||||
/// * The allocated size in bytes must be no larger than `isize::MAX`.
|
||||
/// See the safety documentation of [`pointer::offset`].
|
||||
///
|
||||
/// These requirements are always upheld by any `ptr` that has been allocated
|
||||
/// via `Vec<T>`. Other allocation sources are allowed if the invariants are
|
||||
/// upheld.
|
||||
///
|
||||
/// Violating these may cause problems like corrupting the allocator's
|
||||
/// internal data structures. For example it is normally **not** safe
|
||||
@ -551,6 +557,32 @@ impl<T> Vec<T> {
|
||||
/// assert_eq!(rebuilt, [4, 5, 6]);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Using memory that was allocated elsewhere:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(allocator_api)]
|
||||
///
|
||||
/// use std::alloc::{AllocError, Allocator, Global, Layout};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
|
||||
///
|
||||
/// let vec = unsafe {
|
||||
/// let mem = match Global.allocate(layout) {
|
||||
/// Ok(mem) => mem.cast::<u32>().as_ptr(),
|
||||
/// Err(AllocError) => return,
|
||||
/// };
|
||||
///
|
||||
/// mem.write(1_000_000);
|
||||
///
|
||||
/// Vec::from_raw_parts_in(mem, 1, 16, Global)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(vec, &[1_000_000]);
|
||||
/// assert_eq!(vec.capacity(), 16);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
|
||||
@ -641,21 +673,30 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
|
||||
}
|
||||
|
||||
/// Creates a `Vec<T, A>` directly from the raw components of another vector.
|
||||
/// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
|
||||
/// and an allocator.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is highly unsafe, due to the number of invariants that aren't
|
||||
/// checked:
|
||||
///
|
||||
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
|
||||
/// (at least, it's highly likely to be incorrect if it wasn't).
|
||||
/// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
|
||||
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
|
||||
/// (`T` having a less strict alignment is not sufficient, the alignment really
|
||||
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
|
||||
/// allocated and deallocated with the same layout.)
|
||||
/// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
|
||||
/// to be the same size as the pointer was allocated with. (Because similar to
|
||||
/// alignment, [`dealloc`] must be called with the same layout `size`.)
|
||||
/// * `length` needs to be less than or equal to `capacity`.
|
||||
/// * `capacity` needs to be the capacity that the pointer was allocated with.
|
||||
/// * The first `length` values must be properly initialized values of type `T`.
|
||||
/// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
|
||||
/// * The allocated size in bytes must be no larger than `isize::MAX`.
|
||||
/// See the safety documentation of [`pointer::offset`].
|
||||
///
|
||||
/// These requirements are always upheld by any `ptr` that has been allocated
|
||||
/// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
|
||||
/// upheld.
|
||||
///
|
||||
/// Violating these may cause problems like corrupting the allocator's
|
||||
/// internal data structures. For example it is **not** safe
|
||||
@ -673,6 +714,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
///
|
||||
/// [`String`]: crate::string::String
|
||||
/// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
|
||||
/// [*fit*]: crate::alloc::Allocator#memory-fitting
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -711,6 +753,29 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
/// assert_eq!(rebuilt, [4, 5, 6]);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Using memory that was allocated elsewhere:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::alloc::{alloc, Layout};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
|
||||
/// let vec = unsafe {
|
||||
/// let mem = alloc(layout).cast::<u32>();
|
||||
/// if mem.is_null() {
|
||||
/// return;
|
||||
/// }
|
||||
///
|
||||
/// mem.write(1_000_000);
|
||||
///
|
||||
/// Vec::from_raw_parts(mem, 1, 16)
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(vec, &[1_000_000]);
|
||||
/// assert_eq!(vec.capacity(), 16);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {
|
||||
|
Loading…
x
Reference in New Issue
Block a user