Skip to content

AddBounds::Fields doesn't seem to care about the lifecycle #60

@823984418

Description

@823984418

The following code

use proc_macro2::TokenStream;
use quote::quote;
use syn::parse_quote;
use synstructure::{decl_derive, AddBounds, Structure};

decl_derive!([GcTraget, attributes(unsafe_ignore_trace)] => derive_trace);

fn derive_trace(mut s: Structure<'_>) -> TokenStream {
    s.filter(|_| true);
    let body = s.each(|bi| quote!(::regc::GcTarget::trace(#bi, token);));
    s.add_impl_generic(parse_quote!('regc_lifetime));
    s.add_bounds(AddBounds::Fields);
    s.gen_impl(quote! {
        extern crate self as regc;
        gen impl<'regc_lifetime> ::regc::GcTarget<'regc_lifetime> for @Self {
            fn trace(&self, token: &mut ::regc::GcTraceToken<'regc_lifetime>) {
                match self {
                    #body
                }
            }
        }
    })
}

in

#[derive(GcTraget)]
struct A<'c, S> {
    x: GcRootThin<'c>,
    y: Option<S>,
}

generate

struct A<'c, S> {
    x: GcRootThin<'c>,
    y: Option<S>,
}
#[allow(non_upper_case_globals)]
const _DERIVE_regc_GcTarget_regc_lifetime_FOR_A: () = {
    extern crate self as regc;
    impl<'regc_lifetime, 'c, S> ::regc::GcTarget<'regc_lifetime> for A<'c, S>
    where
        Option<S>: ::regc::GcTarget<'regc_lifetime>,
    {
        fn trace(&self, token: &mut ::regc::GcTraceToken<'regc_lifetime>) {
            match self {
                A { x: ref __binding_0, y: ref __binding_1 } => {
                    {
                        ::regc::GcTarget::trace(__binding_0, token);
                    }
                    {
                        ::regc::GcTarget::trace(__binding_1, token);
                    }
                }
            }
        }
    }
};

Missing

GcRootThin<'c>: ...

This resulted in an implementation for any lifecycle, resulting in an error:

error: lifetime may not live long enough
   --> src\lib.rs:812:10
    |
812 | #[derive(GcTraget)]
    |          ^^^^^^^^
    |          |
    |          lifetime `'regc_lifetime` defined here
    |          argument requires that `'regc_lifetime` must outlive `'c`
813 | struct A<'c, S> {
    |          -- lifetime `'c` defined here
    |
    = help: consider adding the following bound: `'regc_lifetime: 'c`
    = note: requirement occurs because of a mutable reference to `GcTraceToken<'_>`
    = note: mutable references are invariant over their type parameter
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
    = note: this error originates in the derive macro `GcTraget` (in Nightly builds, run with -Z macro-backtrace for more info)

Error disappears after adding where GcRoot.

What I mean is, in add_trait_bounds In the implementation of boundaries', there seems to be a lack of consideration for the lifecycle,but they are also part of the type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions