We could just have three passes: load, expand, load again, meaning macros can introduce lints etc., but not other macros.

(I think this is actually close to the only thing that works, since any macro that's define in a crate loaded from a macro will be undefined on the first expansion run... unless additional plugins are loaded *while* expanding.)

The approach you have here is certainly the most conservative, and should work for now. I guess other approaches should go through an RFC.