As part of my work towards module-qualified names, I've added a new type to the compiler, DeclNameRef
, and adopted it across much of the frontend. If you hack on the compiler a lot, you're suddenly going to see this thing everywhere, so I thought I'd explain a few things about it.
What is it?
DeclNameRef
is used wherever the compiler is processing the name of a declaration that is defined somewhere else. (In SAT question terms, "DeclNameRef
is to DeclName
as DeclRefExpr
is to Decl
".)
For example, in this snippet of code:
struct Foo: Bar.Baz { ... }
Bar
and Baz
should be represented by DeclNameRef
s because they refer to types declared elsewhere, while Foo
should be represented by a DeclName
since it is the place where that declaration's name is actually defined.
This notion is carried beyond the parser and AST themselves and into places where we're processing information about the AST. For example, the type checker should use DeclNameRef
to refer to names extracted from the expression it's type checking and DeclName
to refer to names of overloads it's trying to match to them. (In practice, there are a few workarounds in the type checker that I'll need to address in future patches, but this is the principle, at least.)
Where is it used?
At pretty much every point between where we parse various AST nodes:
- The
TypeRepr
nodes that involve identifiers UnresolvedDeclRefExpr
UnresolvedMemberExpr
UnresolvedDotExpr
KeyPathExpr::Component
EnumElementPattern
TypeAttributes::Convention
DynamicReplacementAttr
DifferentiableAttr
DerivativeAttr
And where we look up names:
- Qualified lookup
- Unqualified lookup
- AnyObject lookup
(Not direct lookup; by that point we've started picking apart the user-written name.)
Why does it exist?
The immediate need is the module qualification proposal. Basically, anywhere you use a DeclNameRef
, you'll be able to include a module name:
struct Foo: XKit::Bar.YKit::Baz { ... }
But anything represented by a DeclName
would not support module names:
struct ZKit::Foo ... // invalid
However, this is a generally useful distinction to make because we usually match DeclNameRef
s to DeclName
s with looser rules. When we're writing something, we should know which one we're trying to do here.
This refactoring has also effectively converted several parts of the compiler that previously used Identifier
to use DeclName
instead. That essentially makes progress towards supporting enum argument label matching more fully or adding the ability to label the generic parameters of types. But those are definitely ideas for the future; for now, this ought not to change any behavior.
How does it work?
Currently, DeclNameRef
is a simple wrapper around DeclName
. You can convert a DeclName
to DeclNameRef
using its constructors. Given an existing DeclNameRef
, you can compute a version with different argument labels using withArgumentLabels()
, or strip them using withoutArgumentLabels()
. Finally, you can fetch a ValueDecl
's name as a DeclNameRef
(usually to look up its name as though the user wrote it) using ValueDecl::createNameRef()
.
Most DeclNameRef
constructors are explicit. This is intended to reduce bugs where you mix up the name you're matching with the name it's supposed to match against, but I'm still trying to figure out if this is worth the trouble.
You can get the DeclName
from a DeclNameRef
using getFullName()
(which is perhaps something of a misnomer); it also supports most of the members of DeclName
. isSimpleName()
seems to be a particularly important member in practice, because it lets you compare a DeclNameRef
to one of the Context.Id_
constants.
Eventually, DeclNameRef
will support an optional second field with a module name, but that will be part of the implementation of module qualification.
What if I don't like something about this type?
Then let's change it! I committed it in its current state because adding it touched so much of the compiler that the branch needed to be rebased constantly, but things like the set of members it should support (and their names) are totally open for discussion. Consider this thread to be an extended code review.