Skip to content

Commit 5b78ad5

Browse files
committed
Add manual Traverse impl for PySlice with clear() and fix comment
1 parent c0b33a6 commit 5b78ad5

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

crates/vm/src/builtins/slice.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,34 @@ use crate::{
1717
use malachite_bigint::{BigInt, ToBigInt};
1818
use num_traits::{One, Signed, Zero};
1919

20-
#[pyclass(module = false, name = "slice", unhashable = true, traverse)]
20+
#[pyclass(module = false, name = "slice", unhashable = true, traverse = "manual")]
2121
#[derive(Debug)]
2222
pub struct PySlice {
2323
pub start: Option<PyObjectRef>,
2424
pub stop: PyObjectRef,
2525
pub step: Option<PyObjectRef>,
2626
}
2727

28+
// SAFETY: Traverse properly visits all owned PyObjectRefs
29+
unsafe impl crate::object::Traverse for PySlice {
30+
fn traverse(&self, traverse_fn: &mut crate::object::TraverseFn<'_>) {
31+
self.start.traverse(traverse_fn);
32+
self.stop.traverse(traverse_fn);
33+
self.step.traverse(traverse_fn);
34+
}
35+
36+
fn clear(&mut self, out: &mut Vec<PyObjectRef>) {
37+
if let Some(start) = self.start.take() {
38+
out.push(start);
39+
}
40+
// stop is not Option, so it will be freed when payload is dropped
41+
// (via drop_in_place on freelist pop, or Box::from_raw on dealloc)
42+
if let Some(step) = self.step.take() {
43+
out.push(step);
44+
}
45+
}
46+
}
47+
2848
thread_local! {
2949
static SLICE_FREELIST: Cell<crate::object::FreeList<PySlice>> = const { Cell::new(crate::object::FreeList::new()) };
3050
}

crates/vm/src/object/core.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1791,7 +1791,8 @@ impl<T: PyPayload + crate::object::MaybeTraverse + core::fmt::Debug> PyRef<T> {
17911791
(*inner).gc_bits.store(0, Ordering::Relaxed);
17921792
core::ptr::drop_in_place(&mut (*inner).payload);
17931793
core::ptr::write(&mut (*inner).payload, payload);
1794-
// typ, vtable, dict(None), weak_list, slots are preserved
1794+
// typ, vtable, slots are preserved; dict is None, weak_list was
1795+
// cleared by drop_slow_inner before freelist push
17951796
}
17961797
// Drop the caller's typ since the cached object already holds one
17971798
drop(typ);

0 commit comments

Comments
 (0)