Modify struct attributes with procedural attribute macro after struct declaration

I was wondering if it was possible to modify fields of a struct after its first declaration, like in the implementation of that struct for example using a procedural attribute macro.

Example:

struct MyStruct {
  name_value: String,
}

impl MyStruct {
  #[my_proc_attribute_macro] // Creates `age_value`
  fn age() -> usize {
    0
  }
}

let my_struct = MyStruct {
  name_value: String::new(),
  age_value:  0,
};

Is it possible to do something that acts like that ?
From my understanding, it's not, but I could very be wrong.
Even tho that example doesn't really make sens, it can be useful for some cases.

No they can't. The general principle is that you should think of an attribute macro like

impl MyStruct {
  #[my_proc_attribute_macro] // Creates `age_value`
  fn age() -> usize {
    0
  }
}

as a function my_proc_attribute_macro[1] that gets the source code it's attached to

  fn age() -> usize {
    0
  }

as input[2] and returns new code that replaces the original.

It cannot really do anything beyond inspecting the code it gets[3] syntactically and produce new code in that place instead.

Some macros might do more fancy things, like try to access some global states via statics with interior mutability, or access the file system to get more information, etc, but that's not the most common thing to do, it also doesn't allow the macro to expand anywhere other than where it's declared, and (for the case of keeping global state) might not stay properly supported in the future.


What you could do of course is make a macro that just gets the whole thing as input, and re-writes it accordingly. E.g. a function-style macro that's called like

handly_my_attribute! { // finds (and removes) `#[my_attribute]`,
                       // and creates `age_value` in `MyStruct` accordingly
  struct MyStruct {
    name_value: String,
  }

  impl MyStruct {
    #[my_attribute]
    fn age() -> usize {
      0
    }
  }

}

  1. not much unlike a simple fn my_proc_attribute_macro(input: String) -> String though the true signature looks a bit different ↩︎

  2. think a String representing the code, though in reality it's a TokenString, but that's quite similar to a string for many intents and purposes ↩︎

  3. and possible arguments it gets like #[macro(arguments here...)] ↩︎

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.