No matter what I do, the compiler complains that Declaration name '==' is not covered by macro 'MyMacro'
The only way I've been able to resolve this is to switch to arbitrary for the names parameter.
Hashable implies Equatable, so I'm not sure if that's the source of the problem or if it's that this name doesn't contain any alphanumerics (I have plenty of declarations that begin with a leading underscore, though, so that seems unlikely).
That works! No idea why it's different for == because right above it I have named(hash(into:)), which works fine. (Maybe because == is a static function?) Either way, thanks.
Operator functions unlabel their implicitly-labeled arguments, since the labels won’t be present anyway when you call them the usual way. Whether you see this as a convenience or an inconsistency is up to your point of view!
I…guess so. The way I think of it is that it is declared the way it’s called, it’s just that “how it’s declared” includes what kind of declaration it is to decide what implicit labels to use. (Subscripts are also like this, and archaeologically pre-Swift-3 the rules were much more complicated.) I’m not sure my model is actually any more helpful than yours though!
For most functions, yes, the argument labels are part of the externally visible (API and ABI) name. But operators discard their labels when mangling as well:
I think there was even some discussion about making the rules more consistent (requiring operators and subscripts to label their arguments with an underscore) but it was considered too a source break with little benefit. That was long before macros, however.
The major source break would be for subscripts, where we can't easily change the meaning of the first argument label without it affecting a ton of users.
For operators, there aren't very many places where you can actually write their full decl name. I don't think the expression grammar allows it:
struct S {
static func == (lhs: S, _ rhs: S) -> Bool { return false }
}
let f: (S, S) -> Bool = (==) // ok, but uninteresting
let f: (S, S) -> Bool = (==(_:_:)) // error
let f: (S, S) -> Bool = (==)(_:_:) // also an error
So AFAIK the only place where something like ==(_:_:) can be written as valid Swift is in attributes, like @attached and @_implements. For those limited cases, it seems like we could make it an error to include labels for operator decl names, since code that includes the labels is already broken in other ways. Unless there are edge cases I'm missing?
To clarify, I'm only suggesting that it be an error when you write the decl name like ==(lhs:rhs:), not that we'd change operator declarations themselves to make the labels errors. That would be a bigger source break.
EDIT: I had originally written "I'm only suggesting that it be an error when you write the decl name like ==(_:_:)", which was the opposite of my intention. Corrected.
It is already illegal to declare an operator with explicit labels (just checked), so it would make sense to not allow forming such a name either. Or at least warning about it.
EDIT: I mean an error to write ==(lhs:rhs:). I think ==(_:_:) is a reasonable thing to write, especially if we ever follow through on the idea of allowing defaulted arguments on operators for capturing from context—#file and #isolation and the like.
This would be a big improvement for macros. named() does not offer auto-complete suggestions, so my usual approach is to just copy/paste the function declaration and then erase the parameter types. That's much easier than trying to remember long functions, but in this case that led to me having lhs and rhs where they were not supposed to exist.