Skip to content

Commit

Permalink
feat(allocator): introduce CloneIn trait.
Browse files Browse the repository at this point in the history
  • Loading branch information
rzvxa committed Aug 7, 2024
1 parent e0832f8 commit 7d9b46c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
89 changes: 89 additions & 0 deletions crates/oxc_allocator/src/clone_in.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use crate::{Allocator, Box, Vec};

/// A trait to explicitly clone an object into an arena allocator.
///
/// As a convention `Cloned` associated type should always be the same as `Self`,
/// It'd only differ in the lifetime, Here's an example:
///
/// ```
/// impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for Struct<'old_alloc> {
/// type Cloned = Struct<'new_alloc>;
/// fn clone_in(&self, alloc: &'new_alloc Allocator) -> Self::Cloned {
/// Struct { a: self.a.clone_in(alloc), b: self.b.clone_in(alloc) }
/// }
/// }
/// ```
///
/// Implementations of this trait on non-allocated items usually short-circuit to `Clone::clone`;
/// However, it **isn't** guaranteed.
///
pub trait CloneIn<'new_alloc>: Sized {
type Cloned;

fn clone_in(&self, alloc: &'new_alloc Allocator) -> Self::Cloned;
}

impl<'a, T, C> CloneIn<'a> for Option<T>
where
T: CloneIn<'a, Cloned = C>,
{
type Cloned = Option<C>;
fn clone_in(&self, alloc: &'a Allocator) -> Self::Cloned {
self.as_ref().map(|it| it.clone_in(alloc))
}
}

impl<'old_alloc, 'new_alloc, T, C> CloneIn<'new_alloc> for Box<'old_alloc, T>
where
T: CloneIn<'new_alloc, Cloned = C>,
{
type Cloned = Box<'new_alloc, C>;
fn clone_in(&self, alloc: &'new_alloc Allocator) -> Self::Cloned {
Self::Cloned::new_in(self.as_ref().clone_in(alloc), alloc)
}
}

impl<'old_alloc, 'new_alloc, T, C> CloneIn<'new_alloc> for Vec<'old_alloc, T>
where
T: CloneIn<'new_alloc, Cloned = C>,
{
type Cloned = Vec<'new_alloc, C>;
fn clone_in(&self, alloc: &'new_alloc Allocator) -> Self::Cloned {
Self::Cloned::from_iter_in(self.iter().map(|it| it.clone_in(alloc)), alloc)
}
}

impl<'a, T: Copy> CloneIn<'a> for std::cell::Cell<T> {
type Cloned = std::cell::Cell<T>;
fn clone_in(&self, _: &'a Allocator) -> Self::Cloned {
Self::Cloned::new(self.get())
}
}

impl<'old_alloc, 'new_alloc> CloneIn<'new_alloc> for &'old_alloc str {
type Cloned = &'new_alloc mut str;
fn clone_in(&self, alloc: &'new_alloc Allocator) -> Self::Cloned {
alloc.alloc_str(self)
}
}

macro_rules! impl_clone_in {
($($t:ty)*) => {
$(
impl<'a> CloneIn<'a> for $t {
type Cloned = Self;
#[inline(always)]
fn clone_in(&self, _: &'a Allocator) -> Self {
*self
}
}
)*
}
}

impl_clone_in! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
f32 f64
bool char
}
2 changes: 2 additions & 0 deletions crates/oxc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use std::{
};

mod arena;
mod clone_in;
mod convert;

use bumpalo::Bump;

pub use arena::{Box, String, Vec};
pub use clone_in::CloneIn;
pub use convert::{FromIn, IntoIn};

#[derive(Default)]
Expand Down

0 comments on commit 7d9b46c

Please sign in to comment.