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
@@ -56,6 +56,7 @@ fn F() {
// CHECK:STDOUT: %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
// CHECK:STDOUT: %Y.impl_witness: <witness> = impl_witness file.%Y.impl_witness_table [concrete]
// CHECK:STDOUT: %W.impl_witness: <witness> = impl_witness file.%W.impl_witness_table [concrete]
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self [symbolic_self]
// CHECK:STDOUT: %D: %Y.type = bind_symbolic_name D, 0 [symbolic]
// CHECK:STDOUT: %pattern_type.667: type = pattern_type %Y.type [concrete]
// CHECK:STDOUT: %CC.type: type = generic_class_type @CC [concrete]
@@ -137,7 +138,10 @@ fn F() {
// CHECK:STDOUT: %CC.decl: %CC.type = class_decl @CC [concrete = constants.%CC.generic] {
// CHECK:STDOUT: %D.patt: %pattern_type.667 = symbolic_binding_pattern D, 0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]
// CHECK:STDOUT: %.loc12: type = splice_block %Y.ref [concrete = constants.%Y.type] {
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
// CHECK:STDOUT: %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]
// CHECK:STDOUT: }
// CHECK:STDOUT: %D.loc12_10.2: %Y.type = bind_symbolic_name D, 0 [symbolic = %D.loc12_10.1 (constants.%D)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}
@@ -152,6 +156,7 @@ fn F() {
// CHECK:STDOUT: %CC.loc19_29.1: type = class_type @CC, @CC(constants.%Y.facet.7ec) [symbolic = %CC.loc19_29.2 (constants.%CC.d02)]
// CHECK:STDOUT: %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]
// CHECK:STDOUT: %.loc19_20.1: type = splice_block %.loc19_20.3 [concrete = constants.%facet_type] {
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
// CHECK:STDOUT: %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]
// CHECK:STDOUT: %W.ref: type = name_ref W, file.%W.decl [concrete = constants.%W.type]
// CHECK:STDOUT: %impl.elem0: %.2af = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]