Injected Inner Attributes do not take effect on a module

But, injected attributes on functions do take effect.

Hi, I currently have a proc macro root_macro which I want to apply at the root of a crate, say in main.rs. This macro parses main.rs and adds an attribute proc macro fn_macro to every function via the visitor pattern provided by the syn parsing library. This is accomplished by pushing my desired attribute onto the function's vector of attributes. Then, when I compile main.rs, both macros take effect. That is, I can verify that all functions in main.rs are affected by fn_macro by running cargo expand and running the program.

Now, I want root_macro to recursively perform this operation to every module in my crate. So if there is a module in main.rs like mod x;, my root_macro currently can visit all such statements and add itself to their attribute list. I simply used the same code I did previously, by just pushing the attribute onto the module's list of attributes.

However, this does not work. When I run cargo expand, all the modules are inlined, but my fn_macro is not applied to the functions inside.

What's the difference here? How come adding attributes to functions does something, but adding attributes to modules has no effect?

Is there a way I can force modules to be inlined before my macro is expanded?

Thanks. I know custom inner attributes are unstable, I just think this should be able to work since there is no ambiguity as to which macro to apply to each module, it is all the same.

You are adding the macro attribute to the mod x;'s list of attributes, not to the module itself. Syntactically there's no way for a macro to change tokens that are not given to it, like the code for a module in a different file

But in Rust, all modules eventually get inlined, right? Is there a way to force inlining to happen first? Or, is there a way for build.rs or something to apply attributes to all modules before compilation, without modifying module source code?

I thought that custom inner attributes applied at the crate root, main.rs, should have access to the entire crate's modules. It is not really an inner attribute in that case, since it only has access to main.rs. It should really be called a file attribute or something. Is there no way to access and manipulate other modules in the crate?

I think the issue is that mod foo; expands to mod foo { ... } after all it's attribute macros are expanded. These attributes may change which file the module points to, remove the module or fill in it's contents. Eager macro expansion for proc macros requires an unstable method (https://doc.rust-lang.org/stable/proc_macro/struct.TokenStream.html#method.expand_expr).

Even if general eager expansion were available, mod isn't a macro. The process that loads the module contents isn't a macro expansion. It could be treated like one, but there's no way it currently is.