1use super::{
2 super::{cons::Cons, object::Object},
3 GcMoveable, GcState, TracePtr,
4};
5use super::{Block, Context, RootSet, ThreadSafeRootSet, 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
157#[doc(hidden)]
165pub(crate) struct __HeapRoot<T: Trace> {
166 data: Box<Rt<T>>,
167 root_ptr: *const dyn Trace,
168 root_set: &'static ThreadSafeRootSet,
169}
170
171impl<T: Trace> __HeapRoot<T> {
172 pub(crate) fn new(value: T, root_set: &'static ThreadSafeRootSet) -> Self {
173 let mut boxed = Box::new(Rt { inner: value, _aliasable: PhantomPinned });
174 let dyn_ptr = &mut boxed.inner as &mut T as &mut dyn Trace as *mut dyn Trace;
175 let dyn_ptr = unsafe { std::mem::transmute::<*mut dyn Trace, *mut dyn Trace>(dyn_ptr) };
178
179 root_set.roots.lock().unwrap().push(dyn_ptr);
180
181 Self { data: boxed, root_ptr: dyn_ptr, root_set }
182 }
183}
184
185impl<T: Trace> Deref for __HeapRoot<T> {
186 type Target = Rt<T>;
187
188 fn deref(&self) -> &Self::Target {
189 &self.data
190 }
191}
192
193impl<T: Trace> DerefMut for __HeapRoot<T> {
194 fn deref_mut(&mut self) -> &mut Self::Target {
195 &mut self.data
196 }
197}
198
199impl<T: Trace> Drop for __HeapRoot<T> {
200 fn drop(&mut self) {
201 let mut roots = self.root_set.roots.lock().unwrap();
203 if let Some(pos) = roots.iter().position(|&ptr| std::ptr::addr_eq(ptr, self.root_ptr)) {
204 roots.swap_remove(pos);
205 }
206 }
207}
208
209unsafe impl<T: Trace> Send for __HeapRoot<T> {}
217unsafe impl<T: Trace> Sync for __HeapRoot<T> {}
218
219impl<T: Trace + Debug> Debug for __HeapRoot<T> {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 Debug::fmt(&**self, f)
222 }
223}
224
225impl<T: Trace + Display> Display for __HeapRoot<T> {
226 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227 Display::fmt(&**self, f)
228 }
229}
230
231pub trait RootedDeref {
243 type Target;
244 fn rooted_deref(rooted: &Rt<Self>) -> &Self::Target;
245 fn rooted_derefmut(rooted: &mut Rt<Self>) -> &mut Self::Target;
246}
247
248impl<T: RootedDeref> Deref for Rt<T> {
249 type Target = <T as RootedDeref>::Target;
250 fn deref(&self) -> &Self::Target {
251 RootedDeref::rooted_deref(self)
252 }
253}
254
255impl<T: RootedDeref> DerefMut for Rt<T> {
256 fn deref_mut(&mut self) -> &mut Self::Target {
257 RootedDeref::rooted_derefmut(self)
258 }
259}
260
261#[repr(transparent)]
267#[derive(PartialEq, Eq)]
268pub struct Rt<T: ?Sized> {
269 _aliasable: PhantomPinned,
270 inner: T,
271}
272
273pub type Rto<T> = Rt<Slot<T>>;
278
279#[repr(transparent)]
283#[derive(Default)]
284pub struct Slot<T: ?Sized> {
285 inner: UnsafeCell<T>,
286}
287
288impl<T: Clone> Clone for Slot<T> {
289 fn clone(&self) -> Self {
290 Self::new(self.get().clone())
291 }
292}
293
294impl<'new, T: WithLifetime<'new> + Copy> WithLifetime<'new> for Slot<T> {
295 type Out = Slot<<T as WithLifetime<'new>>::Out>;
296
297 unsafe fn with_lifetime(self) -> Self::Out {
298 Slot::new(self.get().with_lifetime())
299 }
300}
301
302impl<T: Hash> Hash for Slot<T> {
303 fn hash<H: Hasher>(&self, state: &mut H) {
304 self.get().hash(state);
305 }
306}
307
308impl<T: PartialEq> PartialEq for Slot<T> {
309 fn eq(&self, other: &Self) -> bool {
310 self.get() == other.get()
311 }
312}
313
314impl<'a, T, U> PartialEq<U> for Slot<T>
320where
321 U: WithLifetime<'a> + Copy,
322 T: PartialEq<<U as WithLifetime<'a>>::Out>,
323{
324 fn eq(&self, other: &U) -> bool {
325 *self.get() == unsafe { other.with_lifetime() }
326 }
327}
328
329impl<T: Eq> Eq for Slot<T> {}
330
331impl<T> Slot<T> {
332 fn get(&self) -> &T {
333 unsafe { &*self.inner.get() }
334 }
335
336 unsafe fn set(&self, new: T) {
337 *self.inner.get() = new
338 }
339
340 pub(crate) fn new(val: T) -> Self {
341 Slot { inner: UnsafeCell::new(val) }
342 }
343}
344
345impl<T> Deref for Slot<T> {
346 type Target = T;
347
348 fn deref(&self) -> &Self::Target {
349 self.get()
350 }
351}
352
353impl<T> Trace for Slot<T>
358where
359 T: TracePtr + GcMoveable<Value = T>,
360{
361 fn trace(&self, state: &mut GcState) {
362 if let Some((new, moved)) = self.get().move_value(&state.to_space) {
363 unsafe { self.set(new) };
364 if moved {
365 self.get().trace_ptr(state);
366 state.trace_stack();
369 }
370 }
371 }
372}
373
374impl<T: Debug> Debug for Rt<T> {
375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376 Debug::fmt(&self.inner(), f)
377 }
378}
379
380impl<T: Display> Display for Rt<T> {
381 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
382 Display::fmt(&self.inner(), f)
383 }
384}
385
386impl<T: Debug> Debug for Slot<T> {
387 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
388 Debug::fmt(self.get(), f)
389 }
390}
391
392impl<T: Display> Display for Slot<T> {
393 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
394 Display::fmt(self.get(), f)
395 }
396}
397
398impl<T, U> PartialEq<U> for Rt<Slot<T>>
399where
400 Slot<T>: PartialEq<U>,
401{
402 fn eq(&self, other: &U) -> bool {
403 self.inner() == other
404 }
405}
406
407impl<T> Hash for Rt<T>
408where
409 T: Hash,
410{
411 fn hash<H: Hasher>(&self, state: &mut H) {
412 self.inner().hash(state);
413 }
414}
415
416impl<T> Rt<T> {
417 fn inner(&self) -> &T {
418 &self.inner
419 }
420
421 fn inner_mut(&mut self) -> &mut T {
422 &mut self.inner
423 }
424
425 fn inner_ptr(&self) -> *const T {
426 &self.inner as *const T
427 }
428
429 fn inner_mut_ptr(&mut self) -> *mut T {
430 &mut self.inner as *mut T
431 }
432
433 pub(crate) fn bind_ref<'a, 'ob>(&'a self, _: &'ob Context) -> &'a <T as WithLifetime<'ob>>::Out
434 where
435 T: WithLifetime<'ob>,
436 {
437 unsafe { &*self.inner_ptr().cast::<<T as WithLifetime<'ob>>::Out>() }
439 }
440
441 pub(crate) fn bind_mut<'a, 'ob>(
442 &'a mut self,
443 _: &'ob Context,
444 ) -> &'a mut <T as WithLifetime<'ob>>::Out
445 where
446 T: WithLifetime<'ob>,
447 {
448 unsafe { &mut *self.inner_mut_ptr().cast::<<T as WithLifetime<'ob>>::Out>() }
450 }
451
452 pub(crate) fn set<U: IntoRoot<T>>(&mut self, item: U) {
453 unsafe { *self.inner_mut() = item.into_root() }
456 }
457}
458
459impl<T> Rt<Slot<T>> {
460 pub(crate) fn bind<'ob>(&self, _: &'ob Context) -> <T as WithLifetime<'ob>>::Out
461 where
462 T: WithLifetime<'ob> + Copy,
463 {
464 unsafe { self.inner().get().with_lifetime() }
466 }
467
468 pub(crate) unsafe fn bind_unchecked<'ob>(&'ob self) -> <T as WithLifetime<'ob>>::Out
469 where
470 T: WithLifetime<'ob> + Copy,
471 {
472 self.inner().get().with_lifetime()
473 }
474
475 pub(crate) fn get_inner(&self) -> T
478 where
479 T: Copy,
480 {
481 *self.inner().get()
482 }
483
484 pub(crate) fn bind_slice<'brw, 'ob, U>(
485 slice: &'brw [Rt<Slot<Gc<T>>>],
486 _: &'ob Context,
487 ) -> &'brw [Gc<U>]
488 where
489 Gc<T>: WithLifetime<'ob, Out = Gc<U>>,
490 Gc<U>: 'ob,
491 {
492 unsafe { &*(slice as *const [Rt<Slot<Gc<T>>>] as *const [Gc<U>]) }
495 }
496}
497
498impl<T> Rt<Slot<Gc<T>>> {
499 pub(crate) fn untag<'ob, U>(&self, cx: &'ob Context) -> U
501 where
502 Gc<T>: WithLifetime<'ob, Out = Gc<U>> + Copy,
503 Gc<U>: Untag<U>,
504 {
505 cx.bind(*self.inner().get()).untag_erased()
506 }
507
508 pub(crate) fn try_as<U, E>(&self) -> Result<&Rt<Slot<Gc<U>>>, E>
510 where
511 Gc<T>: TryInto<Gc<U>, Error = E> + Copy,
512 {
513 let _: Gc<U> = (*self.inner().get()).try_into()?;
514 unsafe { Ok(&*((self as *const Self).cast::<Rt<Slot<Gc<U>>>>())) }
516 }
517}
518
519impl TryFrom<&Rt<Slot<Object<'_>>>> for usize {
520 type Error = anyhow::Error;
521
522 fn try_from(value: &Rt<Slot<Object>>) -> Result<Self, Self::Error> {
523 (*value.inner().get()).try_into()
524 }
525}
526
527impl<T> Rt<Slot<Gc<T>>> {
528 pub(crate) fn bind_as<'ob, U, E>(&self, _cx: &'ob Context) -> Result<U, E>
530 where
531 Gc<T>: WithLifetime<'ob> + Copy,
532 <Gc<T> as WithLifetime<'ob>>::Out: TryInto<U, Error = E> + Copy,
533 {
534 unsafe { self.inner().get().with_lifetime().try_into() }
535 }
536
537 pub(crate) fn cast<U>(&self) -> &Rt<Slot<Gc<U>>>
539 where
540 Gc<T>: Into<Gc<U>> + Copy,
541 {
542 unsafe { &*((self as *const Self).cast::<Rt<Slot<Gc<U>>>>()) }
544 }
545
546 pub(crate) fn as_cons(&self) -> &Rt<Slot<Gc<&Cons>>> {
549 match self.inner().as_obj().untag() {
550 crate::core::object::ObjectType::Cons(_) => unsafe {
551 &*(self as *const Self).cast::<Rt<Slot<Gc<&Cons>>>>()
552 },
553 x => panic!("attempt to convert type that was not cons: {x}"),
554 }
555 }
556}
557
558impl From<&Rt<Slot<Object<'_>>>> for OptionalFlag {
559 fn from(value: &Rt<Slot<Object<'_>>>) -> Self {
560 value.inner().is_nil().then_some(())
561 }
562}
563
564impl<'a> Rt<Slot<Object<'a>>> {
565 pub(crate) fn try_as_option<T, E>(&self) -> Result<Option<&Rt<Slot<Gc<T>>>>, E>
566 where
567 Object<'a>: TryInto<Gc<T>, Error = E>,
568 {
569 if self.inner().is_nil() {
570 Ok(None)
571 } else {
572 let _: Gc<T> = (*self.inner().get()).try_into()?;
573 unsafe { Ok(Some(&*((self as *const Self).cast::<Rt<Slot<Gc<T>>>>()))) }
574 }
575 }
576}
577
578impl IntoObject for &Rt<Slot<Object<'_>>> {
579 type Out<'ob> = ObjectType<'ob>;
580
581 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
582 unsafe { self.inner().get().with_lifetime() }
583 }
584}
585
586impl IntoObject for Slot<Object<'_>> {
587 type Out<'ob> = ObjectType<'ob>;
588
589 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
590 unsafe { self.get().with_lifetime() }
591 }
592}
593
594impl IntoObject for &mut Rt<Slot<Object<'_>>> {
595 type Out<'ob> = ObjectType<'ob>;
596
597 fn into_obj<const C: bool>(self, _block: &Block<C>) -> Gc<Self::Out<'_>> {
598 unsafe { self.inner().get().with_lifetime() }
599 }
600}
601
602impl Rt<Slot<&Cons>> {
603 pub(crate) fn car<'ob>(&self, cx: &'ob Context) -> Object<'ob> {
604 self.bind(cx).car()
605 }
606
607 pub(crate) fn cdr<'ob>(&self, cx: &'ob Context) -> Object<'ob> {
608 self.bind(cx).cdr()
609 }
610}
611
612impl<T, U> Deref for Rt<(T, U)> {
613 type Target = (Rt<T>, Rt<U>);
614
615 fn deref(&self) -> &Self::Target {
616 unsafe { &*(self as *const Self).cast::<(Rt<T>, Rt<U>)>() }
617 }
618}
619
620impl<T, U> DerefMut for Rt<(T, U)> {
621 fn deref_mut(&mut self) -> &mut Self::Target {
622 unsafe { &mut *(self as *mut Rt<(T, U)>).cast::<(Rt<T>, Rt<U>)>() }
623 }
624}
625
626impl<T> Deref for Rt<Option<T>> {
630 type Target = Option<Rt<T>>;
631 fn deref(&self) -> &Self::Target {
632 unsafe { &*self.inner_ptr().cast::<Self::Target>() }
633 }
634}
635
636impl<T, I, const N: usize> Index<I> for Rt<[T; N]>
637where
638 [Rt<T>]: Index<I>,
639{
640 type Output = <[Rt<T>] as Index<I>>::Output;
641
642 fn index(&self, index: I) -> &Self::Output {
643 let slice = unsafe { &*self.inner_ptr().cast::<[Rt<T>; N]>() };
644 Index::index(slice, index)
645 }
646}
647
648impl<T, I, const N: usize> IndexMut<I> for Rt<[T; N]>
649where
650 [Rt<T>]: IndexMut<I>,
651{
652 fn index_mut(&mut self, index: I) -> &mut Self::Output {
653 let slice = unsafe { &mut *self.inner_mut_ptr().cast::<[Rt<T>; N]>() };
654 IndexMut::index_mut(slice, index)
655 }
656}
657
658impl<T, const N: usize> AsRef<[Rt<T>]> for Rt<[T; N]> {
659 fn as_ref(&self) -> &[Rt<T>] {
660 unsafe { &*self.inner_ptr().cast::<[Rt<T>; N]>() }
661 }
662}
663
664impl<T> Rt<Vec<T>> {
665 fn as_mut_ref(&mut self) -> &mut Vec<Rt<T>> {
668 unsafe { &mut *(self as *mut Self).cast::<Vec<Rt<T>>>() }
670 }
671
672 pub(crate) fn push<U: IntoRoot<T>>(&mut self, item: U) {
673 self.inner_mut().push(unsafe { item.into_root() });
674 }
675
676 pub(crate) fn truncate(&mut self, len: usize) {
677 self.inner_mut().truncate(len);
678 }
679
680 pub(crate) fn pop(&mut self) {
681 self.inner_mut().pop();
682 }
683
684 pub(crate) fn swap_remove(&mut self, index: usize) {
685 self.inner_mut().swap_remove(index);
686 }
687
688 pub(crate) fn reserve(&mut self, additional: usize) {
689 self.inner_mut().reserve(additional);
690 }
691
692 pub(crate) fn capacity(&self) -> usize {
693 self.inner().capacity()
694 }
695}
696
697impl<T> Rt<Vec<T>> {
698 pub(crate) fn extend_from_slice<U: IntoRoot<T> + Copy>(&mut self, src: &[U]) {
699 let inner = self.inner_mut();
701 for x in src {
702 inner.push(unsafe { x.into_root() })
703 }
704 }
705}
706
707impl<T: Clone> Rt<Vec<T>> {
708 pub(crate) fn extend_from_within(&mut self, src: impl RangeBounds<usize>) {
709 self.inner_mut().extend_from_within(src);
710 }
711}
712
713impl<T> Deref for Rt<Vec<T>> {
714 type Target = [Rt<T>];
715 fn deref(&self) -> &Self::Target {
716 unsafe { &*(self as *const Self).cast::<Vec<Rt<T>>>() }
718 }
719}
720
721impl<T> DerefMut for Rt<Vec<T>> {
722 fn deref_mut(&mut self) -> &mut Self::Target {
723 unsafe { &mut *(self as *mut Self).cast::<Vec<Rt<T>>>() }
725 }
726}
727
728impl<T, I: SliceIndex<[Rt<T>]>> Index<I> for Rt<Vec<T>> {
729 type Output = I::Output;
730
731 fn index(&self, index: I) -> &Self::Output {
732 let slice: &[Rt<T>] = self;
733 Index::index(slice, index)
734 }
735}
736
737impl<T, I: SliceIndex<[Rt<T>]>> IndexMut<I> for Rt<Vec<T>> {
738 fn index_mut(&mut self, index: I) -> &mut Self::Output {
739 IndexMut::index_mut(self.as_mut_ref(), index)
740 }
741}
742
743#[derive(Debug)]
744#[repr(transparent)]
745pub(crate) struct ObjectMap<K, V>(UnsafeCell<IndexMap<K, V>>);
753
754impl<K, V> Default for ObjectMap<K, V> {
755 fn default() -> Self {
756 Self(UnsafeCell::new(Default::default()))
757 }
758}
759
760impl<K, V> Rt<ObjectMap<K, V>>
761where
762 K: Eq + Hash,
763{
764 fn as_ref(&self) -> &IndexMap<K, V> {
766 unsafe { &*self.inner().0.get() }
767 }
768
769 fn as_mut(&mut self) -> &mut IndexMap<K, V> {
771 unsafe { &mut *self.inner_mut().0.get() }
772 }
773
774 pub(crate) fn insert<Kx: IntoRoot<K>, Vx: IntoRoot<V>>(&mut self, k: Kx, v: Vx) {
775 unsafe {
776 self.as_mut().insert(k.into_root(), v.into_root());
777 }
778 }
779
780 pub(crate) fn get<Q: IntoRoot<K>>(&self, k: Q) -> Option<&Rt<V>> {
781 use std::ptr::from_ref;
782 let inner = unsafe { &*from_ref(self.as_ref()).cast::<IndexMap<K, Rt<V>>>() };
783 let root = unsafe { k.into_root() };
784 inner.get(&root)
785 }
786
787 pub(crate) fn get_mut<Q: IntoRoot<K>>(&mut self, k: Q) -> Option<&mut Rt<V>> {
788 use std::ptr::from_mut;
789 let inner = unsafe { &mut *from_mut(self.as_mut()).cast::<IndexMap<K, Rt<V>>>() };
790 let root = unsafe { k.into_root() };
791 inner.get_mut(&root)
792 }
793
794 pub(crate) fn remove<Q: IntoRoot<K>>(&mut self, k: Q) {
795 let root = unsafe { k.into_root() };
796 self.as_mut().swap_remove(&root);
797 }
798}
799
800impl<K, V> Trace for ObjectMap<K, V>
801where
802 K: Trace + Hash + Eq,
803 V: Trace,
804{
805 fn trace(&self, state: &mut GcState) {
806 let map = unsafe { &mut *self.0.get() };
807 map.rehash_keys(|key, val| {
808 key.trace(state);
809 val.trace(state);
810 });
811 }
812}
813
814#[cfg(test)]
815mod test {
816 use crate::core::object::NIL;
817 use rune_core::macros::root;
818
819 use super::*;
820
821 #[test]
822 fn mem_swap() {
823 let root = &RootSet::default();
824 let cx = &mut Context::new(root);
825 let outer = cx.add("outer");
826 root!(outer, cx);
827 {
828 let inner = cx.add("inner");
829 root!(inner, cx);
830 std::mem::swap(outer, inner);
831 }
832 cx.garbage_collect(true);
833 assert_eq!(outer.bind(cx), "inner");
834 }
835
836 #[test]
837 fn indexing() {
838 let root = &RootSet::default();
839 let cx = &Context::new(root);
840 let mut vec = Rt { inner: vec![], _aliasable: PhantomPinned };
841
842 vec.push(NIL);
843 assert_eq!(vec[0], NIL);
844 let str1 = cx.add("str1");
845 let str2 = cx.add("str2");
846 vec.push(str1);
847 vec.push(str2);
848 assert_eq!(vec.bind_ref(cx)[0..3], vec![NIL, str1, str2]);
849 }
850
851 #[test]
852 fn test_object_map() {
853 type Map<'a> = ObjectMap<Slot<Object<'a>>, Slot<Object<'a>>>;
854 let root = &RootSet::default();
855 let cx = &mut Context::new(root);
856 root!(map, new(Map), cx);
857 let key = cx.add("key");
858
859 map.insert(key, cx.add("val"));
860 root!(key, cx);
861 cx.garbage_collect(true);
862 let val = map.get(key.bind(cx)).unwrap().bind(cx);
863 assert_eq!(val, "val");
864 }
865}