diff --git a/nearest/src/buf.rs b/nearest/src/buf.rs index 962dbab..8c7c10f 100644 --- a/nearest/src/buf.rs +++ b/nearest/src/buf.rs @@ -1,8 +1,8 @@ -use core::mem::MaybeUninit; #[cfg(feature = "alloc")] use core::{marker::PhantomData, ptr::NonNull}; +use core::{mem, mem::MaybeUninit, num::NonZero}; -use crate::{Flat, emitter::Pos}; +use crate::{Flat, emitter::Pos, list::Segment}; /// Backing storage for a [`Region`](crate::Region). /// @@ -445,3 +445,158 @@ unsafe impl Send for AlignedBuf {} #[cfg(feature = "alloc")] // SAFETY: &AlignedBuf only provides &[u8] access. unsafe impl Sync for AlignedBuf {} + +// --------------------------------------------------------------------------- +// Shared buffer operations (used by both Emitter and Region) +// --------------------------------------------------------------------------- + +/// Write a [`Flat`] value at position `at`. +/// +/// # Safety +/// +/// `at` must have been allocated for `U`, ensuring correct alignment. +pub unsafe fn write_flat(buf: &mut impl Buf, at: Pos, val: U) { + let start = at.0 as usize; + let size = mem::size_of::(); + assert!( + start + size <= buf.len() as usize, + "write_flat out of bounds: {}..{} but len is {}", + start, + start + size, + buf.len() + ); + // SAFETY: Bounds checked above. `at` was allocated for `U` (caller contract), + // ensuring correct alignment. `mem::forget` prevents double-drop. + unsafe { + let src = core::ptr::from_ref(&val).cast::(); + core::ptr::copy_nonoverlapping(src, buf.as_mut_ptr().add(start), size); + } + mem::forget(val); +} + +/// Patch a [`Near`](crate::Near) at position `at` to point to `target`. +/// +/// # Safety +/// +/// `at` must point to a `Near` field within a previously allocated value, +/// and `target` must be a position allocated for `U`. +pub unsafe fn patch_near(buf: &mut impl Buf, at: Pos, target: Pos) { + let rel = i64::from(target.0) - i64::from(at.0); + let rel_i32: i32 = rel.try_into().expect("near offset overflow"); + let nz = NonZero::new(rel_i32).expect("near offset must be non-zero (target == at)"); + + let start = at.0 as usize; + let size = mem::size_of::>(); + assert!(start + size <= buf.len() as usize, "patch_near out of bounds"); + // SAFETY: Bounds checked above. `at` points to the `Near` field whose + // first 4 bytes hold a `NonZero` offset. + unsafe { + let src = core::ptr::from_ref(&nz).cast::(); + core::ptr::copy_nonoverlapping(src, buf.as_mut_ptr().add(start), size); + } +} + +/// Patch a [`NearList`](crate::NearList) header at position `at`. +/// +/// # Safety +/// +/// `at` must point to a `NearList` field within a previously allocated +/// value, and `target` must be a position of a `Segment` (or `Pos::ZERO` +/// when `len == 0`). +pub unsafe fn patch_list_header(buf: &mut impl Buf, at: Pos, target: Pos, len: u32) { + let off_pos = at.0 as usize; + let len_pos = off_pos + mem::size_of::(); + + assert!(len_pos + mem::size_of::() <= buf.len() as usize, "patch_list_header out of bounds"); + + let rel: i32 = if len == 0 { + 0 + } else { + let r = i64::from(target.0) - i64::from(at.0); + r.try_into().expect("list header offset overflow") + }; + + // SAFETY: Bounds checked above. The list header at `at` has layout + // `[i32 offset, u32 len]`, and both writes are within bounds. + unsafe { + let buf_ptr = buf.as_mut_ptr(); + core::ptr::copy_nonoverlapping( + core::ptr::from_ref(&rel).cast::(), + buf_ptr.add(off_pos), + mem::size_of::(), + ); + core::ptr::copy_nonoverlapping( + core::ptr::from_ref(&len).cast::(), + buf_ptr.add(len_pos), + mem::size_of::(), + ); + } +} + +/// Copy raw bytes to position `at`. +/// +/// # Safety +/// +/// `src` must be valid for reading `len` bytes. `at` must be a valid +/// position with at least `len` bytes available. +pub unsafe fn write_bytes(buf: &mut impl Buf, at: Pos, src: *const u8, len: usize) { + let start = at.0 as usize; + assert!( + start + len <= buf.len() as usize, + "write_bytes out of bounds: {}..{} but len is {}", + start, + start + len, + buf.len() + ); + // SAFETY: Bounds checked above. `src` is valid for `len` bytes (caller + // contract). The destination does not overlap the source. + unsafe { + core::ptr::copy_nonoverlapping(src, buf.as_mut_ptr().add(start), len); + } +} + +/// Allocate a segment header plus `count` contiguous values of type `U`. +/// +/// Returns the position of the segment header. The segment's `len` field +/// is initialized to `count`; `next` is 0 (end of chain, from zero-fill). +pub fn alloc_segment(buf: &mut impl Buf, count: u32) -> Pos { + buf.align_to(align_of::>()); + let pos = Pos(buf.len()); + let values_size = count.checked_mul(size_of::() as u32).expect("segment values overflow"); + let total = + (size_of::>() as u32).checked_add(values_size).expect("segment total size overflow"); + buf.resize(buf.len() + total, 0); + // Write segment len at offset 4 (next is already 0 from zero-fill). + let len_offset = pos.0 as usize + size_of::(); + // SAFETY: `resize` just allocated `total` bytes starting at `pos`. + // The `len` field is at `pos + 4`, within the freshly allocated region. + unsafe { + core::ptr::copy_nonoverlapping( + core::ptr::from_ref(&count).cast::(), + buf.as_mut_ptr().add(len_offset), + size_of::(), + ); + } + pos +} + +/// Patch the `next` pointer of a segment at `seg_pos`. +/// +/// # Safety +/// +/// `seg_pos` must be a position of a previously allocated `Segment`. +pub unsafe fn patch_segment_next(buf: &mut impl Buf, seg_pos: Pos, next_seg_pos: Pos) { + let rel = i64::from(next_seg_pos.0) - i64::from(seg_pos.0); + let rel_i32: i32 = rel.try_into().expect("segment next offset overflow"); + let start = seg_pos.0 as usize; + assert!(start + mem::size_of::() <= buf.len() as usize, "patch_segment_next out of bounds"); + // SAFETY: Bounds checked above. The `next` field is at offset 0 of + // `Segment`, and we write exactly `size_of::()` bytes. + unsafe { + core::ptr::copy_nonoverlapping( + core::ptr::from_ref(&rel_i32).cast::(), + buf.as_mut_ptr().add(start), + mem::size_of::(), + ); + } +} diff --git a/nearest/src/emit.rs b/nearest/src/emit.rs index 9acc168..4485159 100644 --- a/nearest/src/emit.rs +++ b/nearest/src/emit.rs @@ -44,13 +44,6 @@ pub unsafe trait Emit: Sized { unsafe fn write_at(self, p: &mut impl Patch, at: Pos); } -// // SAFETY: `Infallible` is uninhabited — `write_at` is unreachable. -// unsafe impl Emit for Infallible { -// unsafe fn write_at(self, _p: &mut impl Patch, _at: Pos) { -// match self {} -// } -// } - // --- Blanket deep-copy impl: Emit for &T via Flat::deep_copy --- // SAFETY: Delegates to `Flat::deep_copy` which correctly copies all fields diff --git a/nearest/src/emitter.rs b/nearest/src/emitter.rs index aad5e65..d3db330 100644 --- a/nearest/src/emitter.rs +++ b/nearest/src/emitter.rs @@ -1,5 +1,3 @@ -use core::{mem, num::NonZero}; - use crate::{Flat, buf::Buf}; #[doc(hidden)] @@ -84,23 +82,8 @@ impl Emitter { /// /// Panics if the write would exceed the buffer bounds. pub(crate) unsafe fn write(&mut self, pos: Pos, val: U) { - let start = pos.0 as usize; - let size = mem::size_of::(); - assert!( - start + size <= self.buf.len() as usize, - "write out of bounds: {}..{} but buffer len is {}", - start, - start + size, - self.buf.len() - ); - // SAFETY: Bounds checked above. `pos` was previously allocated for `U` via - // `reserve::()` which ensures correct alignment. The source pointer is - // valid for `size` bytes, and `mem::forget` prevents double-drop. - unsafe { - let src = core::ptr::from_ref(&val).cast::(); - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), size); - } - mem::forget(val); + // SAFETY: Caller guarantees `pos` was allocated for `U`. + unsafe { crate::buf::write_flat(&mut self.buf, pos, val) }; } /// Patch a [`Near`](crate::Near) at position `at` to point to `target`. @@ -117,19 +100,9 @@ impl Emitter { /// /// Panics if the offset overflows `i32`, if `target == at`, or if out of bounds. pub(crate) unsafe fn patch_near(&mut self, at: Pos, target: Pos) { - let rel = i64::from(target.0) - i64::from(at.0); - let rel_i32: i32 = rel.try_into().expect("near offset overflow"); - let nz = NonZero::new(rel_i32).expect("near offset must be non-zero (target == at)"); - - let start = at.0 as usize; - let size = mem::size_of::>(); - assert!(start + size <= self.buf.len() as usize, "patch_near out of bounds"); - // SAFETY: Bounds checked above. `at` points to an allocated `Near` field - // whose first 4 bytes are the `NonZero` offset. - unsafe { - let src = core::ptr::from_ref(&nz).cast::(); - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), size); - } + // SAFETY: Caller guarantees `at` points to a `Near` and `target` + // was allocated for `U`. + unsafe { crate::buf::patch_near(&mut self.buf, at, target) }; } /// Copy raw bytes to position `at`. @@ -143,19 +116,9 @@ impl Emitter { /// /// Panics if the write would exceed the buffer bounds. pub(crate) unsafe fn write_bytes_internal(&mut self, at: Pos, src: *const u8, len: usize) { - let start = at.0 as usize; - assert!( - start + len <= self.buf.len() as usize, - "write_bytes out of bounds: {}..{} but buffer len is {}", - start, - start + len, - self.buf.len() - ); - // SAFETY: Bounds checked above. `src` is valid for `len` bytes (caller - // contract). The destination range does not overlap with the source. - unsafe { - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), len); - } + // SAFETY: Caller guarantees `src` is valid for `len` bytes and `at` + // has at least `len` bytes available. + unsafe { crate::buf::write_bytes(&mut self.buf, at, src, len) }; } /// Patch a [`NearList`](crate::NearList) header at position `at`. @@ -172,36 +135,9 @@ impl Emitter { /// /// Panics if the offset overflows `i32` or if out of bounds. pub(crate) unsafe fn patch_list_header(&mut self, at: Pos, target: Pos, len: u32) { - let off_field_pos = at.0 as usize; - let len_field_pos = off_field_pos + mem::size_of::(); - - assert!( - len_field_pos + mem::size_of::() <= self.buf.len() as usize, - "patch_list_header out of bounds" - ); - - let rel: i32 = if len == 0 { - 0 - } else { - let r = i64::from(target.0) - i64::from(at.0); - r.try_into().expect("list header offset overflow") - }; - - // SAFETY: Bounds checked above. The list header at `at` has layout - // `[i32 offset, u32 len]`, and both writes are within bounds. - unsafe { - let buf_ptr = self.buf.as_mut_ptr(); - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&rel).cast::(), - buf_ptr.add(off_field_pos), - mem::size_of::(), - ); - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&len).cast::(), - buf_ptr.add(len_field_pos), - mem::size_of::(), - ); - } + // SAFETY: Caller guarantees `at` points to a `NearList` and `target` + // is a valid segment position (or `Pos::ZERO` when `len == 0`). + unsafe { crate::buf::patch_list_header(&mut self.buf, at, target, len) }; } /// Consume the emitter and produce an aligned [`Region`](crate::Region). @@ -214,11 +150,6 @@ impl Emitter { unsafe { crate::Region::from_buf(self.buf) } } - /// Mutable pointer to buffer start (for Patch impls). - pub(crate) fn buf_mut_ptr(&mut self) -> *mut u8 { - self.buf.as_mut_ptr() - } - /// Const pointer to buffer start. pub(crate) fn buf_ptr(&self) -> *const u8 { self.buf.as_ptr() @@ -235,26 +166,17 @@ impl Emitter { /// is initialized to `count`; `next` is 0 (end of chain, from zero-fill). /// Values start at offset `size_of::>()` from the returned pos. pub(crate) fn alloc_segment_internal(&mut self, count: u32) -> Pos { - use crate::list::Segment; - self.buf.align_to(align_of::>()); - let pos = Pos(self.buf.len()); - let values_size = count.checked_mul(size_of::() as u32).expect("segment values overflow"); - let total = (size_of::>() as u32) - .checked_add(values_size) - .expect("segment total size overflow"); - self.buf.resize(self.buf.len() + total, 0); - // Write segment len at offset 4 (next is already 0 from zero-fill). - let len_offset = pos.0 as usize + size_of::(); - // SAFETY: `resize` just allocated `total` bytes starting at `pos`. - // The `len` field is at `pos + 4`, within the freshly allocated region. - unsafe { - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&count).cast::(), - self.buf.as_mut_ptr().add(len_offset), - size_of::(), - ); - } - pos + crate::buf::alloc_segment::(&mut self.buf, count) + } + + /// Patch the `next` pointer of a segment at `seg_pos`. + /// + /// # Safety + /// + /// `seg_pos` must be a position of a previously allocated `Segment`. + pub(crate) unsafe fn patch_segment_next(&mut self, seg_pos: Pos, next_seg_pos: Pos) { + // SAFETY: Caller guarantees `seg_pos` is a previously allocated segment. + unsafe { crate::buf::patch_segment_next(&mut self.buf, seg_pos, next_seg_pos) }; } /// Extract the underlying buffer (used by [`Region::trim`](crate::Region::trim)). diff --git a/nearest/src/patch.rs b/nearest/src/patch.rs index 411dee7..a648445 100644 --- a/nearest/src/patch.rs +++ b/nearest/src/patch.rs @@ -113,20 +113,8 @@ impl Patch for Emitter { } unsafe fn patch_segment_next(&mut self, seg_pos: Pos, next_seg_pos: Pos) { - // next field is at offset 0 of Segment - let rel = i64::from(next_seg_pos.0) - i64::from(seg_pos.0); - let rel_i32: i32 = rel.try_into().expect("segment next offset overflow"); - let start = seg_pos.0 as usize; - assert!(start + size_of::() <= self.pos().0 as usize, "patch_segment_next out of bounds"); - // SAFETY: Bounds checked above. The `next` field is at offset 0 of - // `Segment`, and we write exactly `size_of::()` bytes. - unsafe { - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&rel_i32).cast::(), - self.buf_mut_ptr().add(start), - size_of::(), - ); - } + // SAFETY: Caller guarantees `seg_pos` is a previously allocated segment. + unsafe { self.patch_segment_next(seg_pos, next_seg_pos) }; } fn byte_len(&self) -> usize { diff --git a/nearest/src/region.rs b/nearest/src/region.rs index ad601fb..58e0246 100644 --- a/nearest/src/region.rs +++ b/nearest/src/region.rs @@ -1,10 +1,9 @@ -use core::{fmt, mem, num::NonZero, ops::Deref}; +use core::{fmt, mem, ops::Deref}; use crate::{ Emit, Flat, buf::Buf, emitter::{Emitter, Pos}, - list::Segment, session::{Brand, Session}, }; @@ -243,7 +242,7 @@ impl Region { pub fn trim(&mut self) { let new_buf = { let root: &T = self; - let mut em = Emitter::::new(); + let mut em = Emitter::::with_capacity(self.buf.len()); Emit::::emit(root, &mut em); em.into_buf() }; @@ -269,23 +268,8 @@ impl Region { /// `at` must have been allocated for `U` via `alloc_internal::()`, /// ensuring correct alignment. pub(crate) unsafe fn write_flat_internal(&mut self, at: Pos, val: U) { - let start = at.0 as usize; - let size = mem::size_of::(); - assert!( - start + size <= self.buf.len() as usize, - "write_flat out of bounds: {}..{} but len is {}", - start, - start + size, - self.buf.len() - ); - // SAFETY: Bounds checked above. `at` was allocated for `U` via - // `alloc_internal::()`, ensuring correct alignment. `mem::forget` - // prevents double-drop. - unsafe { - let src = core::ptr::from_ref(&val).cast::(); - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), size); - } - mem::forget(val); + // SAFETY: Caller guarantees `at` was allocated for `U`. + unsafe { crate::buf::write_flat(&mut self.buf, at, val) }; } /// Patch a [`Near`](crate::Near) at position `at` to point to `target`. @@ -295,19 +279,9 @@ impl Region { /// `at` must point to a `Near` field within a previously allocated /// value, and `target` must be a position allocated for `U`. pub(crate) unsafe fn patch_near_internal(&mut self, at: Pos, target: Pos) { - let rel = i64::from(target.0) - i64::from(at.0); - let rel_i32: i32 = rel.try_into().expect("near offset overflow"); - let nz = NonZero::new(rel_i32).expect("near offset must be non-zero"); - - let start = at.0 as usize; - let size = mem::size_of::>(); - assert!(start + size <= self.buf.len() as usize, "patch_near out of bounds"); - // SAFETY: Bounds checked above. `at` points to the `Near` field whose - // first 4 bytes hold a `NonZero` offset. - unsafe { - let src = core::ptr::from_ref(&nz).cast::(); - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), size); - } + // SAFETY: Caller guarantees `at` points to a `Near` and `target` + // was allocated for `U`. + unsafe { crate::buf::patch_near(&mut self.buf, at, target) }; } /// Patch a [`NearList`](crate::NearList) header at position `at`. @@ -318,36 +292,9 @@ impl Region { /// value, and `target` must be a position of a `Segment` (or /// `Pos::ZERO` when `len == 0`). pub(crate) unsafe fn patch_list_header_internal(&mut self, at: Pos, target: Pos, len: u32) { - let off_pos = at.0 as usize; - let len_pos = off_pos + mem::size_of::(); - - assert!( - len_pos + mem::size_of::() <= self.buf.len() as usize, - "patch_list_header out of bounds" - ); - - let rel: i32 = if len == 0 { - 0 - } else { - let r = i64::from(target.0) - i64::from(at.0); - r.try_into().expect("list header offset overflow") - }; - - // SAFETY: Bounds checked above. The list header at `at` has layout - // `[i32 offset, u32 len]`, and both writes are within bounds. - unsafe { - let buf = self.buf.as_mut_ptr(); - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&rel).cast::(), - buf.add(off_pos), - mem::size_of::(), - ); - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&len).cast::(), - buf.add(len_pos), - mem::size_of::(), - ); - } + // SAFETY: Caller guarantees `at` points to a `NearList` and `target` + // is a valid segment position (or `Pos::ZERO` when `len == 0`). + unsafe { crate::buf::patch_list_header(&mut self.buf, at, target, len) }; } /// Allocate a segment header plus `count` contiguous values of type `U`. @@ -355,26 +302,7 @@ impl Region { /// Returns the position of the segment header. The segment's `len` field /// is initialized to `count`; `next` is 0 (end of chain, from zero-fill). pub(crate) fn alloc_segment_internal(&mut self, count: u32) -> Pos { - self.buf.align_to(align_of::>()); - let pos = Pos(self.buf.len()); - let values_size = - count.checked_mul(mem::size_of::() as u32).expect("segment values overflow"); - let total = (mem::size_of::>() as u32) - .checked_add(values_size) - .expect("segment total size overflow"); - self.buf.resize(self.buf.len() + total, 0); - // Write segment len at offset 4 (next is already 0 from zero-fill). - let len_offset = pos.0 as usize + mem::size_of::(); - // SAFETY: `resize` just allocated `total` bytes at `pos`. The `len` field - // is at `pos + 4`, within the freshly allocated region. - unsafe { - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&count).cast::(), - self.buf.as_mut_ptr().add(len_offset), - mem::size_of::(), - ); - } - pos + crate::buf::alloc_segment::(&mut self.buf, count) } /// Patch the `next` pointer of a segment at `seg_pos`. @@ -383,23 +311,8 @@ impl Region { /// /// `seg_pos` must be a position of a previously allocated `Segment`. pub(crate) unsafe fn patch_segment_next_internal(&mut self, seg_pos: Pos, next_seg_pos: Pos) { - // next field is at offset 0 of Segment - let rel = i64::from(next_seg_pos.0) - i64::from(seg_pos.0); - let rel_i32: i32 = rel.try_into().expect("segment next offset overflow"); - let start = seg_pos.0 as usize; - assert!( - start + mem::size_of::() <= self.buf.len() as usize, - "patch_segment_next out of bounds" - ); - // SAFETY: Bounds checked above. The `next` field is at offset 0 of - // `Segment`, and we write exactly `size_of::()` bytes. - unsafe { - core::ptr::copy_nonoverlapping( - core::ptr::from_ref(&rel_i32).cast::(), - self.buf.as_mut_ptr().add(start), - mem::size_of::(), - ); - } + // SAFETY: Caller guarantees `seg_pos` is a previously allocated segment. + unsafe { crate::buf::patch_segment_next(&mut self.buf, seg_pos, next_seg_pos) }; } /// Copy raw bytes to position `at`. @@ -409,19 +322,9 @@ impl Region { /// `src` must be valid for reading `len` bytes. `at` must be a valid /// position with at least `len` bytes available. pub(crate) unsafe fn write_bytes_internal(&mut self, at: Pos, src: *const u8, len: usize) { - let start = at.0 as usize; - assert!( - start + len <= self.buf.len() as usize, - "write_bytes out of bounds: {}..{} but len is {}", - start, - start + len, - self.buf.len() - ); - // SAFETY: Bounds checked above. `src` is valid for `len` bytes (caller - // contract). The destination does not overlap the source. - unsafe { - core::ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr().add(start), len); - } + // SAFETY: Caller guarantees `src` is valid for `len` bytes and `at` + // has at least `len` bytes available. + unsafe { crate::buf::write_bytes(&mut self.buf, at, src, len) }; } /// Return the raw byte contents of this region. diff --git a/nearest/src/session.rs b/nearest/src/session.rs index 00412df..6aac349 100644 --- a/nearest/src/session.rs +++ b/nearest/src/session.rs @@ -530,6 +530,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { let seg_pos = self.region.alloc_segment_internal::(len); let values_offset = size_of::>(); + let base_addr = self.region.deref_raw().addr(); for (i, &item_ref) in refs.iter().enumerate() { let val_pos = seg_pos.offset(values_offset + i * size_of::()); // SAFETY: The pre-reserve above guarantees no reallocation occurs. @@ -537,7 +538,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // so the `&U` is not derived from `self.region` — avoiding an aliased // `&U` / `&mut Region` pair that Stacked Borrows would reject. unsafe { - let addr = self.region.deref_raw().add(item_ref.pos.0 as usize).addr(); + let addr = base_addr.wrapping_add(item_ref.pos.0 as usize); let val = &*core::ptr::with_exposed_provenance::(addr); Emit::::write_at(val, self.region, val_pos); } @@ -1070,6 +1071,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // into a fresh contiguous segment. No scratch needed. let seg_pos = self.region.alloc_segment_internal::(len); let values_offset = size_of::>(); + let base_addr = self.region.deref_raw().addr(); let mut seg_off = first_seg_off; let mut remaining = count; let mut dest_i = 0; @@ -1078,7 +1080,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // via `with_exposed_provenance` so the read is not derived from // `self.region` — avoiding Stacked Borrows violation. unsafe { - let seg_addr = self.region.deref_raw().add(seg_off).addr(); + let seg_addr = base_addr.wrapping_add(seg_off); let seg = &*core::ptr::with_exposed_provenance::>(seg_addr); let seg_len = seg.len as usize; let vals_base = seg_addr.wrapping_add(size_of::>()); @@ -1153,6 +1155,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { let values_offset = size_of::>(); // Walk old segments forward, write into new segment in reverse order. + let base_addr = self.region.deref_raw().addr(); let mut seg_off = first_seg_off; let mut remaining = count; let mut dest_i = count; // counts down from count to 0 @@ -1161,7 +1164,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // via `with_exposed_provenance` so the read is not derived from // `self.region` — avoiding Stacked Borrows violation. unsafe { - let seg_addr = self.region.deref_raw().add(seg_off).addr(); + let seg_addr = base_addr.wrapping_add(seg_off); let seg = &*core::ptr::with_exposed_provenance::>(seg_addr); let seg_len = seg.len as usize; let vals_base = seg_addr.wrapping_add(size_of::>()); @@ -1245,12 +1248,13 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // Deep-copy elements in sorted order into a fresh contiguous segment. let seg_pos = self.region.alloc_segment_internal::(len); let values_offset = size_of::>(); + let base_addr = self.region.deref_raw().addr(); for (i, &elem_off) in positions.iter().enumerate() { // SAFETY: Pre-reserve guarantees no reallocation. We recover provenance // via `with_exposed_provenance` — no aliasing with `&mut Region`. unsafe { let val_pos = seg_pos.offset(values_offset + i * size_of::()); - let addr = self.region.deref_raw().add(elem_off as usize).addr(); + let addr = base_addr.wrapping_add(elem_off as usize); let val = &*core::ptr::with_exposed_provenance::(addr); Emit::::write_at(val, self.region, val_pos); } @@ -1357,6 +1361,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // run directly into a fresh contiguous segment. No scratch needed. let seg_pos = self.region.alloc_segment_internal::(len); let values_offset = size_of::>(); + let base_addr = self.region.deref_raw().addr(); let mut seg_off = first_seg_off; let mut remaining = count; let mut dest_i = 0; @@ -1366,7 +1371,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { // via `with_exposed_provenance` so the read is not derived from // `self.region` — avoiding Stacked Borrows violation. unsafe { - let seg_addr = self.region.deref_raw().add(seg_off).addr(); + let seg_addr = base_addr.wrapping_add(seg_off); let seg = &*core::ptr::with_exposed_provenance::>(seg_addr); let seg_len = seg.len as usize; let vals_base = seg_addr.wrapping_add(size_of::>()); @@ -1374,8 +1379,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { let val_addr = vals_base.wrapping_add(j * size_of::()); let val = &*core::ptr::with_exposed_provenance::(val_addr); let is_dup = prev_off.is_some_and(|p| { - let prev = - &*core::ptr::with_exposed_provenance::(self.region.deref_raw().add(p).addr()); + let prev = &*core::ptr::with_exposed_provenance::(base_addr.wrapping_add(p)); eq(prev, val) }); if !is_dup { @@ -1383,7 +1387,7 @@ impl<'id, 'a, Root: Flat, B: Buf> Session<'id, 'a, Root, B> { Emit::::write_at(val, self.region, val_pos); dest_i += 1; } - prev_off = Some(val_addr - self.region.deref_raw().addr()); + prev_off = Some(val_addr - base_addr); } remaining -= seg_len; if remaining > 0 {