How to implment copy field defined by macro

struct Base {
    a: i32
}


#[extend(Base)]
struct B {
    b: bool
}
// how to implement extends macro
// expand macro will copy all fields of `struct Base` to B
struct B {
    a: i32,
    b: bool
}



(Playground)

You don't. The only thing macros have access to are the arguments provided to them. In the case of an attribute macro like this, that would be the single identifier token Base, and the definition of the struct B. The extend macro has absolutely no way of knowing what the definition of Base is.

One way around this is to introduce another macro attached to Base which saves the definition of Base somewhere else so that extend can read it back later. But, to be honest, I really don't know if that's something you should do. Currently, I believe macros are expanded in lexical order, but I don't know that this will remain true (for example: maybe in the future macros will expand in parallel?).

In addition, it raises questions like "what happens if Base is in a different module?", "what happens if there's more than one Base?", "how does this interact with incremental compilation?", etc. Things might have changed, but I'm not aware of the compiler making any guarantees around these.

1 Like

Also why do you want this behavior? Rust structs doesn't implies indirection, there's no major cost to wrap some fields with a base struct.

1 Like

Got
I don't think the compiler might support this, and if it does, I think there should be some limitations, such as the need for Base to appear in the context of using macros, and more

I have some similar structs, they have some of the same properties, some are different, I want to be able to reuse existing code when defining it, so that it can be easily modified, I currently use generics to handle it, but the generics will require me to add a level, so I want to know if it can be solved by macros

struct Base {
    base: i32
}


struct A<T> {
    base: bool,
    a: T
}

struct B<T> {
    base: bool,
    b: T
}

Here is how you would apply @Hyeonu's suggestion to wrap a base struct, to get the effect shown in your original post.

struct Base {
    a: i32,
}

struct B {
    base: Base,
    b: bool,
}

No generics are needed. Sometimes there is a reason to use generics for a purpose of this kind, but in that case, you would put the generic on the base struct, not the extension:

struct Base<T> {
    a: i32,
    extra: T,
}

struct B {
    b: bool,
}

// then use Base<B> or Base<A>, etc.
1 Like

yes , That's what I'm doing now. But I had to add one more level.If extend can be implemented, it can be flatten.