I have some code:
pub unsafe trait ArrayRepr<const DIMENSION: usize> {
/// Safety: must always be `Self` or nested arrays of `Self`
type Repr;
}
#[repr(transparent)]
pub struct Array<T: ArrayRepr<DIMENSION>, const DIMENSION: usize>(T::Repr);
impl<T: ArrayRepr<DIMENSION>, const DIMENSION: usize> Array<T, DIMENSION> {
pub fn fill(f: impl FnMut() -> T) -> Self {
todo!()
}
}
unsafe impl<T> ArrayRepr<0> for T {
type Repr = T;
}
macro_rules! make_reprs {
($($dim:literal,)+) => {
$(unsafe impl<T> ArrayRepr<$dim> for T {
type Repr = [<T as ArrayRepr<{$dim - 1}>>::Repr; 2];
})+
};
}
make_reprs!(1, 2, 3, 4, 5, 6, 7, 8,); // ...
I want to use it generically with arenas:
use core::marker::PhantomData;
pub struct Arena<T, A>(PhantomData<T>, A);
impl<T, A> Arena<T, A> {
pub fn new(v: A) -> Self {
todo!()
}
pub fn alloc<'a>(&'a self, v: T) -> &'a T {
todo!()
}
}
#[repr(transparent)]
struct NodeId<'a, const DIMENSION: usize>(Option<&'a NodeData<'a, DIMENSION>>)
where
NodeId<'a, DIMENSION>: ArrayRepr<DIMENSION>;
type NodeData<'a, const DIMENSION: usize> = Array<NodeId<'a, DIMENSION>, DIMENSION>;
fn f<A, const DIMENSION: usize>(a: A)
where
for<'a> NodeId<'a, DIMENSION>: ArrayRepr<DIMENSION>,
{
let arena = Arena::<NodeData<DIMENSION>, A>::new(a);
let node = arena.alloc(Array::fill(|| NodeId(None)));
let node2 = arena.alloc(Array::fill(|| NodeId(Some(node))));
}
How do I say that NodeId::Repr
has the same dropck properties as NodeId
, which will allow me to write f
without tripping the dropck when arena
is dropped?
It works just fine for non-generic DIMENSION
since rustc can then see that NodeId::Repr
is just a nested array of NodeId
.