Skip to content

Commit 2e99282

Browse files
CoAlloc: Vec and VecDeque backwards-compatibility.
1 parent e126d2a commit 2e99282

File tree

3 files changed

+151
-133
lines changed

3 files changed

+151
-133
lines changed

library/alloc/src/collections/vec_deque/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,11 +3042,10 @@ where
30423042

30433043
#[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")]
30443044
#[allow(unused_braces)]
3045-
impl<T, A: Allocator, const CO_ALLOC_PREF: CoAllocPref, const VECDEQUE_CO_ALLOC_PREF: CoAllocPref>
3046-
From<VecDeque<T, A, VECDEQUE_CO_ALLOC_PREF>> for Vec<T, A, CO_ALLOC_PREF>
3045+
impl<T, A: Allocator, const CO_ALLOC_PREF: CoAllocPref> From<VecDeque<T, A, CO_ALLOC_PREF>>
3046+
for Vec<T, A, CO_ALLOC_PREF>
30473047
where
30483048
[(); { crate::meta_num_slots!(A, CO_ALLOC_PREF) }]:,
3049-
[(); { crate::meta_num_slots!(A, VECDEQUE_CO_ALLOC_PREF) }]:,
30503049
{
30513050
/// Turn a [`VecDeque<T>`] into a [`Vec<T>`].
30523051
///
@@ -3077,9 +3076,9 @@ where
30773076
/// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
30783077
/// assert_eq!(vec.as_ptr(), ptr);
30793078
/// ```
3080-
fn from(mut other: VecDeque<T, A, VECDEQUE_CO_ALLOC_PREF>) -> Self
3079+
fn from(mut other: VecDeque<T, A, CO_ALLOC_PREF>) -> Self
30813080
where
3082-
[(); { crate::meta_num_slots!(A, VECDEQUE_CO_ALLOC_PREF) }]:,
3081+
[(); { crate::meta_num_slots!(A, CO_ALLOC_PREF) }]:,
30833082
{
30843083
other.make_contiguous();
30853084

@@ -3094,7 +3093,7 @@ where
30943093
ptr::copy(buf.add(other.head), buf, len);
30953094
}
30963095
// @FIXME: COOP
3097-
Vec::<T, A, CO_ALLOC_PREF>::from_raw_parts_in(buf, len, cap, alloc)
3096+
Vec::<T, A, CO_ALLOC_PREF>::from_raw_parts_in_co(buf, len, cap, alloc)
30983097
}
30993098
}
31003099
}

library/alloc/src/slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub(crate) mod hack {
120120
unsafe {
121121
let len = b.len();
122122
let (b, alloc) = Box::into_raw_with_allocator(b);
123-
Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
123+
Vec::from_raw_parts_in_co(b as *mut T, len, len, alloc)
124124
}
125125
}
126126

library/alloc/src/vec/mod.rs

Lines changed: 145 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ impl<T> Vec<T> {
498498
/// // allocation is necessary
499499
/// let vec_units = Vec::<()>::with_capacity(10);
500500
/// assert_eq!(vec_units.capacity(), usize::MAX);
501-
/// ``` #[cfg(not(no_global_oom_handling))]
501+
#[cfg(not(no_global_oom_handling))]
502502
#[inline]
503503
#[stable(feature = "rust1", since = "1.0.0")]
504504
#[must_use]
@@ -516,6 +516,26 @@ impl<T, A: Allocator> Vec<T, A>
516516
where
517517
[(); { meta_num_slots_default!(A) }]:,
518518
{
519+
/// Constructs a new, empty `Vec<T, A>`.
520+
///
521+
/// The vector will not allocate until elements are pushed onto it.
522+
///
523+
/// # Examples
524+
///
525+
/// ```
526+
/// #![feature(allocator_api)]
527+
///
528+
/// use std::alloc::System;
529+
///
530+
/// # #[allow(unused_mut)]
531+
/// let mut vec: Vec<i32, _> = Vec::new_in(System);
532+
/// ```
533+
#[inline]
534+
#[unstable(feature = "allocator_api", issue = "32838")]
535+
pub const fn new_in(alloc: A) -> Self {
536+
Self::new_in_co(alloc)
537+
}
538+
519539
/// Constructs a new, empty `Vec<T, A>` with at least the specified capacity
520540
/// with the provided allocator.
521541
///
@@ -577,6 +597,117 @@ where
577597
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
578598
Self::with_capacity_in_co(capacity, alloc)
579599
}
600+
601+
/// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
602+
/// and an allocator.
603+
///
604+
/// # Safety
605+
///
606+
/// This is highly unsafe, due to the number of invariants that aren't
607+
/// checked:
608+
///
609+
/// * `ptr` must be [*currently allocated*] via the given allocator `alloc`.
610+
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
611+
/// (`T` having a less strict alignment is not sufficient, the alignment really
612+
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
613+
/// allocated and deallocated with the same layout.)
614+
/// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
615+
/// to be the same size as the pointer was allocated with. (Because similar to
616+
/// alignment, [`dealloc`] must be called with the same layout `size`.)
617+
/// * `length` needs to be less than or equal to `capacity`.
618+
/// * The first `length` values must be properly initialized values of type `T`.
619+
/// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
620+
/// * The allocated size in bytes must be no larger than `isize::MAX`.
621+
/// See the safety documentation of [`pointer::offset`].
622+
///
623+
/// These requirements are always upheld by any `ptr` that has been allocated
624+
/// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
625+
/// upheld.
626+
///
627+
/// Violating these may cause problems like corrupting the allocator's
628+
/// internal data structures. For example it is **not** safe
629+
/// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
630+
/// It's also not safe to build one from a `Vec<u16>` and its length, because
631+
/// the allocator cares about the alignment, and these two types have different
632+
/// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
633+
/// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
634+
///
635+
/// The ownership of `ptr` is effectively transferred to the
636+
/// `Vec<T>` which may then deallocate, reallocate or change the
637+
/// contents of memory pointed to by the pointer at will. Ensure
638+
/// that nothing else uses the pointer after calling this
639+
/// function.
640+
///
641+
/// [`String`]: crate::string::String
642+
/// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
643+
/// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory
644+
/// [*fit*]: crate::alloc::Allocator#memory-fitting
645+
///
646+
/// # Examples
647+
///
648+
/// ```
649+
/// #![feature(allocator_api)]
650+
///
651+
/// use std::alloc::System;
652+
///
653+
/// use std::ptr;
654+
/// use std::mem;
655+
///
656+
/// let mut v = Vec::with_capacity_in(3, System);
657+
/// v.push(1);
658+
/// v.push(2);
659+
/// v.push(3);
660+
///
661+
// FIXME Update this when vec_into_raw_parts is stabilized
662+
/// // Prevent running `v`'s destructor so we are in complete control
663+
/// // of the allocation.
664+
/// let mut v = mem::ManuallyDrop::new(v);
665+
///
666+
/// // Pull out the various important pieces of information about `v`
667+
/// let p = v.as_mut_ptr();
668+
/// let len = v.len();
669+
/// let cap = v.capacity();
670+
/// let alloc = v.allocator();
671+
///
672+
/// unsafe {
673+
/// // Overwrite memory with 4, 5, 6
674+
/// for i in 0..len {
675+
/// ptr::write(p.add(i), 4 + i);
676+
/// }
677+
///
678+
/// // Put everything back together into a Vec
679+
/// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone());
680+
/// assert_eq!(rebuilt, [4, 5, 6]);
681+
/// }
682+
/// ```
683+
///
684+
/// Using memory that was allocated elsewhere:
685+
///
686+
/// ```rust
687+
/// use std::alloc::{alloc, Layout};
688+
///
689+
/// fn main() {
690+
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
691+
/// let vec = unsafe {
692+
/// let mem = alloc(layout).cast::<u32>();
693+
/// if mem.is_null() {
694+
/// return;
695+
/// }
696+
///
697+
/// mem.write(1_000_000);
698+
///
699+
/// Vec::from_raw_parts(mem, 1, 16)
700+
/// };
701+
///
702+
/// assert_eq!(vec, &[1_000_000]);
703+
/// assert_eq!(vec.capacity(), 16);
704+
/// }
705+
/// ```
706+
#[inline]
707+
#[unstable(feature = "allocator_api", issue = "32838")]
708+
pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {
709+
unsafe { Self::from_raw_parts_in_co(ptr, length, capacity, alloc) }
710+
}
580711
}
581712

582713
/**/
@@ -657,7 +788,7 @@ where
657788
#[inline]
658789
#[unstable(feature = "global_co_alloc", issue = "none")]
659790
pub unsafe fn from_raw_parts_co(ptr: *mut T, length: usize, capacity: usize) -> Self {
660-
unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) }
791+
unsafe { Self::from_raw_parts_in_co(ptr, length, capacity, Global) }
661792
}
662793
}
663794

@@ -777,23 +908,10 @@ impl<T, A: Allocator, const CO_ALLOC_PREF: CoAllocPref> Vec<T, A, CO_ALLOC_PREF>
777908
where
778909
[(); { crate::meta_num_slots!(A, CO_ALLOC_PREF) }]:,
779910
{
780-
/// Constructs a new, empty `Vec<T, A>`.
781-
///
782-
/// The vector will not allocate until elements are pushed onto it.
783-
///
784-
/// # Examples
785-
///
786-
/// ```
787-
/// #![feature(allocator_api)]
788-
///
789-
/// use std::alloc::System;
790-
///
791-
/// # #[allow(unused_mut)]
792-
/// let mut vec: Vec<i32, _> = Vec::new_in(System);
793-
/// ```
911+
/** Like `new_in`, but co-allocation-aware. */
794912
#[inline]
795-
#[unstable(feature = "allocator_api", issue = "32838")]
796-
pub const fn new_in(alloc: A) -> Self {
913+
#[unstable(feature = "global_co_alloc", issue = "none")]
914+
pub const fn new_in_co(alloc: A) -> Self {
797915
Vec { buf: RawVec::new_in(alloc), len: 0 }
798916
}
799917

@@ -805,114 +923,15 @@ where
805923
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
806924
}
807925

808-
/// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
809-
/// and an allocator.
810-
///
811-
/// # Safety
812-
///
813-
/// This is highly unsafe, due to the number of invariants that aren't
814-
/// checked:
815-
///
816-
/// * `ptr` must be [*currently allocated*] via the given allocator `alloc`.
817-
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
818-
/// (`T` having a less strict alignment is not sufficient, the alignment really
819-
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
820-
/// allocated and deallocated with the same layout.)
821-
/// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
822-
/// to be the same size as the pointer was allocated with. (Because similar to
823-
/// alignment, [`dealloc`] must be called with the same layout `size`.)
824-
/// * `length` needs to be less than or equal to `capacity`.
825-
/// * The first `length` values must be properly initialized values of type `T`.
826-
/// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
827-
/// * The allocated size in bytes must be no larger than `isize::MAX`.
828-
/// See the safety documentation of [`pointer::offset`].
829-
///
830-
/// These requirements are always upheld by any `ptr` that has been allocated
831-
/// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
832-
/// upheld.
833-
///
834-
/// Violating these may cause problems like corrupting the allocator's
835-
/// internal data structures. For example it is **not** safe
836-
/// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
837-
/// It's also not safe to build one from a `Vec<u16>` and its length, because
838-
/// the allocator cares about the alignment, and these two types have different
839-
/// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
840-
/// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
841-
///
842-
/// The ownership of `ptr` is effectively transferred to the
843-
/// `Vec<T>` which may then deallocate, reallocate or change the
844-
/// contents of memory pointed to by the pointer at will. Ensure
845-
/// that nothing else uses the pointer after calling this
846-
/// function.
847-
///
848-
/// [`String`]: crate::string::String
849-
/// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
850-
/// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory
851-
/// [*fit*]: crate::alloc::Allocator#memory-fitting
852-
///
853-
/// # Examples
854-
///
855-
/// ```
856-
/// #![feature(allocator_api)]
857-
///
858-
/// use std::alloc::System;
859-
///
860-
/// use std::ptr;
861-
/// use std::mem;
862-
///
863-
/// let mut v = Vec::with_capacity_in(3, System);
864-
/// v.push(1);
865-
/// v.push(2);
866-
/// v.push(3);
867-
///
868-
// FIXME Update this when vec_into_raw_parts is stabilized
869-
/// // Prevent running `v`'s destructor so we are in complete control
870-
/// // of the allocation.
871-
/// let mut v = mem::ManuallyDrop::new(v);
872-
///
873-
/// // Pull out the various important pieces of information about `v`
874-
/// let p = v.as_mut_ptr();
875-
/// let len = v.len();
876-
/// let cap = v.capacity();
877-
/// let alloc = v.allocator();
878-
///
879-
/// unsafe {
880-
/// // Overwrite memory with 4, 5, 6
881-
/// for i in 0..len {
882-
/// ptr::write(p.add(i), 4 + i);
883-
/// }
884-
///
885-
/// // Put everything back together into a Vec
886-
/// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone());
887-
/// assert_eq!(rebuilt, [4, 5, 6]);
888-
/// }
889-
/// ```
890-
///
891-
/// Using memory that was allocated elsewhere:
892-
///
893-
/// ```rust
894-
/// use std::alloc::{alloc, Layout};
895-
///
896-
/// fn main() {
897-
/// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
898-
/// let vec = unsafe {
899-
/// let mem = alloc(layout).cast::<u32>();
900-
/// if mem.is_null() {
901-
/// return;
902-
/// }
903-
///
904-
/// mem.write(1_000_000);
905-
///
906-
/// Vec::from_raw_parts(mem, 1, 16)
907-
/// };
908-
///
909-
/// assert_eq!(vec, &[1_000_000]);
910-
/// assert_eq!(vec.capacity(), 16);
911-
/// }
912-
/// ```
926+
/** Like `from_raw_parts_in`, but co-allocation-aware. */
913927
#[inline]
914-
#[unstable(feature = "allocator_api", issue = "32838")]
915-
pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {
928+
#[unstable(feature = "global_co_alloc", issue = "none")]
929+
pub unsafe fn from_raw_parts_in_co(
930+
ptr: *mut T,
931+
length: usize,
932+
capacity: usize,
933+
alloc: A,
934+
) -> Self {
916935
unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } }
917936
}
918937

@@ -2643,7 +2662,7 @@ where
26432662
// `new_cap * size_of::<T>()` == `cap * size_of::<[T; N]>()`
26442663
// - `len` <= `cap`, so `len * N` <= `cap * N`.
26452664
unsafe {
2646-
Vec::<T, A, CO_ALLOC_PREF>::from_raw_parts_in(ptr.cast(), new_len, new_cap, alloc)
2665+
Vec::<T, A, CO_ALLOC_PREF>::from_raw_parts_in_co(ptr.cast(), new_len, new_cap, alloc)
26472666
}
26482667
}
26492668
}

0 commit comments

Comments
 (0)