Skip to content

Commit e1a3ce7

Browse files
authored
T: GcSafe<'gc, T> should no longer imply T: 'gc (#32)
Clarify the lifetime and ownership for `Gc`. A Gc pointer is logically equivalent to a pair of (*mut T, &'gc Id::System). It does *not* contain a &'gc T like you would expect. This means that we can weaken the `T: 'gc` lifetime, which paves the way for temporary borrows that are shorter than the 'gc lifetime. In other words, it should eventually be possible to have &'a T even if 'a < 'gc Also, we can safely make the lifetime covariant now :) Merges #32 I had tried to make GcRebrand take advantage of generic associated types, but that was an utter failure.
1 parent 0691908 commit e1a3ce7

File tree

15 files changed

+206
-145
lines changed

15 files changed

+206
-145
lines changed

libs/context/src/collector.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
8585
owner: &Gc<'gc, O, CollectorId<Self>>,
8686
value: &Gc<'gc, V, CollectorId<Self>>,
8787
field_offset: usize
88-
) where O: GcSafe<'gc, CollectorId<Self>> + ?Sized + 'gc, V: GcSafe<'gc, CollectorId<Self>> + ?Sized + 'gc;
88+
) where O: GcSafe<'gc, CollectorId<Self>> + ?Sized, V: GcSafe<'gc, CollectorId<Self>> + ?Sized;
8989
/// The logger associated with this collector
9090
fn logger(&self) -> &Logger;
9191

@@ -302,21 +302,20 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
302302
type System = CollectorRef<C>;
303303
type RawVecRepr<'gc> = C::RawVecRepr<'gc>;
304304
// TODO: What if clients want to customize this?
305-
type ArrayRepr<'gc, T: 'gc> = zerogc::array::repr::ThinArrayRepr<'gc, T, Self>;
305+
type ArrayRepr<'gc, T> = zerogc::array::repr::ThinArrayRepr<'gc, T, Self>;
306306

307307
#[inline]
308-
fn from_gc_ptr<'a, 'gc, T>(gc: &'a Gc<'gc, T, Self>) -> &'a Self where T: ?Sized + 'gc, 'gc: 'a {
308+
fn from_gc_ptr<'a, 'gc, T>(gc: &'a Gc<'gc, T, Self>) -> &'a Self where T: ?Sized, 'gc: 'a {
309309
C::id_for_gc(gc)
310310
}
311311

312312
#[inline]
313-
fn resolve_array_id<'a, 'gc, T>(gc: &'a Self::ArrayRepr<'gc, T>) -> &'a Self where T: 'gc, 'gc: 'a {
313+
fn resolve_array_id<'a, 'gc, T>(gc: &'a Self::ArrayRepr<'gc, T>) -> &'a Self where 'gc: 'a {
314314
C::id_for_array(gc)
315315
}
316316

317317
#[inline]
318-
fn resolve_array_len<'gc, T>(repr: &ThinArrayRepr<'gc, T, Self>) -> usize
319-
where T: 'gc {
318+
fn resolve_array_len<'gc, T>(repr: &ThinArrayRepr<'gc, T, Self>) -> usize {
320319
C::resolve_array_len(repr)
321320
}
322321

@@ -325,7 +324,7 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
325324
owner: &Gc<'gc, O, Self>,
326325
value: &Gc<'gc, V, Self>,
327326
field_offset: usize
328-
) where O: GcSafe<'gc, Self> + ?Sized + 'gc, V: GcSafe<'gc, Self> + ?Sized + 'gc {
327+
) where O: GcSafe<'gc, Self> + ?Sized, V: GcSafe<'gc, Self> + ?Sized {
329328
C::gc_write_barrier(owner, value, field_offset)
330329
}
331330

@@ -341,7 +340,7 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
341340
}
342341
unsafe impl<C: ~const ConstRawCollectorImpl> const zerogc::internals::ConstCollectorId for CollectorId<C> {
343342
#[inline]
344-
fn resolve_array_len_const<'gc, T>(repr: &Self::ArrayRepr<'gc, T>) -> usize where T: 'gc {
343+
fn resolve_array_len_const<'gc, T>(repr: &Self::ArrayRepr<'gc, T>) -> usize {
345344
C::resolve_array_len_const(repr)
346345
}
347346
}
@@ -390,8 +389,8 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
390389
}
391390

392391
pub unsafe trait RawSimpleAlloc: RawCollectorImpl {
393-
unsafe fn alloc_uninit<'gc, T: GcSafe<'gc, CollectorId<Self>>>(context: &'gc CollectorContext<Self>) -> (CollectorId<Self>, *mut T);
394-
unsafe fn alloc_uninit_slice<'gc, T>(context: &'gc CollectorContext<Self>, len: usize) -> (CollectorId<Self>, *mut T)
392+
unsafe fn alloc_uninit<'gc, T: GcSafe<'gc, CollectorId<Self>>>(context: &'gc CollectorContext<Self>) -> *mut T;
393+
unsafe fn alloc_uninit_slice<'gc, T>(context: &'gc CollectorContext<Self>, len: usize) -> *mut T
395394
where T: GcSafe<'gc, CollectorId<Self>>;
396395
fn alloc_vec<'gc, T>(context: &'gc CollectorContext<Self>) -> GcVec<'gc, T, CollectorContext<Self>>
397396
where T: GcSafe<'gc, CollectorId<Self>>;
@@ -401,24 +400,24 @@ pub unsafe trait RawSimpleAlloc: RawCollectorImpl {
401400
unsafe impl<C> GcSimpleAlloc for CollectorContext<C>
402401
where C: RawSimpleAlloc {
403402
#[inline]
404-
unsafe fn alloc_uninit<'gc, T>(&'gc self) -> (CollectorId<C>, *mut T)
405-
where T: GcSafe<'gc, CollectorId<C>> + 'gc {
403+
unsafe fn alloc_uninit<'gc, T>(&'gc self) -> *mut T
404+
where T: GcSafe<'gc, CollectorId<C>> {
406405
C::alloc_uninit(self)
407406
}
408407

409408
#[inline]
410-
unsafe fn alloc_uninit_slice<'gc, T>(&'gc self, len: usize) -> (Self::Id, *mut T)
411-
where T: GcSafe<'gc, CollectorId<C>> + 'gc {
409+
unsafe fn alloc_uninit_slice<'gc, T>(&'gc self, len: usize) -> *mut T
410+
where T: GcSafe<'gc, CollectorId<C>> {
412411
C::alloc_uninit_slice(self, len)
413412
}
414413

415414
#[inline]
416-
fn alloc_vec<'gc, T>(&'gc self) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> + 'gc {
415+
fn alloc_vec<'gc, T>(&'gc self) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> {
417416
C::alloc_vec(self)
418417
}
419418

420419
#[inline]
421-
fn alloc_vec_with_capacity<'gc, T>(&'gc self, capacity: usize) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> + 'gc {
420+
fn alloc_vec_with_capacity<'gc, T>(&'gc self, capacity: usize) -> GcVec<'gc, T, Self> where T: GcSafe<'gc, CollectorId<C>> {
422421
C::alloc_vec_with_capacity(self, capacity)
423422
}
424423
}

libs/derive/src/derive.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,9 +717,6 @@ impl TraceDeriveInput {
717717
let regular = &regular.ident;
718718
generics.make_where_clause().predicates.push(parse_quote!(#regular: zerogc::NullTrace));
719719
}
720-
for ignored in &self.generics.ignored_lifetimes {
721-
generics.make_where_clause().predicates.push(parse_quote!(#ignored: 'new_gc))
722-
}
723720
generics.make_where_clause().predicates.push(parse_quote!(Self: zerogc::GcSafe<'new_gc, Id>));
724721
if let Some(ref gc_lt) = self.gc_lifetime() {
725722
return Err(Error::custom("A NullTrace type may not have a 'gc lifetime").with_span(gc_lt))
@@ -792,9 +789,6 @@ impl TraceDeriveInput {
792789
}).collect::<Vec<_>>();
793790
generics.make_where_clause().predicates.push(parse_quote!(#target: #(#rewritten_bounds)+*));
794791
}
795-
for ignored in &self.generics.ignored_lifetimes {
796-
generics.make_where_clause().predicates.push(parse_quote!(#ignored: 'new_gc));
797-
}
798792
let target_type = &self.ident;
799793

800794
let rewritten_path: Path = {
@@ -925,7 +919,7 @@ impl TraceDeriveInput {
925919
};
926920
let visit_inside_gc = if !immutable {
927921
let where_clause = quote!(where Visitor: zerogc::GcVisitor,
928-
ActualId: zerogc::CollectorId, Self: zerogc::GcSafe<'actual_gc, ActualId> + 'actual_gc);
922+
ActualId: zerogc::CollectorId, Self: zerogc::GcSafe<'actual_gc, ActualId>);
929923
Some(quote! {
930924
#[inline]
931925
unsafe fn trace_inside_gc<'actual_gc, Visitor, ActualId>(gc: &mut zerogc::Gc<'actual_gc, Self, ActualId>, visitor: &mut Visitor) -> Result<(), Visitor::Err>

libs/derive/src/lib.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,31 @@ pub(crate) fn sort_params(generics: &mut Generics) {
4545
Lifetime,
4646
Type,
4747
Const,
48-
EndPunct
4948
}
5049
let mut pairs = std::mem::take(&mut generics.params).into_pairs()
5150
.collect::<Vec<_>>();
5251
use syn::punctuated::Pair;
5352
pairs.sort_by_key(|pair| {
54-
match pair {
55-
Pair::Punctuated(syn::GenericParam::Lifetime(_), _) => ParamOrder::Lifetime,
56-
Pair::Punctuated(syn::GenericParam::Type(_), _) => ParamOrder::Type,
57-
Pair::Punctuated(syn::GenericParam::Const(_), _) => ParamOrder::Const,
58-
Pair::End(_) => ParamOrder::EndPunct,
53+
match pair.value() {
54+
syn::GenericParam::Lifetime(_) => ParamOrder::Lifetime,
55+
syn::GenericParam::Type(_) => ParamOrder::Type,
56+
syn::GenericParam::Const(_) => ParamOrder::Const,
5957
}
6058
});
59+
/*
60+
* NOTE: The `Pair::End` can only come at the end.
61+
* Now that we've sorted, it's possible the old ending
62+
* could be in the first position or some other position
63+
* before the end.
64+
*
65+
* If that's the case, then add punctuation to the end.
66+
*/
67+
if let Some(old_ending_index) = pairs.iter().position(|p| p.punct().is_none()) {
68+
if old_ending_index != pairs.len() - 1 {
69+
let value = pairs.remove(old_ending_index).into_value();
70+
pairs.insert(old_ending_index, Pair::Punctuated(value, Default::default()));
71+
}
72+
}
6173
generics.params = pairs.into_iter().collect();
6274
}
6375

libs/derive/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ impl MacroInput {
282282
let where_clause = if let Some(ref clause) = self.bounds.visit_inside_gc {
283283
clause.clone()
284284
} else {
285-
parse_quote!(where Visitor: #zerogc_crate::GcVisitor, ActualId: #zerogc_crate::CollectorId, Self: #zerogc_crate::GcSafe<'actual_gc, ActualId> + 'actual_gc)
285+
parse_quote!(where Visitor: #zerogc_crate::GcVisitor, ActualId: #zerogc_crate::CollectorId, Self: #zerogc_crate::GcSafe<'actual_gc, ActualId>)
286286
};
287287
Some(quote! {
288288
#[inline]

libs/simple/src/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,8 @@ impl GcVecHeader {
259259
///
260260
/// NOTE: Length and capacity are stored implicitly in the [GcVecHeader]
261261
#[repr(C)]
262-
pub struct SimpleVecRepr<'gc, T: GcSafe<'gc, crate::CollectorId>> {
263-
marker: PhantomData<&'gc T>,
262+
pub struct SimpleVecRepr<'gc, T: GcSafe<'gc, crate::CollectorId> + Sized> {
263+
marker: PhantomData<(*const [T], &'gc crate::CollectorId)>,
264264
}
265265
impl<'gc, T: GcSafe<'gc, crate::CollectorId>> SimpleVecRepr<'gc, T> {
266266
#[inline]

libs/simple/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use zerogc_context::utils::{ThreadId, MemorySize};
6868
use crate::alloc::{SmallArenaList, SmallArena};
6969
use crate::layout::{StaticGcType, GcType, SimpleVecRepr, DynamicObj, StaticVecType, SimpleMarkData, SimpleMarkDataSnapshot, GcHeader, BigGcObject, HeaderLayout, GcArrayHeader, GcVecHeader, GcTypeLayout};
7070

71-
use zerogc_context::collector::{RawSimpleAlloc, RawCollectorImpl};
71+
use zerogc_context::collector::{RawSimpleAlloc};
7272
use zerogc_context::handle::{GcHandleList, RawHandleImpl};
7373
use zerogc_context::{CollectionManager as AbstractCollectionManager, RawContext as AbstractRawContext, CollectorContext};
7474
use zerogc::vec::{GcRawVec};
@@ -152,23 +152,23 @@ static GLOBAL_COLLECTOR: AtomicPtr<RawSimpleCollector> = AtomicPtr::new(std::ptr
152152

153153
unsafe impl RawSimpleAlloc for RawSimpleCollector {
154154
#[inline]
155-
unsafe fn alloc_uninit<'gc, T>(context: &'gc SimpleCollectorContext) -> (CollectorId, *mut T) where T: GcSafe<'gc, crate::CollectorId> {
155+
unsafe fn alloc_uninit<'gc, T>(context: &'gc SimpleCollectorContext) -> *mut T where T: GcSafe<'gc, crate::CollectorId> {
156156
let (_header, ptr) = context.collector().heap.allocator.alloc_layout(
157157
GcHeader::LAYOUT,
158158
Layout::new::<T>(),
159159
T::STATIC_TYPE
160160
);
161-
(context.collector().id(), ptr as *mut T)
161+
ptr as *mut T
162162
}
163163

164-
unsafe fn alloc_uninit_slice<'gc, T>(context: &'gc CollectorContext<Self>, len: usize) -> (CollectorId, *mut T) where T: GcSafe<'gc, crate::CollectorId> {
164+
unsafe fn alloc_uninit_slice<'gc, T>(context: &'gc CollectorContext<Self>, len: usize) -> *mut T where T: GcSafe<'gc, crate::CollectorId> {
165165
let (header, ptr) = context.collector().heap.allocator.alloc_layout(
166166
GcArrayHeader::LAYOUT,
167167
Layout::array::<T>(len).unwrap(),
168168
<[T] as StaticGcType>::STATIC_TYPE
169169
);
170170
(*header).len = len;
171-
(context.collector().id(), ptr.cast())
171+
ptr.cast()
172172
}
173173

174174
#[inline]

src/array.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,13 @@ impl<'gc, Id: CollectorId> Display for GcString<'gc, Id> {
112112
/// This is a `#[repr(transparent)]` wrapper around
113113
/// [GcArrayRepr].
114114
#[repr(transparent)]
115-
pub struct GcArray<'gc, T: 'gc, Id: CollectorId> {
115+
pub struct GcArray<'gc, T, Id: CollectorId> {
116116
repr: Id::ArrayRepr<'gc, T>
117117
}
118118
impl<'gc, T, Id: CollectorId> GcArray<'gc, T, Id> {
119119
/// Convert this array into a slice
120120
#[inline]
121-
pub fn as_slice(&self) -> &'gc [T] {
121+
pub fn as_slice<'a>(&self) -> &'a [T] where 'gc: 'a {
122122
self.repr.as_slice()
123123
}
124124
/// Load a raw pointer to the array's value
@@ -159,7 +159,7 @@ impl<'gc, T, Id: CollectorId> GcArray<'gc, T, Id> {
159159
/// Const access to [GcString]
160160
pub trait ConstArrayAccess<'gc, T> {
161161
/// The value of the array as a slice
162-
fn as_slice_const(&self) -> &'gc [T];
162+
fn as_slice_const<'a>(&self) -> &'a [T] where 'gc: 'a;
163163
/// Load a raw pointer to the array's value
164164
fn as_raw_ptr_const(&self) -> *mut T;
165165
/// The length of this array
@@ -168,7 +168,7 @@ pub trait ConstArrayAccess<'gc, T> {
168168
// Relax T: GcSafe bound
169169
impl<'gc, T, Id: ~const ConstCollectorId> const ConstArrayAccess<'gc, T> for GcArray<'gc, T, Id> {
170170
#[inline]
171-
fn as_slice_const(&self) -> &'gc [T] {
171+
fn as_slice_const<'a>(&self) -> &'a [T] where 'gc: 'a {
172172
/*
173173
* TODO: This is horrible, but currently nessicarry
174174
* to do this in a const-fn context.
@@ -178,7 +178,7 @@ impl<'gc, T, Id: ~const ConstCollectorId> const ConstArrayAccess<'gc, T> for GcA
178178
unsafe {
179179
core::mem::transmute_copy::<
180180
Id::ArrayRepr<'gc, T>,
181-
&'gc [T]
181+
&'a [T]
182182
>(&self.repr)
183183
}
184184
},

src/array/repr.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub unsafe trait GcArrayRepr<'gc, T>: Copy + sealed::Sealed {
5454
/// The combination of pointer + length must be valid.
5555
unsafe fn from_raw_parts(ptr: NonNull<T>, len: usize) -> Self;
5656
/// Convert the value to a slice
57-
fn as_slice(&self) -> &'gc [T];
57+
fn as_slice<'a>(&self) -> &'a [T] where 'gc: 'a;
5858
/// Get a raw pointer to this array's elements.
5959
fn as_raw_ptr(&self) -> *mut T;
6060
/// Get the length of this value
@@ -67,7 +67,7 @@ pub unsafe trait GcArrayRepr<'gc, T>: Copy + sealed::Sealed {
6767
/// This type is guaranteed to be compatible with `&[T]`.
6868
/// Transmuting back and forth is safe.
6969
#[repr(transparent)]
70-
pub struct FatArrayRepr<'gc, T: 'gc, Id: CollectorId> {
70+
pub struct FatArrayRepr<'gc, T, Id: CollectorId> {
7171
slice: NonNull<[T]>,
7272
marker: PhantomData<Gc<'gc, [T], Id>>
7373
}
@@ -104,7 +104,7 @@ unsafe impl<'gc, T, Id: CollectorId> GcArrayRepr<'gc, T> for FatArrayRepr<'gc, T
104104
}
105105

106106
#[inline]
107-
fn as_slice(&self) -> &'gc [T] {
107+
fn as_slice<'a>(&self) -> &'a [T] where 'gc: 'a {
108108
unsafe { &*self.slice.as_ptr() }
109109
}
110110

@@ -127,7 +127,7 @@ unsafe impl<'gc, T, Id: CollectorId> GcArrayRepr<'gc, T> for FatArrayRepr<'gc, T
127127
/// and can be transmuted back and forth
128128
/// (assuming the appropriate invariants are met).
129129
#[repr(transparent)]
130-
pub struct ThinArrayRepr<'gc, T: 'gc, Id: CollectorId> {
130+
pub struct ThinArrayRepr<'gc, T, Id: CollectorId> {
131131
elements: NonNull<T>,
132132
marker: PhantomData<Gc<'gc, [T], Id>>
133133
}
@@ -152,7 +152,7 @@ unsafe impl<'gc, T, Id: CollectorId> GcArrayRepr<'gc, T> for ThinArrayRepr<'gc,
152152
res
153153
}
154154
#[inline]
155-
fn as_slice(&self) -> &'gc [T] {
155+
fn as_slice<'a>(&self) -> &'a [T] where 'gc: 'a {
156156
unsafe { core::slice::from_raw_parts(
157157
self.elements.as_ptr(),
158158
self.len()
@@ -173,4 +173,4 @@ unsafe impl<'gc, T, Id: CollectorId> GcArrayRepr<'gc, T> for ThinArrayRepr<'gc,
173173

174174
mod sealed {
175175
pub trait Sealed {}
176-
}
176+
}

0 commit comments

Comments
 (0)