Diagnose where in a binding that introduces a .Self that does not refer to the binding (#7517)

This is in addition to finding a `where` on the RHS of another `where`.
Since a generic binding introduces `.Self`, any `where` expression that
isn't part of a facet type modifying the binding itself would introduce
an ambiguous `.Self`.

Add virtual parse nodes for let, var, and form bindings, which goes
before the type. This allows us to track if `where` appears in the
binding's type. We only need to look for an invalid `where` if any
appeared in the type. We combine these three nodes together into a
single node kind, which requires us to remove the name from it as a
child. We move it up to the Pattern node again, and rename the
PatternStart nodes to PatternTypeStart as they are now located in the
middle of the Pattern nodes, just before the type.

And we only need to thaw `.Self` in generic bindings. Non-generic
bindings can only have `.Self` through a `where` expression, since the
name is not provided otherwise to non-generic bindings. And `where`
expressions thaw their `.Self` independently. So the binding only needs
to thaw a `.Self` that it introduced, which is only for generic
bindings.
This commit is contained in:
Dana Jansens
2026-07-22 16:45:00 +00:00
committed by GitHub
parent 21dc5cde04
commit d2ac9b3933
170 changed files with 1858 additions and 1314 deletions
+8 -4
View File
@@ -163,7 +163,8 @@ auto HandleBindingPattern(Context& context) -> void {
return;
}
on_error(/*expected_name=*/false);
// Add a substitute for a type node.
// Add a substitute for the identifier name and virtual type-start nodes.
context.AddInvalidParse(*context.position());
context.AddInvalidParse(*context.position());
context.PushState(state, StateKind::BindingPatternFinishAsRegular);
return;
@@ -255,10 +256,13 @@ auto HandleBindingPattern(Context& context) -> void {
// Use the `:` or `:?` for the root node.
state.token = context.Consume();
// Add a virtual node before the binding's type expression.
if (!is_form && resolved_generic) {
// Add a virtual node before the compile time binding's type expression.
context.AddNode(NodeKind::CompileTimeBindingPatternStart, state.token,
state.has_error);
context.AddLeafNode(NodeKind::CompileTimeBindingPatternTypeStart,
state.token, state.has_error);
} else {
context.AddLeafNode(NodeKind::BindingPatternTypeStart, state.token,
state.has_error);
}
context.PushState(state);