1use super::{
2 super::{cons::Cons, object::Object},
3 GcMoveable, GcState, TracePtr,
4};
5use super::{Block, Context, RootSet, Trace};
6use crate::core::object::{Gc, GcPtr, IntoObject, ObjectType, OptionalFlag, Untag, WithLifetime};
7use rune_core::hashmap::IndexMap;
8use std::hash::{Hash, Hasher};
9use std::slice::SliceIndex;
10use std::{
11 cell::UnsafeCell,
12 fmt,
13 ops::{Deref, DerefMut, Index, IndexMut, RangeBounds},
14};
15use std::{
16 fmt::{Debug, Display},
17 marker::PhantomPinned,
18};
19
20#[diagnostic::on_unimplemented(
34 message = "`{Self}` does not implement `Trace`",
35 label = "cannot be rooted",
36 note = "Use #[derive(Trace)] to make `{Self}` Rootable",
37 note = "If this is a foreign type, implement `Trace` and `IntoRoot` manually"
38)]
39pub(crate) trait IntoRoot<T> {
40 unsafe fn into_root(self) -> T;
41}
42
43impl<'new, T, U> IntoRoot<Slot<U>> for T
44where
45 T: WithLifetime<'new, Out = U> + GcPtr,
46{
47 unsafe fn into_root(self) -> Slot<U> {
48 Slot::new(self.with_lifetime())
49 }
50}
51
52impl<T, U> IntoRoot<Option<U>> for Option<T>
53where
54 T: IntoRoot<U>,
55{
56 unsafe fn into_root(self) -> Option<U> {
57 self.map(|x| x.into_root())
58 }
59}
60
61impl<T, U> IntoRoot<Vec<U>> for Vec<T>
62where
63 T: IntoRoot<U>,
64{
65 unsafe fn into_root(self) -> Vec<U> {
66 let mut new = Vec::with_capacity(self.len());
67 for x in self {
68 new.push(x.into_root());
69 }
70 new
71 }
72}
73
74impl<T, U, Tx, Ux> IntoRoot<(Tx, Ux)> for (T, U)
75where
76 T: IntoRoot<Tx>,
77 U: IntoRoot<Ux>,
78{
79 unsafe fn into_root(self) -> (Tx, Ux) {
80 (self.0.into_root(), self.1.into_root())
81 }
82}
83
84impl<'a, T, U> IntoRoot<Slot<U>> for &Rt<Slot<T>>
85where
86 T: WithLifetime<'a, Out = U> + Copy,
87{
88 unsafe fn into_root(self) -> Slot<U> {
89 Slot::new(self.inner().get().with_lifetime())
90 }
91}
92
93impl<'a> IntoRoot<Slot<Object<'a>>> for bool {
94 unsafe fn into_root(self) -> Slot<Object<'a>> {
95 Slot::new(self.into())
96 }
97}
98
99impl<'a> IntoRoot<Slot<Object<'a>>> for i64 {
100 unsafe fn into_root(self) -> Slot<Object<'a>> {
101 Slot::new(self.into())
102 }
103}
104
105#[doc(hidden)]
108pub(crate) struct __StackRoot<'rt, T> {
109 data: &'rt mut Rt<T>,
110 root_set: &'rt RootSet,
111}
112
113impl<T> AsMut<Rt<T>> for __StackRoot<'_, T> {
114 fn as_mut(&mut self) -> &mut Rt<T> {
115 self.data
116 }
117}
118
119impl<T: Debug> Debug for __StackRoot<'_, T> {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 Debug::fmt(self.data, f)
122 }
123}
124
125impl<T: Display> Display for __StackRoot<'_, T> {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 Display::fmt(self.data, f)
128 }
129}
130
131impl<'rt, T: Trace> __StackRoot<'rt, T> {
137 pub(crate) unsafe fn new(data: &'rt mut T, root_set: &'rt RootSet) -> __StackRoot<'rt, T> {
138 let dyn_ptr = data as &mut dyn Trace as *mut dyn Trace;
139 let dyn_ptr = std::mem::transmute::<*mut dyn Trace, *mut dyn Trace>(dyn_ptr);
144 let data = &mut *(dyn_ptr.cast::<Rt<T>>());
145 let root = Self { data, root_set };
146 root_set.roots.borrow_mut().push(dyn_ptr);
147 root
148 }
149}
150
151impl<T> Drop for __StackRoot<'_, T> {
152 fn drop(&mut self) {
153 self.root_set.roots.borrow_mut().pop();
154 }
155}
156
157pub trait RootedDeref {
169 type Target;
170 fn rooted_deref(rooted: &Rt<Self>) -> &Self::Target;
171 fn rooted_derefmut(rooted: &mut Rt<Self>) -> &mut Self::Target;
172}
173
174impl<T: RootedDeref> Deref for Rt<T> {
175 type Target = <T as RootedDeref>::Target;
176 fn deref(&self) -> &Self::Target {
177 RootedDeref::rooted_deref(self)
178 }
179}
180
181impl<T: RootedDeref> DerefMut for Rt<T> {
182 fn deref_mut(&mut self) -> &mut Self::Target {
183 RootedDeref::rooted_derefmut(self)
184 }
185}
186
187#[repr(transparent)]
193#[derive(PartialEq, Eq)]
194pub struct Rt<T: ?Sized> {
195 _aliasable: PhantomPinned,
196 inner: T,
197}
198
199pub type Rto<T> = Rt<Slot<T>>;
204
205#[repr(transparent)]
209#[derive(Default)]
210pub struct Slot<T: ?Sized> {
211 inner: UnsafeCell<T>,
212}
213
214impl<T: Clone> Clone for Slot<T> {
215 fn clone(&self) -> Self {
216 Self::new(self.get().clone())
217 }
218}
219
220impl<'new, T: WithLifetime<'new> + Copy> WithLifetime<'new> for Slot<T> {
221 type Out = Slot<<T as WithLifetime<'new>>::Out>;
222
223 unsafe fn with_lifetime(self) -> Self::Out {
224 Slot::new(self.get().with_lifetime())
225 }
226}
227
228impl<T: Hash> Hash for Slot<T> {
229 fn hash<H: Hasher>(&self, state: &mut H) {
230 self.get().hash(state);
231 }
232}
233
234impl<T: PartialEq> PartialEq for Slot<T> {
235 fn eq(&self, other: &Self) -> bool {
236 self.get() == other.get()
237 }
238}
239
240impl<'a, T, U> PartialEq<U> for Slot<T>
246where
247 U: WithLifetime<'a> + Copy,
248 T: PartialEq<<U as WithLifetime<'a>>::Out>,
249{
250 fn eq(&self, other: &U) -> bool {
251 *self.get() == unsafe { other.with_lifetime() }
252 }
253}
254
255impl<T: Eq> Eq for Slot<T> {}
256
257impl<T> Slot<T> {
258 fn get(&self) -> &T {
259 unsafe { &*self.inner.get() }
260 }
261
262 unsafe fn set(&self, new: T) {
263 *self.inner.get() = new
264 }
265
266 pub(crate) fn new(val: T) -> Self {
267 Slot { inner: UnsafeCell::new(val) }
268 }
269}
270
271impl<T> Deref for Slot<T> {
272 type Target = T;
273
274 fn deref(&self) -> &Self::Target {
275 self.get()
276 }
277}
278
279impl<T> Trace for Slot<T>
284where
285 T: TracePtr + GcMoveable<Value = T>,
286{
287 fn trace(&self, state: &mut GcState) {
288 if let Some((new, moved)) = self.get().move_value(&state.to_space) {
289 unsafe { self.set(new) };
290 if moved {
291 self.get().trace_ptr(state);
292 state.trace_stack();
295 }
296 }
297 }
298}
299
300impl<T: Debug> Debug for Rt<T> {
301 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302 Debug::fmt(&self.inner(), f)
303 }
304}
305
306impl<T: Display> Display for Rt<T> {
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 Display::fmt(&self.inner(), f)
309 }
310}
311
312impl<T: Debug> Debug for Slot<T> {
313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314 Debug::fmt(self.get(), f)
315 }
316}
317
318impl<T: Display> Display for Slot<T> {
319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 Display::fmt(self.get(), f)
321 }
322}
323
324impl<T, U> PartialEq<U> for Rt<Slot<T>>
325where
326 Slot<T>: PartialEq<U>,
327{
328 fn eq(&self, other: &U) -> bool {
329 self.inner() == other
330 }
331}
332
333impl<T> Hash for Rt<T>
334where
335 T: Hash,
336{
337 fn hash<H: Hasher>(&self, state: &mut H) {
338 self.inner().hash(state);
339 }
340}
341
342impl<T> Rt<T> {
343 fn inner(&self) -> &T {
344 &self.inner
345 }
346
347 fn inner_mut(&mut self) -> &mut T {
348 &mut self.inner
349 }
350
351 fn inner_ptr(&self) -> *const T {
352 &self.inner as *const T
353 }
354
355 fn inner_mut_ptr(&mut self) -> *mut T {
356 &mut self.inner as *mut T
357 }
358
359 pub(crate) fn bind_ref<'a, 'ob>(&'a self, _: &'ob Context) -> &'a <T as WithLifetime<'ob>>::Out
360 where
361 T: WithLifetime<'ob>,
362 {
363 unsafe { &*self.inner_ptr().cast::<<T as WithLifetime<'ob>>::Out>() }
365 }
366
367 pub(crate) fn bind_mut<'a, 'ob>(
368 &'a mut self,
369 _: &'ob Context,
370 ) -> &'a mut <T as WithLifetime<'ob>>::Out
371 where
372 T: WithLifetime<'ob>,
373 {
374 unsafe { &mut *self.inner_mut_ptr().cast::<<T as WithLifetime<'ob>>::Out>() }
376 }
377
378 pub(crate) fn set<U: IntoRoot<T>>(&mut self, item: U) {
379 unsafe { *self.inner_mut() = item.into_root() }
382 }
383}
384
385impl<T> Rt<Slot<T>> {
386 pub(crate) fn bind<'ob>(&self, _: &'ob Context) -> <T as WithLifetime<'ob>>::Out
387 where
388 T: WithLifetime<'ob> + Copy,
389 {
390 unsafe { self.inner().get().with_lifetime() }
392 }
393
394 pub(crate) unsafe fn bind_unchecked<'ob>(&'ob self) -> <T as WithLifetime<'ob>>::Out
395 where
396 T: WithLifetime<'ob> + Copy,
397 {
398 self.inner().get().with_lifetime()
399 }
400
401 pub(crate) fn bind_slice<'brw, 'ob, U>(
402 slice: &'brw [Rt<Slot<Gc<T>>>],
403 _: &'ob Context,
404 ) -> &'brw [Gc<U>]
405 where
406 Gc<T>: WithLifetime<'ob, Out = Gc<U>>,
407 Gc<U>: 'ob,
408 {
409 unsafe { &*(slice as *const [Rt<Slot<Gc<T>>>] as *const [Gc<U>]) }
412 }
413}
414
415impl<T> Rt<Slot<Gc<T>>> {
416 pub(crate) fn untag<'ob, U>(&self, cx: &'ob Context) -> U
418 where
419 Gc<T>: WithLifetime<'ob, Out = Gc<U>> + Copy,
420 Gc<U>: Untag<U>,
421 {
422 cx.bind(*self.inner().get()).untag_erased()
423 }
424
425 pub(crate) fn try_as<U, E>(&self) -> Result<&Rt<Slot<Gc<U>>>, E>
427 where
428 Gc<T>: TryInto<Gc<U>, Error = E> + Copy,
429 {
430 let _: Gc<U> = (*self.inner().get()).try_into()?;
431 unsafe { Ok(&*((self as *const Self).cast::<Rt<Slot<Gc<U>>>>())) }
433 }
434}
435
436impl TryFrom<&Rt<Slot<Object<'_>>>> for usize {
437 type Error = anyhow::Error;
438
439 fn try_from(value: &Rt<Slot<Object>>) -> Result<Self, Self::Error> {
440 (*value.inner().get()).try_into()
441 }
442}
443
444impl<T> Rt<Slot<Gc<T>>> {
445 pub(crate) fn bind_as<'ob, U, E>(&self, _cx: &'ob Context) -> Result<U, E>
447 where
448 Gc<T>: WithLifetime<'ob> + Copy,
449 <Gc<T> as WithLifetime<'ob>>::Out: TryInto<U, Error = E> + Copy,
450 {
451 unsafe { self.inner().get().with_lifetime().try_into() }
452 }
453
454 pub(crate) fn cast<U>(&self) -> &Rt<Slot<Gc<U>>>
456 where
457 Gc<T>: Into<Gc<U>> + Copy,
458 {
459 unsafe { &*((self as *const Self).cast::<Rt<Slot<Gc<U>>>>()) }
461 }
462
463 pub(crate) fn as_cons(&self) -> &Rt<Slot<Gc<&Cons>>> {
466 match self.inner().as_obj().untag() {
467 crate::core::object::ObjectType::Cons(_) => unsafe {
468 &*(self as *const Self).cast::<Rt<Slot<Gc<&Cons>>>>()
469 },
470 x => panic!("attempt to convert type that was not cons: {x}"),
471 }
472 }
473}
474
475impl From<&Rt<Slot<Object<'_>>>> for OptionalFlag {
476 fn from(value: &Rt<Slot<Object<'_>>>) -> Self {
477 value.inner().is_nil().then_some(())
478 }
479}
480
481impl<'a> Rt<Slot<Object<'a>>> {
482 pub(crate) fn try_as_option<T, E>(&self) -> Result<Option<&Rt<Slot<Gc<T>>>>, E>
483 where
484 Object<'a>: TryInto<Gc<T>, Error = E>,
485 {
486 if self.inner().is_nil() {
487 Ok(None)
488 } else {
489 let _: Gc<T> = (*self.inner().get()).try_into()?;
490 unsafe { Ok(Some(&*((self as *const Self).cast::<Rt<Slot<Gc<T>>>>()))) }
491 }
492 }
493}
494
495impl IntoObject for &Rt<Slot<Object<'_>>> {
496 type Out<'ob> = ObjectType<'ob>;
497
498 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
499 unsafe { self.inner().get().with_lifetime() }
500 }
501}
502
503impl IntoObject for Slot<Object<'_>> {
504 type Out<'ob> = ObjectType<'ob>;
505
506 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
507 unsafe { self.get().with_lifetime() }
508 }
509}
510
511impl IntoObject for &mut Rt<Slot<Object<'_>>> {
512 type Out<'ob> = ObjectType<'ob>;
513
514 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
515 unsafe { self.inner().get().with_lifetime() }
516 }
517}
518
519impl Rt<Slot<&Cons>> {
520 pub(crate) fn car<'ob>(&self, cx: &'ob Context) -> Object<'ob> {
521 self.bind(cx).car()
522 }
523
524 pub(crate) fn cdr<'ob>(&self, cx: &'ob Context) -> Object<'ob> {
525 self.bind(cx).cdr()
526 }
527}
528
529impl<T, U> Deref for Rt<(T, U)> {
530 type Target = (Rt<T>, Rt<U>);
531
532 fn deref(&self) -> &Self::Target {
533 unsafe { &*(self as *const Self).cast::<(Rt<T>, Rt<U>)>() }
534 }
535}
536
537impl<T, U> DerefMut for Rt<(T, U)> {
538 fn deref_mut(&mut self) -> &mut Self::Target {
539 unsafe { &mut *(self as *mut Rt<(T, U)>).cast::<(Rt<T>, Rt<U>)>() }
540 }
541}
542
543impl<T> Deref for Rt<Option<T>> {
547 type Target = Option<Rt<T>>;
548 fn deref(&self) -> &Self::Target {
549 unsafe { &*self.inner_ptr().cast::<Self::Target>() }
550 }
551}
552
553impl<T, I, const N: usize> Index<I> for Rt<[T; N]>
554where
555 [Rt<T>]: Index<I>,
556{
557 type Output = <[Rt<T>] as Index<I>>::Output;
558
559 fn index(&self, index: I) -> &Self::Output {
560 let slice = unsafe { &*self.inner_ptr().cast::<[Rt<T>; N]>() };
561 Index::index(slice, index)
562 }
563}
564
565impl<T, I, const N: usize> IndexMut<I> for Rt<[T; N]>
566where
567 [Rt<T>]: IndexMut<I>,
568{
569 fn index_mut(&mut self, index: I) -> &mut Self::Output {
570 let slice = unsafe { &mut *self.inner_mut_ptr().cast::<[Rt<T>; N]>() };
571 IndexMut::index_mut(slice, index)
572 }
573}
574
575impl<T, const N: usize> AsRef<[Rt<T>]> for Rt<[T; N]> {
576 fn as_ref(&self) -> &[Rt<T>] {
577 unsafe { &*self.inner_ptr().cast::<[Rt<T>; N]>() }
578 }
579}
580
581impl<T> Rt<Vec<T>> {
582 fn as_mut_ref(&mut self) -> &mut Vec<Rt<T>> {
585 unsafe { &mut *(self as *mut Self).cast::<Vec<Rt<T>>>() }
587 }
588
589 pub(crate) fn push<U: IntoRoot<T>>(&mut self, item: U) {
590 self.inner_mut().push(unsafe { item.into_root() });
591 }
592
593 pub(crate) fn truncate(&mut self, len: usize) {
594 self.inner_mut().truncate(len);
595 }
596
597 pub(crate) fn pop(&mut self) {
598 self.inner_mut().pop();
599 }
600
601 pub(crate) fn swap_remove(&mut self, index: usize) {
602 self.inner_mut().swap_remove(index);
603 }
604
605 pub(crate) fn reserve(&mut self, additional: usize) {
606 self.inner_mut().reserve(additional);
607 }
608
609 pub(crate) fn capacity(&self) -> usize {
610 self.inner().capacity()
611 }
612}
613
614impl<T> Rt<Vec<T>> {
615 pub(crate) fn extend_from_slice<U: IntoRoot<T> + Copy>(&mut self, src: &[U]) {
616 let inner = self.inner_mut();
618 for x in src {
619 inner.push(unsafe { x.into_root() })
620 }
621 }
622}
623
624impl<T: Clone> Rt<Vec<T>> {
625 pub(crate) fn extend_from_within(&mut self, src: impl RangeBounds<usize>) {
626 self.inner_mut().extend_from_within(src);
627 }
628}
629
630impl<T> Deref for Rt<Vec<T>> {
631 type Target = [Rt<T>];
632 fn deref(&self) -> &Self::Target {
633 unsafe { &*(self as *const Self).cast::<Vec<Rt<T>>>() }
635 }
636}
637
638impl<T> DerefMut for Rt<Vec<T>> {
639 fn deref_mut(&mut self) -> &mut Self::Target {
640 unsafe { &mut *(self as *mut Self).cast::<Vec<Rt<T>>>() }
642 }
643}
644
645impl<T, I: SliceIndex<[Rt<T>]>> Index<I> for Rt<Vec<T>> {
646 type Output = I::Output;
647
648 fn index(&self, index: I) -> &Self::Output {
649 let slice: &[Rt<T>] = self;
650 Index::index(slice, index)
651 }
652}
653
654impl<T, I: SliceIndex<[Rt<T>]>> IndexMut<I> for Rt<Vec<T>> {
655 fn index_mut(&mut self, index: I) -> &mut Self::Output {
656 IndexMut::index_mut(self.as_mut_ref(), index)
657 }
658}
659
660#[derive(Debug)]
661#[repr(transparent)]
662pub(crate) struct ObjectMap<K, V>(UnsafeCell<IndexMap<K, V>>);
670
671impl<K, V> Default for ObjectMap<K, V> {
672 fn default() -> Self {
673 Self(UnsafeCell::new(Default::default()))
674 }
675}
676
677impl<K, V> Rt<ObjectMap<K, V>>
678where
679 K: Eq + Hash,
680{
681 fn as_ref(&self) -> &IndexMap<K, V> {
683 unsafe { &*self.inner().0.get() }
684 }
685
686 fn as_mut(&mut self) -> &mut IndexMap<K, V> {
688 unsafe { &mut *self.inner_mut().0.get() }
689 }
690
691 pub(crate) fn insert<Kx: IntoRoot<K>, Vx: IntoRoot<V>>(&mut self, k: Kx, v: Vx) {
692 unsafe {
693 self.as_mut().insert(k.into_root(), v.into_root());
694 }
695 }
696
697 pub(crate) fn get<Q: IntoRoot<K>>(&self, k: Q) -> Option<&Rt<V>> {
698 use std::ptr::from_ref;
699 let inner = unsafe { &*from_ref(self.as_ref()).cast::<IndexMap<K, Rt<V>>>() };
700 let root = unsafe { k.into_root() };
701 inner.get(&root)
702 }
703
704 pub(crate) fn get_mut<Q: IntoRoot<K>>(&mut self, k: Q) -> Option<&mut Rt<V>> {
705 use std::ptr::from_mut;
706 let inner = unsafe { &mut *from_mut(self.as_mut()).cast::<IndexMap<K, Rt<V>>>() };
707 let root = unsafe { k.into_root() };
708 inner.get_mut(&root)
709 }
710
711 pub(crate) fn remove<Q: IntoRoot<K>>(&mut self, k: Q) {
712 let root = unsafe { k.into_root() };
713 self.as_mut().swap_remove(&root);
714 }
715}
716
717impl<K, V> Trace for ObjectMap<K, V>
718where
719 K: Trace + Hash + Eq,
720 V: Trace,
721{
722 fn trace(&self, state: &mut GcState) {
723 let map = unsafe { &mut *self.0.get() };
724 map.rehash_keys(|key, val| {
725 key.trace(state);
726 val.trace(state);
727 });
728 }
729}
730
731#[cfg(test)]
732mod test {
733 use crate::core::object::NIL;
734 use rune_core::macros::root;
735
736 use super::*;
737
738 #[test]
739 fn mem_swap() {
740 let root = &RootSet::default();
741 let cx = &mut Context::new(root);
742 let outer = cx.add("outer");
743 root!(outer, cx);
744 {
745 let inner = cx.add("inner");
746 root!(inner, cx);
747 std::mem::swap(outer, inner);
748 }
749 cx.garbage_collect(true);
750 assert_eq!(outer.bind(cx), "inner");
751 }
752
753 #[test]
754 fn indexing() {
755 let root = &RootSet::default();
756 let cx = &Context::new(root);
757 let mut vec = Rt { inner: vec![], _aliasable: PhantomPinned };
758
759 vec.push(NIL);
760 assert_eq!(vec[0], NIL);
761 let str1 = cx.add("str1");
762 let str2 = cx.add("str2");
763 vec.push(str1);
764 vec.push(str2);
765 assert_eq!(vec.bind_ref(cx)[0..3], vec![NIL, str1, str2]);
766 }
767
768 #[test]
769 fn test_object_map() {
770 type Map<'a> = ObjectMap<Slot<Object<'a>>, Slot<Object<'a>>>;
771 let root = &RootSet::default();
772 let cx = &mut Context::new(root);
773 root!(map, new(Map), cx);
774 let key = cx.add("key");
775
776 map.insert(key, cx.add("val"));
777 root!(key, cx);
778 cx.garbage_collect(true);
779 let val = map.get(key.bind(cx)).unwrap().bind(cx);
780 assert_eq!(val, "val");
781 }
782}