简体   繁体   中英

Rust macro_rules: nested repetition zips instead of producting

I'm currenly working on a macro that essentially transforms this:

// MyTrait is an existing trait
// Here I list default implementations of MyTrait's methods
trait MyTrait {
    fn f(&self, arg: i32) {
        println!("f default implementation: {}", arg);
    }

    fn g(&self) {
        println!("g default implementation");
    }
}

// No custom implementations, both f and g are default
struct A {}

// Custom implementation of g
struct B {
    fn g(..) {
        println!("g custom implementation");
    }
}

into this:

struct A {}

impl MyTrait for A {
    fn f(&self, arg: i32) {
        println!("f default implementation: {}", arg);
    }

    fn g(&self) {
        println!("g default implementation");
    }
}

struct B {}

impl MyTrait for B {
    fn f(&self, arg: i32) {
        println!("f default implementation: {}", arg);
    }

    // These two overloads will be later combined using proc_macro (or do you know a way to do it with macro_rules?)
    fn g(&self) {
        println!("g default implementation");
    }

    fn g(..) {
        println!("g custom implementation");
    }
}

Here is really simplified version of my code, minimal required to reproduce the macro issue:

macro_rules! impled_structs {
    (
        $($Struct:ident),*
        ;
        $($Method:ident),*
    ) => {
        $(
            struct $Struct {}

            impl $Struct {
                $(
                    fn $Method(&self) {}
                )*
            }
        )*
    };
}

impled_structs!(A, B; f, g, h);

The issue is that Rust just ignores $()* of $(...$Method...)* and treats the nested repetitions as a single $(...$Struct...$Method...) (ie zips them instead of cartesian producting) and throws the meta-variable `Struct` repeats 2 times, but `Method` repeats 3 times error. What can I do to make it generate its own $(...$Method...)* for every iteration of $(...$Struct...)* , ie product them?

#![feature(macro_metavar_expr)]

macro_rules! impled_structs {
    (
        $($Struct:ident),*
        ;
        $($Method:ident),*
    ) => {
        macro_rules! methods {
            () => {
                $(fn $Method(&self) {})*
            };
        }

        $(
            struct $Struct {}

            impl $Struct {
                methods!($Struct);
            }
        )*
    };
}

impled_structs!(A, B; f, g, h);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM