1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! References to boxed values
//!
//! These are all transparent; they're used for either readability or marker traits.

use std::ops::Deref;
use std::ptr;
use std::{fmt, hash};

use crate::boxed::Boxed;

/// Reference to a garbage collected value
///
/// This is not memory safe and does not GC root; it's just sugar for a raw pointer.
#[repr(transparent)]
pub struct Gc<T: Boxed> {
    inner: ptr::NonNull<T>,
}

// Manual Clone implementation to work around Rust issue #26925
impl<T: Boxed> Clone for Gc<T> {
    fn clone(&self) -> Self {
        Gc { inner: self.inner }
    }
}

impl<T: Boxed> Copy for Gc<T> {}

impl<T: Boxed> Deref for Gc<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { self.inner.as_ref() }
    }
}

impl<T: Boxed> Gc<T> {
    /// Returns a new instance wrapping a pointer to a garbage collected box
    ///
    /// # Safety
    /// The requires a valid pointer to a box
    pub unsafe fn new(ptr: *const T) -> Gc<T> {
        Gc {
            inner: ptr::NonNull::new_unchecked(ptr as *mut T),
        }
    }

    /// Unchecked cast to the passed type
    ///
    /// # Safety
    /// The requires the box to be of the asserted type
    pub unsafe fn cast<U: Boxed>(self) -> Gc<U> {
        Gc {
            inner: self.inner.cast::<U>(),
        }
    }

    /// Returns a pointer to the garbage collected box
    pub fn as_ptr(self) -> *const T {
        self.inner.as_ptr()
    }

    /// Returns a mutable to the garbage collected box
    pub(super) fn as_mut_ptr(self) -> *mut T {
        self.inner.as_ptr()
    }
}

impl<T: Boxed> PartialEq for Gc<T>
where
    T: PartialEq,
{
    fn eq(&self, other: &Gc<T>) -> bool {
        unsafe { *self.as_ptr() == *other.as_ptr() }
    }
}

impl<T> Eq for Gc<T> where T: Boxed + Eq {}

impl<T: Boxed> hash::Hash for Gc<T>
where
    T: hash::Hash,
{
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        unsafe { (*self.as_ptr()).hash(state) }
    }
}

impl<T: Boxed> fmt::Debug for Gc<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        unsafe { (*self.as_ptr()).fmt(formatter) }
    }
}

macro_rules! define_marker_ref {
    (
        $(#[$docs:meta])*
        $ref_name:ident
    ) => {
        $(#[$docs])*
        #[repr(transparent)]
        pub struct $ref_name<T: Boxed> {
            inner: ptr::NonNull<T>,
        }

        impl<T: Boxed> Deref for $ref_name<T> {
            type Target = T;
            fn deref(&self) -> &T {
                unsafe { self.inner.as_ref() }
            }
        }

        impl<T: Boxed> From<$ref_name<T>> for Gc<T> {
            fn from(marker_ref: $ref_name<T>) -> Gc<T> {
                Gc {
                    inner: marker_ref.inner,
                }
            }
        }
    };
}

define_marker_ref!(
    /// Special marker ref for parameters that are explicitly not captured
    ///
    /// This can be used for performance-sensitive functions where the compiler cannot prove the
    /// parameter can't be captured.
    NoCapture
);

define_marker_ref!(
    /// Special marker ref for parameters that are explicitly captured
    ///
    /// Capturing GC managed values is usually not allowed as the captured values become invisible
    /// to the garbage collector and will become invalid on the next collection cycle. This is
    /// intended for use by special runtime functions that expose their captured values to the
    /// collector via an internal mechanism.
    Capture
);