I've been in trouble when using tracing (or mark-n-sweep) garbage collector libraries, mainly because I tried to inherit a trait. In practice previously, with a symbol table for my own language's compiler, I got a suggestion in using Weak<RefCell<T>> (and keep a strong
Rc refererence in a symbol pool), however this way I can't have two or more references to the same resource in the same scope. Another thing I did before this is use the gc crate, however Gc cannot be used as self parameter.
Another possibility is to use unsafe code, use struct Symbol instead of trait Symbol and a [repr(C)] attribute, but even with unsafe the code gets weird.
Possible solutions
a) Proper reference types (struct(ref)) and struct(ref) subtypes
There's a Rust dialect that supports a struct(gc) annotation to indicate the struct is by-reference. And WebAssembly supports reference types. So why not do the same and support inheritance together, which is a benefit for compiler developers, among other purposes?
Instead of struct(gc), it could be struct(ref), since ref is an existing keyword and gc would need to be a context keyword.
How it'd look like:
struct(ref) Symbol {
}
impl Symbol {
    fn method_that_takes_self(&self) {
    }
}
struct(ref) StringConstant: Symbol {
}
impl StringConstant {
    #[override]
    fn method_that_takes_self(&self) {
    }
}
// covariant conversion
let s: &Symbol = StringConstant { ... };
// contravariant conversion
let c = s as StringConstant;
let c = s.try_into::<StringConstant>();
It'd implement:
- 
std::clone::Clone(no way to override) std::marker::Copystd::convert::TryInto- Field inheritance
 - Method inheritance and overriding
 - Instance-of test (do know what syntax or method could fit)
 
b) Smart pointer as self parameter
There's also another way instead of the feature a): supporting a Gc-like smart pointer as a self parameter (and thus you use a trait). But I believe proper reference types are more efficient, because for a trait to be used, several default methods are reimplemented for different types (like is_string_constant to determine whether a Symbol is a StringConstant object), for example:
trait Symbol {
    fn is_string_constant(&self) -> bool { false }
    fn method_that_takes_self(self: &Gc<Self>) {
    }
}
struct StringConstant {
}
impl Symbol for StringConstant {
    fn is_string_constant(&self) -> bool { true }
    fn method_that_takes_self(self: &Gc<Self>) {
    }
}