diff --git a/crates/oxc_allocator/src/vec2/mod.rs b/crates/oxc_allocator/src/vec2/mod.rs index 0505c1cbf7df9..29da153c05725 100644 --- a/crates/oxc_allocator/src/vec2/mod.rs +++ b/crates/oxc_allocator/src/vec2/mod.rs @@ -689,28 +689,24 @@ impl<'bump, T: 'bump> Vec<'bump, T> { Vec { buf: RawVec::from_raw_parts_in(ptr, bump, capacity, length) } } - /// Returns a shared reference to the allocator backing this `Vec`. + /// Returns the number of elements in the vector, also referred to as its 'length'. /// /// # Examples /// /// ``` /// use bumpalo::{Bump, collections::Vec}; /// - /// // uses the same allocator as the provided `Vec` - /// fn add_strings<'bump>(vec: &mut Vec<'bump, &'bump str>) { - /// for string in ["foo", "bar", "baz"] { - /// vec.push(vec.bump().alloc_str(string)); - /// } - /// } + /// let b = Bump::new(); + /// + /// let a = bumpalo::vec![in &b; 1, 2, 3]; + /// assert_eq!(a.len(), 3); /// ``` #[inline] - #[must_use] - pub fn bump(&self) -> &'bump Bump { - self.buf.bump() + pub fn len(&self) -> usize { + self.buf.len_usize() } - /// Returns the number of elements the vector can hold without - /// reallocating. + /// Returns the number of elements the vector can hold without reallocating. /// /// # Examples /// @@ -726,6 +722,105 @@ impl<'bump, T: 'bump> Vec<'bump, T> { self.buf.cap_usize() } + /// Sets the length of a vector. + /// + /// This will explicitly set the size of the vector, without actually modifying its buffers, + /// so it is up to the caller to ensure that the vector is actually the specified size. + /// + /// # Safety + /// + /// * `new_len` must be less than or equal to `u32::MAX`. + /// * `new_len` must be less than or equal to [`capacity()`]. + /// * The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Vec::capacity + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// use std::ptr; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; 'r', 'u', 's', 't']; + /// + /// unsafe { + /// ptr::drop_in_place(&mut vec[3]); + /// vec.set_len(3); + /// } + /// assert_eq!(vec, ['r', 'u', 's']); + /// ``` + /// + /// In this example, there is a memory leak since the memory locations + /// owned by the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let b = Bump::new(); + /// + /// let mut vec = bumpalo::vec![in &b; + /// bumpalo::vec![in &b; 1, 0, 0], + /// bumpalo::vec![in &b; 0, 1, 0], + /// bumpalo::vec![in &b; 0, 0, 1]]; + /// unsafe { + /// vec.set_len(0); + /// } + /// ``` + /// + /// In this example, the vector gets expanded from zero to four items + /// but we directly initialize uninitialized memory: + /// + // TODO: rely upon `spare_capacity_mut` + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// let len = 4; + /// let b = Bump::new(); + /// + /// let mut vec: Vec = Vec::with_capacity_in(len, &b); + /// + /// for i in 0..len { + /// // SAFETY: we initialize memory via `pointer::write` + /// unsafe { vec.as_mut_ptr().add(i).write(b'a') } + /// } + /// + /// unsafe { + /// vec.set_len(len); + /// } + /// + /// assert_eq!(b"aaaa", &*vec); + /// ``` + #[inline] + pub unsafe fn set_len(&mut self, new_len: usize) { + // Caller guarantees `new_len <= u32::MAX`, so `new_len as u32` cannot truncate `new_len` + #[expect(clippy::cast_possible_truncation)] + let new_len = new_len as u32; + self.buf.len = new_len; + } + + /// Returns a shared reference to the allocator backing this `Vec`. + /// + /// # Examples + /// + /// ``` + /// use bumpalo::{Bump, collections::Vec}; + /// + /// // uses the same allocator as the provided `Vec` + /// fn add_strings<'bump>(vec: &mut Vec<'bump, &'bump str>) { + /// for string in ["foo", "bar", "baz"] { + /// vec.push(vec.bump().alloc_str(string)); + /// } + /// } + /// ``` + #[inline] + #[must_use] + pub fn bump(&self) -> &'bump Bump { + self.buf.bump() + } + /// Reserves capacity for at least `additional` more elements to be inserted /// in the given `Vec<'bump, T>`. The collection may reserve more space to avoid /// frequent reallocations. After calling `reserve`, capacity will be @@ -1087,86 +1182,6 @@ impl<'bump, T: 'bump> Vec<'bump, T> { ptr } - /// Sets the length of a vector. - /// - /// This will explicitly set the size of the vector, without actually - /// modifying its buffers, so it is up to the caller to ensure that the - /// vector is actually the specified size. - /// - /// # Safety - /// - /// - `new_len` must be less than or equal to `u32::MAX`. - /// - `new_len` must be less than or equal to [`capacity()`]. - /// - The elements at `old_len..new_len` must be initialized. - /// - /// [`capacity()`]: struct.Vec.html#method.capacity - /// - /// # Examples - /// - /// ``` - /// use bumpalo::{Bump, collections::Vec}; - /// - /// use std::ptr; - /// - /// let b = Bump::new(); - /// - /// let mut vec = bumpalo::vec![in &b; 'r', 'u', 's', 't']; - /// - /// unsafe { - /// ptr::drop_in_place(&mut vec[3]); - /// vec.set_len(3); - /// } - /// assert_eq!(vec, ['r', 'u', 's']); - /// ``` - /// - /// In this example, there is a memory leak since the memory locations - /// owned by the inner vectors were not freed prior to the `set_len` call: - /// - /// ``` - /// use bumpalo::{Bump, collections::Vec}; - /// - /// let b = Bump::new(); - /// - /// let mut vec = bumpalo::vec![in &b; - /// bumpalo::vec![in &b; 1, 0, 0], - /// bumpalo::vec![in &b; 0, 1, 0], - /// bumpalo::vec![in &b; 0, 0, 1]]; - /// unsafe { - /// vec.set_len(0); - /// } - /// ``` - /// - /// In this example, the vector gets expanded from zero to four items - /// but we directly initialize uninitialized memory: - /// - // TODO: rely upon `spare_capacity_mut` - /// ``` - /// use bumpalo::{Bump, collections::Vec}; - /// - /// let len = 4; - /// let b = Bump::new(); - /// - /// let mut vec: Vec = Vec::with_capacity_in(len, &b); - /// - /// for i in 0..len { - /// // SAFETY: we initialize memory via `pointer::write` - /// unsafe { vec.as_mut_ptr().add(i).write(b'a') } - /// } - /// - /// unsafe { - /// vec.set_len(len); - /// } - /// - /// assert_eq!(b"aaaa", &*vec); - /// ``` - #[inline] - pub unsafe fn set_len(&mut self, new_len: usize) { - // Caller guarantees `new_len <= u32::MAX`, so `new_len as u32` cannot truncate `new_len` - #[expect(clippy::cast_possible_truncation)] - let new_len = new_len as u32; - self.buf.len = new_len; - } - /// Removes an element from the vector and returns it. /// /// The removed element is replaced by the last element of the vector. @@ -1749,24 +1764,6 @@ impl<'bump, T: 'bump> Vec<'bump, T> { self.truncate(0) } - /// Returns the number of elements in the vector, also referred to - /// as its 'length'. - /// - /// # Examples - /// - /// ``` - /// use bumpalo::{Bump, collections::Vec}; - /// - /// let b = Bump::new(); - /// - /// let a = bumpalo::vec![in &b; 1, 2, 3]; - /// assert_eq!(a.len(), 3); - /// ``` - #[inline] - pub fn len(&self) -> usize { - self.buf.len_usize() - } - /// Returns `true` if the vector contains no elements. /// /// # Examples diff --git a/crates/oxc_allocator/src/vec2/raw_vec.rs b/crates/oxc_allocator/src/vec2/raw_vec.rs index 01034f13f7e76..8ab2ab75e5e9e 100644 --- a/crates/oxc_allocator/src/vec2/raw_vec.rs +++ b/crates/oxc_allocator/src/vec2/raw_vec.rs @@ -120,9 +120,7 @@ impl<'a, T> RawVec<'a, T> { RawVec { ptr, a, cap, len: 0 } } } -} -impl<'a, T> RawVec<'a, T> { /// Reconstitutes a RawVec from a pointer, capacity, and allocator. /// /// # SAFETY @@ -147,9 +145,7 @@ impl<'a, T> RawVec<'a, T> { RawVec { ptr, len, cap, a } } -} -impl<'a, T> RawVec<'a, T> { /// Gets a raw pointer to the start of the allocation. Note that this is /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must /// be careful. @@ -157,6 +153,13 @@ impl<'a, T> RawVec<'a, T> { self.ptr.as_ptr() } + /// Gets the usize number of elements. + pub fn len_usize(&self) -> usize { + // `self.len as usize` is safe because it's is `u32` so it must be + // less than `usize::MAX`. + self.len as usize + } + /// Gets the capacity of the allocation. /// /// This will always be `u32::MAX` if `T` is zero-sized. @@ -175,13 +178,6 @@ impl<'a, T> RawVec<'a, T> { if mem::size_of::() == 0 { !0 } else { self.cap as usize } } - /// Gets the usize number of elements. - pub fn len_usize(&self) -> usize { - // `self.len as usize` is safe because it's is `u32` so it must be - // less than `usize::MAX`. - self.len as usize - } - /// Returns a shared reference to the allocator backing this RawVec. pub fn bump(&self) -> &'a Bump { self.a