Skip to content

feat!: change TraceWith trait bounds to be on the field types and not on generics when deriving Trace#82

Open
bluurryy wants to merge 2 commits intoclaytonwramsey:masterfrom
bluurryy:derive-with-field-bounds
Open

feat!: change TraceWith trait bounds to be on the field types and not on generics when deriving Trace#82
bluurryy wants to merge 2 commits intoclaytonwramsey:masterfrom
bluurryy:derive-with-field-bounds

Conversation

@bluurryy
Copy link
Copy Markdown
Contributor

NOTE: This is a breaking change!

Currently deriving Trace on a struct like...

struct GenericStruct<T> {
    fn_ptr: fn(T) -> T,
    phantom: PhantomData<T>,
}

...expands to...

unsafe impl<
    __V: ::dumpster::Visitor,
    T: ::dumpster::TraceWith<__V>,
> ::dumpster::TraceWith<__V> for GenericStruct<T> {
    #[inline]
    fn accept(&self, visitor: &mut __V) -> ::core::result::Result<(), ()> {
        ::dumpster::TraceWith::accept(&self.fn_ptr, visitor)?;
        ::dumpster::TraceWith::accept(&self.phantom, visitor)?;
        ::core::result::Result::Ok(())
    }
}

Here there is a trait bound on the generic parameter T even though both the fields implement
TraceWith regardless of T. We should only care that the field types implement TraceWith, not T, so that
GenericStruct implements Trace even if T doesn't.

To implement this I've added a new dependency synstructure that delegates to the fields and collects trait bounds. I think it's worth adding this dependency because it massively simplifies the code and would allow easily adding field attributes in the future (like a trace(ignore) (I'd send a PR if this is merged)).

With this PR the derive macro expands to...

const _: () = {
    unsafe impl<__V: ::dumpster::Visitor, T> ::dumpster::TraceWith<__V>
    for GenericStruct<T>
    where
        fn(T) -> T: ::dumpster::TraceWith<__V>,
        PhantomData<T>: ::dumpster::TraceWith<__V>,
    {
        #[inline]
        fn accept(&self, visitor: &mut __V) -> ::core::result::Result<(), ()> {
            match *self {
                GenericStruct {
                    fn_ptr: ref __binding_0,
                    phantom: ref __binding_1,
                } => {
                    {
                        ::dumpster::TraceWith::accept(__binding_0, visitor)?;
                    }
                    {
                        ::dumpster::TraceWith::accept(__binding_1, visitor)?;
                    }
                }
            }
            ::core::result::Result::Ok(())
        }
    }
};

@claytonwramsey
Copy link
Copy Markdown
Owner

Thanks! I think this is a good idea. I'll shelve this PR for a little while as I wait to bundle more breaking changes (e.g. #81) but will merge soon.

@bluurryy bluurryy force-pushed the derive-with-field-bounds branch from da4d332 to 12b0d60 Compare March 30, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants