Add the .Self name for the type expression of a compile time binding (#5937)

We add a virtual node (`CompileTimeBindingPatternStart`) as the first
child of `CompileTimeBindingPattern` which holds the identifier
underneath it, so that it is checked just before the type expression of
the `CompileTimeBindingPattern`. When we reach this virtual node during
check, we add `.Self` as a name in the current scope, and when we reach
`CompileTimeBindingPattern` we remove it from scope, which ensures it's
present during only the checking of the type expression for the compile
time pattern.

At the moment the `.Self` has a different type (it's a `TypeType`) than
other `.Self` in the facet type (which are a single `FacetType`), but
the intention is to immediately substitute it out of the facet type
entirely, replacing it with a reference to the compile time binding (a
`BindSymbolicName`) itself. A TODO has been added for this.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Dana Jansens
2025-08-12 16:27:07 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent 2e509e9103
commit 4b0e2b03b6
172 changed files with 2381 additions and 1034 deletions
+11 -7
View File
@@ -35,27 +35,23 @@ auto HandleBindingPattern(Context& context) -> void {
// A `template` keyword may precede the name.
auto template_token = context.ConsumeIf(Lex::TokenKind::Template);
// The first item should be an identifier or `self`.
bool has_name = false;
// The first item should be an identifier, the placeholder `_`, or `self`.
if (auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier)) {
context.AddLeafNode(NodeKind::IdentifierNameNotBeforeParams, *identifier);
has_name = true;
} else if (auto self =
context.ConsumeIf(Lex::TokenKind::SelfValueIdentifier)) {
// Checking will validate the `self` is only declared in the implicit
// parameter list of a function.
context.AddLeafNode(NodeKind::SelfValueName, *self);
has_name = true;
} else if (auto underscore = context.ConsumeIf(Lex::TokenKind::Underscore)) {
context.AddLeafNode(NodeKind::UnderscoreName, *underscore);
has_name = true;
}
if (!has_name) {
} else {
// Add a placeholder for the name.
context.AddLeafNode(NodeKind::IdentifierNameNotBeforeParams,
*context.position(), /*has_error=*/true);
on_error(/*expected_name=*/true);
}
if (auto token_kind = context.PositionKind();
token_kind == Lex::TokenKind::Colon ||
token_kind == Lex::TokenKind::ColonExclaim) {
@@ -77,6 +73,14 @@ auto HandleBindingPattern(Context& context) -> void {
: StateKind::BindingPatternFinishAsGeneric;
// Use the `:` or `:!` for the root node.
state.token = context.Consume();
if (token_kind == Lex::TokenKind::ColonExclaim) {
// Add a virtual node before the compile time binding's type
// expression.
context.AddNode(NodeKind::CompileTimeBindingPatternStart, state.token,
state.has_error);
}
context.PushState(state);
context.PushStateForExpr(PrecedenceGroup::ForType());
} else {