Trying to derive gc::Trace on object with Drop

I need to implement Trace from gc crate in my own string type so that my other garbage-collected types can contain this string type.

Here's the full source without Trace derived: https://github.com/matheusdiasdesouzads/rust-scalar-value-string/blob/master/src/sv_string.rs

I'm having difficulty though because one of the backend types of my string type implements Drop to cleanup Weak interned strings and I get conflict:

impl Drop for StringRepr0 {
    fn drop(&mut self) {
        if self.m_len > INTERN_LIMIT {
            return;
        }
        let p1 = &mut *INTERNED.lock().unwrap();
        let p2 = p1.get_mut(&self.m_len);
        if p2.is_none() {
            return;
        }
        let p2 = p2.unwrap();
        let mut i: usize = 0;
        let mut f: Vec<usize> = vec![];
        for s2 in p2.iter() {
            if s2.upgrade().is_none() {
                f.push(i);
            }
            i += 1;
        }
        for &i in f.iter().rev() {
            p2.remove(i);
        }
        if p2.len() == 0 {
            p1.remove(&self.m_len);
        }
    }
}

I'm trying to derive Finalize, Trace for StringRepr0, but I get conflict. Any idea?

1 Like

The Trace derive adds a Drop impl, the relevant portion of the README is

Destructors should not access Gc/GcCell values. This is enforced by the Trace custom derive automatically implementing Drop with a safe empty drop method. Finalize should be used for cleanup instead.

Assuming your string type doesn't contain any Gc types you can use unsafe_empty_trace!();

Here's an example

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

pub struct Test(String);

unsafe impl Trace for Test {
    unsafe_empty_trace!();
}

impl Drop for Test {
    fn drop(&mut self) {
        println!("Dropping");
    }
}

impl Finalize for Test {
    fn finalize(&self) {
        println!("Finalize")
    }
}

fn main() {
    Gc::new(Test("One".into()));
    force_collect();
}

Which produces the output

   Compiling sample v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 0.66s
     Running `target/debug/main`
Finalize
Dropping
3 Likes