oxc_allocator/
clone_in.rs

1use std::cell::Cell;
2
3use crate::{Allocator, Box, Vec};
4
5/// A trait to explicitly clone an object into an arena allocator.
6///
7/// As a convention `Cloned` associated type should always be the same as `Self`,
8/// It'd only differ in the lifetime, Here's an example:
9///
10/// ```
11/// # use oxc_allocator::{Allocator, CloneIn, Vec};
12/// # struct Struct<'a> {a: Vec<'a, u8>, b: u8}
13///
14/// impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Struct<'old_alloc> {
15///     type Cloned = Struct<'new_alloc>;
16///     fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
17///         Struct { a: self.a.clone_in(allocator), b: self.b.clone_in(allocator) }
18///     }
19/// }
20/// ```
21///
22/// Implementations of this trait on non-allocated items usually short-circuit to `Clone::clone`;
23/// However, it **isn't** guaranteed.
24///
25pub trait CloneIn<'new_alloc>: Sized {
26    /// The type of the cloned object.
27    ///
28    /// This should always be `Self` with a different lifetime.
29    type Cloned;
30
31    /// Clone `self` into the given `allocator`. `allocator` may be the same one
32    /// that `self` is already in.
33    fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned;
34
35    /// Almost identical as `clone_in`, but for some special type, it will also clone the semantic ids.
36    /// Please use this method only if you make sure semantic info is synced with the ast node.
37    #[inline]
38    fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
39        self.clone_in(allocator)
40    }
41}
42
43impl<'alloc, T, C> CloneIn<'alloc> for Option<T>
44where
45    T: CloneIn<'alloc, Cloned = C>,
46{
47    type Cloned = Option<C>;
48
49    fn clone_in(&self, allocator: &'alloc Allocator) -> Self::Cloned {
50        self.as_ref().map(|it| it.clone_in(allocator))
51    }
52
53    fn clone_in_with_semantic_ids(&self, allocator: &'alloc Allocator) -> Self::Cloned {
54        self.as_ref().map(|it| it.clone_in_with_semantic_ids(allocator))
55    }
56}
57
58impl<'new_alloc, T, C> CloneIn<'new_alloc> for Box<'_, T>
59where
60    T: CloneIn<'new_alloc, Cloned = C>,
61{
62    type Cloned = Box<'new_alloc, C>;
63
64    fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
65        Box::new_in(self.as_ref().clone_in(allocator), allocator)
66    }
67
68    fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
69        Box::new_in(self.as_ref().clone_in_with_semantic_ids(allocator), allocator)
70    }
71}
72
73impl<'new_alloc, T, C> CloneIn<'new_alloc> for Vec<'_, T>
74where
75    T: CloneIn<'new_alloc, Cloned = C>,
76    // TODO: This lifetime bound possibly shouldn't be required.
77    // https://github.com/oxc-project/oxc/pull/9656#issuecomment-2719762898
78    C: 'new_alloc,
79{
80    type Cloned = Vec<'new_alloc, C>;
81
82    fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
83        Vec::from_iter_in(self.iter().map(|it| it.clone_in(allocator)), allocator)
84    }
85
86    fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
87        Vec::from_iter_in(self.iter().map(|it| it.clone_in_with_semantic_ids(allocator)), allocator)
88    }
89}
90
91impl<'alloc, T: Copy> CloneIn<'alloc> for Cell<T> {
92    type Cloned = Cell<T>;
93
94    fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned {
95        Cell::new(self.get())
96    }
97}
98
99impl<'new_alloc> CloneIn<'new_alloc> for &str {
100    type Cloned = &'new_alloc str;
101
102    fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
103        allocator.alloc_str(self)
104    }
105}
106
107macro_rules! impl_clone_in {
108    ($($t:ty)*) => {
109        $(
110            impl<'alloc> CloneIn<'alloc> for $t {
111                type Cloned = Self;
112                #[inline(always)]
113                fn clone_in(&self, _: &'alloc Allocator) -> Self {
114                    *self
115                }
116            }
117        )*
118    }
119}
120
121impl_clone_in! {
122    usize u8 u16 u32 u64 u128
123    isize i8 i16 i32 i64 i128
124    f32 f64
125    bool char
126}