Skip to content

Commit 2110d2d

Browse files
authored
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 #98780.
2 parents 098e8b7 + a85ee3e commit 2110d2d

File tree

1 file changed

+73
-8
lines changed

1 file changed

+73
-8
lines changed

library/alloc/src/vec/mod.rs

+73-8
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,13 @@ impl<T> Vec<T> {
483483
Self::with_capacity_in(capacity, Global)
484484
}
485485

486-
/// Creates a `Vec<T>` directly from the raw components of another vector.
486+
/// Creates a `Vec<T>` directly from a pointer, a capacity, and a length.
487487
///
488488
/// # Safety
489489
///
490490
/// This is highly unsafe, due to the number of invariants that aren't
491491
/// checked:
492492
///
493-
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
494-
/// (at least, it's highly likely to be incorrect if it wasn't).
495493
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
496494
/// (`T` having a less strict alignment is not sufficient, the alignment really
497495
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
@@ -500,6 +498,14 @@ impl<T> Vec<T> {
500498
/// to be the same size as the pointer was allocated with. (Because similar to
501499
/// alignment, [`dealloc`] must be called with the same layout `size`.)
502500
/// * `length` needs to be less than or equal to `capacity`.
501+
/// * The first `length` values must be properly initialized values of type `T`.
502+
/// * `capacity` needs to be the capacity that the pointer was allocated with.
503+
/// * The allocated size in bytes must be no larger than `isize::MAX`.
504+
/// See the safety documentation of [`pointer::offset`].
505+
///
506+
/// These requirements are always upheld by any `ptr` that has been allocated
507+
/// via `Vec<T>`. Other allocation sources are allowed if the invariants are
508+
/// upheld.
503509
///
504510
/// Violating these may cause problems like corrupting the allocator's
505511
/// internal data structures. For example it is normally **not** safe
@@ -551,6 +557,32 @@ impl<T> Vec<T> {
551557
/// assert_eq!(rebuilt, [4, 5, 6]);
552558
/// }
553559
/// ```
560+
///
561+
/// Using memory that was allocated elsewhere:
562+
///
563+
/// ```rust
564+
/// #![feature(allocator_api)]
565+
///
566+
/// use std::alloc::{AllocError, Allocator, Global, Layout};
567+
///
568+
/// fn main() {
569+
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
570+
///
571+
/// let vec = unsafe {
572+
/// let mem = match Global.allocate(layout) {
573+
/// Ok(mem) => mem.cast::<u32>().as_ptr(),
574+
/// Err(AllocError) => return,
575+
/// };
576+
///
577+
/// mem.write(1_000_000);
578+
///
579+
/// Vec::from_raw_parts_in(mem, 1, 16, Global)
580+
/// };
581+
///
582+
/// assert_eq!(vec, &[1_000_000]);
583+
/// assert_eq!(vec.capacity(), 16);
584+
/// }
585+
/// ```
554586
#[inline]
555587
#[stable(feature = "rust1", since = "1.0.0")]
556588
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> {
641673
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
642674
}
643675

644-
/// Creates a `Vec<T, A>` directly from the raw components of another vector.
676+
/// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
677+
/// and an allocator.
645678
///
646679
/// # Safety
647680
///
648681
/// This is highly unsafe, due to the number of invariants that aren't
649682
/// checked:
650683
///
651-
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
652-
/// (at least, it's highly likely to be incorrect if it wasn't).
653-
/// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
684+
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
654685
/// (`T` having a less strict alignment is not sufficient, the alignment really
655686
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
656687
/// allocated and deallocated with the same layout.)
688+
/// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
689+
/// to be the same size as the pointer was allocated with. (Because similar to
690+
/// alignment, [`dealloc`] must be called with the same layout `size`.)
657691
/// * `length` needs to be less than or equal to `capacity`.
658-
/// * `capacity` needs to be the capacity that the pointer was allocated with.
692+
/// * The first `length` values must be properly initialized values of type `T`.
693+
/// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
694+
/// * The allocated size in bytes must be no larger than `isize::MAX`.
695+
/// See the safety documentation of [`pointer::offset`].
696+
///
697+
/// These requirements are always upheld by any `ptr` that has been allocated
698+
/// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
699+
/// upheld.
659700
///
660701
/// Violating these may cause problems like corrupting the allocator's
661702
/// internal data structures. For example it is **not** safe
@@ -673,6 +714,7 @@ impl<T, A: Allocator> Vec<T, A> {
673714
///
674715
/// [`String`]: crate::string::String
675716
/// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
717+
/// [*fit*]: crate::alloc::Allocator#memory-fitting
676718
///
677719
/// # Examples
678720
///
@@ -711,6 +753,29 @@ impl<T, A: Allocator> Vec<T, A> {
711753
/// assert_eq!(rebuilt, [4, 5, 6]);
712754
/// }
713755
/// ```
756+
///
757+
/// Using memory that was allocated elsewhere:
758+
///
759+
/// ```rust
760+
/// use std::alloc::{alloc, Layout};
761+
///
762+
/// fn main() {
763+
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
764+
/// let vec = unsafe {
765+
/// let mem = alloc(layout).cast::<u32>();
766+
/// if mem.is_null() {
767+
/// return;
768+
/// }
769+
///
770+
/// mem.write(1_000_000);
771+
///
772+
/// Vec::from_raw_parts(mem, 1, 16)
773+
/// };
774+
///
775+
/// assert_eq!(vec, &[1_000_000]);
776+
/// assert_eq!(vec.capacity(), 16);
777+
/// }
778+
/// ```
714779
#[inline]
715780
#[unstable(feature = "allocator_api", issue = "32838")]
716781
pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {

0 commit comments

Comments
 (0)