diff --git a/gc/src/gc.rs b/gc/src/gc.rs index 58cb3c2..9526c28 100644 --- a/gc/src/gc.rs +++ b/gc/src/gc.rs @@ -109,7 +109,7 @@ impl GcBoxHeader { } #[repr(C)] // to justify the layout computations in GcBox::from_box, Gc::from_raw -pub(crate) struct GcBox { +pub(crate) struct GcBox { header: GcBoxHeader, data: T, } @@ -217,14 +217,16 @@ unsafe fn insert_gcbox(gcbox: NonNull>) { }); } -impl GcBox { +impl GcBox { /// Returns `true` if the two references refer to the same `GcBox`. pub(crate) fn ptr_eq(this: &GcBox, other: &GcBox) -> bool { // Use .header to ignore fat pointer vtables, to work around // https://github.com/rust-lang/rust/issues/46139 ptr::eq(&this.header, &other.header) } +} +impl GcBox { /// Marks this `GcBox` and marks through its data. pub(crate) unsafe fn trace_inner(&self) { if !self.header.is_marked() { @@ -232,7 +234,9 @@ impl GcBox { self.data.trace(); } } +} +impl GcBox { /// Increases the root count on this `GcBox`. /// Roots prevent the `GcBox` from being destroyed by the garbage collector. pub(crate) unsafe fn root_inner(&self) { diff --git a/gc/src/lib.rs b/gc/src/lib.rs index 927705a..b38e4ba 100644 --- a/gc/src/lib.rs +++ b/gc/src/lib.rs @@ -4,7 +4,10 @@ //! It is marked as non-sendable because the garbage collection only occurs //! thread-locally. -#![cfg_attr(feature = "nightly", feature(coerce_unsized, unsize))] +#![cfg_attr( + feature = "nightly", + feature(coerce_unsized, dispatch_from_dyn, unsize) +)] use crate::gc::{GcBox, GcBoxHeader}; use std::alloc::Layout; @@ -21,7 +24,7 @@ use std::rc::Rc; #[cfg(feature = "nightly")] use std::marker::Unsize; #[cfg(feature = "nightly")] -use std::ops::CoerceUnsized; +use std::ops::{CoerceUnsized, DispatchFromDyn}; mod gc; #[cfg(feature = "serde")] @@ -48,13 +51,16 @@ pub use crate::gc::{stats, GcStats}; /// A garbage-collected pointer type over an immutable value. /// /// See the [module level documentation](./) for more details. -pub struct Gc { +pub struct Gc { ptr_root: Cell>>, marker: PhantomData>, } #[cfg(feature = "nightly")] -impl, U: Trace + ?Sized> CoerceUnsized> for Gc {} +impl, U: ?Sized> CoerceUnsized> for Gc {} + +#[cfg(feature = "nightly")] +impl, U: ?Sized> DispatchFromDyn> for Gc {} impl Gc { /// Constructs a new `Gc` with the given value. @@ -99,7 +105,7 @@ impl Gc { } } -impl Gc { +impl Gc { /// Returns `true` if the two `Gc`s point to the same allocation. pub fn ptr_eq(this: &Gc, other: &Gc) -> bool { GcBox::ptr_eq(this.inner(), other.inner()) @@ -107,7 +113,7 @@ impl Gc { } /// Returns the given pointer with its root bit cleared. -unsafe fn clear_root_bit(ptr: NonNull>) -> NonNull> { +unsafe fn clear_root_bit(ptr: NonNull>) -> NonNull> { let ptr = ptr.as_ptr(); let data = ptr.cast::(); let addr = data as isize; @@ -115,7 +121,7 @@ unsafe fn clear_root_bit(ptr: NonNull>) -> NonNull Gc { +impl Gc { fn rooted(&self) -> bool { self.ptr_root.get().as_ptr().cast::() as usize & 1 != 0 } @@ -151,7 +157,7 @@ impl Gc { } } -impl Gc { +impl Gc { /// Consumes the `Gc`, returning the wrapped pointer. /// /// To avoid a memory leak, the pointer must be converted back into a `Gc` @@ -225,7 +231,7 @@ impl Gc { } } -impl Finalize for Gc {} +impl Finalize for Gc {} unsafe impl Trace for Gc { #[inline] @@ -263,7 +269,7 @@ unsafe impl Trace for Gc { } } -impl Clone for Gc { +impl Clone for Gc { #[inline] fn clone(&self) -> Self { unsafe { @@ -278,7 +284,7 @@ impl Clone for Gc { } } -impl Deref for Gc { +impl Deref for Gc { type Target = T; #[inline] @@ -287,7 +293,7 @@ impl Deref for Gc { } } -impl Drop for Gc { +impl Drop for Gc { #[inline] fn drop(&mut self) { // If this pointer was a root, we should unroot it. @@ -306,16 +312,16 @@ impl Default for Gc { } } -impl PartialEq for Gc { +impl PartialEq for Gc { #[inline(always)] fn eq(&self, other: &Self) -> bool { **self == **other } } -impl Eq for Gc {} +impl Eq for Gc {} -impl PartialOrd for Gc { +impl PartialOrd for Gc { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { (**self).partial_cmp(&**other) @@ -342,32 +348,32 @@ impl PartialOrd for Gc { } } -impl Ord for Gc { +impl Ord for Gc { #[inline] fn cmp(&self, other: &Self) -> Ordering { (**self).cmp(&**other) } } -impl Hash for Gc { +impl Hash for Gc { fn hash(&self, state: &mut H) { (**self).hash(state); } } -impl Display for Gc { +impl Display for Gc { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(&**self, f) } } -impl Debug for Gc { +impl Debug for Gc { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Debug::fmt(&**self, f) } } -impl fmt::Pointer for Gc { +impl fmt::Pointer for Gc { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Pointer::fmt(&self.inner(), f) } @@ -392,13 +398,13 @@ impl< } } -impl std::borrow::Borrow for Gc { +impl std::borrow::Borrow for Gc { fn borrow(&self) -> &T { self } } -impl std::convert::AsRef for Gc { +impl std::convert::AsRef for Gc { fn as_ref(&self) -> &T { self } @@ -491,7 +497,7 @@ pub struct GcCell { cell: UnsafeCell, } -impl GcCell { +impl GcCell { /// Creates a new `GcCell` containing `value`. #[inline] pub fn new(value: T) -> Self { @@ -508,7 +514,7 @@ impl GcCell { } } -impl GcCell { +impl GcCell { /// Immutably borrows the wrapped value. /// /// The borrow lasts until the returned `GcCellRef` exits scope. @@ -524,7 +530,9 @@ impl GcCell { Err(e) => panic!("{}", e), } } +} +impl GcCell { /// Mutably borrows the wrapped value. /// /// The borrow lasts until the returned `GcCellRefMut` exits scope. @@ -540,7 +548,9 @@ impl GcCell { Err(e) => panic!("{}", e), } } +} +impl GcCell { /// Immutably borrows the wrapped value, returning an error if the value is currently mutably /// borrowed. /// @@ -583,7 +593,9 @@ impl GcCell { }) } } +} +impl GcCell { /// Mutably borrows the wrapped value, returning an error if the value is currently borrowed. /// /// The borrow lasts until the returned `GcCellRefMut` exits scope. @@ -646,7 +658,7 @@ impl std::fmt::Display for BorrowMutError { } } -impl Finalize for GcCell {} +impl Finalize for GcCell {} unsafe impl Trace for GcCell { #[inline] @@ -926,30 +938,30 @@ impl<'a, T: Trace + ?Sized, U: Display + ?Sized> Display for GcCellRefMut<'a, T, unsafe impl Send for GcCell {} -impl Clone for GcCell { +impl Clone for GcCell { #[inline] fn clone(&self) -> Self { Self::new(self.borrow().clone()) } } -impl Default for GcCell { +impl Default for GcCell { #[inline] fn default() -> Self { Self::new(Default::default()) } } -impl PartialEq for GcCell { +impl PartialEq for GcCell { #[inline(always)] fn eq(&self, other: &Self) -> bool { *self.borrow() == *other.borrow() } } -impl Eq for GcCell {} +impl Eq for GcCell {} -impl PartialOrd for GcCell { +impl PartialOrd for GcCell { #[inline(always)] fn partial_cmp(&self, other: &Self) -> Option { (*self.borrow()).partial_cmp(&*other.borrow()) @@ -976,14 +988,14 @@ impl PartialOrd for GcCell { } } -impl Ord for GcCell { +impl Ord for GcCell { #[inline] fn cmp(&self, other: &GcCell) -> Ordering { (*self.borrow()).cmp(&*other.borrow()) } } -impl Debug for GcCell { +impl Debug for GcCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.flags.get().borrowed() { BorrowState::Unused | BorrowState::Reading => f diff --git a/gc/src/serde.rs b/gc/src/serde.rs index 44d86d0..6da1dd2 100644 --- a/gc/src/serde.rs +++ b/gc/src/serde.rs @@ -10,7 +10,7 @@ impl<'de, T: Deserialize<'de> + Trace> Deserialize<'de> for Gc { } } -impl Serialize for Gc { +impl Serialize for Gc { fn serialize(&self, serializer: S) -> Result where S: Serializer, diff --git a/gc/tests/gc_self_method.rs b/gc/tests/gc_self_method.rs new file mode 100644 index 0000000..6740538 --- /dev/null +++ b/gc/tests/gc_self_method.rs @@ -0,0 +1,21 @@ +#![cfg(feature = "nightly")] +#![feature(arbitrary_self_types)] + +use gc::{Finalize, Gc, Trace}; + +trait Foo: Trace { + fn foo(self: Gc); +} + +#[derive(Trace, Finalize)] +struct Bar; + +impl Foo for Bar { + fn foo(self: Gc) {} +} + +#[test] +fn gc_self_method() { + let gc: Gc = Gc::new(Bar); + gc.foo(); +}