Skip to content

Commit de3769d

Browse files
authored
Merge pull request #162 from andersk/dispatch-from-dyn
Allow trait objects with methods on `self: Gc<Self>` on nightly
2 parents a243a10 + 4aad4f8 commit de3769d

File tree

4 files changed

+72
-35
lines changed

4 files changed

+72
-35
lines changed

gc/src/gc.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl GcBoxHeader {
109109
}
110110

111111
#[repr(C)] // to justify the layout computations in GcBox::from_box, Gc::from_raw
112-
pub(crate) struct GcBox<T: Trace + ?Sized + 'static> {
112+
pub(crate) struct GcBox<T: ?Sized + 'static> {
113113
header: GcBoxHeader,
114114
data: T,
115115
}
@@ -217,22 +217,26 @@ unsafe fn insert_gcbox(gcbox: NonNull<GcBox<dyn Trace>>) {
217217
});
218218
}
219219

220-
impl<T: Trace + ?Sized> GcBox<T> {
220+
impl<T: ?Sized> GcBox<T> {
221221
/// Returns `true` if the two references refer to the same `GcBox`.
222222
pub(crate) fn ptr_eq(this: &GcBox<T>, other: &GcBox<T>) -> bool {
223223
// Use .header to ignore fat pointer vtables, to work around
224224
// https://github.com/rust-lang/rust/issues/46139
225225
ptr::eq(&this.header, &other.header)
226226
}
227+
}
227228

229+
impl<T: Trace + ?Sized> GcBox<T> {
228230
/// Marks this `GcBox` and marks through its data.
229231
pub(crate) unsafe fn trace_inner(&self) {
230232
if !self.header.is_marked() {
231233
self.header.mark();
232234
self.data.trace();
233235
}
234236
}
237+
}
235238

239+
impl<T: ?Sized> GcBox<T> {
236240
/// Increases the root count on this `GcBox`.
237241
/// Roots prevent the `GcBox` from being destroyed by the garbage collector.
238242
pub(crate) unsafe fn root_inner(&self) {

gc/src/lib.rs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
//! It is marked as non-sendable because the garbage collection only occurs
55
//! thread-locally.
66
7-
#![cfg_attr(feature = "nightly", feature(coerce_unsized, unsize))]
7+
#![cfg_attr(
8+
feature = "nightly",
9+
feature(coerce_unsized, dispatch_from_dyn, unsize)
10+
)]
811

912
use crate::gc::{GcBox, GcBoxHeader};
1013
use std::alloc::Layout;
@@ -21,7 +24,7 @@ use std::rc::Rc;
2124
#[cfg(feature = "nightly")]
2225
use std::marker::Unsize;
2326
#[cfg(feature = "nightly")]
24-
use std::ops::CoerceUnsized;
27+
use std::ops::{CoerceUnsized, DispatchFromDyn};
2528

2629
mod gc;
2730
#[cfg(feature = "serde")]
@@ -48,13 +51,16 @@ pub use crate::gc::{stats, GcStats};
4851
/// A garbage-collected pointer type over an immutable value.
4952
///
5053
/// See the [module level documentation](./) for more details.
51-
pub struct Gc<T: Trace + ?Sized + 'static> {
54+
pub struct Gc<T: ?Sized + 'static> {
5255
ptr_root: Cell<NonNull<GcBox<T>>>,
5356
marker: PhantomData<Rc<T>>,
5457
}
5558

5659
#[cfg(feature = "nightly")]
57-
impl<T: Trace + ?Sized + Unsize<U>, U: Trace + ?Sized> CoerceUnsized<Gc<U>> for Gc<T> {}
60+
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Gc<U>> for Gc<T> {}
61+
62+
#[cfg(feature = "nightly")]
63+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Gc<U>> for Gc<T> {}
5864

5965
impl<T: Trace> Gc<T> {
6066
/// Constructs a new `Gc<T>` with the given value.
@@ -99,23 +105,23 @@ impl<T: Trace + ?Sized> Gc<T> {
99105
}
100106
}
101107

102-
impl<T: Trace + ?Sized> Gc<T> {
108+
impl<T: ?Sized> Gc<T> {
103109
/// Returns `true` if the two `Gc`s point to the same allocation.
104110
pub fn ptr_eq(this: &Gc<T>, other: &Gc<T>) -> bool {
105111
GcBox::ptr_eq(this.inner(), other.inner())
106112
}
107113
}
108114

109115
/// Returns the given pointer with its root bit cleared.
110-
unsafe fn clear_root_bit<T: ?Sized + Trace>(ptr: NonNull<GcBox<T>>) -> NonNull<GcBox<T>> {
116+
unsafe fn clear_root_bit<T: ?Sized>(ptr: NonNull<GcBox<T>>) -> NonNull<GcBox<T>> {
111117
let ptr = ptr.as_ptr();
112118
let data = ptr.cast::<u8>();
113119
let addr = data as isize;
114120
let ptr = set_data_ptr(ptr, data.wrapping_offset((addr & !1) - addr));
115121
NonNull::new_unchecked(ptr)
116122
}
117123

118-
impl<T: Trace + ?Sized> Gc<T> {
124+
impl<T: ?Sized> Gc<T> {
119125
fn rooted(&self) -> bool {
120126
self.ptr_root.get().as_ptr().cast::<u8>() as usize & 1 != 0
121127
}
@@ -151,7 +157,7 @@ impl<T: Trace + ?Sized> Gc<T> {
151157
}
152158
}
153159

154-
impl<T: Trace + ?Sized> Gc<T> {
160+
impl<T: ?Sized> Gc<T> {
155161
/// Consumes the `Gc`, returning the wrapped pointer.
156162
///
157163
/// To avoid a memory leak, the pointer must be converted back into a `Gc`
@@ -225,7 +231,7 @@ impl<T: Trace + ?Sized> Gc<T> {
225231
}
226232
}
227233

228-
impl<T: Trace + ?Sized> Finalize for Gc<T> {}
234+
impl<T: ?Sized> Finalize for Gc<T> {}
229235

230236
unsafe impl<T: Trace + ?Sized> Trace for Gc<T> {
231237
#[inline]
@@ -263,7 +269,7 @@ unsafe impl<T: Trace + ?Sized> Trace for Gc<T> {
263269
}
264270
}
265271

266-
impl<T: Trace + ?Sized> Clone for Gc<T> {
272+
impl<T: ?Sized> Clone for Gc<T> {
267273
#[inline]
268274
fn clone(&self) -> Self {
269275
unsafe {
@@ -278,7 +284,7 @@ impl<T: Trace + ?Sized> Clone for Gc<T> {
278284
}
279285
}
280286

281-
impl<T: Trace + ?Sized> Deref for Gc<T> {
287+
impl<T: ?Sized> Deref for Gc<T> {
282288
type Target = T;
283289

284290
#[inline]
@@ -287,7 +293,7 @@ impl<T: Trace + ?Sized> Deref for Gc<T> {
287293
}
288294
}
289295

290-
impl<T: Trace + ?Sized> Drop for Gc<T> {
296+
impl<T: ?Sized> Drop for Gc<T> {
291297
#[inline]
292298
fn drop(&mut self) {
293299
// If this pointer was a root, we should unroot it.
@@ -306,16 +312,16 @@ impl<T: Trace + Default> Default for Gc<T> {
306312
}
307313
}
308314

309-
impl<T: Trace + ?Sized + PartialEq> PartialEq for Gc<T> {
315+
impl<T: ?Sized + PartialEq> PartialEq for Gc<T> {
310316
#[inline(always)]
311317
fn eq(&self, other: &Self) -> bool {
312318
**self == **other
313319
}
314320
}
315321

316-
impl<T: Trace + ?Sized + Eq> Eq for Gc<T> {}
322+
impl<T: ?Sized + Eq> Eq for Gc<T> {}
317323

318-
impl<T: Trace + ?Sized + PartialOrd> PartialOrd for Gc<T> {
324+
impl<T: ?Sized + PartialOrd> PartialOrd for Gc<T> {
319325
#[inline(always)]
320326
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
321327
(**self).partial_cmp(&**other)
@@ -342,32 +348,32 @@ impl<T: Trace + ?Sized + PartialOrd> PartialOrd for Gc<T> {
342348
}
343349
}
344350

345-
impl<T: Trace + ?Sized + Ord> Ord for Gc<T> {
351+
impl<T: ?Sized + Ord> Ord for Gc<T> {
346352
#[inline]
347353
fn cmp(&self, other: &Self) -> Ordering {
348354
(**self).cmp(&**other)
349355
}
350356
}
351357

352-
impl<T: Trace + ?Sized + Hash> Hash for Gc<T> {
358+
impl<T: ?Sized + Hash> Hash for Gc<T> {
353359
fn hash<H: Hasher>(&self, state: &mut H) {
354360
(**self).hash(state);
355361
}
356362
}
357363

358-
impl<T: Trace + ?Sized + Display> Display for Gc<T> {
364+
impl<T: ?Sized + Display> Display for Gc<T> {
359365
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360366
Display::fmt(&**self, f)
361367
}
362368
}
363369

364-
impl<T: Trace + ?Sized + Debug> Debug for Gc<T> {
370+
impl<T: ?Sized + Debug> Debug for Gc<T> {
365371
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366372
Debug::fmt(&**self, f)
367373
}
368374
}
369375

370-
impl<T: Trace + ?Sized> fmt::Pointer for Gc<T> {
376+
impl<T: ?Sized> fmt::Pointer for Gc<T> {
371377
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372378
fmt::Pointer::fmt(&self.inner(), f)
373379
}
@@ -392,13 +398,13 @@ impl<
392398
}
393399
}
394400

395-
impl<T: Trace + ?Sized> std::borrow::Borrow<T> for Gc<T> {
401+
impl<T: ?Sized> std::borrow::Borrow<T> for Gc<T> {
396402
fn borrow(&self) -> &T {
397403
self
398404
}
399405
}
400406

401-
impl<T: Trace + ?Sized> std::convert::AsRef<T> for Gc<T> {
407+
impl<T: ?Sized> std::convert::AsRef<T> for Gc<T> {
402408
fn as_ref(&self) -> &T {
403409
self
404410
}
@@ -491,7 +497,7 @@ pub struct GcCell<T: ?Sized + 'static> {
491497
cell: UnsafeCell<T>,
492498
}
493499

494-
impl<T: Trace> GcCell<T> {
500+
impl<T> GcCell<T> {
495501
/// Creates a new `GcCell` containing `value`.
496502
#[inline]
497503
pub fn new(value: T) -> Self {
@@ -508,7 +514,7 @@ impl<T: Trace> GcCell<T> {
508514
}
509515
}
510516

511-
impl<T: Trace + ?Sized> GcCell<T> {
517+
impl<T: ?Sized> GcCell<T> {
512518
/// Immutably borrows the wrapped value.
513519
///
514520
/// The borrow lasts until the returned `GcCellRef` exits scope.
@@ -524,7 +530,9 @@ impl<T: Trace + ?Sized> GcCell<T> {
524530
Err(e) => panic!("{}", e),
525531
}
526532
}
533+
}
527534

535+
impl<T: Trace + ?Sized> GcCell<T> {
528536
/// Mutably borrows the wrapped value.
529537
///
530538
/// The borrow lasts until the returned `GcCellRefMut` exits scope.
@@ -540,7 +548,9 @@ impl<T: Trace + ?Sized> GcCell<T> {
540548
Err(e) => panic!("{}", e),
541549
}
542550
}
551+
}
543552

553+
impl<T: ?Sized> GcCell<T> {
544554
/// Immutably borrows the wrapped value, returning an error if the value is currently mutably
545555
/// borrowed.
546556
///
@@ -583,7 +593,9 @@ impl<T: Trace + ?Sized> GcCell<T> {
583593
})
584594
}
585595
}
596+
}
586597

598+
impl<T: Trace + ?Sized> GcCell<T> {
587599
/// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
588600
///
589601
/// The borrow lasts until the returned `GcCellRefMut` exits scope.
@@ -646,7 +658,7 @@ impl std::fmt::Display for BorrowMutError {
646658
}
647659
}
648660

649-
impl<T: Trace + ?Sized> Finalize for GcCell<T> {}
661+
impl<T: ?Sized> Finalize for GcCell<T> {}
650662

651663
unsafe impl<T: Trace + ?Sized> Trace for GcCell<T> {
652664
#[inline]
@@ -926,30 +938,30 @@ impl<'a, T: Trace + ?Sized, U: Display + ?Sized> Display for GcCellRefMut<'a, T,
926938

927939
unsafe impl<T: ?Sized + Send> Send for GcCell<T> {}
928940

929-
impl<T: Trace + Clone> Clone for GcCell<T> {
941+
impl<T: Clone> Clone for GcCell<T> {
930942
#[inline]
931943
fn clone(&self) -> Self {
932944
Self::new(self.borrow().clone())
933945
}
934946
}
935947

936-
impl<T: Trace + Default> Default for GcCell<T> {
948+
impl<T: Default> Default for GcCell<T> {
937949
#[inline]
938950
fn default() -> Self {
939951
Self::new(Default::default())
940952
}
941953
}
942954

943-
impl<T: Trace + ?Sized + PartialEq> PartialEq for GcCell<T> {
955+
impl<T: ?Sized + PartialEq> PartialEq for GcCell<T> {
944956
#[inline(always)]
945957
fn eq(&self, other: &Self) -> bool {
946958
*self.borrow() == *other.borrow()
947959
}
948960
}
949961

950-
impl<T: Trace + ?Sized + Eq> Eq for GcCell<T> {}
962+
impl<T: ?Sized + Eq> Eq for GcCell<T> {}
951963

952-
impl<T: Trace + ?Sized + PartialOrd> PartialOrd for GcCell<T> {
964+
impl<T: ?Sized + PartialOrd> PartialOrd for GcCell<T> {
953965
#[inline(always)]
954966
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
955967
(*self.borrow()).partial_cmp(&*other.borrow())
@@ -976,14 +988,14 @@ impl<T: Trace + ?Sized + PartialOrd> PartialOrd for GcCell<T> {
976988
}
977989
}
978990

979-
impl<T: Trace + ?Sized + Ord> Ord for GcCell<T> {
991+
impl<T: ?Sized + Ord> Ord for GcCell<T> {
980992
#[inline]
981993
fn cmp(&self, other: &GcCell<T>) -> Ordering {
982994
(*self.borrow()).cmp(&*other.borrow())
983995
}
984996
}
985997

986-
impl<T: Trace + ?Sized + Debug> Debug for GcCell<T> {
998+
impl<T: ?Sized + Debug> Debug for GcCell<T> {
987999
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9881000
match self.flags.get().borrowed() {
9891001
BorrowState::Unused | BorrowState::Reading => f

gc/src/serde.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ impl<'de, T: Deserialize<'de> + Trace> Deserialize<'de> for Gc<T> {
1010
}
1111
}
1212

13-
impl<T: Serialize + Trace> Serialize for Gc<T> {
13+
impl<T: Serialize> Serialize for Gc<T> {
1414
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1515
where
1616
S: Serializer,

gc/tests/gc_self_method.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![cfg(feature = "nightly")]
2+
#![feature(arbitrary_self_types)]
3+
4+
use gc::{Finalize, Gc, Trace};
5+
6+
trait Foo: Trace {
7+
fn foo(self: Gc<Self>);
8+
}
9+
10+
#[derive(Trace, Finalize)]
11+
struct Bar;
12+
13+
impl Foo for Bar {
14+
fn foo(self: Gc<Bar>) {}
15+
}
16+
17+
#[test]
18+
fn gc_self_method() {
19+
let gc: Gc<dyn Foo> = Gc::new(Bar);
20+
gc.foo();
21+
}

0 commit comments

Comments
 (0)