@@ -603,15 +603,116 @@ impl<T> Vec<T> {
603
603
unsafe { Self :: from_raw_parts_in ( ptr, length, capacity, Global ) }
604
604
}
605
605
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.
607
608
///
608
609
/// # Safety
609
610
///
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
+ /// ```
611
712
#[ 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 ) }
615
716
}
616
717
}
617
718
@@ -830,19 +931,119 @@ impl<T, A: Allocator> Vec<T, A> {
830
931
unsafe { Vec { buf : RawVec :: from_raw_parts_in ( ptr, capacity, alloc) , len : length } }
831
932
}
832
933
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.
834
937
///
835
938
/// # Safety
836
939
///
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
+ /// ```
838
1043
#[ 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 {
846
1047
unsafe { Vec { buf : RawVec :: from_nonnull_in ( ptr, capacity, alloc) , len : length } }
847
1048
}
848
1049
@@ -885,6 +1086,49 @@ impl<T, A: Allocator> Vec<T, A> {
885
1086
( me. as_mut_ptr ( ) , me. len ( ) , me. capacity ( ) )
886
1087
}
887
1088
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
+
888
1132
/// Decomposes a `Vec<T>` into its raw components: `(pointer, length, capacity, allocator)`.
889
1133
///
890
1134
/// 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> {
934
1178
( ptr, len, capacity, alloc)
935
1179
}
936
1180
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
+
937
1229
/// Returns the total number of elements the vector can hold without
938
1230
/// reallocating.
939
1231
///
0 commit comments