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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
//! Includes manual `GarbageCollected` implementations for various types.
//!
//! Since unsafe code and third-party libraries can't have an automatically derived `GarbageCollected` implementation,
//! we need to manually provide them here.
//! This is done for all stdlib types and some feature gated external libraries.
#![doc(hidden)] // This is unstable

/// Unsafely implement `GarbageCollected` for the specified type,
/// by acquiring a 'lock' in order to trace the underlying value.
///
/// This is good for interior mutability types like `RefCell` and `Mutex` where you need to acquire a lock,
/// in order to safely view the interior.
/// Usually `unsafe_trace_deref!` is sufficient since it also lets you run
/// arbitrary code in order to 'convert' the macro to the necessary type,
/// and the only restriction is that the interior can be directly traced.
///
/// However, that isn't sufficient if you need to hold RAII guards (like `Ref` or `MutexGuard`s)
/// on the values you're tracing in addition to just accessing them.
/// For example, for `RefCell` you'd call `borrow` in order to acquire a `Ref` to the interior.
/// Although tracing garbage collection is already unsafe,
/// it's always completely undefined behavior to bypass the locking of `Mutex` and `RefCell`,
/// even if it's just for a 'little bit' since it may cause mutable references to alias.
/// It is currently the most powerful of the unsafe implementation macros,
/// since it lets you not only run an arbitrary expression like `unsafe_trace_deref!`,
/// but also acquire and hold a RAII guard object.
///
/// This macro is usually only useful for types like `Mutex` and `RefCell` who use raw pointers internally,
/// since raw pointers can't be automatically traced without additional type information.
/// Otherwise, it's best to use an automatically derived implementation since that's always safe.
/// However, using this macro is always better than a manual implementation, since it makes your intent clearer.
///
/// ## Usage
/// ````
/// // You can use an arbitrary expression to acquire a lock's guard
/// unsafe_trace_lock!(RefCell, target = T, |cell| cell.borrow());
/// unsafe_trace_lock!(Mutex, target = T, |lock| lock.lock().unwrap());
/// unsafe_trace_lock!(RwLock, target = T, |lock| lock.lock().unwrap());
/// ````
///
/// ## Safety
/// Always prefer automatically derived implementations where possible,
/// since they're just as fast and can never cause undefined behavior.
/// This is basically an _unsafe automatically derived_ implementation,
/// to be used only when a safe automatically derived implementation isn't possible (like with `Vec`).
///
/// Undefined behavior if there could be additional garbage collected objects that are not reachable
/// by dereferencing the specified lock, since the macro only traces the item the lock dereferences to.
/// This usually isn't the case with most locks and would be somewhat rare,
/// but it's still a possibility that causes the macro to be unsafe.
///
///
/// This delegates to `unsafe_gc_brand` to provide the `GcBrand` implementation,
/// so that could also trigger undefined behavior.
#[macro_export]
macro_rules! unsafe_trace_lock {
    ($target:ident, target = $target_type:ident; |$get_mut:ident| $get_mut_expr:expr, |$lock:ident| $acquire_guard:expr) => {
        unsafe_gc_brand!($target, $target_type);
        unsafe impl<$target_type: Trace> Trace for $target<$target_type> {
            const NEEDS_TRACE: bool = T::NEEDS_TRACE;
            #[inline]
            fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
                let $get_mut = self;
                let value: &mut $target_type = $get_mut_expr;
                visitor.visit(value)
            }
        }
        unsafe impl<$target_type: Trace> $crate::TraceImmutable for $target<$target_type> {
            #[inline]
            fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
                if !Self::NEEDS_TRACE { return Ok(()) };
                // We can immutably visit a lock by acquiring it
                let $lock = self;
                #[allow(unused_mut)]
                let mut guard = $acquire_guard;
                let guard_value = &mut *guard;
                visitor.visit(guard_value)
            }
        }
        unsafe impl<$target_type: $crate::NullTrace> $crate::NullTrace for $target<$target_type> {}
        unsafe impl<$target_type: $crate::GcSafe> $crate::GcSafe for $target<$target_type> {}
    };
}

/// Unsafely implement `GarbageCollected` for the specified type,
/// by converting the specified wrapper type in order to trace the underlying objects.
///
/// In addition to smart pointers, it can be used for newtype structs like `Wrapping` or `NonZero`,
/// as long as the types can properly traced by just reading their underlying value.
/// However, it's slightly easier to invoke if you implement `Deref`,
/// since the expression is inferred based on the target type.
/// However, you will always need to explicitly indicate the dereferencing output type,
/// in order to be eplicit about the intended operation.
///
/// This macro is usually only useful for unsafe wrappers like `NonZero` and smart pointers like `Rc` and `Box` who use raw pointers internally,
/// since raw pointers can't be automatically traced without additional type information.
/// Otherwise, it's best to use an automatically derived implementation since that's always safe.
/// However, using this macro is always better than a manual implementation, since it makes your intent clearer.
///
/// ## Usage
/// ````
/// // Easy to use for wrappers that `Deref` to their type parameter
/// unsafe_trace_deref!(Box, target = T);
/// unsafe_trace_deref!(Rc, target = T);
/// unsafe_trace_deref!(Arc, target = T);
/// // The `Deref::Output` type can be declared separately from the type paremters
/// unsafe_trace_deref!(Vec, target = { [T] }, T);
/// /*
///  * You can use an arbitrary expression to acquire the underlying value,
///  * and the type doesn't need to implement `Deref` at all
///  */
/// unsafe_trace_deref!(Cell, T; |cell| cell.get());
/// unsafe_trace_deref!(Wrapping, T; |wrapping| &wrapping.0);
/// unsafe_trace_deref!(NonZero, T; |nonzero| &nonzero.get());
/// ````
///
/// ## Safety
/// Always prefer automatically derived implementations where possible,
/// since they're just as fast and can never cause undefined behavior.
/// This is basically an _unsafe automatically derived_ implementation,
/// to be used only when a safe automatically derived implementation isn't possible (like with `Vec`).
///
/// Undefined behavior if there could be garbage collected objects that are not reachable via iteration,
/// since the macro only traces objects it can iterate over,
/// and the garbage collector will free objects that haven't been traced.
/// This usually isn't the case with collections and would be somewhat rare,
/// but it's still a possibility that causes the macro to be unsafe.
///
/// This delegates to `unsafe_gc_brand` to provide the [GcBrand] implementation,
/// so that could also trigger undefined behavior.
#[macro_export]
macro_rules! unsafe_trace_deref {
    ($target:ident, target = $target_type:ident) => {
        unsafe_trace_deref!($target, target = $target_type; $target_type);
    };
    ($target:ident, target = $target_type:ident; $($param:ident),*) => {
        unsafe_trace_deref!($target, target = { $target_type }; $($param),*);
    };
    ($target:ident, target = { $target_type:ty }; $($param:ident),*) => {
        unsafe impl<$($param: TraceImmutable),*> $crate::TraceImmutable for $target<$($param),*> {
            #[inline]
            fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
                let extracted: &$target_type = &**self;
                visitor.visit_immutable(extracted)
            }
        }
        unsafe_trace_deref!($target, $($param),*; immut = false; |value| {
            // I wish we had type ascription -_-
            let dereferenced: &mut $target_type = &mut **value;
            dereferenced
        });
    };
    ($target:ident, $($param:ident),*; immut = required; |$value:ident| $extract:expr) => {
        unsafe_gc_brand!($target, immut = required; $($param),*);
        unsafe impl<$($param),*> Trace for $target<$($param),*>
            where $($param: TraceImmutable),* {

            const NEEDS_TRACE: bool = $($param::NEEDS_TRACE || )* false;
            #[inline]
            fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
                let extracted = {
                    let $value = self;
                    $extract
                };
                visitor.visit_immutable(extracted)
            }
        }
        unsafe impl<$($param),*> TraceImmutable for $target<$($param),*>
            where $($param: TraceImmutable),* {

            #[inline]
            fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), V::Err> {
                let extracted = {
                    let $value = self;
                    $extract
                };
                visitor.visit_immutable(extracted)
            }
        }
        unsafe impl<$($param: NullTrace),*> NullTrace for $target<$($param),*> {}
        /// We trust ourselves to not do anything bad as long as our paramaters don't
        unsafe impl<$($param),*> GcSafe for $target<$($param),*>
            where $($param: GcSafe + TraceImmutable),*  {
            const NEEDS_DROP: bool = std::mem::needs_drop::<Self>();
        }
    };
    ($target:ident, $($param:ident),*; immut = false; |$value:ident| $extract:expr) => {
        unsafe_gc_brand!($target, $($param),*);
        unsafe impl<$($param),*> Trace for $target<$($param),*>
            where $($param: Trace),* {

            const NEEDS_TRACE: bool = $($param::NEEDS_TRACE || )* false;
            #[inline]
            fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
                let extracted = {
                    let $value = self;
                    $extract
                };
                visitor.visit(extracted)
            }
        }
        unsafe impl<$($param: NullTrace),*> NullTrace for $target<$($param),*> {}
        /// We trust ourselves to not do anything bad as long as our paramaters don't
        unsafe impl<$($param),*> GcSafe for $target<$($param),*>
            where $($param: GcSafe),*  {
            const NEEDS_DROP: bool = std::mem::needs_drop::<Self>();
        }
    };
}


/// Unsafely implement `ImmutableTrace` for the specified iterable type,
/// by iterating over the type to trace all objects.
///
/// You still have to implement the regular `Trace` and `GcSafe` traits by hand.
///
/// This macro is only useful for unsafe collections like `Vec` and `HashMap` who use raw pointers internally,
/// since raw pointers can't have automatically derived tracing implementations.
/// Otherwise, it's best to use an automatically derived implementation since that's always safe.
/// In order to prevent ambiguity, this always requires the type of the element being traced.
///
/// ## Usage
/// ````
/// unsafe_trace_iterable!(Vec, element = T);
/// unsafe_trace_iterable!(HashMap, element = { (&K, &V) }; K, V);
/// unsafe_trace_iterable!(HashSet, element = T);
/// ````
///
/// ## Safety
/// Always prefer automatically derived implementations where possible,
/// since they're just as fast and can never cause undefined behavior.
/// This is basically an _unsafe automatically derived_ implementation,
/// to be used only when a safe automatically derived implementation isn't possible (like with `Vec`).
///
/// Undefined behavior if there could be garbage collected objects that are not reachable via iteration,
/// since the macro only traces objects it can iterate over,
/// and the garbage collector will free objects that haven't been traced.
/// This usually isn't the case with collections and would be somewhat rare,
/// but it's still a possibility that causes the macro to be unsafe.
///
///
/// This delegates to `unsafe_gc_brand!` to provide the [GcBrand] implementation,
/// so that could also trigger undefined behavior.
#[macro_export]
macro_rules! unsafe_immutable_trace_iterable {
    ($target:ident, element = $element_type:ident) => {
        unsafe_trace_iterable!($target, element = &$element_type; $element_type);
    };
    ($target:ident<$($param:ident),*>; element = { $element_type:ty }) => {
        unsafe impl<$($param),*> TraceImmutable for $target<$($param),*>
            where $($param: TraceImmutable),* {
            fn visit_immutable<Visit: GcVisitor>(&self, visitor: &mut Visit) -> Result<(), Visit::Err> {
                if !Self::NEEDS_TRACE { return Ok(()) };
                let iter = IntoIterator::into_iter(self);
                for element in iter {
                    let element: $element_type = element;
                    visitor.visit_immutable(&element)?;
                }
                Ok(())
            }
        }
        unsafe impl<$($param: $crate::NullTrace),*> NullTrace for $target<$($param),*> {}
    };
}


/// Unsafely implement `GarbageCollected` for the specified type,
/// by assuming it's a 'primitive' and never needs to be traced.
///
/// The fact that this type is a 'primitive' means it's assumed to have no type parameters,
/// and that there's nothing .
/// This macro is only useful for unsafe types like `String` who use raw pointers internally,
/// since raw pointers can't be automatically traced without additional type information.
///
/// ## Safety
/// Always prefer automatically derived implementations where possible,
/// since they're just as fast and can never cause undefined behavior.
/// This is basically an _unsafe automatically derived_ implementation,
/// to be used only when a safe automatically derived implementation isn't possible (like with `String`).
///
/// Undefined behavior only if there are garbage collected pointers in the type's interior,
/// since the implementation assumes there's nothing to trace in the first place.
///
/// This delegates to `unsafe_gc_brand!` to provide the [GcBrand] implementation,
/// but that will never cause undefined behavior unless you
/// already have garbage collected pointers inside
/// (which are already undefined behavior for tracing).
#[macro_export]
macro_rules! unsafe_trace_primitive {
    ($target:ty) => {
        unsafe_gc_brand!($target);
        unsafe impl Trace for $target {
            const NEEDS_TRACE: bool = false;
            #[inline(always)] // This method does nothing and is always a win to inline
            fn visit<V: $crate::GcVisitor>(&mut self, _visitor: &mut V) -> Result<(), V::Err> {
                Ok(())
            }
        }
        unsafe impl $crate::TraceImmutable for $target {
            #[inline(always)]
            fn visit_immutable<V: $crate::GcVisitor>(&self, _visitor: &mut V) -> Result<(), V::Err> {
                Ok(())
            }
        }
        unsafe impl $crate::NullTrace for $target {}
        /// No drop/custom behavior -> GcSafe
        unsafe impl GcSafe for $target {
            const NEEDS_DROP: bool = std::mem::needs_drop::<$target>();
        }
    };
}


/// Unsafely assume that the generic implementation of [GcBrand] is valid,
/// if and only if it's valid for the generic lifetime and type parameters.
///
/// Always _prefer automatically derived implementations where possible_,
/// since they can never cause undefined behavior.
/// This macro is only necessary if you have raw pointers internally,
/// which can't have automatically derived safe implementations.
/// This is basically an _unsafe automatically derived_ implementation,
/// to be used only when a safe automatically derived implementation isn't possible (like with `Vec`).
///
/// This macro takes a varying number of parameters referring to the type's generic parameters,
/// which are all properly bounded and required to implement [GcBrand] correctly.
///
/// This macro can only cause undefined behavior if there are garbage collected pointers
/// that aren't included in the type parameter.
/// For example including `Gc<u32>` would be completely undefined behavior,
/// since we'd blindly erase its lifetime.
///
/// However, generally this macro provides the correct implementation
/// for straighrtforward wrapper/collection types.
/// Currently the only exception is when you have garbage collected lifetimes like `Gc`.
#[macro_export]
macro_rules! unsafe_gc_brand {
    ($target:tt) => {
        unsafe impl<'new_gc, S: $crate::GcSystem> $crate::GcBrand<'new_gc, S> for $target {
            type Branded = Self;
        }
    };
    ($target:ident, $($param:ident),+) => {
        unsafe impl<'new_gc, S, $($param),*> $crate::GcBrand<'new_gc, S> for $target<$($param),*>
            where S: crate::GcSystem, $($param: $crate::GcBrand<'new_gc, S>,)*
                  $(<$param as $crate::GcBrand<'new_gc, S>>::Branded: Trace,)* {
            type Branded = $target<$(<$param as $crate::GcBrand<'new_gc, S>>::Branded),*>;
        }
    };
    ($target:tt, immut = required; $($param:ident),+) => {
        unsafe impl<'new_gc, S, $($param),*> $crate::GcBrand<'new_gc, S> for $target<$($param),*>
            where S: crate::GcSystem, $($param: $crate::GcBrand<'new_gc, S> + TraceImmutable,)*
                  $(<$param as $crate::GcBrand<'new_gc, S>>::Branded: TraceImmutable,)* {
            type Branded = $target<$(<$param as $crate::GcBrand<'new_gc, S>>::Branded),*>;
        }
    }
}

mod core;
mod stdlib;