In a Semantic Data Model for an ECMAScript dialect, how to deal with this circular reference?

I originally wanted my compiler base to be in Node.js, because it compiles anywhere (for example, using Termux from Google Play Store you can compile and install NPM packages environmentally), however Node.js/V8 performance has been terribly bad.

Today I've my last compiler base in Adobe AIR, however it can only be easily compiled from Windows, which is not satisfying. It's a bit possible to use Adobe AIR SDK from Android through the app UserLAnd, but it's very indirectly usable.

So, I'm wanting to re-implement my compiler base in Rust, however I'm afraid of Semantic Data Model. Sometime I was trying to do the Semantic Data Model in Rust, but the popular gc crate doesn't let you do Gc<dyn Symbol>, what leads me to be limited with Rc<dyn Symbol> and Weak<dyn Symbol>.

For example, I've this ActionScript on my Semantic Data Model:

package dsc.semantics.values {
	import dsc.semantics.*;
    import dsc.semantics.constants.*;

    public class ObjectValue extends Constant {
    	private const _names:Names = new Names;
		private var _definedIn:Symbol;
    }
}

Where Constant extends Symbol and where Names leads to further Constants.

If Names contained a collection of Rc<dyn Symbol> pairs, where any element may refer to the parent Rc<dyn Symbol>, a circular reference would arise. Is there any way to use the gc crate with traits using dyn? A collection of Weak<dyn Symbol> is not viable.

Can you use a Vec and indexes?

Adding Trace as a super trait to Symbol should make it work.

This makes sense, I don't remind if I had gc::Trace as super type of Symbol. Right now I'm trying:

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

trait Symbol : Trace {
    fn some_fn(&self) {
        println!("default");
    }
}

#[derive(Trace, Finalize)]
struct F {}

impl Symbol for F {
    fn some_fn(&self) {
        println!("s");
    }
}

fn main() {
    let s: Gc<dyn Symbol> = Gc::new(F {});
    s.some_fn();
}

Right now I get this VerifyError:

error[E0308]: mismatched types
  --> src\main.rs:19:29
   |
19 |     let s: Gc<dyn Symbol> = Gc::new(F {});
   |            --------------   ^^^^^^^^^^^^^ expected trait object `dyn Symbol`, found struct `F`
   |            |
   |            expected due to this
   |
   = note: expected struct `gc::Gc<(dyn Symbol + 'static)>`
              found struct `gc::Gc<F>`

I don't see a CoerceUnsized impl for the Gc type in the docs. If indeed there isn't one, then I think this is not possible.

I tried switching to nightly toolchain. Gc<T> implements CoerceUnsized<Gc<U>>.

However when I supply the feature nightly (along with derive), compiler outputs the error:

error[E0557]: feature has been removed
 --> C:\Users\PCUser\.cargo\registry\src\github.com-1ecc6299db9ec823\gc-0.3.6\src\lib.rs:9:29
  |
9 |     feature(coerce_unsized, optin_builtin_traits, unsize, specialization)
  |                             ^^^^^^^^^^^^^^^^^^^^ feature has been removed
  |
  = note: renamed to `auto_traits`

This was fixed in this pr 2 months ago, but I guess the crate on crates.io hasn't been updated since then. You can either ask for it to be updated and wait or swap the dependency registry to github.

1 Like