From a20d46dd48b13d87324785cffdec6b680ec7e63c Mon Sep 17 00:00:00 2001 From: shruti2522 Date: Sun, 19 Apr 2026 13:25:33 +0000 Subject: [PATCH 1/2] share finalization code and generalize collector abstractions --- oscars/src/collectors/common.rs | 180 ++++++++++++++++++ oscars/src/collectors/mark_sweep/trace.rs | 94 +++------ .../src/collectors/mark_sweep_arena2/mod.rs | 65 +++++-- .../mark_sweep_arena2/pointers/gc.rs | 5 +- .../mark_sweep_arena2/pointers/weak.rs | 4 +- .../mark_sweep_arena2/pointers/weak_map.rs | 8 +- oscars/src/collectors/mod.rs | 1 + 7 files changed, 266 insertions(+), 91 deletions(-) create mode 100644 oscars/src/collectors/common.rs diff --git a/oscars/src/collectors/common.rs b/oscars/src/collectors/common.rs new file mode 100644 index 0000000..c76502d --- /dev/null +++ b/oscars/src/collectors/common.rs @@ -0,0 +1,180 @@ +//! Common types shared across all mark-and-sweep collector implementations. + +use core::any::TypeId; +use core::cell::{Cell, OnceCell}; +use core::marker::PhantomData; +use core::num::{ + NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, +}; +use core::sync::atomic; + +use rust_alloc::borrow::{Cow, ToOwned}; +use rust_alloc::boxed::Box; +use rust_alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; +use rust_alloc::rc::Rc; +use rust_alloc::string::String; +use rust_alloc::vec::Vec; + +#[cfg(feature = "std")] +use std::collections::{HashMap, HashSet}; + +/// Substitute for the [`Drop`] trait for garbage collected types +/// +/// Implement this to run cleanup logic before the GC frees an object. +/// The default implementation is a no-op +pub trait Finalize { + /// Cleanup logic for a type + fn finalize(&self) {} +} + +// primitive and standard library blanket impls + +macro_rules! simple_finalize { + ($($T:ty),* $(,)?) => { + $( impl Finalize for $T {} )* + } +} + +simple_finalize![ + (), + bool, + isize, + usize, + i8, + u8, + i16, + u16, + i32, + u32, + i64, + u64, + i128, + u128, + f32, + f64, + char, + TypeId, + String, + str, + Rc, + NonZeroIsize, + NonZeroUsize, + NonZeroI8, + NonZeroU8, + NonZeroI16, + NonZeroU16, + NonZeroI32, + NonZeroU32, + NonZeroI64, + NonZeroU64, + NonZeroI128, + NonZeroU128, +]; + +#[cfg(target_has_atomic = "8")] +simple_finalize![atomic::AtomicBool, atomic::AtomicI8, atomic::AtomicU8]; + +#[cfg(target_has_atomic = "16")] +simple_finalize![atomic::AtomicI16, atomic::AtomicU16]; + +#[cfg(target_has_atomic = "32")] +simple_finalize![atomic::AtomicI32, atomic::AtomicU32]; + +#[cfg(target_has_atomic = "64")] +simple_finalize![atomic::AtomicI64, atomic::AtomicU64]; + +#[cfg(target_has_atomic = "ptr")] +simple_finalize![atomic::AtomicIsize, atomic::AtomicUsize]; + +impl Finalize for &'static T {} + +impl Finalize for [T; N] {} + +// Function pointer tuples, provide `Finalize` for function types. +macro_rules! fn_finalize_one { + ($ty:ty $(,$args:ident)*) => { + impl Finalize for $ty {} + } +} +macro_rules! fn_finalize_group { + () => { + fn_finalize_one!(extern "Rust" fn () -> Ret); + fn_finalize_one!(extern "C" fn () -> Ret); + fn_finalize_one!(unsafe extern "Rust" fn () -> Ret); + fn_finalize_one!(unsafe extern "C" fn () -> Ret); + }; + ($($args:ident),*) => { + fn_finalize_one!(extern "Rust" fn ($($args),*) -> Ret, $($args),*); + fn_finalize_one!(extern "C" fn ($($args),*) -> Ret, $($args),*); + fn_finalize_one!(extern "C" fn ($($args),*, ...) -> Ret, $($args),*); + fn_finalize_one!(unsafe extern "Rust" fn ($($args),*) -> Ret, $($args),*); + fn_finalize_one!(unsafe extern "C" fn ($($args),*) -> Ret, $($args),*); + fn_finalize_one!(unsafe extern "C" fn ($($args),*, ...) -> Ret, $($args),*); + } +} + +macro_rules! tuple_finalize { + () => {}; + ($($args:ident),*) => { + impl<$($args),*> Finalize for ($($args,)*) {} + } +} + +macro_rules! type_arg_impls { + ($(($($args:ident),*);)*) => { + $( + fn_finalize_group!($($args),*); + tuple_finalize!($($args),*); + )* + } +} + +type_arg_impls![ + (); + (A); + (A, B); + (A, B, C); + (A, B, C, D); + (A, B, C, D, E); + (A, B, C, D, E, F); + (A, B, C, D, E, F, G); + (A, B, C, D, E, F, G, H); + (A, B, C, D, E, F, G, H, I); + (A, B, C, D, E, F, G, H, I, J); + (A, B, C, D, E, F, G, H, I, J, K); + (A, B, C, D, E, F, G, H, I, J, K, L); +]; + +impl Finalize for Box {} +impl Finalize for Box<[T]> {} +impl Finalize for Vec {} + +#[cfg(feature = "thin-vec")] +impl Finalize for thin_vec::ThinVec {} + +impl Finalize for Option {} +impl Finalize for Result {} +impl Finalize for BinaryHeap {} +impl Finalize for BTreeMap {} +impl Finalize for BTreeSet {} +impl Finalize for LinkedList {} +impl Finalize for VecDeque {} + +use core::hash::{BuildHasher, Hash}; +impl Finalize + for hashbrown::hash_map::HashMap +{ +} + +#[cfg(feature = "std")] +impl Finalize for HashMap {} + +#[cfg(feature = "std")] +impl Finalize for HashSet {} + +impl Finalize for Cell> {} +impl Finalize for OnceCell {} +impl Finalize for Cow<'static, T> where T::Owned: Finalize {} + +impl Finalize for PhantomData {} diff --git a/oscars/src/collectors/mark_sweep/trace.rs b/oscars/src/collectors/mark_sweep/trace.rs index 580120d..68413eb 100644 --- a/oscars/src/collectors/mark_sweep/trace.rs +++ b/oscars/src/collectors/mark_sweep/trace.rs @@ -18,11 +18,8 @@ use rust_alloc::vec::Vec; #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; -/// Substitute for the [`Drop`] trait for garbage collected types. -pub trait Finalize { - /// Cleanup logic for a type. - fn finalize(&self) {} -} +// Re-export the shared `Finalize` trait and all its stdlib blanket impls. +pub use crate::collectors::common::Finalize; #[derive(Debug, Clone, Copy, Default)] #[repr(u8)] @@ -110,17 +107,14 @@ macro_rules! custom_trace { }; } -impl Finalize for &'static T {} // SAFETY: 'static references don't need to be traced, since they live indefinitely. unsafe impl Trace for &'static T { empty_trace!(); } -macro_rules! simple_empty_finalize_trace { - ($($T:ty),*) => { +macro_rules! simple_empty_trace { + ($($T:ty),* $(,)?) => { $( - impl Finalize for $T {} - // SAFETY: // Primitive types and string types don't have inner nodes that need to be marked. unsafe impl Trace for $T { empty_trace!(); } @@ -128,11 +122,11 @@ macro_rules! simple_empty_finalize_trace { } } -simple_empty_finalize_trace![ +simple_empty_trace![ (), bool, isize, - usize, + usize, i8, u8, i16, @@ -165,21 +159,20 @@ simple_empty_finalize_trace![ ]; #[cfg(target_has_atomic = "8")] -simple_empty_finalize_trace![atomic::AtomicBool, atomic::AtomicI8, atomic::AtomicU8]; +simple_empty_trace![atomic::AtomicBool, atomic::AtomicI8, atomic::AtomicU8]; #[cfg(target_has_atomic = "16")] -simple_empty_finalize_trace![atomic::AtomicI16, atomic::AtomicU16]; +simple_empty_trace![atomic::AtomicI16, atomic::AtomicU16]; -#[cfg(target_has_atomic = "32")] -simple_empty_finalize_trace![atomic::AtomicI32, atomic::AtomicU32]; +#[cfg(target_has_atomic = "32")] +simple_empty_trace![atomic::AtomicI32, atomic::AtomicU32]; #[cfg(target_has_atomic = "64")] -simple_empty_finalize_trace![atomic::AtomicI64, atomic::AtomicU64]; +simple_empty_trace![atomic::AtomicI64, atomic::AtomicU64]; #[cfg(target_has_atomic = "ptr")] -simple_empty_finalize_trace![atomic::AtomicIsize, atomic::AtomicUsize]; +simple_empty_trace![atomic::AtomicIsize, atomic::AtomicUsize]; -impl Finalize for [T; N] {} // SAFETY: // All elements inside the array are correctly marked. unsafe impl Trace for [T; N] { @@ -190,35 +183,33 @@ unsafe impl Trace for [T; N] { }); } -macro_rules! fn_finalize_trace_one { +macro_rules! fn_trace_one { ($ty:ty $(,$args:ident)*) => { - impl Finalize for $ty {} // SAFETY: // Function pointers don't have inner nodes that need to be marked. unsafe impl Trace for $ty { empty_trace!(); } } } -macro_rules! fn_finalize_trace_group { +macro_rules! fn_trace_group { () => { - fn_finalize_trace_one!(extern "Rust" fn () -> Ret); - fn_finalize_trace_one!(extern "C" fn () -> Ret); - fn_finalize_trace_one!(unsafe extern "Rust" fn () -> Ret); - fn_finalize_trace_one!(unsafe extern "C" fn () -> Ret); + fn_trace_one!(extern "Rust" fn () -> Ret); + fn_trace_one!(extern "C" fn () -> Ret); + fn_trace_one!(unsafe extern "Rust" fn () -> Ret); + fn_trace_one!(unsafe extern "C" fn () -> Ret); }; ($($args:ident),*) => { - fn_finalize_trace_one!(extern "Rust" fn ($($args),*) -> Ret, $($args),*); - fn_finalize_trace_one!(extern "C" fn ($($args),*) -> Ret, $($args),*); - fn_finalize_trace_one!(extern "C" fn ($($args),*, ...) -> Ret, $($args),*); - fn_finalize_trace_one!(unsafe extern "Rust" fn ($($args),*) -> Ret, $($args),*); - fn_finalize_trace_one!(unsafe extern "C" fn ($($args),*) -> Ret, $($args),*); - fn_finalize_trace_one!(unsafe extern "C" fn ($($args),*, ...) -> Ret, $($args),*); + fn_trace_one!(extern "Rust" fn ($($args),*) -> Ret, $($args),*); + fn_trace_one!(extern "C" fn ($($args),*) -> Ret, $($args),*); + fn_trace_one!(extern "C" fn ($($args),*, ...) -> Ret, $($args),*); + fn_trace_one!(unsafe extern "Rust" fn ($($args),*) -> Ret, $($args),*); + fn_trace_one!(unsafe extern "C" fn ($($args),*) -> Ret, $($args),*); + fn_trace_one!(unsafe extern "C" fn ($($args),*, ...) -> Ret, $($args),*); } } -macro_rules! tuple_finalize_trace { - () => {}; // This case is handled above, by simple_finalize_empty_trace!(). +macro_rules! tuple_trace { + () => {}; // () handled by simple_empty_trace! ($($args:ident),*) => { - impl<$($args),*> Finalize for ($($args,)*) {} // SAFETY: // All elements inside the tuple are correctly marked. unsafe impl<$($args: $crate::collectors::mark_sweep::Trace),*> Trace for ($($args,)*) { @@ -234,16 +225,16 @@ macro_rules! tuple_finalize_trace { } } -macro_rules! type_arg_tuple_based_finalize_trace_impls { +macro_rules! type_arg_trace_impls { ($(($($args:ident),*);)*) => { $( - fn_finalize_trace_group!($($args),*); - tuple_finalize_trace!($($args),*); + fn_trace_group!($($args),*); + tuple_trace!($($args),*); )* } } -type_arg_tuple_based_finalize_trace_impls![ +type_arg_trace_impls![ (); (A); (A, B); @@ -259,7 +250,6 @@ type_arg_tuple_based_finalize_trace_impls![ (A, B, C, D, E, F, G, H, I, J, K, L); ]; -impl Finalize for Box {} // SAFETY: The inner value of the `Box` is correctly marked. unsafe impl Trace for Box { #[inline] @@ -277,7 +267,6 @@ unsafe impl Trace for Box { } } -impl Finalize for Box<[T]> {} // SAFETY: All the inner elements of the `Box` array are correctly marked. unsafe impl Trace for Box<[T]> { custom_trace!(this, mark, { @@ -287,7 +276,6 @@ unsafe impl Trace for Box<[T]> { }); } -impl Finalize for Vec {} // SAFETY: All the inner elements of the `Vec` are correctly marked. unsafe impl Trace for Vec { custom_trace!(this, mark, { @@ -297,9 +285,6 @@ unsafe impl Trace for Vec { }); } -#[cfg(feature = "thin-vec")] -impl Finalize for thin_vec::ThinVec {} - #[cfg(feature = "thin-vec")] // SAFETY: All the inner elements of the `ThinVec` are correctly marked. unsafe impl Trace for thin_vec::ThinVec { @@ -310,7 +295,6 @@ unsafe impl Trace for thin_vec::ThinVec { }); } -impl Finalize for Option {} // SAFETY: The inner value of the `Option` is correctly marked. unsafe impl Trace for Option { custom_trace!(this, mark, { @@ -320,7 +304,6 @@ unsafe impl Trace for Option { }); } -impl Finalize for Result {} // SAFETY: Both inner values of the `Result` are correctly marked. unsafe impl Trace for Result { custom_trace!(this, mark, { @@ -331,7 +314,6 @@ unsafe impl Trace for Result { }); } -impl Finalize for BinaryHeap {} // SAFETY: All the elements of the `BinaryHeap` are correctly marked. unsafe impl Trace for BinaryHeap { custom_trace!(this, mark, { @@ -341,7 +323,6 @@ unsafe impl Trace for BinaryHeap { }); } -impl Finalize for BTreeMap {} // SAFETY: All the elements of the `BTreeMap` are correctly marked. unsafe impl Trace for BTreeMap { custom_trace!(this, mark, { @@ -352,7 +333,6 @@ unsafe impl Trace for BTreeMap { }); } -impl Finalize for BTreeSet {} // SAFETY: All the elements of the `BTreeSet` are correctly marked. unsafe impl Trace for BTreeSet { custom_trace!(this, mark, { @@ -362,10 +342,6 @@ unsafe impl Trace for BTreeSet { }); } -impl Finalize - for hashbrown::hash_map::HashMap -{ -} // SAFETY: All the elements of the `HashMap` are correctly marked. unsafe impl Trace for hashbrown::hash_map::HashMap @@ -378,8 +354,6 @@ unsafe impl Trace }); } -#[cfg(feature = "std")] -impl Finalize for HashMap {} #[cfg(feature = "std")] // SAFETY: All the elements of the `HashMap` are correctly marked. unsafe impl Trace for HashMap { @@ -391,8 +365,6 @@ unsafe impl Trace for HashMap Finalize for HashSet {} #[cfg(feature = "std")] // SAFETY: All the elements of the `HashSet` are correctly marked. unsafe impl Trace for HashSet { @@ -403,7 +375,6 @@ unsafe impl Trace for HashSet { }); } -impl Finalize for LinkedList {} // SAFETY: All the elements of the `LinkedList` are correctly marked. unsafe impl Trace for LinkedList { custom_trace!(this, mark, { @@ -414,13 +385,11 @@ unsafe impl Trace for LinkedList { }); } -impl Finalize for PhantomData {} // SAFETY: A `PhantomData` doesn't have inner data that needs to be marked. unsafe impl Trace for PhantomData { empty_trace!(); } -impl Finalize for VecDeque {} // SAFETY: All the elements of the `VecDeque` are correctly marked. unsafe impl Trace for VecDeque { custom_trace!(this, mark, { @@ -430,7 +399,6 @@ unsafe impl Trace for VecDeque { }); } -impl Finalize for Cow<'static, T> {} // SAFETY: 'static references don't need to be traced, since they live indefinitely, and the owned // variant is correctly marked. unsafe impl Trace for Cow<'static, T> @@ -444,7 +412,6 @@ where }); } -impl Finalize for Cell> {} // SAFETY: Taking and setting is done in a single action, and recursive traces should find a `None` // value instead of the original `T`, making this safe. unsafe impl Trace for Cell> { @@ -456,7 +423,6 @@ unsafe impl Trace for Cell> { }); } -impl Finalize for OnceCell {} // SAFETY: We only trace the inner cell if the cell has a value. unsafe impl Trace for OnceCell { custom_trace!(this, mark, { diff --git a/oscars/src/collectors/mark_sweep_arena2/mod.rs b/oscars/src/collectors/mark_sweep_arena2/mod.rs index 8fc1437..f1deb89 100644 --- a/oscars/src/collectors/mark_sweep_arena2/mod.rs +++ b/oscars/src/collectors/mark_sweep_arena2/mod.rs @@ -27,6 +27,41 @@ pub use pointers::ErasedWeakMap; pub use pointers::{Gc, WeakGc, WeakMap}; pub use trace::{Finalize, Trace, TraceColor}; +pub trait Collector { + // trigger a full collection cycle + fn collect(&self); + + // returns the current trace color for newly allocated objects + fn gc_color(&self) -> TraceColor; + + // Allocates a standard GC node for `value`, wrapping it in a `GcBox`. + // + // The returned pointer is tied to the collector's lifetime. + fn alloc_gc_node<'gc, T: Trace + 'static>( + &'gc self, + value: T, + ) -> Result< + crate::alloc::arena2::ArenaPointer<'gc, internals::GcBox>, + crate::alloc::arena2::ArenaAllocError, + >; + + // Allocates an ephemeron node pointing to an existing GC key and a new value. + // + // The returned pointer is tied to the collector's lifetime. + fn alloc_ephemeron_node<'gc, K: Trace + 'static, V: Trace + 'static>( + &'gc self, + key: &Gc, + value: V, + ) -> Result< + crate::alloc::arena2::ArenaPointer<'gc, internals::Ephemeron>, + crate::alloc::arena2::ArenaAllocError, + >; + + // Register a weak map with the GC so it can prune dead entries. + #[doc(hidden)] + fn track_weak_map(&self, map: core::ptr::NonNull); +} + type GcErasedPointer = NonNull>>; pub(crate) type ErasedEphemeron = NonNull>>; @@ -365,12 +400,20 @@ impl MarkSweepGarbageCollector { } } -impl MarkSweepGarbageCollector { +impl Collector for MarkSweepGarbageCollector { + fn collect(&self) { + MarkSweepGarbageCollector::collect(self); + } + + fn gc_color(&self) -> TraceColor { + self.trace_color.get() + } + // Allocates a standard GC node for `value`, wrapping it in a `GcBox` // // the returned pointer is only valid while the collector (`&self`) is alive // the lifetime ties the pointer to the collector - fn alloc_gc_node<'gc, T: crate::collectors::mark_sweep_arena2::trace::Trace + 'static>( + fn alloc_gc_node<'gc, T: Trace + 'static>( &'gc self, value: T, ) -> Result>, crate::alloc::arena2::ArenaAllocError> { @@ -381,13 +424,11 @@ impl MarkSweepGarbageCollector { let gc_box = GcBox::new_in(value, self.trace_color.get()); - // try_alloc creates a new arena page on OOM — no pre-creation needed. let mut alloc = self.allocator.borrow_mut(); let arena_ptr = alloc.try_alloc(gc_box)?; let needs_collect = !alloc.is_below_threshold(); drop(alloc); - // flag for a deferred collection if the heap crossed its threshold if needs_collect { self.collect_needed.set(true); } @@ -406,13 +447,9 @@ impl MarkSweepGarbageCollector { // // the returned pointer is only valid while the collector (`&self`) is alive // the lifetime ties the pointer to the collector - fn alloc_ephemeron_node< - 'gc, - K: crate::collectors::mark_sweep_arena2::trace::Trace + 'static, - V: crate::collectors::mark_sweep_arena2::trace::Trace + 'static, - >( + fn alloc_ephemeron_node<'gc, K: Trace + 'static, V: Trace + 'static>( &'gc self, - key: &crate::collectors::mark_sweep_arena2::pointers::Gc, + key: &Gc, value: V, ) -> Result>, crate::alloc::arena2::ArenaAllocError> { if self.collect_needed.get() && !self.is_collecting.get() { @@ -422,7 +459,6 @@ impl MarkSweepGarbageCollector { let ephemeron = Ephemeron::new(key, value, self.trace_color.get()); - // try_alloc creates a new arena page on OOM let mut alloc = self.allocator.borrow_mut(); let inner_ptr = alloc.try_alloc(ephemeron)?; let needs_collect = !alloc.is_below_threshold(); @@ -445,12 +481,7 @@ impl MarkSweepGarbageCollector { Ok(inner_ptr) } - fn track_weak_map( - &self, - map: core::ptr::NonNull< - dyn crate::collectors::mark_sweep_arena2::pointers::weak_map::ErasedWeakMap, - >, - ) { + fn track_weak_map(&self, map: core::ptr::NonNull) { self.weak_maps.borrow_mut().push(map); } } diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs index cd88f28..36e3f2a 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs @@ -16,10 +16,9 @@ pub struct Gc { } impl Gc { - #[must_use] - pub fn new_in( + pub fn new_in( value: T, - collector: &crate::collectors::mark_sweep_arena2::MarkSweepGarbageCollector, + collector: &C, ) -> Self { let inner_ptr = collector .alloc_gc_node(value) diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs index 0438098..4b2de8f 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs @@ -12,9 +12,9 @@ pub struct WeakGc { } impl WeakGc { - pub fn new_in( + pub fn new_in( value: &super::Gc, - collector: &crate::collectors::mark_sweep_arena2::MarkSweepGarbageCollector, + collector: &C, ) -> Self where T: Sized, diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/weak_map.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/weak_map.rs index 579f186..ccf30d7 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/weak_map.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/weak_map.rs @@ -117,9 +117,7 @@ pub struct WeakMap { impl WeakMap { // create a new map and give the collector ownership of its memory - pub fn new( - collector: &crate::collectors::mark_sweep_arena2::MarkSweepGarbageCollector, - ) -> Self { + pub fn new(collector: &C) -> Self { let boxed: rust_alloc::boxed::Box> = rust_alloc::boxed::Box::new(WeakMapInner::::new()); @@ -133,11 +131,11 @@ impl WeakMap { } // insert a value for `key`, replacing and invalidating any old ephemeron - pub fn insert( + pub fn insert( &mut self, key: &Gc, value: V, - collector: &crate::collectors::mark_sweep_arena2::MarkSweepGarbageCollector, + collector: &C, ) { let key_addr = key.inner_ptr.as_non_null().as_ptr() as usize; diff --git a/oscars/src/collectors/mod.rs b/oscars/src/collectors/mod.rs index c8bfd75..0e53749 100644 --- a/oscars/src/collectors/mod.rs +++ b/oscars/src/collectors/mod.rs @@ -1,4 +1,5 @@ //! This module contains various collector implementations. +pub mod common; pub mod mark_sweep; pub mod mark_sweep_arena2; From 3a842f475a96bea6d0d32f4ba937cbc6fe4d7149 Mon Sep 17 00:00:00 2001 From: shruti2522 Date: Mon, 20 Apr 2026 13:36:26 +0000 Subject: [PATCH 2/2] fix fmt --- oscars/src/collectors/mark_sweep/trace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oscars/src/collectors/mark_sweep/trace.rs b/oscars/src/collectors/mark_sweep/trace.rs index 68413eb..2a3a5ff 100644 --- a/oscars/src/collectors/mark_sweep/trace.rs +++ b/oscars/src/collectors/mark_sweep/trace.rs @@ -126,7 +126,7 @@ simple_empty_trace![ (), bool, isize, - usize, + usize, i8, u8, i16, @@ -164,7 +164,7 @@ simple_empty_trace![atomic::AtomicBool, atomic::AtomicI8, atomic::AtomicU8]; #[cfg(target_has_atomic = "16")] simple_empty_trace![atomic::AtomicI16, atomic::AtomicU16]; -#[cfg(target_has_atomic = "32")] +#[cfg(target_has_atomic = "32")] simple_empty_trace![atomic::AtomicI32, atomic::AtomicU32]; #[cfg(target_has_atomic = "64")]