Skip to content

AVec[T, A]

MaulingMonkey edited this page Feb 16, 2024 · 2 revisions

Given even the relatively simple:

type A = SomeNonZstAllocator;
struct S { pub a: AVec<u32, A>, pub b: AVec<u32, A> }

"Ideal" by-value borrowing is complicated:

struct Exclusive<'s> { pub a: &'s mut           [u32],     ... } // ❌ drops `Allocator` breaking ABI
struct Exclusive<'s> { pub a: &'s mut       AVec<u32, A>,  ... } // ❌ changes indirection, breaking ABI
struct Exclusive<'s> { pub a: Valrow<'s,    AVec<u32, A>>, ... } // ❌ freezes `u32`s, preventing modification
struct Exclusive<'s> { pub a: ValrowMut<'s, AVec<u32, A>>, ... } // ❌ original value might UAF if vec resized

You more-or-less must have a custom partially-frozen type, which doesn't even deref into a shared-borrow:

type                        AVecValrowRef<'v, T, A> = valrow::Valrow<'a, AVec<T, A>>;
#[repr(transparent)] struct AVecValrowMut<'v, T, A>(ManuallyDrop<AVec<T, A>>, PhantomData<&'v mut AVec<T, A>>);

impl<'v, T, A> Deref    for AVecValrowMut<'v, T, A> { fn deref    (&    self) -> &    [T] { &    self.0[..] } type Target = [T]; }
impl<'v, T, A> DerefMut for AVecValrowMut<'v, T, A> { fn deref_mut(&mut self) -> &mut [T] { &mut self.0[..] } }
impl<'v, T, A> From<AVecValrowMut<'v, T, A>> for AVecValrowRef<'v, T, A> { fn from(exc: ...) -> Self { unsafe { transmute(exc) } } }

And that still impacts downstream's codegen for S:

struct Exclusive<'s> { pub a: AVecValrowMut<'s, u32, A>, ... }
struct Shared   <'s> { pub a: AVecValrowRef<'s, u32, A>, ... }
Clone this wiki locally