Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instantiating structs using the macro #26

Closed
oeed opened this issue Jun 1, 2021 · 3 comments
Closed

Instantiating structs using the macro #26

oeed opened this issue Jun 1, 2021 · 3 comments
Labels
I-support This issue (I) supports the users of the project T-accepted Triage (T): Initial review accepted issue/PR as valid

Comments

@oeed
Copy link

oeed commented Jun 1, 2021

Awesome crate! Part of my needs include a situation where a number of structs have a large number of fields all instantiated the same way. The struct is simply the glue between two libraries so it's all fairly repetitive and I want to keep it as dry as possible.

I can't seem to figure out how to/if it's possible to instantiate structs using the macro though. Take this highly contrived example:

struct Example {
  one: usize,
  two: usize,
}

impl Example {
  fn inline_new() -> Self {
    Example {
      duplicate_inline! {
        [
          key;
          [ one ];
          [ two ];
        ]
        key: 0,
      }
    }
  }

  fn attr_new() -> Self {
    Example {
      #[duplicate(
        key;
        [ one ];
        [ two ];
      )]
      key: 0,
    }
  }
}

It fails with the following:

error: expected one of `,` or `}`, found `!`
  --> src/example.rs:57:23
   |
56 |     Example {
   |     ------- while parsing this struct
57 |       duplicate_inline! {
   |                       ^ expected one of `,` or `}`

error: expected non-macro attribute, found attribute macro `duplicate`
  --> src/example.rs:70:9
   |
70 |       #[duplicate(
   |         ^^^^^^^^^ not a non-macro attribute

error[E0063]: missing fields `one` and `two` in initializer of `Example`
  --> src/example.rs:56:5
   |
56 |     Example {
   |     ^^^^^^^ missing `one` and `two`

error[E0560]: struct `Example` has no field named `key`
  --> src/example.rs:75:7
   |
75 |       key: 0,
   |       ^^^ `Example` does not have this field
   |
   = note: available fields are: `one`, `two`

It seems like the macros can't operate on struct fields, is that indeed the case? Is it simply a limitation of the macro system currently?

@oeed oeed added the I-support This issue (I) supports the users of the project label Jun 1, 2021
@ghost ghost added the T-new Triage (T): Has yet to be reviewed label Jun 1, 2021
@Emoun Emoun added T-accepted Triage (T): Initial review accepted issue/PR as valid and removed T-new Triage (T): Has yet to be reviewed labels Jun 1, 2021
@Emoun
Copy link
Owner

Emoun commented Jun 1, 2021

Yes, the errors you are having are caused by rust's syntax limitations. I think you simply are not allowed to call macros in those positions.

An alternative could be:

#[duplicate(
  keys; [one: 0 , two: 0,]
)]
impl Example {
  fn inline_new() -> Self {
    Example { keys }
  }

  fn attr_new() -> Self {
    Example {keys}
  }
}

Here I have moved the macro invocation onto the impl and then put the keys variable in the struct instantiations.
This effectively doesn't make extra duplicates of the impl but simply replaces keys by the struct members.
This gets you what you want (in this example), though I realize you will have to repeat the =0 bit.

I hope this helps. I'm always on the lookout for code examples that might motivate new features to the crate, so feel to ask more or propose features. I will look into whether a feature could make your situation easier to implement.

@oeed
Copy link
Author

oeed commented Jun 2, 2021

That's good to know, thanks. Nested invocation certainly sounds like it'd be ideal for this.

Alternatively, just thinking aloud, but perhaps it'd make sense for it to be a different macro? duplicate duplicates the item it's attached to, whereas maybe there could be a macro like duplicate_inner or something that repeats inside the item, rather the whole item itself? Haven't put a ton of thought in to that though so mightn't make sense.

@Emoun
Copy link
Owner

Emoun commented Jun 3, 2021

Yes, I have also thought about a macro like duplicate_inner. I will think about how such a macro would work.

@Emoun Emoun closed this as completed Jun 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-support This issue (I) supports the users of the project T-accepted Triage (T): Initial review accepted issue/PR as valid
Projects
None yet
Development

No branches or pull requests

2 participants