Как отмечалось в комментариях, это действительно невозможно с корзиной индексации.Однако это не значит, что хранить фирменные индексы вообще невозможно.Фактически, избавление от замыкания будет работать нормально, как в следующем коде:
use std::marker::PhantomData;
use std::ops::Index;
#[derive(Copy, Clone)]
struct InvariantLifetime<'a>(PhantomData<fn(&'a ()) -> &'a ()>);
pub struct Arena<'b, T>(Vec<T>, InvariantLifetime<'b>);
pub struct Idx<'b>(usize, InvariantLifetime<'b>);
impl<'b, T> Arena<'b, T> {
pub unsafe fn new(_: &'b mut ()) -> Self {
Arena(vec![], InvariantLifetime(PhantomData))
}
pub fn add(&mut self, t: T) -> Idx<'b> {
let i = self.0.len();
self.0.push(t);
Idx(i, self.1)
}
}
impl<'b, T> Index<Idx<'b>> for Arena<'b, T> {
type Output = T;
fn index(&self, i: Idx<'b>) -> &T {
unsafe { &self.0.get_unchecked(i.0) }
}
}
macro_rules! mk_arena {
($arena:ident) => {
let mut tag = ();
let mut $arena = unsafe { Arena::new(&mut tag) };
};
}
struct Tree<'b>(Option<(Idx<'b>, Idx<'b>)>);
fn tree<'b>(a: &mut Arena<'b, Tree<'b>>, d: usize) -> Idx<'b> {
if d > 0 {
a.add(Tree(Some((tree(a, d - 1), tree(a, d - 1)))))
} else {
a.add(Tree(None))
}
}
pub fn main() {
mk_arena!(arena);
let _ = tree(&mut arena, 3);
}
Ящик compact_arena имеет то же решение с лучшими документами.