1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::thir::*;

macro_rules! declare_arena {
    ([], [$($a:tt $name:ident: $ty:ty,)*]) => {
        #[derive(Default)]
        pub struct Arena<'thir, 'tcx> {
            pub dropless: rustc_arena::DroplessArena,
            drop: rustc_arena::DropArena,
            $($name: rustc_arena::arena_for_type!($a[$ty]),)*
        }

        pub trait ArenaAllocatable<'thir, 'tcx, T = Self>: Sized {
            fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self;
            fn allocate_from_iter(
                arena: &'thir Arena<'thir, 'tcx>,
                iter: impl ::std::iter::IntoIterator<Item = Self>,
            ) -> &'thir mut [Self];
        }

        impl<'thir, 'tcx, T: Copy> ArenaAllocatable<'thir, 'tcx, ()> for T {
            #[inline]
            fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self {
                arena.dropless.alloc(self)
            }
            #[inline]
            fn allocate_from_iter(
                arena: &'thir Arena<'thir, 'tcx>,
                iter: impl ::std::iter::IntoIterator<Item = Self>,
            ) -> &'thir mut [Self] {
                arena.dropless.alloc_from_iter(iter)
            }

        }
        $(
            impl<'thir, 'tcx> ArenaAllocatable<'thir, 'tcx, $ty> for $ty {
                #[inline]
                fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self {
                    if !::std::mem::needs_drop::<Self>() {
                        return arena.dropless.alloc(self);
                    }
                    match rustc_arena::which_arena_for_type!($a[&arena.$name]) {
                        ::std::option::Option::<&rustc_arena::TypedArena<Self>>::Some(ty_arena) => {
                            ty_arena.alloc(self)
                        }
                        ::std::option::Option::None => unsafe { arena.drop.alloc(self) },
                    }
                }

                #[inline]
                fn allocate_from_iter(
                    arena: &'thir Arena<'thir, 'tcx>,
                    iter: impl ::std::iter::IntoIterator<Item = Self>,
                ) -> &'thir mut [Self] {
                    if !::std::mem::needs_drop::<Self>() {
                        return arena.dropless.alloc_from_iter(iter);
                    }
                    match rustc_arena::which_arena_for_type!($a[&arena.$name]) {
                        ::std::option::Option::<&rustc_arena::TypedArena<Self>>::Some(ty_arena) => {
                            ty_arena.alloc_from_iter(iter)
                        }
                        ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
                    }
                }
            }
        )*

        impl<'thir, 'tcx> Arena<'thir, 'tcx> {
            #[inline]
            pub fn alloc<T: ArenaAllocatable<'thir, 'tcx, U>, U>(&'thir self, value: T) -> &'thir mut T {
                value.allocate_on(self)
            }

            #[allow(dead_code)] // function is never used
            #[inline]
            pub fn alloc_slice<T: ::std::marker::Copy>(&'thir self, value: &[T]) -> &'thir mut [T] {
                if value.is_empty() {
                    return &mut [];
                }
                self.dropless.alloc_slice(value)
            }

            pub fn alloc_from_iter<T: ArenaAllocatable<'thir, 'tcx, U>, U>(
                &'thir self,
                iter: impl ::std::iter::IntoIterator<Item = T>,
            ) -> &'thir mut [T] {
                T::allocate_from_iter(self, iter)
            }
        }
    }
}

declare_arena!([], [
    [] arm: Arm<'thir, 'tcx>,
    [] expr: Expr<'thir, 'tcx>,
    [] field_expr: FieldExpr<'thir, 'tcx>,
    [few] inline_asm_operand: InlineAsmOperand<'thir, 'tcx>,
    [] stmt: Stmt<'thir, 'tcx>,
]);