rustc_middle/query/
arena_cached.rs

1/// Helper trait that allows `arena_cache` queries to return `Option<&T>`
2/// instead of `&Option<T>`, and avoid allocating `None` in the arena.
3///
4/// An arena-cached query must be declared to return a type that implements
5/// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then
6/// determines the types returned by the provider and stored in the arena,
7/// and provides a function to bridge between the three types.
8pub trait ArenaCached<'tcx>: Sized {
9    /// Type that is returned by the query provider.
10    type Provided;
11    /// Type that is stored in the arena.
12    type Allocated: 'tcx;
13
14    /// Takes a provided value, and allocates it in the arena (if appropriate)
15    /// with the help of the given `arena_alloc` closure.
16    fn alloc_in_arena(
17        arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
18        value: Self::Provided,
19    ) -> Self;
20}
21
22impl<'tcx, T> ArenaCached<'tcx> for &'tcx T {
23    type Provided = T;
24    type Allocated = T;
25
26    fn alloc_in_arena(
27        arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
28        value: Self::Provided,
29    ) -> Self {
30        // Just allocate in the arena normally.
31        arena_alloc(value)
32    }
33}
34
35impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> {
36    type Provided = Option<T>;
37    /// The provide value is `Option<T>`, but we only store `T` in the arena.
38    type Allocated = T;
39
40    fn alloc_in_arena(
41        arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
42        value: Self::Provided,
43    ) -> Self {
44        // Don't store None in the arena, and wrap the allocated reference in Some.
45        value.map(arena_alloc)
46    }
47}