Skip to content

Commit 7c84a56

Browse files
committed
docs(allocator/vec): correct safety comments for RawVec::append_elements (#11072)
Follow-on after #10884. The original safety conditions aren't required any more, because of the change made to `Vec::reserve` in #10884 - `reserve` will panic if `other.len` or `self.len + other.len` exceeds `u32::MAX`. So nothing can go wrong if these conditions aren't satisfied. Which is lucky, because `append` doesn't do anything to make sure `self.len + other.len <= u32::MAX`! `append_elements` originally had no safety docs at all (naughty bumpalo!). So add some.
1 parent fc2f040 commit 7c84a56

File tree

1 file changed

+9
-8
lines changed
  • crates/oxc_allocator/src/vec2

1 file changed

+9
-8
lines changed

crates/oxc_allocator/src/vec2/mod.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
16271627
#[inline]
16281628
pub fn append(&mut self, other: &mut Self) {
16291629
unsafe {
1630+
// SAFETY: The elements in `other` are made inaccessible by `other.set_len(0)` straight after
16301631
self.append_elements(other.as_slice() as _);
16311632
other.set_len(0);
16321633
}
@@ -1636,21 +1637,21 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
16361637
///
16371638
/// # SAFETY
16381639
///
1639-
/// The caller must ensure that the length of buffer passed in is less than or
1640-
/// equal to `u32::MAX`.
1641-
/// The length of the `Self` and `other` buffer add up to must be less than or
1642-
/// equal to `u32::MAX`.
1640+
/// Elements from `other` will be copied into `self`'s buffer.
1641+
/// Caller must ensure either that `T` is `Copy`, or the elements of `other` are not accessible
1642+
/// except by the pointer `other`, and that they are not read after this call.
16431643
#[inline]
16441644
#[expect(clippy::cast_possible_truncation)]
16451645
unsafe fn append_elements(&mut self, other: *const [T]) {
16461646
let count = (*other).len();
16471647
self.reserve(count);
16481648
let len = self.len();
16491649
ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count);
1650-
// `unwrap_unchecked()` is okay because that caller needs to ensure that
1651-
// the length of the buffer passed in is less than or equal to `u32::MAX`,
1652-
// otherwise it is UB.
1653-
self.buf.len = self.buf.len.checked_add(count as u32).unwrap_unchecked()
1650+
// `count` cannot be `> u32::MAX`, so `count as u32` cannot truncate `count`.
1651+
// `self.buf.len + count` cannot be `> u32::MAX`.
1652+
// If either of these conditions was violated, `self.reserve(count)` above would have panicked.
1653+
// So this addition cannot wrap around.
1654+
self.buf.len += count as u32;
16541655
}
16551656

16561657
/// Creates a draining iterator that removes the specified range in the vector

0 commit comments

Comments
 (0)