/// Helper trait that allows `arena_cache` queries to return `Option<&T>` /// instead of `&Option`, and avoid allocating `None` in the arena. /// /// An arena-cached query must be declared to return a type that implements /// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then /// determines the types returned by the provider and stored in the arena, /// and provides a function to bridge between the three types. pub trait ArenaCached<'tcx>: Sized { /// Type that is returned by the query provider. type Provided; /// Type that is stored in the arena. type Allocated: 'tcx; /// Takes a provided value, and allocates it in the arena (if appropriate) /// with the help of the given `arena_alloc` closure. fn alloc_in_arena( arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, value: Self::Provided, ) -> Self; } impl<'tcx, T> ArenaCached<'tcx> for &'tcx T { type Provided = T; type Allocated = T; fn alloc_in_arena( arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, value: Self::Provided, ) -> Self { // Just allocate in the arena normally. arena_alloc(value) } } impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { type Provided = Option; /// The provide value is `Option`, but we only store `T` in the arena. type Allocated = T; fn alloc_in_arena( arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, value: Self::Provided, ) -> Self { // Don't store None in the arena, and wrap the allocated reference in Some. value.map(arena_alloc) } }