Manishearth / rust-gc

Simple tracing (mark and sweep) garbage collector for Rust
Mozilla Public License 2.0
972 stars 50 forks source link

Recursive objects break #168

Closed Elizafox closed 1 year ago

Elizafox commented 1 year ago

Hello,

At present, something like this is impossible, due to a recursive type overflow:

use gc::{Gc, GcCell, Finalize, Trace};

#[derive(Finalize, Trace)]
struct Node<T: Trace + ?Sized + 'static> {
    prev: Option<Gc<GcCell<Node<T>>>>,
    next: Option<Gc<GcCell<Node<T>>>>,
    data: T,
}

A workaround that sacrifices type safety I've found (I would never use this in production):

use std::any::Any;
use gc::{Gc, GcCell, Trace, Finalize};

#[derive(Finalize, Trace)]
struct Node {
    prev: Option<Gc<GcCell<Node>>>,
    next: Option<Gc<GcCell<Node>>>,

    #[unsafe_ignore_trace]
    data: Box<dyn Any>,
}

Maybe I'm doing something wrong though. 🤷‍♀️

Elizafox commented 1 year ago

I think this might actually be a duplicate of #161, you can close it if it is.

andersk commented 1 year ago

This was already fixed in Git by 7a26ecafda75510c92f3b1882797523291f68aed (#162), but there hasn’t been a release yet.

Elizafox commented 1 year ago

Alright, I'll consider this fixed then. Any chance this can work on stable?

andersk commented 1 year ago

Although this was an auxiliary commit on a PR that added a feature requiring Rust nightly, it also happens to make your example work on Rust stable (if that’s what you mean).

Elizafox commented 1 year ago

Thank you so much! Yeah, this is perfect.

I'll close for now.