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:
overlookmotel committed 2026-06-28 14:00:01 +00:00
1 parent 0ab64ecfbd
commit 0b3021f884
1 file changed
+7 -98
+7 -98
View File
@@ -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> {