Asserting lifetime/dropck equality

I have some code:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=4b5739ed8831f922e561d08662bad2c1

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.

Hmm, it looks like something's missing here... should that say for Array<T, LENGTH>?

This doesn't make sense, because the aliases are mutually recursive... you can't define a type alias in terms of itself like that. The types have to make sense without being aliased.

Edited to fix the code, added a playground link with a working example

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.