@@ -603,15 +603,116 @@ impl<T> Vec<T> {
603603 unsafe { Self :: from_raw_parts_in ( ptr, length, capacity, Global ) }
604604 }
605605
606- /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts`].
606+ #[ doc( alias = "from_non_null_parts" ) ]
607+ /// Creates a `Vec<T>` directly from a `NonNull` pointer, a length, and a capacity.
607608 ///
608609 /// # Safety
609610 ///
610- /// See [`Vec::from_raw_parts`].
611+ /// This is highly unsafe, due to the number of invariants that aren't
612+ /// checked:
613+ ///
614+ /// * `ptr` must have been allocated using the global allocator, such as via
615+ /// the [`alloc::alloc`] function.
616+ /// * `T` needs to have the same alignment as what `ptr` was allocated with.
617+ /// (`T` having a less strict alignment is not sufficient, the alignment really
618+ /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
619+ /// allocated and deallocated with the same layout.)
620+ /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
621+ /// to be the same size as the pointer was allocated with. (Because similar to
622+ /// alignment, [`dealloc`] must be called with the same layout `size`.)
623+ /// * `length` needs to be less than or equal to `capacity`.
624+ /// * The first `length` values must be properly initialized values of type `T`.
625+ /// * `capacity` needs to be the capacity that the pointer was allocated with.
626+ /// * The allocated size in bytes must be no larger than `isize::MAX`.
627+ /// See the safety documentation of [`pointer::offset`].
628+ ///
629+ /// These requirements are always upheld by any `ptr` that has been allocated
630+ /// via `Vec<T>`. Other allocation sources are allowed if the invariants are
631+ /// upheld.
632+ ///
633+ /// Violating these may cause problems like corrupting the allocator's
634+ /// internal data structures. For example it is normally **not** safe
635+ /// to build a `Vec<u8>` from a pointer to a C `char` array with length
636+ /// `size_t`, doing so is only safe if the array was initially allocated by
637+ /// a `Vec` or `String`.
638+ /// It's also not safe to build one from a `Vec<u16>` and its length, because
639+ /// the allocator cares about the alignment, and these two types have different
640+ /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
641+ /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
642+ /// these issues, it is often preferable to do casting/transmuting using
643+ /// [`NonNull::slice_from_raw_parts`] instead.
644+ ///
645+ /// The ownership of `ptr` is effectively transferred to the
646+ /// `Vec<T>` which may then deallocate, reallocate or change the
647+ /// contents of memory pointed to by the pointer at will. Ensure
648+ /// that nothing else uses the pointer after calling this
649+ /// function.
650+ ///
651+ /// [`String`]: crate::string::String
652+ /// [`alloc::alloc`]: crate::alloc::alloc
653+ /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
654+ ///
655+ /// # Examples
656+ ///
657+ /// ```
658+ /// #![feature(box_vec_non_null)]
659+ ///
660+ /// use std::ptr::NonNull;
661+ /// use std::mem;
662+ ///
663+ /// let v = vec![1, 2, 3];
664+ ///
665+ // FIXME Update this when vec_into_raw_parts is stabilized
666+ /// // Prevent running `v`'s destructor so we are in complete control
667+ /// // of the allocation.
668+ /// let mut v = mem::ManuallyDrop::new(v);
669+ ///
670+ /// // Pull out the various important pieces of information about `v`
671+ /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) };
672+ /// let len = v.len();
673+ /// let cap = v.capacity();
674+ ///
675+ /// unsafe {
676+ /// // Overwrite memory with 4, 5, 6
677+ /// for i in 0..len {
678+ /// p.add(i).write(4 + i);
679+ /// }
680+ ///
681+ /// // Put everything back together into a Vec
682+ /// let rebuilt = Vec::from_parts(p, len, cap);
683+ /// assert_eq!(rebuilt, [4, 5, 6]);
684+ /// }
685+ /// ```
686+ ///
687+ /// Using memory that was allocated elsewhere:
688+ ///
689+ /// ```rust
690+ /// #![feature(box_vec_non_null)]
691+ ///
692+ /// use std::alloc::{alloc, Layout};
693+ /// use std::ptr::NonNull;
694+ ///
695+ /// fn main() {
696+ /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
697+ ///
698+ /// let vec = unsafe {
699+ /// let Some(mem) = NonNull::new(alloc(layout).cast::<u32>()) else {
700+ /// return;
701+ /// };
702+ ///
703+ /// mem.write(1_000_000);
704+ ///
705+ /// Vec::from_parts(mem, 1, 16)
706+ /// };
707+ ///
708+ /// assert_eq!(vec, &[1_000_000]);
709+ /// assert_eq!(vec.capacity(), 16);
710+ /// }
711+ /// ```
611712 #[ inline]
612- #[ cfg ( not ( no_global_oom_handling ) ) ] // required by tests/run-make/alloc-no-oom-handling
613- pub ( crate ) unsafe fn from_nonnull ( ptr : NonNull < T > , length : usize , capacity : usize ) -> Self {
614- unsafe { Self :: from_nonnull_in ( ptr, length, capacity, Global ) }
713+ #[ unstable ( feature = "box_vec_non_null" , reason = "new API" , issue = "none" ) ]
714+ pub unsafe fn from_parts ( ptr : NonNull < T > , length : usize , capacity : usize ) -> Self {
715+ unsafe { Self :: from_parts_in ( ptr, length, capacity, Global ) }
615716 }
616717}
617718
@@ -830,19 +931,119 @@ impl<T, A: Allocator> Vec<T, A> {
830931 unsafe { Vec { buf : RawVec :: from_raw_parts_in ( ptr, capacity, alloc) , len : length } }
831932 }
832933
833- /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts_in`].
934+ #[ doc( alias = "from_non_null_parts_in" ) ]
935+ /// Creates a `Vec<T, A>` directly from a `NonNull` pointer, a length, a capacity,
936+ /// and an allocator.
834937 ///
835938 /// # Safety
836939 ///
837- /// See [`Vec::from_raw_parts_in`].
940+ /// This is highly unsafe, due to the number of invariants that aren't
941+ /// checked:
942+ ///
943+ /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`.
944+ /// * `T` needs to have the same alignment as what `ptr` was allocated with.
945+ /// (`T` having a less strict alignment is not sufficient, the alignment really
946+ /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
947+ /// allocated and deallocated with the same layout.)
948+ /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
949+ /// to be the same size as the pointer was allocated with. (Because similar to
950+ /// alignment, [`dealloc`] must be called with the same layout `size`.)
951+ /// * `length` needs to be less than or equal to `capacity`.
952+ /// * The first `length` values must be properly initialized values of type `T`.
953+ /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
954+ /// * The allocated size in bytes must be no larger than `isize::MAX`.
955+ /// See the safety documentation of [`pointer::offset`].
956+ ///
957+ /// These requirements are always upheld by any `ptr` that has been allocated
958+ /// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
959+ /// upheld.
960+ ///
961+ /// Violating these may cause problems like corrupting the allocator's
962+ /// internal data structures. For example it is **not** safe
963+ /// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
964+ /// It's also not safe to build one from a `Vec<u16>` and its length, because
965+ /// the allocator cares about the alignment, and these two types have different
966+ /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
967+ /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
968+ ///
969+ /// The ownership of `ptr` is effectively transferred to the
970+ /// `Vec<T>` which may then deallocate, reallocate or change the
971+ /// contents of memory pointed to by the pointer at will. Ensure
972+ /// that nothing else uses the pointer after calling this
973+ /// function.
974+ ///
975+ /// [`String`]: crate::string::String
976+ /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
977+ /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory
978+ /// [*fit*]: crate::alloc::Allocator#memory-fitting
979+ ///
980+ /// # Examples
981+ ///
982+ /// ```
983+ /// #![feature(allocator_api, box_vec_non_null)]
984+ ///
985+ /// use std::alloc::System;
986+ ///
987+ /// use std::ptr::NonNull;
988+ /// use std::mem;
989+ ///
990+ /// let mut v = Vec::with_capacity_in(3, System);
991+ /// v.push(1);
992+ /// v.push(2);
993+ /// v.push(3);
994+ ///
995+ // FIXME Update this when vec_into_raw_parts is stabilized
996+ /// // Prevent running `v`'s destructor so we are in complete control
997+ /// // of the allocation.
998+ /// let mut v = mem::ManuallyDrop::new(v);
999+ ///
1000+ /// // Pull out the various important pieces of information about `v`
1001+ /// let p = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) };
1002+ /// let len = v.len();
1003+ /// let cap = v.capacity();
1004+ /// let alloc = v.allocator();
1005+ ///
1006+ /// unsafe {
1007+ /// // Overwrite memory with 4, 5, 6
1008+ /// for i in 0..len {
1009+ /// p.add(i).write(4 + i);
1010+ /// }
1011+ ///
1012+ /// // Put everything back together into a Vec
1013+ /// let rebuilt = Vec::from_parts_in(p, len, cap, alloc.clone());
1014+ /// assert_eq!(rebuilt, [4, 5, 6]);
1015+ /// }
1016+ /// ```
1017+ ///
1018+ /// Using memory that was allocated elsewhere:
1019+ ///
1020+ /// ```rust
1021+ /// #![feature(allocator_api, box_vec_non_null)]
1022+ ///
1023+ /// use std::alloc::{AllocError, Allocator, Global, Layout};
1024+ ///
1025+ /// fn main() {
1026+ /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
1027+ ///
1028+ /// let vec = unsafe {
1029+ /// let mem = match Global.allocate(layout) {
1030+ /// Ok(mem) => mem.cast::<u32>(),
1031+ /// Err(AllocError) => return,
1032+ /// };
1033+ ///
1034+ /// mem.write(1_000_000);
1035+ ///
1036+ /// Vec::from_parts_in(mem, 1, 16, Global)
1037+ /// };
1038+ ///
1039+ /// assert_eq!(vec, &[1_000_000]);
1040+ /// assert_eq!(vec.capacity(), 16);
1041+ /// }
1042+ /// ```
8381043 #[ inline]
839- #[ cfg( not( no_global_oom_handling) ) ] // required by tests/run-make/alloc-no-oom-handling
840- pub ( crate ) unsafe fn from_nonnull_in (
841- ptr : NonNull < T > ,
842- length : usize ,
843- capacity : usize ,
844- alloc : A ,
845- ) -> Self {
1044+ #[ unstable( feature = "allocator_api" , reason = "new API" , issue = "32838" ) ]
1045+ // #[unstable(feature = "box_vec_non_null", issue = "none")]
1046+ pub unsafe fn from_parts_in ( ptr : NonNull < T > , length : usize , capacity : usize , alloc : A ) -> Self {
8461047 unsafe { Vec { buf : RawVec :: from_nonnull_in ( ptr, capacity, alloc) , len : length } }
8471048 }
8481049
@@ -885,6 +1086,49 @@ impl<T, A: Allocator> Vec<T, A> {
8851086 ( me. as_mut_ptr ( ) , me. len ( ) , me. capacity ( ) )
8861087 }
8871088
1089+ #[ doc( alias = "into_non_null_parts" ) ]
1090+ /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity)`.
1091+ ///
1092+ /// Returns the `NonNull` pointer to the underlying data, the length of
1093+ /// the vector (in elements), and the allocated capacity of the
1094+ /// data (in elements). These are the same arguments in the same
1095+ /// order as the arguments to [`from_parts`].
1096+ ///
1097+ /// After calling this function, the caller is responsible for the
1098+ /// memory previously managed by the `Vec`. The only way to do
1099+ /// this is to convert the `NonNull` pointer, length, and capacity back
1100+ /// into a `Vec` with the [`from_parts`] function, allowing
1101+ /// the destructor to perform the cleanup.
1102+ ///
1103+ /// [`from_parts`]: Vec::from_parts
1104+ ///
1105+ /// # Examples
1106+ ///
1107+ /// ```
1108+ /// #![feature(vec_into_raw_parts, box_vec_non_null)]
1109+ ///
1110+ /// let v: Vec<i32> = vec![-1, 0, 1];
1111+ ///
1112+ /// let (ptr, len, cap) = v.into_parts();
1113+ ///
1114+ /// let rebuilt = unsafe {
1115+ /// // We can now make changes to the components, such as
1116+ /// // transmuting the raw pointer to a compatible type.
1117+ /// let ptr = ptr.cast::<u32>();
1118+ ///
1119+ /// Vec::from_parts(ptr, len, cap)
1120+ /// };
1121+ /// assert_eq!(rebuilt, [4294967295, 0, 1]);
1122+ /// ```
1123+ #[ must_use = "losing the pointer will leak memory" ]
1124+ #[ unstable( feature = "box_vec_non_null" , reason = "new API" , issue = "none" ) ]
1125+ // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
1126+ pub fn into_parts ( self ) -> ( NonNull < T > , usize , usize ) {
1127+ let ( ptr, len, capacity) = self . into_raw_parts ( ) ;
1128+ // SAFETY: A `Vec` always has a non-null pointer.
1129+ ( unsafe { NonNull :: new_unchecked ( ptr) } , len, capacity)
1130+ }
1131+
8881132 /// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity, allocator)`.
8891133 ///
8901134 /// Returns the raw pointer to the underlying data, the length of the vector (in elements),
@@ -934,6 +1178,54 @@ impl<T, A: Allocator> Vec<T, A> {
9341178 ( ptr, len, capacity, alloc)
9351179 }
9361180
1181+ #[ doc( alias = "into_non_null_parts_with_alloc" ) ]
1182+ /// Decomposes a `Vec<T>` into its raw components: `(NonNull pointer, length, capacity, allocator)`.
1183+ ///
1184+ /// Returns the `NonNull` pointer to the underlying data, the length of the vector (in elements),
1185+ /// the allocated capacity of the data (in elements), and the allocator. These are the same
1186+ /// arguments in the same order as the arguments to [`from_parts_in`].
1187+ ///
1188+ /// After calling this function, the caller is responsible for the
1189+ /// memory previously managed by the `Vec`. The only way to do
1190+ /// this is to convert the `NonNull` pointer, length, and capacity back
1191+ /// into a `Vec` with the [`from_parts_in`] function, allowing
1192+ /// the destructor to perform the cleanup.
1193+ ///
1194+ /// [`from_parts_in`]: Vec::from_parts_in
1195+ ///
1196+ /// # Examples
1197+ ///
1198+ /// ```
1199+ /// #![feature(allocator_api, vec_into_raw_parts, box_vec_non_null)]
1200+ ///
1201+ /// use std::alloc::System;
1202+ ///
1203+ /// let mut v: Vec<i32, System> = Vec::new_in(System);
1204+ /// v.push(-1);
1205+ /// v.push(0);
1206+ /// v.push(1);
1207+ ///
1208+ /// let (ptr, len, cap, alloc) = v.into_parts_with_alloc();
1209+ ///
1210+ /// let rebuilt = unsafe {
1211+ /// // We can now make changes to the components, such as
1212+ /// // transmuting the raw pointer to a compatible type.
1213+ /// let ptr = ptr.cast::<u32>();
1214+ ///
1215+ /// Vec::from_parts_in(ptr, len, cap, alloc)
1216+ /// };
1217+ /// assert_eq!(rebuilt, [4294967295, 0, 1]);
1218+ /// ```
1219+ #[ must_use = "losing the pointer will leak memory" ]
1220+ #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
1221+ // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "none")]
1222+ // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
1223+ pub fn into_parts_with_alloc ( self ) -> ( NonNull < T > , usize , usize , A ) {
1224+ let ( ptr, len, capacity, alloc) = self . into_raw_parts_with_alloc ( ) ;
1225+ // SAFETY: A `Vec` always has a non-null pointer.
1226+ ( unsafe { NonNull :: new_unchecked ( ptr) } , len, capacity, alloc)
1227+ }
1228+
9371229 /// Returns the total number of elements the vector can hold without
9381230 /// reallocating.
9391231 ///
0 commit comments