How do I access nested struct members via macros?

I've got the following example code:


macro_rules! foo_func {
    ($function:ident, $foo:ident, $var:ident, $cls:ident) => {
        fn $function(self: Bar) -> $cls {
            self.$foo.$var
        }
    };
}

#[derive(Debug)]
pub struct Int {
    pub int: u32
}

impl Int {
    pub fn new() -> Int {
        Int { int: 0 }
    }
}

#[derive(Debug)]
pub struct Foo {
    pub foo: Int
}

impl Foo {
    pub fn new() -> Foo {
        Foo { foo: Int::new() }
    }
}

#[derive(Debug)]
pub struct Bar {
    pub foo: Foo
}

impl Bar {
    pub fn new() -> Bar {
        Bar { foo: Foo::new() }
    }

    foo_func!(access_foo, foo, foo, Int);
    foo_func!(access_int, foo.int, int, u32);
}


fn main() {
    let bar = Bar::new();
    println!("{:?}", bar.access_foo());
    println!("{}", bar.access_int());
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: unexpected token: `foo`
  --> src/main.rs:5:18
   |
5  |             self.$foo.$var
   |                  ^^^^
...
42 |     foo_func!(access_foo, foo, foo, Int);
   |     ------------------------------------- in this macro invocation
   |
   = note: this error originates in the macro `foo_func` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `foo`
  --> src/main.rs:5:18
   |
5  |             self.$foo.$var
   |                  ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
...
42 |     foo_func!(access_foo, foo, foo, Int);
   |     ------------------------------------- in this macro invocation
   |
   = note: this error originates in the macro `foo_func` (in Nightly builds, run with -Z macro-backtrace for more info)

error: unexpected token: `foo.int`
  --> src/main.rs:5:18
   |
5  |             self.$foo.$var
   |                  ^^^^
...
43 |     foo_func!(access_int, foo.int, int, u32);
   |     ----------------------------------------- in this macro invocation
   |
   = note: this error originates in the macro `foo_func` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `foo.int`
  --> src/main.rs:5:18
   |
5  |             self.$foo.$var
   |                  ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
...
43 |     foo_func!(access_int, foo.int, int, u32);
   |     ----------------------------------------- in this macro invocation
   |
   = note: this error originates in the macro `foo_func` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 4 previous errors

error: could not compile `playground`

To learn more, run the command again with --verbose.

The argument $foo should accept identifiers like "foo" and "foo.int". So also identifiers with a dot.
Unfortunately dots are not allowed with type "ident". I've also tried "expr", but then I get a different error.
How can I solve this?

Just after a few minutes creating this issue I've found the solution on stackoverflow:
https://stackoverflow.com/questions/65451484/passing-nested-struct-field-path-as-macro-parameter
The solution is using repetition.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.