The macro protocols don't provide a way to create instances of the macro types, but I don't think that should limit what kinds of types people can use to define macros. Maybe their expansion(of:in:) method creates an instance and performs operations on it, because that's convenient.
If your goal is to replace the need to specify struct / enum / actor / class so we have just one version of this macro, we can do that. I used the keywords because it's easier for the implementation (we know exactly what mangled name to look for) and it emphasizes that you need to have one of these concrete type kinds---typealiases or non-nominal types won't work. I do like the idea of having a single externalMacro(module:type:), though.
It is technically redundant, yes. However, the macro implementations are mostly hidden from clients of the macro, so there would still be value in having something there on the macro declaration that you can see in the code / documentation / generated interface.
The main reason I held back on adding something like expression macro is a concern that we'd be adding a bunch of very specific declaration modifiers. expression is a simple declaration modifier, but the vision document lays out a bunch more potential ones: things like declaration, propertyWrapper, or functionBody. Some of these might need arguments (e.g., to say what kinds of names they introduce) as well. The declaration-modifier part of the grammar isn't all that easy to extend without affecting source compatibility.
Perhaps this pushes us to attributes. @expression macro isn't so bad here, and we get to re-use @propertyWrapper if we want a macro form of property wrappers. But we'd still be adding a bunch of attributes, most of which only make any sense on a macro, which bothers me a little bit. It's probably better than deriving information about where/how a macro can be used from the macro implementation, though.
There are several benefits of using protocols that I don't want to give up. For one, the compiler checks that you've provided the right signature, which we wouldn't get for free functions. Also, we can evolve the protocol a bit---for example, maybe we want to add more requirements (with default implementations) to help customize the interaction, e.g., "does this macro want to see a raw syntax tree or one on which operator folding has occurred?". Or perhaps we add an async version of the requirement later on. None of that is straightforward with the free-function approach.
Doug