Skip to main content

oxc_allocator/
take_in.rs

1use std::{cell::Cell, mem, num};
2
3use crate::{Allocator, Box, GetAllocator, Vec};
4
5/// A trait to replace an existing AST node with a dummy.
6pub trait TakeIn<'a>: Dummy<'a> {
7    /// Replace node with a dummy, and return the original.
8    ///
9    /// If you're taking the node out to build a new node from it and store the result back
10    /// in the same slot, prefer [`replace_with`]. `take_in` writes a dummy into the arena,
11    /// which takes up space there forever. `replace_with` avoids that (no dummy), so is faster
12    /// and uses less memory.
13    ///
14    /// [`replace_with`]: crate::ReplaceWith::replace_with
15    #[must_use]
16    fn take_in<A: GetAllocator<'a>>(&mut self, allocator_accessor: &A) -> Self {
17        let allocator = allocator_accessor.allocator();
18        let dummy = Dummy::dummy(allocator);
19        mem::replace(self, dummy)
20    }
21
22    /// Replace node with a dummy, allocate the original node into the arena,
23    /// and return it as a [`Box<Self>`].
24    ///
25    /// If you're taking the node out to build a new node from it and store the result back
26    /// in the same slot, prefer [`replace_with`]. `take_in` writes a dummy into the arena,
27    /// which takes up space there forever. `replace_with` avoids that (no dummy), so is faster
28    /// and uses less memory.
29    ///
30    /// [`replace_with`]: crate::ReplaceWith::replace_with
31    #[must_use]
32    fn take_in_box<A: GetAllocator<'a>>(&mut self, allocator_accessor: &A) -> Box<'a, Self> {
33        let allocator = allocator_accessor.allocator();
34        let dummy = Dummy::dummy(allocator);
35        Box::new_in(mem::replace(self, dummy), &allocator)
36    }
37}
38
39impl<'a, T> TakeIn<'a> for Vec<'a, T> {}
40
41impl<'a, T> TakeIn<'a> for Box<'a, [T]> {}
42
43/// A trait to create a dummy AST node.
44pub trait Dummy<'a>: Sized {
45    /// Create a dummy node.
46    fn dummy(allocator: &'a Allocator) -> Self;
47}
48
49impl<'a, T> Dummy<'a> for Option<T> {
50    /// Create a dummy [`Option`].
51    #[expect(clippy::inline_always)]
52    #[inline(always)]
53    fn dummy(_allocator: &'a Allocator) -> Self {
54        None
55    }
56}
57
58impl<'a, T: Dummy<'a>> Dummy<'a> for Box<'a, T> {
59    /// Create a dummy [`Box`].
60    #[inline]
61    fn dummy(allocator: &'a Allocator) -> Self {
62        Box::new_in(Dummy::dummy(allocator), &allocator)
63    }
64}
65
66impl<'a, T> Dummy<'a> for Box<'a, [T]> {
67    /// Create a dummy empty [`Box<[T]>`] boxed slice.
68    #[inline]
69    fn dummy(_allocator: &'a Allocator) -> Self {
70        Box::new_empty_boxed_slice()
71    }
72}
73
74impl<'a, T> Dummy<'a> for Vec<'a, T> {
75    /// Create a dummy [`Vec`].
76    #[inline]
77    fn dummy(allocator: &'a Allocator) -> Self {
78        Vec::new_in(&allocator)
79    }
80}
81
82impl<'a, T: Dummy<'a>> Dummy<'a> for Cell<T> {
83    /// Create a dummy [`Cell`].
84    #[expect(clippy::inline_always)]
85    #[inline(always)]
86    fn dummy(allocator: &'a Allocator) -> Self {
87        Cell::new(Dummy::dummy(allocator))
88    }
89}
90
91impl<'a> Dummy<'a> for () {
92    #[inline(always)]
93    fn dummy(_allocator: &'a Allocator) {}
94}
95
96impl<'a> Dummy<'a> for bool {
97    #[expect(clippy::inline_always)]
98    #[inline(always)]
99    fn dummy(_allocator: &'a Allocator) -> Self {
100        false
101    }
102}
103
104impl<'a> Dummy<'a> for &'a str {
105    #[expect(clippy::inline_always)]
106    #[inline(always)]
107    fn dummy(_allocator: &'a Allocator) -> Self {
108        ""
109    }
110}
111
112macro_rules! dummy_impl_int {
113    ($ty:ident) => {
114        impl<'a> Dummy<'a> for $ty {
115            #[inline(always)]
116            fn dummy(_allocator: &'a Allocator) -> Self {
117                0
118            }
119        }
120    };
121}
122
123dummy_impl_int!(u8);
124dummy_impl_int!(u16);
125dummy_impl_int!(u32);
126dummy_impl_int!(u64);
127dummy_impl_int!(u128);
128dummy_impl_int!(usize);
129dummy_impl_int!(i8);
130dummy_impl_int!(i16);
131dummy_impl_int!(i32);
132dummy_impl_int!(i64);
133dummy_impl_int!(i128);
134dummy_impl_int!(isize);
135
136macro_rules! dummy_impl_float {
137    ($ty:ident) => {
138        impl<'a> Dummy<'a> for $ty {
139            #[inline(always)]
140            fn dummy(_allocator: &'a Allocator) -> Self {
141                0.0
142            }
143        }
144    };
145}
146
147dummy_impl_float!(f32);
148dummy_impl_float!(f64);
149
150macro_rules! dummy_impl_non_zero {
151    ($ty:ident) => {
152        impl<'a> Dummy<'a> for num::$ty {
153            #[inline(always)]
154            fn dummy(_allocator: &'a Allocator) -> Self {
155                Self::MIN
156            }
157        }
158    };
159}
160
161dummy_impl_non_zero!(NonZeroU8);
162dummy_impl_non_zero!(NonZeroU16);
163dummy_impl_non_zero!(NonZeroU32);
164dummy_impl_non_zero!(NonZeroU64);
165dummy_impl_non_zero!(NonZeroU128);
166dummy_impl_non_zero!(NonZeroUsize);
167dummy_impl_non_zero!(NonZeroI8);
168dummy_impl_non_zero!(NonZeroI16);
169dummy_impl_non_zero!(NonZeroI32);
170dummy_impl_non_zero!(NonZeroI64);
171dummy_impl_non_zero!(NonZeroI128);
172dummy_impl_non_zero!(NonZeroIsize);