Skip to content

Commit 5742b90

Browse files
authored
Add a minimal CI + cleanup (#17)
* Add a minimal CI + cleanup * Fix lints * cargo fmt --all
1 parent 47cb475 commit 5742b90

File tree

10 files changed

+107
-53
lines changed

10 files changed

+107
-53
lines changed

.github/workflows/rust.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Rust - Continuous integration
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
branches: ["main"]
8+
9+
jobs:
10+
lint:
11+
name: Lint
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Set environment
15+
# Setting `RUSTFLAGS` overrides any flags set on .cargo/config.toml, so we need to
16+
# set the target flags instead which are cumulative.
17+
# Track https://github.com/rust-lang/cargo/issues/5376
18+
run: |
19+
target=$(rustc -vV | awk '/^host/ { print $2 }' | tr [:lower:] [:upper:] | tr '-' '_')
20+
echo "CARGO_TARGET_${target}_RUSTFLAGS=$FLAGS" >> $GITHUB_ENV
21+
22+
- uses: actions/checkout@v6
23+
- uses: dtolnay/rust-toolchain@stable
24+
with:
25+
components: clippy, rustfmt
26+
- uses: Swatinem/rust-cache@v2
27+
with:
28+
key: lint
29+
- name: Install cargo-workspaces
30+
run: cargo install cargo-workspaces
31+
- name: Check rustfmt
32+
run: cargo fmt --all -- --check
33+
- name: Check clippy
34+
run: cargo ws exec cargo clippy --all-features --all-targets
35+
- name: Check clippy (No features)
36+
run: cargo ws exec cargo clippy --no-default-features --all-targets
37+
38+
docs:
39+
name: Documentation
40+
runs-on: ubuntu-latest
41+
env:
42+
RUSTDOCFLAGS: -D warnings
43+
steps:
44+
- uses: actions/checkout@v6
45+
- uses: dtolnay/rust-toolchain@stable
46+
- uses: Swatinem/rust-cache@v2
47+
with:
48+
key: docs
49+
- name: Generate documentation
50+
run: cargo doc -v --document-private-items --all-features

oscars/src/alloc/arena2/alloc.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ impl ErasedHeapItem {
7272
self.buf.cast::<T>()
7373
}
7474

75-
pub fn as_ref<T>(&self) -> &T {
76-
unsafe { self.get().as_ref() }
77-
}
78-
7975
pub fn mark_dropped(&mut self) {
8076
if !self.next.is_tagged() {
8177
self.next.tag()
@@ -87,6 +83,13 @@ impl ErasedHeapItem {
8783
}
8884
}
8985

86+
impl<T> core::convert::AsRef<T> for ErasedHeapItem {
87+
fn as_ref(&self) -> &T {
88+
// SAFETY: TODO
89+
unsafe { self.get().as_ref() }
90+
}
91+
}
92+
9093
const MASK: usize = 1usize << (usize::BITS as usize - 1usize);
9194

9295
#[derive(Debug, Clone, Copy)]

oscars/src/alloc/arena2/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rust_alloc::collections::LinkedList;
66
mod alloc;
77

88
use alloc::Arena;
9-
pub use alloc::{ArenaAllocationData, ArenaHeapItem, ArenaPointer, ErasedArenaPointer, ErasedHeapItem};
9+
pub use alloc::{
10+
ArenaAllocationData, ArenaHeapItem, ArenaPointer, ErasedArenaPointer, ErasedHeapItem,
11+
};
1012

1113
#[cfg(test)]
1214
mod tests;

oscars/src/collectors/mark_sweep/internals/ephemeron.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ impl<K: Trace, V: Trace> Ephemeron<K, V> {
2424
// Creates a new [`Ephemeron`] with given key and value
2525
//
2626
// The [`WeakGcBox`] for the key is created internally from the provided [`Gc`] pointer
27-
pub fn new_in(key: &Gc<K>, value: V, collector: &mut MarkSweepGarbageCollector) -> Self
28-
{
27+
pub fn new_in(key: &Gc<K>, value: V, collector: &mut MarkSweepGarbageCollector) -> Self {
2928
let weak_key = WeakGcBox::new(key.inner_ptr);
3029
let value = GcBox::new(value, &collector.state);
3130
let vtable = vtable_of::<K, V>();
32-
Self { key: weak_key, value, vtable }
31+
Self {
32+
key: weak_key,
33+
value,
34+
vtable,
35+
}
3336
}
3437

3538
pub fn key(&self) -> &K {
@@ -61,7 +64,7 @@ impl<K: Trace, V: Trace> Ephemeron<K, V> {
6164
pub(crate) fn is_reachable_fn(&self) -> EphemeronIsReachableFn {
6265
self.vtable.is_reachable_fn
6366
}
64-
67+
6568
pub(crate) fn finalize_fn(&self) -> EphemeronFinalizeFn {
6669
self.vtable.finalize_fn
6770
}

oscars/src/collectors/mark_sweep/internals/gc_box.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ unsafe impl Trace for NonTraceable {
2626

2727
// NOTE: This may not be the best idea, but let's find out.
2828
//
29-
use crate::alloc::arena2::{ErasedArenaPointer, ArenaHeapItem};
30-
use core::ptr::NonNull;
29+
use crate::alloc::arena2::{ArenaHeapItem, ErasedArenaPointer};
3130
use core::marker::PhantomData;
31+
use core::ptr::NonNull;
3232

3333
#[repr(transparent)]
3434
pub struct WeakGcBox<T: Trace + ?Sized + 'static> {
@@ -38,7 +38,10 @@ pub struct WeakGcBox<T: Trace + ?Sized + 'static> {
3838

3939
impl<T: Trace + Finalize + ?Sized> WeakGcBox<T> {
4040
pub fn new(inner_ptr: ErasedArenaPointer<'static>) -> Self {
41-
Self { inner_ptr, marker: PhantomData }
41+
Self {
42+
inner_ptr,
43+
marker: PhantomData,
44+
}
4245
}
4346

4447
pub(crate) fn erased_inner_ptr(&self) -> NonNull<GcBox<NonTraceable>> {
@@ -65,10 +68,6 @@ impl<T: Trace + Finalize + ?Sized> WeakGcBox<T> {
6568
self.inner_ref().is_reachable(color)
6669
}
6770

68-
pub(crate) fn is_rooted(&self) -> bool {
69-
self.inner_ref().is_rooted()
70-
}
71-
7271
pub(crate) fn mark(&self, color: HeaderColor) {
7372
self.inner_ref().header.mark(color);
7473
}
@@ -80,7 +79,7 @@ impl<T: Trace + Finalize + ?Sized> WeakGcBox<T> {
8079

8180
impl<T: Trace> WeakGcBox<T> {
8281
pub(crate) fn inner_ptr(&self) -> crate::alloc::arena2::ArenaPointer<'static, GcBox<T>> {
83-
// SAFETY: This pointer started out as a `GcBox<T>`, so it's safe to cast
82+
// SAFETY: This pointer started out as a `GcBox<T>`, so it's safe to cast
8483
// it back, the `PhantomData` guarantees that the type `T` is still correct
8584
unsafe { self.inner_ptr.to_typed_arena_pointer::<GcBox<T>>() }
8685
}
@@ -128,10 +127,7 @@ impl<T: Trace> GcBox<T> {
128127

129128
// TODO (nekevss): What is the best function signature here?
130129
#[inline]
131-
pub(crate) fn new_typed(
132-
value: T,
133-
collection_state: &CollectionState,
134-
) -> Self {
130+
pub(crate) fn new_typed(value: T, collection_state: &CollectionState) -> Self {
135131
//check for color sync issue
136132
let header = match collection_state.color {
137133
TraceColor::White => GcHeader::new_typed::<true>(),

oscars/src/collectors/mark_sweep/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ pub(crate) mod trace;
1919

2020
pub mod cell;
2121

22-
#[cfg(test)]
22+
#[cfg(all(test, feature = "mark_sweep"))]
2323
mod tests;
2424

2525
pub(crate) mod internals;
2626

27-
pub use trace::{Trace, Finalize, TraceColor};
27+
pub use trace::{Finalize, Trace, TraceColor};
2828

2929
pub use pointers::{Gc, WeakGc, WeakMap};
3030

@@ -196,7 +196,7 @@ impl MarkSweepGarbageCollector {
196196
self.run_sweep_phase();
197197
// We've run a collection, so we switch the color.
198198
self.state.color = self.state.color.flip();
199-
// NOTE: It would actually be interesting to reuse the arenas that are dead rather
199+
// NOTE: It would actually be interesting to reuse the arenas that are dead rather
200200
// than drop the page and reallocate when a new page is needed ... TBD
201201

202202
// prune dead entries from each collector owned weak map before freeing
@@ -259,8 +259,7 @@ impl MarkSweepGarbageCollector {
259259
let color = self.state.color;
260260

261261
// check if the key is reachable via the vtable
262-
let is_reachable =
263-
unsafe { ephemeron.is_reachable_fn()(*node, color) };
262+
let is_reachable = unsafe { ephemeron.is_reachable_fn()(*node, color) };
264263

265264
if !is_reachable {
266265
unsafe { ephemeron.finalize_fn()(*node) };

oscars/src/collectors/mark_sweep/pointers/weak.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ pub struct WeakGc<T: Trace + 'static> {
99
}
1010

1111
impl<T: Trace> WeakGc<T> {
12-
pub fn new_in(value: &super::Gc<T>, collector: &mut MarkSweepGarbageCollector) -> Self
13-
{
12+
pub fn new_in(value: &super::Gc<T>, collector: &mut MarkSweepGarbageCollector) -> Self {
1413
let ephemeron = Ephemeron::new_in(value, (), collector);
1514
let inner_ptr = collector.alloc_epemeron_with_collection(ephemeron);
1615
Self { inner_ptr }

oscars/src/collectors/mark_sweep/pointers/weak_map.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use hashbrown::HashMap;
33
use crate::{
44
alloc::arena2::{ArenaPointer, ErasedHeapItem},
55
collectors::mark_sweep::{
6-
Finalize, MarkSweepGarbageCollector, TraceColor,
7-
internals::Ephemeron,
8-
trace::Trace,
6+
Finalize, MarkSweepGarbageCollector, TraceColor, internals::Ephemeron, trace::Trace,
97
},
108
};
119

@@ -25,15 +23,12 @@ struct WeakMapInner<K: Trace + 'static, V: Trace + 'static> {
2523

2624
impl<K: Trace, V: Trace> WeakMapInner<K, V> {
2725
fn new() -> Self {
28-
Self { entries: HashMap::new() }
26+
Self {
27+
entries: HashMap::new(),
28+
}
2929
}
3030

31-
fn insert(
32-
&mut self,
33-
key: &Gc<K>,
34-
value: V,
35-
collector: &mut MarkSweepGarbageCollector,
36-
) {
31+
fn insert(&mut self, key: &Gc<K>, value: V, collector: &mut MarkSweepGarbageCollector) {
3732
let key_addr = key.inner_ptr.as_non_null().as_ptr() as usize;
3833

3934
// Drop the old entry before allocating a new one to prevent the old
@@ -77,9 +72,7 @@ impl<K: Trace, V: Trace> ErasedWeakMap for WeakMapInner<K, V> {
7772
self.entries.retain(|_, ephemeron_ptr| {
7873
// SAFETY: Memory is valid until next collector step
7974
// We only read the dropped flag
80-
let heap_item = unsafe {
81-
ephemeron_ptr.as_ptr().cast::<ErasedHeapItem>().as_ref()
82-
};
75+
let heap_item = unsafe { ephemeron_ptr.as_ptr().cast::<ErasedHeapItem>().as_ref() };
8376
!heap_item.is_dropped()
8477
});
8578
}
@@ -90,7 +83,7 @@ impl<K: Trace, V: Trace> ErasedWeakMap for WeakMapInner<K, V> {
9083
// the collector owns the actual data, this is just a thin pointer
9184
// wrapper that stays valid as long as the collector does
9285
pub struct WeakMap<K: Trace + 'static, V: Trace + 'static> {
93-
// raw pointer to collector owned memory
86+
// raw pointer to collector owned memory
9487
inner: *mut WeakMapInner<K, V>,
9588
}
9689

@@ -102,7 +95,8 @@ impl<K: Trace, V: Trace> WeakMap<K, V> {
10295
// get a raw pointer that stays valid even after the box is moved
10396
let inner: *mut WeakMapInner<K, V> = rust_alloc::boxed::Box::into_raw(boxed);
10497
// SAFETY: we just got this from into_raw, and we are giving ownership to the collector
105-
let erased: rust_alloc::boxed::Box<dyn ErasedWeakMap> = unsafe { rust_alloc::boxed::Box::from_raw(inner) };
98+
let erased: rust_alloc::boxed::Box<dyn ErasedWeakMap> =
99+
unsafe { rust_alloc::boxed::Box::from_raw(inner) };
106100
collector.weak_maps.push(erased);
107101
Self { inner }
108102
}

oscars/src/collectors/mark_sweep/tests.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use crate::{Finalize, Trace};
2-
31
use crate::collectors::mark_sweep::MarkSweepGarbageCollector;
2+
use crate::{Finalize, Trace};
43

54
use super::Gc;
65
use super::WeakMap;
@@ -60,7 +59,6 @@ fn gc_recursion() {
6059
.with_arena_size(4096)
6160
.with_heap_threshold(8_192);
6261

63-
6462
#[derive(Debug, Finalize, Trace)]
6563
struct S {
6664
i: usize,
@@ -71,10 +69,13 @@ fn gc_recursion() {
7169

7270
let mut root = Gc::new_in(S { i: 0, next: None }, collector);
7371
for i in 1..COUNT {
74-
root = Gc::new_in(S {
72+
root = Gc::new_in(
73+
S {
7574
i,
7675
next: Some(root),
77-
}, collector);
76+
},
77+
collector,
78+
);
7879
}
7980

8081
drop(root);
@@ -96,7 +97,7 @@ fn drop_gc() {
9697
drop(gc);
9798
collector.collect();
9899

99-
// TODO: don't drop an active arena
100+
// TODO: don't drop an active arena
100101
assert_eq!(collector.allocator.arenas_len(), 0, "arena not freed");
101102
}
102103

@@ -237,7 +238,11 @@ fn update_wm() {
237238
drop(key);
238239
collector.collect();
239240

240-
assert_eq!(collector.allocator.arenas_len(), 0, "arena leaked after update");
241+
assert_eq!(
242+
collector.allocator.arenas_len(),
243+
0,
244+
"arena leaked after update"
245+
);
241246
}
242247

243248
#[test]
@@ -330,7 +335,11 @@ fn remove_then_collect() {
330335
drop(key);
331336
collector.collect();
332337

333-
assert_eq!(collector.allocator.arenas_len(), 0, "ephemeron leaked after remove");
338+
assert_eq!(
339+
collector.allocator.arenas_len(),
340+
0,
341+
"ephemeron leaked after remove"
342+
);
334343
}
335344

336345
#[test]

oscars/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ extern crate std;
1515
#[cfg(feature = "mark_sweep")]
1616
pub use crate::collectors::mark_sweep::*;
1717
#[cfg(feature = "mark_sweep")]
18-
pub use oscars_derive::{Trace, Finalize};
19-
18+
pub use oscars_derive::{Finalize, Trace};
2019

2120
pub mod alloc;
2221
pub mod collectors;

0 commit comments

Comments
 (0)