Replace :! binding syntax with phase keywords and contextual defaults (#7479)

Implement the toolchain side of proposal #7254, removing the `:!`
binding
syntax for generic and template parameters in favor of the keywords
`generic`,
`template`, and `runtime` plus contextual defaults for phase.

For valid programs this is semantics-preserving: each binding resolves
to the
same phase, and produces the same SemIR, as it did under `:!`/`:`. The
parser
derives a binding's phase from its syntactic context plus any explicit
phase
keyword; new diagnostics and error recovery for misused keywords are
described
below.

Implementation details for each component:

- Lexer: remove the `:!` (`ColonExclaim`) token, move its virtual
parse-node
  budget onto `:`, and add the `generic` and `runtime` keywords.
- Parser: thread a `BindingContext` (`ExplicitParam`, `DeducedParam`, or
`CompileTimeEntityParam`) from declaration introducers down through
parameter
lists to each binding pattern, using a one-token lookahead to
distinguish a
name-qualifier parameter list from a declaration's own final list.
Parameters
of a compile-time entity (`class`, `interface`, `constraint`, `choice`,
`alias`, `export`, `namespace`) and deduced `[]` parameters default to
checked
generic; explicit function parameters and local bindings default to
runtime.
`HandleBindingPattern` resolves the phase from that context plus the
keyword: a
`generic` keyword needs no node of its own (the phase is carried by the
  binding's node kind), while a `runtime` keyword is preserved as a
`RuntimeBindingName` node so `check` can name it in a diagnostic. A
phase
keyword that is merely redundant with the contextual default is
diagnosed
  here, without invalidating the parse tree.
- Check: a phase keyword that is invalid for its context (for example
`runtime`
on a checked-generic parameter) is diagnosed here, and recovers by
building an
error binding that still introduces the name so that later uses of it do
not
  produce cascading errors.

The removed `:!` syntax is now rejected as an ordinary parse error.

The `form`/`:?`/`->?` ("extended types") portion of proposal #7254 is
left for a
separate change.

Assisted-by: Claude Code
This commit is contained in:
Chandler Carruth
2026-07-11 01:22:44 +00:00
committed by GitHub
parent bf106c3b4b
commit 8be274cf60
482 changed files with 16917 additions and 16226 deletions
@@ -17,8 +17,8 @@ fn F1() {}
fn F2() -> i32 { return 0; }
fn F3(_: i32) {}
fn HasGenericArg(T:! type, a: T) { a; }
fn HasDeducedArg[T:! type](a: T) { a; }
fn HasGenericArg(generic T: type, a: T) { a; }
fn HasDeducedArg[T: type](a: T) { a; }
// --- function.carbon
@@ -87,12 +87,12 @@ library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_todo_generic.carbon:[[@LINE+9]]:1: in import [InImport]
// CHECK:STDERR: other.carbon:7:1: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch]
// CHECK:STDERR: fn HasGenericArg(T:! type, a: T) { a; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn HasGenericArg(generic T: type, a: T) { a; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_todo_generic.carbon:[[@LINE+5]]:1: in import [InImport]
// CHECK:STDERR: other.carbon:7:1: note: calling function declared here [InCallToEntity]
// CHECK:STDERR: fn HasGenericArg(T:! type, a: T) { a; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn HasGenericArg(generic T: type, a: T) { a; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
import Other;
import Cpp inline '''
@@ -30,7 +30,7 @@ class B {
}
}
fn F[T:! I](t: T) {
fn F[T: I](t: T) {
t.Doit();
}
@@ -49,10 +49,10 @@ library "[[@TEST_NAME]]";
import Cpp;
// CHECK:STDERR: fail_todo_non_type_generic.carbon:[[@LINE+4]]:1: error: semantics TODO: `binding maps to a non-type template parameter` [SemanticsTodo]
// CHECK:STDERR: fn F[unused N:! i32]() {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn F[unused N: i32]() {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
fn F[unused N:! i32]() {}
fn F[unused N: i32]() {}
inline Cpp '''
void G() {
@@ -72,7 +72,7 @@ void G() {
library "[[@TEST_NAME]]";
import Cpp;
fn F[T:! type](unused t: T*) {}
fn F[T: type](unused t: T*) {}
inline Cpp '''
void G() {
@@ -81,9 +81,9 @@ void G() {
// CHECK:STDERR: fail_todo_generic_pointer.carbon:[[@LINE+7]]:3: error: no matching function for call to 'F' [CppInteropParseError]
// CHECK:STDERR: 17 | Carbon::F(p);
// CHECK:STDERR: | ^~~~~~~~~
// CHECK:STDERR: fail_todo_generic_pointer.carbon:[[@LINE-9]]:30: note: candidate template ignored: deduced type 'T * _Nonnull' of 1st parameter does not match adjusted type 'int * _Nonnull' of argument [with T = int] [CppInteropParseNote]
// CHECK:STDERR: 4 | fn F[T:! type](unused t: T*) {}
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_todo_generic_pointer.carbon:[[@LINE-9]]:29: note: candidate template ignored: deduced type 'T * _Nonnull' of 1st parameter does not match adjusted type 'int * _Nonnull' of argument [with T = int] [CppInteropParseNote]
// CHECK:STDERR: 4 | fn F[T: type](unused t: T*) {}
// CHECK:STDERR: | ^
// CHECK:STDERR:
Carbon::F(p);
}
@@ -93,8 +93,8 @@ void G() {
library "[[@TEST_NAME]]";
import Cpp;
class A(T:! type) {
fn F[U:! type](x: T, y: U);
class A(T: type) {
fn F[U: type](x: T, y: U);
}
alias B = A(i32);
@@ -121,10 +121,10 @@ library "[[@TEST_NAME]]";
import Cpp;
// CHECK:STDERR: fail_generic_unsupported_type.carbon:[[@LINE+4]]:1: error: semantics TODO: `failed to import C++ type` [SemanticsTodo]
// CHECK:STDERR: fn F[T:! type](unused t: T) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn F[T: type](unused t: T) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
fn F[T:! type](unused t: T) {}
fn F[T: type](unused t: T) {}
inline Cpp '''
void G() {
@@ -132,9 +132,9 @@ void G() {
// CHECK:STDERR: fail_generic_unsupported_type.carbon:[[@LINE+7]]:3: error: no matching function for call to 'F' [CppInteropParseError]
// CHECK:STDERR: 20 | Carbon::F(x);
// CHECK:STDERR: | ^~~~~~~~~
// CHECK:STDERR: fail_generic_unsupported_type.carbon:[[@LINE-8]]:29: note: candidate template ignored: substitution failure [with T = volatile int] [CppInteropParseNote]
// CHECK:STDERR: 8 | fn F[T:! type](unused t: T) {}
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_generic_unsupported_type.carbon:[[@LINE-8]]:28: note: candidate template ignored: substitution failure [with T = volatile int] [CppInteropParseNote]
// CHECK:STDERR: 8 | fn F[T: type](unused t: T) {}
// CHECK:STDERR: | ^
// CHECK:STDERR:
Carbon::F(x);
}
@@ -231,21 +231,21 @@ void G() {
// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {}
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %T.patt.loc20_7.1: %pattern_type.6cb = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc20_7.2 (constants.%T.patt)]
// CHECK:STDOUT: %t.param_patt.loc20_14.1: @F.%pattern_type (%pattern_type.b3a) = value_param_pattern [symbolic = %t.param_patt.loc20_14.2 (constants.%t.param_patt.5db)]
// CHECK:STDOUT: %t.patt.loc20_14.1: @F.%pattern_type (%pattern_type.b3a) = at_binding_pattern t, %t.param_patt.loc20_14.1 [symbolic = %t.patt.loc20_14.2 (constants.%t.patt.030)]
// CHECK:STDOUT: %t.param_patt.loc20_13.1: @F.%pattern_type (%pattern_type.b3a) = value_param_pattern [symbolic = %t.param_patt.loc20_13.2 (constants.%t.param_patt.5db)]
// CHECK:STDOUT: %t.patt.loc20_13.1: @F.%pattern_type (%pattern_type.b3a) = at_binding_pattern t, %t.param_patt.loc20_13.1 [symbolic = %t.patt.loc20_13.2 (constants.%t.patt.030)]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc20_10: type = splice_block %I.ref [concrete = constants.%I.type] {
// CHECK:STDOUT: %.loc20_9: type = splice_block %I.ref [concrete = constants.%I.type] {
// CHECK:STDOUT: %.Self.frozen: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen]
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
// CHECK:STDOUT: }
// CHECK:STDOUT: %T.loc20_7.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc20_7.1 (constants.%T)]
// CHECK:STDOUT: %t.param: @F.%T.as_type.loc20_16.1 (%T.as_type) = value_param call_param0
// CHECK:STDOUT: %.loc20_16.1: type = splice_block %.loc20_16.2 [symbolic = %T.as_type.loc20_16.1 (constants.%T.as_type)] {
// CHECK:STDOUT: %t.param: @F.%T.as_type.loc20_15.1 (%T.as_type) = value_param call_param0
// CHECK:STDOUT: %.loc20_15.1: type = splice_block %.loc20_15.2 [symbolic = %T.as_type.loc20_15.1 (constants.%T.as_type)] {
// CHECK:STDOUT: %T.ref: %I.type = name_ref T, %T.loc20_7.2 [symbolic = %T.loc20_7.1 (constants.%T)]
// CHECK:STDOUT: %T.as_type.loc20_16.2: type = facet_access_type %T.ref [symbolic = %T.as_type.loc20_16.1 (constants.%T.as_type)]
// CHECK:STDOUT: %.loc20_16.2: type = converted %T.ref, %T.as_type.loc20_16.2 [symbolic = %T.as_type.loc20_16.1 (constants.%T.as_type)]
// CHECK:STDOUT: %T.as_type.loc20_15.2: type = facet_access_type %T.ref [symbolic = %T.as_type.loc20_15.1 (constants.%T.as_type)]
// CHECK:STDOUT: %.loc20_15.2: type = converted %T.ref, %T.as_type.loc20_15.2 [symbolic = %T.as_type.loc20_15.1 (constants.%T.as_type)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %t: @F.%T.as_type.loc20_16.1 (%T.as_type) = wrapper_binding t, %t.param
// CHECK:STDOUT: %t: @F.%T.as_type.loc20_15.1 (%T.as_type) = wrapper_binding t, %t.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: inline_cpp "void G() {\n Carbon::A a;\n Carbon::B b;\n Carbon::F(a);\n Carbon::F(b);\n}\n"
@@ -369,22 +369,22 @@ void G() {
// CHECK:STDOUT: generic fn @F(%T.loc20_7.2: %I.type) {
// CHECK:STDOUT: %T.patt.loc20_7.2: %pattern_type.6cb = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc20_7.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.loc20_7.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc20_7.1 (constants.%T)]
// CHECK:STDOUT: %T.as_type.loc20_16.1: type = facet_access_type %T.loc20_7.1 [symbolic = %T.as_type.loc20_16.1 (constants.%T.as_type)]
// CHECK:STDOUT: %pattern_type: type = pattern_type %T.as_type.loc20_16.1 [symbolic = %pattern_type (constants.%pattern_type.b3a)]
// CHECK:STDOUT: %t.param_patt.loc20_14.2: @F.%pattern_type (%pattern_type.b3a) = value_param_pattern [symbolic = %t.param_patt.loc20_14.2 (constants.%t.param_patt.5db)]
// CHECK:STDOUT: %t.patt.loc20_14.2: @F.%pattern_type (%pattern_type.b3a) = at_binding_pattern t, %t.param_patt.loc20_14.2 [symbolic = %t.patt.loc20_14.2 (constants.%t.patt.030)]
// CHECK:STDOUT: %T.as_type.loc20_15.1: type = facet_access_type %T.loc20_7.1 [symbolic = %T.as_type.loc20_15.1 (constants.%T.as_type)]
// CHECK:STDOUT: %pattern_type: type = pattern_type %T.as_type.loc20_15.1 [symbolic = %pattern_type (constants.%pattern_type.b3a)]
// CHECK:STDOUT: %t.param_patt.loc20_13.2: @F.%pattern_type (%pattern_type.b3a) = value_param_pattern [symbolic = %t.param_patt.loc20_13.2 (constants.%t.param_patt.5db)]
// CHECK:STDOUT: %t.patt.loc20_13.2: @F.%pattern_type (%pattern_type.b3a) = at_binding_pattern t, %t.param_patt.loc20_13.2 [symbolic = %t.patt.loc20_13.2 (constants.%t.patt.030)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %T.as_type.loc20_16.1 [symbolic = %require_complete (constants.%require_complete)]
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %T.as_type.loc20_15.1 [symbolic = %require_complete (constants.%require_complete)]
// CHECK:STDOUT: %I.WithSelf.Doit.type: type = fn_type @I.WithSelf.Doit, @I.WithSelf(%T.loc20_7.1) [symbolic = %I.WithSelf.Doit.type (constants.%I.WithSelf.Doit.type.860)]
// CHECK:STDOUT: %.loc21_4: type = fn_type_with_self_type %I.WithSelf.Doit.type, %T.loc20_7.1 [symbolic = %.loc21_4 (constants.%.8a9)]
// CHECK:STDOUT: %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc20_7.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]
// CHECK:STDOUT: %impl.elem0.loc21_4.2: @F.%.loc21_4 (%.8a9) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc21_4.2 (constants.%impl.elem0)]
// CHECK:STDOUT: %specific_impl_fn.loc21_4.2: <specific function> = specific_impl_function %impl.elem0.loc21_4.2, @I.WithSelf.Doit(%T.loc20_7.1) [symbolic = %specific_impl_fn.loc21_4.2 (constants.%specific_impl_fn)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%t.param: @F.%T.as_type.loc20_16.1 (%T.as_type)) {
// CHECK:STDOUT: fn(%t.param: @F.%T.as_type.loc20_15.1 (%T.as_type)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %t.ref: @F.%T.as_type.loc20_16.1 (%T.as_type) = name_ref t, %t
// CHECK:STDOUT: %t.ref: @F.%T.as_type.loc20_15.1 (%T.as_type) = name_ref t, %t
// CHECK:STDOUT: %Doit.ref: %I.assoc_type = name_ref Doit, @I.WithSelf.%assoc0 [concrete = constants.%assoc0.628]
// CHECK:STDOUT: %impl.elem0.loc21_4.1: @F.%.loc21_4 (%.8a9) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc21_4.2 (constants.%impl.elem0)]
// CHECK:STDOUT: %bound_method.loc21_4: <bound method> = bound_method %t.ref, %impl.elem0.loc21_4.1
@@ -438,13 +438,13 @@ void G() {
// CHECK:STDOUT: fn @F__carbon_thunkinst64000035(%_.param: ref %A) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F__carbon_thunkinst64000035.ref: %F.type = name_ref F__carbon_thunkinst64000035, file.%F.decl [concrete = constants.%F]
// CHECK:STDOUT: %I.facet.loc20_19.1: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %.loc20_19.1: %I.type = converted constants.%A, %I.facet.loc20_19.1 [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %I.facet.loc20_19.2: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %.loc20_19.2: %I.type = converted constants.%A, %I.facet.loc20_19.2 [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %I.facet.loc20_18.1: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %.loc20_18.1: %I.type = converted constants.%A, %I.facet.loc20_18.1 [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %I.facet.loc20_18.2: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %.loc20_18.2: %I.type = converted constants.%A, %I.facet.loc20_18.2 [concrete = constants.%I.facet.64b]
// CHECK:STDOUT: %F.specific_fn: <specific function> = specific_function %F__carbon_thunkinst64000035.ref, @F(constants.%I.facet.64b) [concrete = constants.%F.specific_fn.f33]
// CHECK:STDOUT: %.loc20_19.3: %A = acquire_value %_.param
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc20_19.3)
// CHECK:STDOUT: %.loc20_18.3: %A = acquire_value %_.param
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc20_18.3)
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
@@ -453,13 +453,13 @@ void G() {
// CHECK:STDOUT: fn @F__carbon_thunkinst64000050(%_.param: ref %B) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F__carbon_thunkinst64000050.ref: %F.type = name_ref F__carbon_thunkinst64000050, file.%F.decl [concrete = constants.%F]
// CHECK:STDOUT: %I.facet.loc20_19.1: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %.loc20_19.1: %I.type = converted constants.%B, %I.facet.loc20_19.1 [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %I.facet.loc20_19.2: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %.loc20_19.2: %I.type = converted constants.%B, %I.facet.loc20_19.2 [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %I.facet.loc20_18.1: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %.loc20_18.1: %I.type = converted constants.%B, %I.facet.loc20_18.1 [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %I.facet.loc20_18.2: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %.loc20_18.2: %I.type = converted constants.%B, %I.facet.loc20_18.2 [concrete = constants.%I.facet.9f8]
// CHECK:STDOUT: %F.specific_fn: <specific function> = specific_function %F__carbon_thunkinst64000050.ref, @F(constants.%I.facet.9f8) [concrete = constants.%F.specific_fn.db2]
// CHECK:STDOUT: %.loc20_19.3: %B = acquire_value %_.param
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc20_19.3)
// CHECK:STDOUT: %.loc20_18.3: %B = acquire_value %_.param
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc20_18.3)
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
@@ -513,10 +513,10 @@ void G() {
// CHECK:STDOUT: specific @F(constants.%T) {
// CHECK:STDOUT: %T.patt.loc20_7.2 => constants.%T.patt
// CHECK:STDOUT: %T.loc20_7.1 => constants.%T
// CHECK:STDOUT: %T.as_type.loc20_16.1 => constants.%T.as_type
// CHECK:STDOUT: %T.as_type.loc20_15.1 => constants.%T.as_type
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.b3a
// CHECK:STDOUT: %t.param_patt.loc20_14.2 => constants.%t.param_patt.5db
// CHECK:STDOUT: %t.patt.loc20_14.2 => constants.%t.patt.030
// CHECK:STDOUT: %t.param_patt.loc20_13.2 => constants.%t.param_patt.5db
// CHECK:STDOUT: %t.patt.loc20_13.2 => constants.%t.patt.030
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @I.WithSelf(constants.%T) {
@@ -537,10 +537,10 @@ void G() {
// CHECK:STDOUT: specific @F(constants.%I.facet.64b) {
// CHECK:STDOUT: %T.patt.loc20_7.2 => constants.%T.patt
// CHECK:STDOUT: %T.loc20_7.1 => constants.%I.facet.64b
// CHECK:STDOUT: %T.as_type.loc20_16.1 => constants.%A
// CHECK:STDOUT: %T.as_type.loc20_15.1 => constants.%A
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.9ef
// CHECK:STDOUT: %t.param_patt.loc20_14.2 => constants.%t.param_patt.169
// CHECK:STDOUT: %t.patt.loc20_14.2 => constants.%t.patt.ee8
// CHECK:STDOUT: %t.param_patt.loc20_13.2 => constants.%t.param_patt.169
// CHECK:STDOUT: %t.patt.loc20_13.2 => constants.%t.patt.ee8
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete => constants.%complete_type
@@ -554,10 +554,10 @@ void G() {
// CHECK:STDOUT: specific @F(constants.%I.facet.9f8) {
// CHECK:STDOUT: %T.patt.loc20_7.2 => constants.%T.patt
// CHECK:STDOUT: %T.loc20_7.1 => constants.%I.facet.9f8
// CHECK:STDOUT: %T.as_type.loc20_16.1 => constants.%B
// CHECK:STDOUT: %T.as_type.loc20_15.1 => constants.%B
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.e39
// CHECK:STDOUT: %t.param_patt.loc20_14.2 => constants.%t.param_patt.267
// CHECK:STDOUT: %t.patt.loc20_14.2 => constants.%t.patt.062
// CHECK:STDOUT: %t.param_patt.loc20_13.2 => constants.%t.param_patt.267
// CHECK:STDOUT: %t.patt.loc20_13.2 => constants.%t.patt.062
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete => constants.%complete_type