Manishearth / rust-gc

Simple tracing (mark and sweep) garbage collector for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

First readme example is confusing

frankmcsherry opened this issue · comments

The first example in README.md is

#[macro_use]
extern crate gc_derive;
extern crate gc;

use gc::Gc;

#[derive(Trace, Finalize)]
struct Foo {
    x: Gc<Foo>,
    y: u8,
    // ...
}

// now, `Gc<Foo>` may be used

Though it has caused some confusion because how can you construct an instance of Foo (safely)? Perhaps the type of x should be Option<Gc<Foo>>?

Yes, it would be impossible to construct an instance of Foo safely. I would definitely merge a PR which fixes this example, or I can fix it when I get the time :).

#54 is the PR you are looking for. ;)

Looks like this can be closed now.

Related question... how can I create a cycle like that? I'm making an interpreted language where... Every value has a type (type will never be null, so I don't want to make type an option). Additionally, types themselves are values. The type of a type value is the value type. type, being a value, also has a type. That type has to be type.

This is the only situation I'll need to do this, so I don't mind doing something a bit scary.

A good way to describe the problem is... We can't create a val at all, until we have a val to put in its type field.

  let mut type_type = unsafe{
    Gc::new(Varl((Val{ ty: uninitialized(), v: Void })))
  };
  unsafe{
    forget(replace(&mut (*type_type.0.get()).ty, type_type.clone()));
  }

This compiles, but it's segfaulting.

Perhaps I should just accept that the structure Gc<Varl(UnsafeCell<Val>)> is already so ugly that adding a MaybeUninit or an Option that is never None isn't that much of an additional burden, then keep all of that wrapped away.