mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(allocator): remove Vec::from_box_in (#23873)
Remove this method, which was added in #23717. The method is sound, and could be useful in some cases, but I realised it's not forward-compatible with planned future changes to allocator. So I think best not to introduce it. This would be a breaking change, but it was only added a few days ago, so hadn't got into a release yet.
This commit is contained in:
1 parent
0ab64ecfbd
commit
0b3021f884
1 file changed
+7
-98
@@ -174,7 +174,11 @@ impl<'alloc, T> Vec<'alloc, T> {
|
||||
|
||||
let allocator = allocator.allocator();
|
||||
let boxed = Box::new_in(value, &allocator);
|
||||
Self::from_box_in(boxed, &allocator)
|
||||
let ptr = Box::into_non_null(boxed).as_ptr();
|
||||
// SAFETY: `ptr` contains a valid `T`.
|
||||
// A `Vec` with length 1, capacity 1 can own the same allocation.
|
||||
let vec = unsafe { InnerVec::from_raw_parts_in(ptr, 1, 1, allocator.arena()) };
|
||||
Self(vec)
|
||||
}
|
||||
|
||||
/// Create a new [`Vec`] from a fixed-size array, allocated in the given `allocator`.
|
||||
@@ -211,71 +215,6 @@ impl<'alloc, T> Vec<'alloc, T> {
|
||||
Self(vec)
|
||||
}
|
||||
|
||||
/// Convert a [`Box<T>`] into a [`Vec<T>`] containing the single `T`.
|
||||
///
|
||||
/// `allocator` should usually be the original allocator the `Box` was allocated in.
|
||||
/// The lifetime of the returned `Vec` is the intersection of the lifetimes of the allocator
|
||||
/// that the `Box` was originally allocated in, and the provided `allocator`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use oxc_allocator::{Allocator, Box, Vec};
|
||||
///
|
||||
/// let allocator = Allocator::default();
|
||||
/// let allocator = &allocator;
|
||||
/// let boxed = Box::new_in(123u32, &allocator);
|
||||
/// let vec = Vec::from_box_in(boxed, &allocator);
|
||||
/// assert_eq!(vec, [123]);
|
||||
/// ```
|
||||
///
|
||||
/// The returned `Vec` cannot outlive either allocator.
|
||||
/// If the allocator the `Box` was allocated in does not live long enough, it fails to compile:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use oxc_allocator::{Allocator, Box, Vec};
|
||||
///
|
||||
/// let vec_allocator = Allocator::default();
|
||||
/// let vec_allocator = &vec_allocator;
|
||||
/// let vec = {
|
||||
/// let box_allocator = Allocator::default();
|
||||
/// let box_allocator = &box_allocator;
|
||||
/// let boxed = Box::new_in(123u32, &box_allocator);
|
||||
/// Vec::from_box_in(boxed, &vec_allocator)
|
||||
/// };
|
||||
/// assert_eq!(vec, [123]);
|
||||
/// ```
|
||||
///
|
||||
/// Likewise if the allocator passed to `from_box_in` does not live long enough:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use oxc_allocator::{Allocator, Box, Vec};
|
||||
///
|
||||
/// let box_allocator = Allocator::default();
|
||||
/// let box_allocator = &box_allocator;
|
||||
/// let boxed = Box::new_in(123u32, &box_allocator);
|
||||
/// let vec = {
|
||||
/// let vec_allocator = Allocator::default();
|
||||
/// let vec_allocator = &vec_allocator;
|
||||
/// Vec::from_box_in(boxed, &vec_allocator)
|
||||
/// };
|
||||
/// assert_eq!(vec, [123]);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_box_in<A: GetAllocator<'alloc>>(boxed: Box<'alloc, T>, allocator: &A) -> Self {
|
||||
let ptr = Box::into_non_null(boxed).as_ptr();
|
||||
// SAFETY: `boxed` owns its backing memory which comprises 1 valid initialized `T`.
|
||||
// A `Vec` with length 1, capacity 1 owns the same memory.
|
||||
// `allocator` is not necessarily the same `Allocator` the box was allocated in, but the signature
|
||||
// ties both `boxed` and `allocator` to the lifetime `'alloc` of the returned `Vec`.
|
||||
// So both the original allocator and `allocator` outlive the returned `Vec`.
|
||||
// The single element stays valid (it lives in the original allocator) for the lifetime of the returned `Vec`.
|
||||
// If the `Vec` is grown later, it reallocates in `allocator`. Both outlive the `Vec`, so either way the memory
|
||||
// is valid for the whole life of the returned `Vec`.
|
||||
let vec = unsafe { InnerVec::from_raw_parts_in(ptr, 1, 1, allocator.allocator().arena()) };
|
||||
Self(vec)
|
||||
}
|
||||
|
||||
/// Convert [`Vec<T>`] into [`Box<[T]>`].
|
||||
///
|
||||
/// Any spare capacity in the `Vec` is lost.
|
||||
@@ -506,8 +445,9 @@ impl<T: Debug> Debug for Vec<'_, T> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::Allocator;
|
||||
|
||||
use super::Vec;
|
||||
use crate::{Allocator, Box};
|
||||
|
||||
#[test]
|
||||
fn vec_with_capacity() {
|
||||
@@ -648,37 +588,6 @@ mod test {
|
||||
assert_eq!(v, [123, 456]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_from_box_in() {
|
||||
let allocator = Allocator::default();
|
||||
let allocator = &allocator;
|
||||
let boxed = Box::new_in(123u32, &allocator);
|
||||
let mut v = Vec::from_box_in(boxed, &allocator);
|
||||
assert_eq!(v, [123]);
|
||||
assert_eq!(v.len(), 1);
|
||||
assert_eq!(v.capacity(), 1);
|
||||
|
||||
// Growing the `Vec` reallocates into the allocator, preserving the original element
|
||||
v.push(456);
|
||||
assert_eq!(v, [123, 456]);
|
||||
}
|
||||
|
||||
// The `Box` and the `Vec` it's converted into can be allocated in different allocators
|
||||
#[test]
|
||||
fn vec_from_box_in_different_allocator() {
|
||||
let vec_allocator = Allocator::default();
|
||||
let vec_allocator = &vec_allocator;
|
||||
let box_allocator = Allocator::default();
|
||||
let box_allocator = &box_allocator;
|
||||
let boxed = Box::new_in(123u32, &box_allocator);
|
||||
let mut v = Vec::from_box_in(boxed, &vec_allocator);
|
||||
assert_eq!(v, [123]);
|
||||
|
||||
// Growing reallocates into `vec_allocator`, copying the element out of `box_allocator`
|
||||
v.push(456);
|
||||
assert_eq!(v, [123, 456]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lifetime_variance() {
|
||||
fn _assert_vec_variant_lifetime<'a: 'b, 'b, T>(program: Vec<'a, T>) -> Vec<'b, T> {
|
||||
|
||||
Reference in new issue
Block a user