rust_cc

Derive Macro Trace

Source
#[derive(Trace)]
{
    // Attributes available to this derive:
    #[rust_cc]
}
Available on crate feature derive only.
Expand description

Derive macro for safely deriving Trace implementations.

The derived implementation calls the trace method on every field of the implementing type.

§Ignoring fields

The #[rust_cc(ignore)] attribute can be used to avoid tracing a field (or variant, in case of an enum). This may be useful, for example, if the field’s type doesn’t implement Trace, like external library types or some types from std.

Not tracing a field is safe, although it may lead to memory leaks if the ignored field contains any Cc.

§Automatic Drop implementation

This macro enforces the Drop-related safety requirements of Trace by always emitting an empty Drop implementation for the implementing type.

The #[rust_cc(unsafe_no_drop)] attribute can be used to suppress the automatic Drop implementation, allowing to implement a custom one. Using this attribute is considered unsafe and must respect the safety requirements of Trace.

Safe alternatives to #[rust_cc(unsafe_no_drop)] are finalizers and cleaners.

§Example

#[derive(Trace)]
struct Foo<A: Trace + 'static, B: Trace + 'static> {
    a_field: Cc<A>,
    another_field: Cc<B>,
}

Ignoring a field:

#[derive(Trace)]
struct Foo<T: Trace + 'static> {
    traced_field: Cc<T>,
    #[rust_cc(ignore)] // Cell doesn't implement Trace, let's ignore it
    ignored_field: Cell<i32>, // ignored_field doesn't contain any Cc, so there will be no memory leak
}

#[derive(Trace)]
enum Bar<T: Trace + 'static> {
    #[rust_cc(ignore)] // Ignores the A variant
    A {
        // ...
    },
    B(Cc<T>, #[rust_cc(ignore)] Cell<u32>), // Only the Cell is ignored
}

Implementing a custom Drop implementation:

#[derive(Trace)]
#[rust_cc(unsafe_no_drop)] // UNSAFE!!!
struct Foo {
    // ...
}

impl Drop for Foo {
    fn drop(&mut self) {
        // MUST respect the safety requirements of Trace
    }
}