Просмотр исходного кода

adds a field to `SemIR::Interface` to indicate whether it is a core interface (#7091)

The existing `GetCoreInterface` has linear-time complexity and adds more
than the search criteria to the `CoreInterfaceCache`. Adding a new field
to `Interface` changes this operation when building packages other than
`Core`, as this should only be set for the core library.
Christopher Di Bella 1 неделя назад
Родитель
Сommit
f0c4b37c63

+ 7 - 7
toolchain/check/cpp/impl_lookup.cpp

@@ -220,7 +220,7 @@ static auto BuildDestroyWitness(
 }
 
 auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
-                   CoreInterface core_interface,
+                   SemIR::CoreInterface core_interface,
                    SemIR::ConstantId query_self_const_id,
                    SemIR::SpecificInterfaceId query_specific_interface_id,
                    const TypeStructure* best_impl_type_structure,
@@ -231,24 +231,24 @@ auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
   static_cast<void>(best_impl_loc_id);
 
   switch (core_interface) {
-    case CoreInterface::Copy:
+    case SemIR::CoreInterface::Copy:
       return BuildCopyWitness(context, loc_id, query_self_const_id,
                               query_specific_interface_id);
-    case CoreInterface::CppUnsafeDeref:
+    case SemIR::CoreInterface::CppUnsafeDeref:
       return BuildCppUnsafeDerefWitness(context, loc_id, query_self_const_id,
                                         query_specific_interface_id);
-    case CoreInterface::Default:
+    case SemIR::CoreInterface::Default:
       return BuildDefaultWitness(context, loc_id, query_self_const_id,
                                  query_specific_interface_id);
-    case CoreInterface::Destroy:
+    case SemIR::CoreInterface::Destroy:
       return BuildDestroyWitness(context, loc_id, query_self_const_id,
                                  query_specific_interface_id);
 
     // IntFitsIn is for Carbon integer types only.
-    case CoreInterface::IntFitsIn:
+    case SemIR::CoreInterface::IntFitsIn:
       return SemIR::InstId::None;
 
-    case CoreInterface::Unknown:
+    case SemIR::CoreInterface::Unknown:
       CARBON_FATAL("unexpected CoreInterface `{0}`", core_interface);
   }
 }

+ 1 - 1
toolchain/check/cpp/impl_lookup.h

@@ -38,7 +38,7 @@ namespace Carbon::Check {
 // type structure, and can be `None` if `best_impl_type_structure` is null. This
 // parameter is used only for ambiguity diagnostics.
 auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
-                   CoreInterface core_interface,
+                   SemIR::CoreInterface core_interface,
                    SemIR::ConstantId query_self_const_id,
                    SemIR::SpecificInterfaceId query_specific_interface_id,
                    const TypeStructure* best_impl_type_structure,

+ 10 - 23
toolchain/check/custom_witness.cpp

@@ -528,27 +528,14 @@ auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
 }
 
 auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
-    -> CoreInterface {
+    -> SemIR::CoreInterface {
   const auto& interface = context.interfaces().Get(interface_id);
   if (!context.name_scopes().IsCorePackage(interface.parent_scope_id) ||
       !interface.name_id.AsIdentifierId().has_value()) {
-    return CoreInterface::Unknown;
+    return SemIR::CoreInterface::Unknown;
   }
 
-  constexpr auto CoreIdentifiersToInterfaces = std::array{
-      std::pair{CoreIdentifier::Copy, CoreInterface::Copy},
-      std::pair{CoreIdentifier::CppUnsafeDeref, CoreInterface::CppUnsafeDeref},
-      std::pair{CoreIdentifier::Default, CoreInterface::Default},
-      std::pair{CoreIdentifier::Destroy, CoreInterface::Destroy},
-      std::pair{CoreIdentifier::IntFitsIn, CoreInterface::IntFitsIn}};
-
-  for (auto [core_identifier, core_interface] : CoreIdentifiersToInterfaces) {
-    if (interface.name_id ==
-        context.core_identifiers().AddNameId(core_identifier)) {
-      return core_interface;
-    }
-  }
-  return CoreInterface::Unknown;
+  return interface.core_interface;
 }
 
 auto BuildPrimitiveCopyWitness(
@@ -667,21 +654,21 @@ static auto MakeIntFitsInWitness(
 }
 
 auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
-                         CoreInterface core_interface,
+                         SemIR::CoreInterface core_interface,
                          SemIR::ConstantId query_self_const_id,
                          SemIR::SpecificInterfaceId query_specific_interface_id,
                          bool build_witness) -> std::optional<SemIR::InstId> {
   switch (core_interface) {
-    case CoreInterface::Destroy:
+    case SemIR::CoreInterface::Destroy:
       return MakeDestroyWitness(context, loc_id, query_self_const_id,
                                 query_specific_interface_id, build_witness);
-    case CoreInterface::IntFitsIn:
+    case SemIR::CoreInterface::IntFitsIn:
       return MakeIntFitsInWitness(context, loc_id, query_self_const_id,
                                   query_specific_interface_id, build_witness);
-    case CoreInterface::Copy:
-    case CoreInterface::CppUnsafeDeref:
-    case CoreInterface::Default:
-    case CoreInterface::Unknown:
+    case SemIR::CoreInterface::Copy:
+    case SemIR::CoreInterface::CppUnsafeDeref:
+    case SemIR::CoreInterface::Default:
+    case SemIR::CoreInterface::Unknown:
       // TODO: Handle more interfaces, particularly copy, move, and conversion.
       return std::nullopt;
   }

+ 2 - 14
toolchain/check/custom_witness.h

@@ -25,22 +25,10 @@ auto BuildPrimitiveCopyWitness(
     SemIR::ConstantId query_self_const_id,
     SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId;
 
-// Significant interfaces in `Core` which correspond to language features and
-// can have custom witnesses.
-enum class CoreInterface {
-  Copy,
-  CppUnsafeDeref,
-  Default,
-  Destroy,
-  IntFitsIn,
-
-  Unknown,
-};
-
 // Given an interface, returns the corresponding enum if it's covered by
 // `CoreInterface`, or `Unknown` if it's some other interface.
 auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
-    -> CoreInterface;
+    -> SemIR::CoreInterface;
 
 // Returns a witness for a `CoreInterface` `CustomWitness`. A return value of
 // `None` indicates a non-final witness should be produced, while `std::nullopt`
@@ -50,7 +38,7 @@ auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
 // witness, whether it would be final or not. It is used to indicate the
 // presence of such a witness without adding instructions for it.
 auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
-                         CoreInterface core_interface,
+                         SemIR::CoreInterface core_interface,
                          SemIR::ConstantId query_self_const_id,
                          SemIR::SpecificInterfaceId query_specific_interface_id,
                          bool build_witness) -> std::optional<SemIR::InstId>;

+ 12 - 0
toolchain/check/handle_interface.cpp

@@ -87,6 +87,18 @@ static auto BuildInterfaceDecl(Context& context,
   } else {
     // Create a new interface if this isn't a valid redeclaration.
     interface_info.generic_id = BuildGenericDecl(context, decl_inst_id);
+
+    if (context.sem_ir().package_id() == PackageNameId::Core) {
+      auto name = context.names().GetIRBaseName(interface_info.name_id);
+      interface_info.core_interface =
+          llvm::StringSwitch<SemIR::CoreInterface>(name)
+              .Case("Copy", SemIR::CoreInterface::Copy)
+              .Case("CppUnsafeDeref", SemIR::CoreInterface::CppUnsafeDeref)
+              .Case("Default", SemIR::CoreInterface::Default)
+              .Case("Destroy", SemIR::CoreInterface::Destroy)
+              .Case("IntFitsIn", SemIR::CoreInterface::IntFitsIn)
+              .Default(SemIR::CoreInterface::Unknown);
+    }
     interface_decl.interface_id = context.interfaces().Add(interface_info);
     if (interface_info.has_parameters()) {
       interface_decl.type_id =

+ 1 - 1
toolchain/check/impl_lookup.cpp

@@ -1208,7 +1208,7 @@ auto EvalLookupSingleFinalWitness(Context& context, SemIR::LocId loc_id,
   }
 
   if (query_is_concrete && candidates.consider_cpp_candidates &&
-      core_interface != CoreInterface::Unknown) {
+      core_interface != SemIR::CoreInterface::Unknown) {
     // Also check for a C++ candidate that is a better match than whatever
     // `impl` we may have found in Carbon.
     auto cpp_witness_id = LookupCppImpl(

+ 2 - 1
toolchain/check/import_ref.cpp

@@ -2822,7 +2822,8 @@ static auto ImportInterfaceDecl(ImportContext& context,
                                      : SemIR::NameScopeId::None,
         .scope_with_self_id = import_interface.is_complete()
                                   ? AddPlaceholderNameScope(context)
-                                  : SemIR::NameScopeId::None}});
+                                  : SemIR::NameScopeId::None,
+        .core_interface = import_interface.core_interface}});
 
   if (import_interface.has_parameters()) {
     interface_decl.type_id = GetGenericInterfaceType(

+ 866 - 0
toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon

@@ -0,0 +1,866 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// EXTRA-ARGS: --no-prelude-import --dump-raw-sem-ir --no-dump-sem-ir
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/non_core_interfaces.carbon
+
+// Tests that a non-core interface with the same name as a core interface does
+// not produce a `core_interfce: ${interface_name}` entry. We test this for both
+// locally-defined interfaces and imported interfaces.
+
+// --- non_core.carbon
+package NonCore;
+interface Destroy {
+  let T1:! type;
+  let T2:! type;
+}
+
+// --- main.carbon
+import NonCore;
+
+interface Copy {
+  let T1:! type;
+  let T2:! type;
+}
+
+//@dump-sem-ir-begin
+fn UseNonCoreDestroy[T:! NonCore.Destroy](_: T.T1, _: T.T2) {}
+fn UseLocalCopy[T:! Copy](_: T.T1, _: T.T2) {}
+//@dump-sem-ir-end
+
+// CHECK:STDOUT: ---
+// CHECK:STDOUT: filename:        non_core.carbon
+// CHECK:STDOUT: sem_ir:
+// CHECK:STDOUT:   names:
+// CHECK:STDOUT:     name0:           NonCore
+// CHECK:STDOUT:     name1:           Destroy
+// CHECK:STDOUT:     name2:           T1
+// CHECK:STDOUT:     name3:           T2
+// CHECK:STDOUT:   import_irs:
+// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}
+// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}
+// CHECK:STDOUT:   import_ir_insts: {}
+// CHECK:STDOUT:   clang_decls:     {}
+// CHECK:STDOUT:   name_scopes:
+// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst60000010}}
+// CHECK:STDOUT:     name_scope60000001: {inst: inst60000010, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst60000012}}
+// CHECK:STDOUT:     name_scope60000002: {inst: inst60000015, parent_scope: name_scope60000001, has_error: false, extended_scopes: [], names: {name2: inst60000019, name3: inst6000001D}}
+// CHECK:STDOUT:   entity_names:
+// CHECK:STDOUT:     entity_name60000000: {name: name(SelfType), parent_scope: name_scope60000001, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:   cpp_global_vars: {}
+// CHECK:STDOUT:   functions:       {}
+// CHECK:STDOUT:   classes:         {}
+// CHECK:STDOUT:   interfaces:
+// CHECK:STDOUT:     interface60000000: {name: name1, parent_scope: name_scope0, require_impls_block_id: require_block_empty}
+// CHECK:STDOUT:   associated_constants:
+// CHECK:STDOUT:     assoc_const60000000: {name: name2, parent_scope: name_scope60000002, decl_id: inst60000017, default_value_id: inst<none>}
+// CHECK:STDOUT:     assoc_const60000001: {name: name3, parent_scope: name_scope60000002, decl_id: inst6000001C, default_value_id: inst<none>}
+// CHECK:STDOUT:   impls:           {}
+// CHECK:STDOUT:   generics:
+// CHECK:STDOUT:     generic60000000: {decl: inst<none>, bindings: inst_block<none>, self_specific_id: specific<none>, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}
+// CHECK:STDOUT:     generic60000001: {decl: inst60000015, bindings: inst_block60000005, self_specific_id: specific60000000, decl_block_id: inst_block_empty, definition_block_id: inst_block_empty}
+// CHECK:STDOUT:   specifics:
+// CHECK:STDOUT:     specific60000000: {generic: generic60000001, args: inst_block60000006, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:   specific_interfaces: {}
+// CHECK:STDOUT:   struct_type_fields:
+// CHECK:STDOUT:     struct_type_fields_empty: {}
+// CHECK:STDOUT:   types:
+// CHECK:STDOUT:     'type(TypeType)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(FormType))':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(Error)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(NamespaceType))':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:   facet_types:
+// CHECK:STDOUT:     facet_type60000000: {extends interface: interface60000000}
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:     inst60000010:    {kind: InterfaceDecl, arg0: interface60000000, arg1: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst60000011:    {kind: FacetType, arg0: facet_type60000000, type: type(TypeType)}
+// CHECK:STDOUT:     inst60000012:    {kind: SymbolicBinding, arg0: entity_name60000000, arg1: inst<none>, type: type(inst60000011)}
+// CHECK:STDOUT:     inst60000013:    {kind: SymbolicBinding, arg0: entity_name60000000, arg1: inst<none>, type: type(inst60000011)}
+// CHECK:STDOUT:     inst60000014:    {kind: SymbolicBinding, arg0: entity_name60000000, arg1: inst<none>, type: type(inst60000011)}
+// CHECK:STDOUT:     inst60000015:    {kind: InterfaceWithSelfDecl, arg0: interface60000000}
+// CHECK:STDOUT:     inst60000016:    {kind: TypeLiteral, arg0: inst(TypeType), type: type(TypeType)}
+// CHECK:STDOUT:     inst60000017:    {kind: AssociatedConstantDecl, arg0: assoc_const60000000, arg1: inst_block6000000A, type: type(TypeType)}
+// CHECK:STDOUT:     inst60000018:    {kind: AssociatedEntityType, arg0: interface60000000, arg1: specific<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst60000019:    {kind: AssociatedEntity, arg0: element0, arg1: inst60000017, type: type(inst60000018)}
+// CHECK:STDOUT:     inst6000001A:    {kind: AssociatedEntity, arg0: element0, arg1: inst60000017, type: type(inst60000018)}
+// CHECK:STDOUT:     inst6000001B:    {kind: TypeLiteral, arg0: inst(TypeType), type: type(TypeType)}
+// CHECK:STDOUT:     inst6000001C:    {kind: AssociatedConstantDecl, arg0: assoc_const60000001, arg1: inst_block6000000C, type: type(TypeType)}
+// CHECK:STDOUT:     inst6000001D:    {kind: AssociatedEntity, arg0: element1, arg1: inst6000001C, type: type(inst60000018)}
+// CHECK:STDOUT:     inst6000001E:    {kind: AssociatedEntity, arg0: element1, arg1: inst6000001C, type: type(inst60000018)}
+// CHECK:STDOUT:   constant_values:
+// CHECK:STDOUT:     values:
+// CHECK:STDOUT:       instF:           concrete_constant(instF)
+// CHECK:STDOUT:       inst60000010:    concrete_constant(inst60000011)
+// CHECK:STDOUT:       inst60000011:    concrete_constant(inst60000011)
+// CHECK:STDOUT:       inst60000012:    symbolic_constant60000000
+// CHECK:STDOUT:       inst60000013:    symbolic_constant60000000
+// CHECK:STDOUT:       inst60000014:    symbolic_constant60000001
+// CHECK:STDOUT:       inst60000015:    concrete_constant(inst60000015)
+// CHECK:STDOUT:       inst60000016:    concrete_constant(inst(TypeType))
+// CHECK:STDOUT:       inst60000017:    concrete_constant(inst60000017)
+// CHECK:STDOUT:       inst60000018:    concrete_constant(inst60000018)
+// CHECK:STDOUT:       inst60000019:    concrete_constant(inst6000001A)
+// CHECK:STDOUT:       inst6000001A:    concrete_constant(inst6000001A)
+// CHECK:STDOUT:       inst6000001B:    concrete_constant(inst(TypeType))
+// CHECK:STDOUT:       inst6000001C:    concrete_constant(inst6000001C)
+// CHECK:STDOUT:       inst6000001D:    concrete_constant(inst6000001E)
+// CHECK:STDOUT:       inst6000001E:    concrete_constant(inst6000001E)
+// CHECK:STDOUT:     symbolic_constants:
+// CHECK:STDOUT:       symbolic_constant60000000: {inst: inst60000013, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant60000001: {inst: inst60000013, kind: checked, attached: {generic: generic60000000, index: generic_inst_in_def0}}
+// CHECK:STDOUT:   inst_blocks:
+// CHECK:STDOUT:     inst_block_empty: {}
+// CHECK:STDOUT:     exports:
+// CHECK:STDOUT:       0:               inst60000010
+// CHECK:STDOUT:     generated:       {}
+// CHECK:STDOUT:     imports:         {}
+// CHECK:STDOUT:     global_init:     {}
+// CHECK:STDOUT:     inst_block60000005:
+// CHECK:STDOUT:       0:               inst60000012
+// CHECK:STDOUT:     inst_block60000006:
+// CHECK:STDOUT:       0:               inst60000013
+// CHECK:STDOUT:     inst_block60000007:
+// CHECK:STDOUT:       0:               inst60000012
+// CHECK:STDOUT:       1:               inst60000015
+// CHECK:STDOUT:     inst_block60000008:
+// CHECK:STDOUT:       0:               inst60000017
+// CHECK:STDOUT:       1:               inst6000001C
+// CHECK:STDOUT:     inst_block60000009:
+// CHECK:STDOUT:       0:               inst60000016
+// CHECK:STDOUT:     inst_block6000000A:
+// CHECK:STDOUT:       0:               inst60000019
+// CHECK:STDOUT:     inst_block6000000B:
+// CHECK:STDOUT:       0:               inst6000001B
+// CHECK:STDOUT:     inst_block6000000C:
+// CHECK:STDOUT:       0:               inst6000001D
+// CHECK:STDOUT:     inst_block6000000D:
+// CHECK:STDOUT:       0:               inst60000017
+// CHECK:STDOUT:       1:               inst6000001C
+// CHECK:STDOUT:     inst_block6000000E:
+// CHECK:STDOUT:       0:               instF
+// CHECK:STDOUT:       1:               inst60000010
+// CHECK:STDOUT:   value_stores:
+// CHECK:STDOUT:     shared_values:
+// CHECK:STDOUT:       ints:            {}
+// CHECK:STDOUT:       reals:           {}
+// CHECK:STDOUT:       floats:          {}
+// CHECK:STDOUT:       identifiers:
+// CHECK:STDOUT:         identifier0:     NonCore
+// CHECK:STDOUT:         identifier1:     Destroy
+// CHECK:STDOUT:         identifier2:     T1
+// CHECK:STDOUT:         identifier3:     T2
+// CHECK:STDOUT:       strings:         {}
+// CHECK:STDOUT: ...
+// CHECK:STDOUT: ---
+// CHECK:STDOUT: filename:        main.carbon
+// CHECK:STDOUT: sem_ir:
+// CHECK:STDOUT:   names:
+// CHECK:STDOUT:     name0:           NonCore
+// CHECK:STDOUT:     name1:           Copy
+// CHECK:STDOUT:     name2:           T1
+// CHECK:STDOUT:     name3:           T2
+// CHECK:STDOUT:     name4:           UseNonCoreDestroy
+// CHECK:STDOUT:     name5:           T
+// CHECK:STDOUT:     name6:           Destroy
+// CHECK:STDOUT:     name7:           UseLocalCopy
+// CHECK:STDOUT:   import_irs:
+// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}
+// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}
+// CHECK:STDOUT:     import_ir50000002: {decl_id: inst50000010, is_export: false}
+// CHECK:STDOUT:   import_ir_insts:
+// CHECK:STDOUT:     import_ir_inst0: {ir_id: import_ir50000002, inst_id: inst60000010}
+// CHECK:STDOUT:     import_ir_inst1: {ir_id: import_ir50000002, inst_id: inst60000010}
+// CHECK:STDOUT:     import_ir_inst2: {ir_id: import_ir50000002, inst_id: inst60000015}
+// CHECK:STDOUT:     import_ir_inst3: {ir_id: import_ir50000002, inst_id: inst60000019}
+// CHECK:STDOUT:     import_ir_inst4: {ir_id: import_ir50000002, inst_id: inst6000001D}
+// CHECK:STDOUT:     import_ir_inst5: {ir_id: import_ir50000002, inst_id: inst60000017}
+// CHECK:STDOUT:     import_ir_inst6: {ir_id: import_ir50000002, inst_id: inst6000001C}
+// CHECK:STDOUT:     import_ir_inst7: {ir_id: import_ir50000002, inst_id: inst60000012}
+// CHECK:STDOUT:     import_ir_inst8: {ir_id: import_ir50000002, inst_id: inst60000012}
+// CHECK:STDOUT:     import_ir_inst9: {ir_id: import_ir50000002, inst_id: inst60000017}
+// CHECK:STDOUT:     import_ir_instA: {ir_id: import_ir50000002, inst_id: inst60000017}
+// CHECK:STDOUT:     import_ir_instB: {ir_id: import_ir50000002, inst_id: inst6000001C}
+// CHECK:STDOUT:     import_ir_instC: {ir_id: import_ir50000002, inst_id: inst6000001C}
+// CHECK:STDOUT:   clang_decls:     {}
+// CHECK:STDOUT:   name_scopes:
+// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000011, name1: inst50000012, name4: inst50000061, name7: inst50000095}}
+// CHECK:STDOUT:     name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name6: inst50000026}}
+// CHECK:STDOUT:     name_scope50000002: {inst: inst50000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst50000014}}
+// CHECK:STDOUT:     name_scope50000003: {inst: inst50000017, parent_scope: name_scope50000002, has_error: false, extended_scopes: [], names: {name2: inst5000001B, name3: inst5000001F}}
+// CHECK:STDOUT:     name_scope50000004: {inst: inst50000027, parent_scope: name_scope50000001, has_error: false, extended_scopes: [], names: {name(SelfType): inst50000030}}
+// CHECK:STDOUT:     name_scope50000005: {inst: inst50000029, parent_scope: name_scope50000004, has_error: false, extended_scopes: [], names: {name2: inst5000002B, name3: inst5000002C}}
+// CHECK:STDOUT:   entity_names:
+// CHECK:STDOUT:     entity_name50000000: {name: name(SelfType), parent_scope: name_scope50000002, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000001: {name: name(PeriodSelf), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000002: {name: name6, parent_scope: name_scope50000001, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000003: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000004: {name: name2, parent_scope: name_scope50000005, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000005: {name: name3, parent_scope: name_scope50000005, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000006: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000007: {name: name5, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000008: {name: name(Underscore), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 1, form: inst<none>}
+// CHECK:STDOUT:     entity_name50000009: {name: name(Underscore), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 1, form: inst<none>}
+// CHECK:STDOUT:     entity_name5000000A: {name: name5, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
+// CHECK:STDOUT:     entity_name5000000B: {name: name(Underscore), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 1, form: inst<none>}
+// CHECK:STDOUT:     entity_name5000000C: {name: name(Underscore), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 1, form: inst<none>}
+// CHECK:STDOUT:   cpp_global_vars: {}
+// CHECK:STDOUT:   functions:
+// CHECK:STDOUT:     function50000000: {name: name4, parent_scope: name_scope0, call_param_patterns_id: inst_block50000018, call_params_id: inst_block50000019, body: [inst_block5000001F]}
+// CHECK:STDOUT:     function50000001: {name: name7, parent_scope: name_scope0, call_param_patterns_id: inst_block50000028, call_params_id: inst_block50000029, body: [inst_block5000002F]}
+// CHECK:STDOUT:   classes:         {}
+// CHECK:STDOUT:   interfaces:
+// CHECK:STDOUT:     interface50000000: {name: name1, parent_scope: name_scope0, require_impls_block_id: require_block_empty}
+// CHECK:STDOUT:     interface50000001: {name: name6, parent_scope: name_scope50000001, require_impls_block_id: require_block_empty}
+// CHECK:STDOUT:   associated_constants:
+// CHECK:STDOUT:     assoc_const50000000: {name: name2, parent_scope: name_scope50000003, decl_id: inst50000019, default_value_id: inst<none>}
+// CHECK:STDOUT:     assoc_const50000001: {name: name3, parent_scope: name_scope50000003, decl_id: inst5000001E, default_value_id: inst<none>}
+// CHECK:STDOUT:     assoc_const50000002: {name: name2, parent_scope: name_scope50000005, decl_id: inst50000042, default_value_id: inst<none>}
+// CHECK:STDOUT:     assoc_const50000003: {name: name3, parent_scope: name_scope50000005, decl_id: inst50000053, default_value_id: inst<none>}
+// CHECK:STDOUT:   impls:           {}
+// CHECK:STDOUT:   generics:
+// CHECK:STDOUT:     generic50000000: {decl: inst<none>, bindings: inst_block<none>, self_specific_id: specific<none>, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}
+// CHECK:STDOUT:     generic50000001: {decl: inst50000017, bindings: inst_block50000005, self_specific_id: specific50000000, decl_block_id: inst_block_empty, definition_block_id: inst_block_empty}
+// CHECK:STDOUT:     generic50000002: {decl: inst50000029, bindings: inst_block50000010, self_specific_id: specific50000001, decl_block_id: inst_block_empty, definition_block_id: inst_block_empty}
+// CHECK:STDOUT:     generic50000003: {decl: inst50000061, bindings: inst_block5000001C, self_specific_id: specific50000003, decl_block_id: inst_block5000001D, definition_block_id: inst_block50000020}
+// CHECK:STDOUT:     generic50000004: {decl: inst50000095, bindings: inst_block5000002C, self_specific_id: specific50000005, decl_block_id: inst_block5000002D, definition_block_id: inst_block50000030}
+// CHECK:STDOUT:   specifics:
+// CHECK:STDOUT:     specific50000000: {generic: generic50000001, args: inst_block50000006, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block_empty, definition_has_error: 0}
+// CHECK:STDOUT:     specific50000001: {generic: generic50000002, args: inst_block50000011, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block_empty, definition_has_error: 0}
+// CHECK:STDOUT:     specific50000002: {generic: generic50000002, args: inst_block50000014, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block_empty, definition_has_error: 0}
+// CHECK:STDOUT:     specific50000003: {generic: generic50000003, args: inst_block50000014, decl_block_id: inst_block5000001E, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific50000004: {generic: generic50000001, args: inst_block50000024, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block_empty, definition_has_error: 0}
+// CHECK:STDOUT:     specific50000005: {generic: generic50000004, args: inst_block50000024, decl_block_id: inst_block5000002E, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:   specific_interfaces:
+// CHECK:STDOUT:     specific_interface50000000: {interface_id: interface50000001, specific_id: specific<none>}
+// CHECK:STDOUT:     specific_interface50000001: {interface_id: interface50000000, specific_id: specific<none>}
+// CHECK:STDOUT:   struct_type_fields:
+// CHECK:STDOUT:     struct_type_fields_empty: {}
+// CHECK:STDOUT:   types:
+// CHECK:STDOUT:     'type(TypeType)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(FormType))':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(Error)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(NamespaceType))':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(InstType))':
+// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000025)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst50000025)':
+// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000025)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst50000028)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst50000028)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst(WitnessType))':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(WitnessType))}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst50000062)':
+// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000025)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(symbolic_constant50000009)':
+// CHECK:STDOUT:       value_repr:      {kind: dependent, type: type(symbolic_constant50000009)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       0
+// CHECK:STDOUT:     'type(symbolic_constant5000000E)':
+// CHECK:STDOUT:       value_repr:      {kind: dependent, type: type(symbolic_constant5000000E)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       0
+// CHECK:STDOUT:     'type(inst50000013)':
+// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst50000013)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(inst50000096)':
+// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000025)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       1
+// CHECK:STDOUT:     'type(symbolic_constant5000001B)':
+// CHECK:STDOUT:       value_repr:      {kind: dependent, type: type(symbolic_constant5000001B)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       0
+// CHECK:STDOUT:     'type(symbolic_constant50000020)':
+// CHECK:STDOUT:       value_repr:      {kind: dependent, type: type(symbolic_constant50000020)}
+// CHECK:STDOUT:       object_layout:
+// CHECK:STDOUT:         size:            0
+// CHECK:STDOUT:         alignment:       0
+// CHECK:STDOUT:   facet_types:
+// CHECK:STDOUT:     facet_type50000000: {extends interface: interface50000000}
+// CHECK:STDOUT:     facet_type50000001: {}
+// CHECK:STDOUT:     facet_type50000002: {extends interface: interface50000001}
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:     inst50000010:    {kind: ImportDecl, arg0: name0}
+// CHECK:STDOUT:     inst50000011:    {kind: Namespace, arg0: name_scope50000001, arg1: inst50000010, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:     inst50000012:    {kind: InterfaceDecl, arg0: interface50000000, arg1: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000013:    {kind: FacetType, arg0: facet_type50000000, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000014:    {kind: SymbolicBinding, arg0: entity_name50000000, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000015:    {kind: SymbolicBinding, arg0: entity_name50000000, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000016:    {kind: SymbolicBinding, arg0: entity_name50000000, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000017:    {kind: InterfaceWithSelfDecl, arg0: interface50000000}
+// CHECK:STDOUT:     inst50000018:    {kind: TypeLiteral, arg0: inst(TypeType), type: type(TypeType)}
+// CHECK:STDOUT:     inst50000019:    {kind: AssociatedConstantDecl, arg0: assoc_const50000000, arg1: inst_block5000000A, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000001A:    {kind: AssociatedEntityType, arg0: interface50000000, arg1: specific<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000001B:    {kind: AssociatedEntity, arg0: element0, arg1: inst50000019, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst5000001C:    {kind: AssociatedEntity, arg0: element0, arg1: inst50000019, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst5000001D:    {kind: TypeLiteral, arg0: inst(TypeType), type: type(TypeType)}
+// CHECK:STDOUT:     inst5000001E:    {kind: AssociatedConstantDecl, arg0: assoc_const50000001, arg1: inst_block5000000C, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000001F:    {kind: AssociatedEntity, arg0: element1, arg1: inst5000001E, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst50000020:    {kind: AssociatedEntity, arg0: element1, arg1: inst5000001E, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst50000021:    {kind: FacetType, arg0: facet_type50000001, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000022:    {kind: SymbolicBinding, arg0: entity_name50000001, arg1: inst<none>, type: type(inst50000021)}
+// CHECK:STDOUT:     inst50000023:    {kind: SymbolicBinding, arg0: entity_name50000001, arg1: inst<none>, type: type(inst50000021)}
+// CHECK:STDOUT:     inst50000024:    {kind: NameRef, arg0: name0, arg1: inst50000011, type: type(inst(NamespaceType))}
+// CHECK:STDOUT:     inst50000025:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000026:    {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name50000002, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000027:    {kind: InterfaceDecl, arg0: interface50000001, arg1: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000028:    {kind: FacetType, arg0: facet_type50000002, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000029:    {kind: InterfaceWithSelfDecl, arg0: interface50000001}
+// CHECK:STDOUT:     inst5000002A:    {kind: SymbolicBinding, arg0: entity_name50000003, arg1: inst<none>, type: type(inst50000028)}
+// CHECK:STDOUT:     inst5000002B:    {kind: ImportRefLoaded, arg0: import_ir_inst3, arg1: entity_name<none>, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst5000002C:    {kind: ImportRefLoaded, arg0: import_ir_inst4, arg1: entity_name<none>, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst5000002D:    {kind: ImportRefUnloaded, arg0: import_ir_inst5, arg1: entity_name50000004}
+// CHECK:STDOUT:     inst5000002E:    {kind: ImportRefUnloaded, arg0: import_ir_inst6, arg1: entity_name50000005}
+// CHECK:STDOUT:     inst5000002F:    {kind: ImportRefLoaded, arg0: import_ir_inst7, arg1: entity_name<none>, type: type(inst50000028)}
+// CHECK:STDOUT:     inst50000030:    {kind: ImportRefUnloaded, arg0: import_ir_inst8, arg1: entity_name<none>}
+// CHECK:STDOUT:     inst50000031:    {kind: NameRef, arg0: name6, arg1: inst50000026, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000032:    {kind: PatternType, arg0: inst50000028, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000033:    {kind: SymbolicBinding, arg0: entity_name50000007, arg1: inst<none>, type: type(inst50000028)}
+// CHECK:STDOUT:     inst50000034:    {kind: SymbolicBinding, arg0: entity_name50000007, arg1: inst<none>, type: type(inst50000028)}
+// CHECK:STDOUT:     inst50000035:    {kind: SymbolicBinding, arg0: entity_name50000007, arg1: inst<none>, type: type(inst50000028)}
+// CHECK:STDOUT:     inst50000036:    {kind: SymbolicBindingPattern, arg0: entity_name50000007, type: type(inst50000032)}
+// CHECK:STDOUT:     inst50000037:    {kind: NameRef, arg0: name5, arg1: inst50000033, type: type(inst50000028)}
+// CHECK:STDOUT:     inst50000038:    {kind: FacetAccessType, arg0: inst50000037, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000039:    {kind: SymbolicBindingType, arg0: entity_name50000007, arg1: inst50000034, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000003A:    {kind: SymbolicBindingType, arg0: entity_name50000007, arg1: inst50000035, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000003B:    {kind: Converted, arg0: inst50000037, arg1: inst50000038, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000003C:    {kind: AssociatedEntityType, arg0: interface50000001, arg1: specific<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000003D:    {kind: ImportRefLoaded, arg0: import_ir_inst9, arg1: entity_name<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000003E:    {kind: AssociatedEntity, arg0: element0, arg1: inst5000003D, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst5000003F:    {kind: NameRef, arg0: name2, arg1: inst5000002B, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst50000040:    {kind: LookupImplWitness, arg0: inst50000034, arg1: specific_interface50000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000041:    {kind: LookupImplWitness, arg0: inst50000034, arg1: specific_interface50000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000042:    {kind: AssociatedConstantDecl, arg0: assoc_const50000002, arg1: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000043:    {kind: ImplWitnessAccess, arg0: inst50000041, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000044:    {kind: ImplWitnessAccess, arg0: inst50000041, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000045:    {kind: LookupImplWitness, arg0: inst50000035, arg1: specific_interface50000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000046:    {kind: ImplWitnessAccess, arg0: inst50000045, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000047:    {kind: PatternType, arg0: inst50000044, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000048:    {kind: ValueParamPattern, arg0: name(Underscore), type: type(symbolic_constant5000000D)}
+// CHECK:STDOUT:     inst50000049:    {kind: PatternType, arg0: inst50000046, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000004A:    {kind: ValueBinding, arg0: entity_name50000008, arg1: inst5000005D, type: type(symbolic_constant5000000B)}
+// CHECK:STDOUT:     inst5000004B:    {kind: WrapperBindingPattern, arg0: entity_name50000008, arg1: inst50000048, type: type(symbolic_constant5000000D)}
+// CHECK:STDOUT:     inst5000004C:    {kind: NameRef, arg0: name5, arg1: inst50000033, type: type(inst50000028)}
+// CHECK:STDOUT:     inst5000004D:    {kind: FacetAccessType, arg0: inst5000004C, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000004E:    {kind: Converted, arg0: inst5000004C, arg1: inst5000004D, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000004F:    {kind: ImportRefLoaded, arg0: import_ir_instB, arg1: entity_name<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000050:    {kind: AssociatedEntity, arg0: element1, arg1: inst5000004F, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst50000051:    {kind: NameRef, arg0: name3, arg1: inst5000002C, type: type(inst5000003C)}
+// CHECK:STDOUT:     inst50000052:    {kind: LookupImplWitness, arg0: inst50000034, arg1: specific_interface50000000, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000053:    {kind: AssociatedConstantDecl, arg0: assoc_const50000003, arg1: inst_block_empty, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000054:    {kind: ImplWitnessAccess, arg0: inst50000041, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000055:    {kind: ImplWitnessAccess, arg0: inst50000041, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000056:    {kind: ImplWitnessAccess, arg0: inst50000045, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000057:    {kind: PatternType, arg0: inst50000055, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000058:    {kind: ValueParamPattern, arg0: name(Underscore), type: type(symbolic_constant50000011)}
+// CHECK:STDOUT:     inst50000059:    {kind: PatternType, arg0: inst50000056, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000005A:    {kind: ValueBinding, arg0: entity_name50000009, arg1: inst5000005F, type: type(symbolic_constant5000000F)}
+// CHECK:STDOUT:     inst5000005B:    {kind: WrapperBindingPattern, arg0: entity_name50000009, arg1: inst50000058, type: type(symbolic_constant50000011)}
+// CHECK:STDOUT:     inst5000005C:    {kind: SpliceBlock, arg0: inst_block5000000E, arg1: inst50000031, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000005D:    {kind: ValueParam, arg0: call_param0, arg1: name(Underscore), type: type(symbolic_constant5000000B)}
+// CHECK:STDOUT:     inst5000005E:    {kind: SpliceBlock, arg0: inst_block50000013, arg1: inst50000043, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000005F:    {kind: ValueParam, arg0: call_param1, arg1: name(Underscore), type: type(symbolic_constant5000000F)}
+// CHECK:STDOUT:     inst50000060:    {kind: SpliceBlock, arg0: inst_block50000016, arg1: inst50000054, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000061:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block5000001B, type: type(inst50000062)}
+// CHECK:STDOUT:     inst50000062:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000063:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000062)}
+// CHECK:STDOUT:     inst50000064:    {kind: RequireCompleteType, arg0: inst50000044, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000065:    {kind: RequireCompleteType, arg0: inst50000044, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000066:    {kind: RequireCompleteType, arg0: inst50000046, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000067:    {kind: RequireCompleteType, arg0: inst50000055, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000068:    {kind: RequireCompleteType, arg0: inst50000055, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000069:    {kind: RequireCompleteType, arg0: inst50000056, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000006A:    {kind: Return}
+// CHECK:STDOUT:     inst5000006B:    {kind: SymbolicBinding, arg0: entity_name50000001, arg1: inst<none>, type: type(inst50000021)}
+// CHECK:STDOUT:     inst5000006C:    {kind: NameRef, arg0: name1, arg1: inst50000012, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000006D:    {kind: PatternType, arg0: inst50000013, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000006E:    {kind: SymbolicBinding, arg0: entity_name5000000A, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst5000006F:    {kind: SymbolicBinding, arg0: entity_name50000007, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000070:    {kind: SymbolicBinding, arg0: entity_name50000007, arg1: inst<none>, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000071:    {kind: SymbolicBindingPattern, arg0: entity_name5000000A, type: type(inst5000006D)}
+// CHECK:STDOUT:     inst50000072:    {kind: NameRef, arg0: name5, arg1: inst5000006E, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000073:    {kind: FacetAccessType, arg0: inst50000072, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000074:    {kind: SymbolicBindingType, arg0: entity_name50000007, arg1: inst5000006F, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000075:    {kind: SymbolicBindingType, arg0: entity_name50000007, arg1: inst50000070, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000076:    {kind: Converted, arg0: inst50000072, arg1: inst50000073, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000077:    {kind: NameRef, arg0: name2, arg1: inst5000001B, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst50000078:    {kind: LookupImplWitness, arg0: inst5000006F, arg1: specific_interface50000001, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000079:    {kind: LookupImplWitness, arg0: inst5000006F, arg1: specific_interface50000001, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000007A:    {kind: ImplWitnessAccess, arg0: inst50000079, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000007B:    {kind: ImplWitnessAccess, arg0: inst50000079, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000007C:    {kind: LookupImplWitness, arg0: inst50000070, arg1: specific_interface50000001, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000007D:    {kind: ImplWitnessAccess, arg0: inst5000007C, arg1: element0, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000007E:    {kind: PatternType, arg0: inst5000007B, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000007F:    {kind: ValueParamPattern, arg0: name(Underscore), type: type(symbolic_constant5000001F)}
+// CHECK:STDOUT:     inst50000080:    {kind: PatternType, arg0: inst5000007D, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000081:    {kind: ValueBinding, arg0: entity_name5000000B, arg1: inst50000091, type: type(symbolic_constant5000001D)}
+// CHECK:STDOUT:     inst50000082:    {kind: WrapperBindingPattern, arg0: entity_name5000000B, arg1: inst5000007F, type: type(symbolic_constant5000001F)}
+// CHECK:STDOUT:     inst50000083:    {kind: NameRef, arg0: name5, arg1: inst5000006E, type: type(inst50000013)}
+// CHECK:STDOUT:     inst50000084:    {kind: FacetAccessType, arg0: inst50000083, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000085:    {kind: Converted, arg0: inst50000083, arg1: inst50000084, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000086:    {kind: NameRef, arg0: name3, arg1: inst5000001F, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst50000087:    {kind: LookupImplWitness, arg0: inst5000006F, arg1: specific_interface50000001, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000088:    {kind: ImplWitnessAccess, arg0: inst50000079, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000089:    {kind: ImplWitnessAccess, arg0: inst50000079, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000008A:    {kind: ImplWitnessAccess, arg0: inst5000007C, arg1: element1, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000008B:    {kind: PatternType, arg0: inst50000089, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000008C:    {kind: ValueParamPattern, arg0: name(Underscore), type: type(symbolic_constant50000023)}
+// CHECK:STDOUT:     inst5000008D:    {kind: PatternType, arg0: inst5000008A, type: type(TypeType)}
+// CHECK:STDOUT:     inst5000008E:    {kind: ValueBinding, arg0: entity_name5000000C, arg1: inst50000093, type: type(symbolic_constant50000021)}
+// CHECK:STDOUT:     inst5000008F:    {kind: WrapperBindingPattern, arg0: entity_name5000000C, arg1: inst5000008C, type: type(symbolic_constant50000023)}
+// CHECK:STDOUT:     inst50000090:    {kind: SpliceBlock, arg0: inst_block50000021, arg1: inst5000006C, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000091:    {kind: ValueParam, arg0: call_param0, arg1: name(Underscore), type: type(symbolic_constant5000001D)}
+// CHECK:STDOUT:     inst50000092:    {kind: SpliceBlock, arg0: inst_block50000023, arg1: inst5000007A, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000093:    {kind: ValueParam, arg0: call_param1, arg1: name(Underscore), type: type(symbolic_constant50000021)}
+// CHECK:STDOUT:     inst50000094:    {kind: SpliceBlock, arg0: inst_block50000026, arg1: inst50000088, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000095:    {kind: FunctionDecl, arg0: function50000001, arg1: inst_block5000002B, type: type(inst50000096)}
+// CHECK:STDOUT:     inst50000096:    {kind: FunctionType, arg0: function50000001, arg1: specific<none>, type: type(TypeType)}
+// CHECK:STDOUT:     inst50000097:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000096)}
+// CHECK:STDOUT:     inst50000098:    {kind: RequireCompleteType, arg0: inst5000007B, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst50000099:    {kind: RequireCompleteType, arg0: inst5000007B, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000009A:    {kind: RequireCompleteType, arg0: inst5000007D, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000009B:    {kind: RequireCompleteType, arg0: inst50000089, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000009C:    {kind: RequireCompleteType, arg0: inst50000089, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000009D:    {kind: RequireCompleteType, arg0: inst5000008A, type: type(inst(WitnessType))}
+// CHECK:STDOUT:     inst5000009E:    {kind: Return}
+// CHECK:STDOUT:   constant_values:
+// CHECK:STDOUT:     values:
+// CHECK:STDOUT:       instF:           concrete_constant(instF)
+// CHECK:STDOUT:       inst50000011:    concrete_constant(inst50000011)
+// CHECK:STDOUT:       inst50000012:    concrete_constant(inst50000013)
+// CHECK:STDOUT:       inst50000013:    concrete_constant(inst50000013)
+// CHECK:STDOUT:       inst50000014:    symbolic_constant50000000
+// CHECK:STDOUT:       inst50000015:    symbolic_constant50000000
+// CHECK:STDOUT:       inst50000016:    symbolic_constant50000001
+// CHECK:STDOUT:       inst50000017:    concrete_constant(inst50000017)
+// CHECK:STDOUT:       inst50000018:    concrete_constant(inst(TypeType))
+// CHECK:STDOUT:       inst50000019:    concrete_constant(inst50000019)
+// CHECK:STDOUT:       inst5000001A:    concrete_constant(inst5000001A)
+// CHECK:STDOUT:       inst5000001B:    concrete_constant(inst5000001C)
+// CHECK:STDOUT:       inst5000001C:    concrete_constant(inst5000001C)
+// CHECK:STDOUT:       inst5000001D:    concrete_constant(inst(TypeType))
+// CHECK:STDOUT:       inst5000001E:    concrete_constant(inst5000001E)
+// CHECK:STDOUT:       inst5000001F:    concrete_constant(inst50000020)
+// CHECK:STDOUT:       inst50000020:    concrete_constant(inst50000020)
+// CHECK:STDOUT:       inst50000021:    concrete_constant(inst50000021)
+// CHECK:STDOUT:       inst50000022:    symbolic_constant50000002
+// CHECK:STDOUT:       inst50000023:    symbolic_constant50000002
+// CHECK:STDOUT:       inst50000024:    concrete_constant(inst50000011)
+// CHECK:STDOUT:       inst50000025:    concrete_constant(inst50000025)
+// CHECK:STDOUT:       inst50000026:    concrete_constant(inst50000028)
+// CHECK:STDOUT:       inst50000027:    concrete_constant(inst50000028)
+// CHECK:STDOUT:       inst50000028:    concrete_constant(inst50000028)
+// CHECK:STDOUT:       inst50000029:    concrete_constant(inst50000029)
+// CHECK:STDOUT:       inst5000002A:    symbolic_constant50000003
+// CHECK:STDOUT:       inst5000002B:    concrete_constant(inst5000003E)
+// CHECK:STDOUT:       inst5000002C:    concrete_constant(inst50000050)
+// CHECK:STDOUT:       inst5000002D:    constant<none>
+// CHECK:STDOUT:       inst5000002E:    constant<none>
+// CHECK:STDOUT:       inst5000002F:    symbolic_constant50000003
+// CHECK:STDOUT:       inst50000030:    constant<none>
+// CHECK:STDOUT:       inst50000031:    concrete_constant(inst50000028)
+// CHECK:STDOUT:       inst50000032:    concrete_constant(inst50000032)
+// CHECK:STDOUT:       inst50000033:    symbolic_constant50000005
+// CHECK:STDOUT:       inst50000034:    symbolic_constant50000004
+// CHECK:STDOUT:       inst50000035:    symbolic_constant50000005
+// CHECK:STDOUT:       inst50000036:    concrete_constant(inst50000036)
+// CHECK:STDOUT:       inst50000037:    symbolic_constant50000005
+// CHECK:STDOUT:       inst50000038:    symbolic_constant50000007
+// CHECK:STDOUT:       inst50000039:    symbolic_constant50000006
+// CHECK:STDOUT:       inst5000003A:    symbolic_constant50000007
+// CHECK:STDOUT:       inst5000003B:    symbolic_constant50000007
+// CHECK:STDOUT:       inst5000003C:    concrete_constant(inst5000003C)
+// CHECK:STDOUT:       inst5000003D:    concrete_constant(inst50000042)
+// CHECK:STDOUT:       inst5000003E:    concrete_constant(inst5000003E)
+// CHECK:STDOUT:       inst5000003F:    concrete_constant(inst5000003E)
+// CHECK:STDOUT:       inst50000041:    symbolic_constant50000008
+// CHECK:STDOUT:       inst50000042:    concrete_constant(inst50000042)
+// CHECK:STDOUT:       inst50000043:    symbolic_constant5000000B
+// CHECK:STDOUT:       inst50000044:    symbolic_constant50000009
+// CHECK:STDOUT:       inst50000045:    symbolic_constant5000000A
+// CHECK:STDOUT:       inst50000046:    symbolic_constant5000000B
+// CHECK:STDOUT:       inst50000047:    symbolic_constant5000000C
+// CHECK:STDOUT:       inst50000048:    concrete_constant(inst50000048)
+// CHECK:STDOUT:       inst50000049:    symbolic_constant5000000D
+// CHECK:STDOUT:       inst5000004B:    concrete_constant(inst5000004B)
+// CHECK:STDOUT:       inst5000004C:    symbolic_constant50000005
+// CHECK:STDOUT:       inst5000004D:    symbolic_constant50000007
+// CHECK:STDOUT:       inst5000004E:    symbolic_constant50000007
+// CHECK:STDOUT:       inst5000004F:    concrete_constant(inst50000053)
+// CHECK:STDOUT:       inst50000050:    concrete_constant(inst50000050)
+// CHECK:STDOUT:       inst50000051:    concrete_constant(inst50000050)
+// CHECK:STDOUT:       inst50000053:    concrete_constant(inst50000053)
+// CHECK:STDOUT:       inst50000054:    symbolic_constant5000000F
+// CHECK:STDOUT:       inst50000055:    symbolic_constant5000000E
+// CHECK:STDOUT:       inst50000056:    symbolic_constant5000000F
+// CHECK:STDOUT:       inst50000057:    symbolic_constant50000010
+// CHECK:STDOUT:       inst50000058:    concrete_constant(inst50000058)
+// CHECK:STDOUT:       inst50000059:    symbolic_constant50000011
+// CHECK:STDOUT:       inst5000005B:    concrete_constant(inst5000005B)
+// CHECK:STDOUT:       inst5000005C:    concrete_constant(inst50000028)
+// CHECK:STDOUT:       inst5000005E:    symbolic_constant5000000B
+// CHECK:STDOUT:       inst50000060:    symbolic_constant5000000F
+// CHECK:STDOUT:       inst50000061:    concrete_constant(inst50000063)
+// CHECK:STDOUT:       inst50000062:    concrete_constant(inst50000062)
+// CHECK:STDOUT:       inst50000063:    concrete_constant(inst50000063)
+// CHECK:STDOUT:       inst50000064:    symbolic_constant50000013
+// CHECK:STDOUT:       inst50000065:    symbolic_constant50000012
+// CHECK:STDOUT:       inst50000066:    symbolic_constant50000013
+// CHECK:STDOUT:       inst50000067:    symbolic_constant50000015
+// CHECK:STDOUT:       inst50000068:    symbolic_constant50000014
+// CHECK:STDOUT:       inst50000069:    symbolic_constant50000015
+// CHECK:STDOUT:       inst5000006B:    symbolic_constant50000002
+// CHECK:STDOUT:       inst5000006C:    concrete_constant(inst50000013)
+// CHECK:STDOUT:       inst5000006D:    concrete_constant(inst5000006D)
+// CHECK:STDOUT:       inst5000006E:    symbolic_constant50000017
+// CHECK:STDOUT:       inst5000006F:    symbolic_constant50000016
+// CHECK:STDOUT:       inst50000070:    symbolic_constant50000017
+// CHECK:STDOUT:       inst50000071:    concrete_constant(inst50000071)
+// CHECK:STDOUT:       inst50000072:    symbolic_constant50000017
+// CHECK:STDOUT:       inst50000073:    symbolic_constant50000019
+// CHECK:STDOUT:       inst50000074:    symbolic_constant50000018
+// CHECK:STDOUT:       inst50000075:    symbolic_constant50000019
+// CHECK:STDOUT:       inst50000076:    symbolic_constant50000019
+// CHECK:STDOUT:       inst50000077:    concrete_constant(inst5000001C)
+// CHECK:STDOUT:       inst50000079:    symbolic_constant5000001A
+// CHECK:STDOUT:       inst5000007A:    symbolic_constant5000001D
+// CHECK:STDOUT:       inst5000007B:    symbolic_constant5000001B
+// CHECK:STDOUT:       inst5000007C:    symbolic_constant5000001C
+// CHECK:STDOUT:       inst5000007D:    symbolic_constant5000001D
+// CHECK:STDOUT:       inst5000007E:    symbolic_constant5000001E
+// CHECK:STDOUT:       inst5000007F:    concrete_constant(inst5000007F)
+// CHECK:STDOUT:       inst50000080:    symbolic_constant5000001F
+// CHECK:STDOUT:       inst50000082:    concrete_constant(inst50000082)
+// CHECK:STDOUT:       inst50000083:    symbolic_constant50000017
+// CHECK:STDOUT:       inst50000084:    symbolic_constant50000019
+// CHECK:STDOUT:       inst50000085:    symbolic_constant50000019
+// CHECK:STDOUT:       inst50000086:    concrete_constant(inst50000020)
+// CHECK:STDOUT:       inst50000088:    symbolic_constant50000021
+// CHECK:STDOUT:       inst50000089:    symbolic_constant50000020
+// CHECK:STDOUT:       inst5000008A:    symbolic_constant50000021
+// CHECK:STDOUT:       inst5000008B:    symbolic_constant50000022
+// CHECK:STDOUT:       inst5000008C:    concrete_constant(inst5000008C)
+// CHECK:STDOUT:       inst5000008D:    symbolic_constant50000023
+// CHECK:STDOUT:       inst5000008F:    concrete_constant(inst5000008F)
+// CHECK:STDOUT:       inst50000090:    concrete_constant(inst50000013)
+// CHECK:STDOUT:       inst50000092:    symbolic_constant5000001D
+// CHECK:STDOUT:       inst50000094:    symbolic_constant50000021
+// CHECK:STDOUT:       inst50000095:    concrete_constant(inst50000097)
+// CHECK:STDOUT:       inst50000096:    concrete_constant(inst50000096)
+// CHECK:STDOUT:       inst50000097:    concrete_constant(inst50000097)
+// CHECK:STDOUT:       inst50000098:    symbolic_constant50000025
+// CHECK:STDOUT:       inst50000099:    symbolic_constant50000024
+// CHECK:STDOUT:       inst5000009A:    symbolic_constant50000025
+// CHECK:STDOUT:       inst5000009B:    symbolic_constant50000027
+// CHECK:STDOUT:       inst5000009C:    symbolic_constant50000026
+// CHECK:STDOUT:       inst5000009D:    symbolic_constant50000027
+// CHECK:STDOUT:     symbolic_constants:
+// CHECK:STDOUT:       symbolic_constant50000000: {inst: inst50000015, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000001: {inst: inst50000015, kind: checked, attached: {generic: generic50000000, index: generic_inst_in_def0}}
+// CHECK:STDOUT:       symbolic_constant50000002: {inst: inst50000023, kind: self, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000003: {inst: inst5000002A, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000004: {inst: inst50000034, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000005: {inst: inst50000034, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl0}}
+// CHECK:STDOUT:       symbolic_constant50000006: {inst: inst50000039, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000007: {inst: inst50000039, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl1}}
+// CHECK:STDOUT:       symbolic_constant50000008: {inst: inst50000041, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000009: {inst: inst50000044, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000000A: {inst: inst50000041, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl2}}
+// CHECK:STDOUT:       symbolic_constant5000000B: {inst: inst50000044, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl3}}
+// CHECK:STDOUT:       symbolic_constant5000000C: {inst: inst50000047, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000000D: {inst: inst50000047, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl4}}
+// CHECK:STDOUT:       symbolic_constant5000000E: {inst: inst50000055, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000000F: {inst: inst50000055, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl5}}
+// CHECK:STDOUT:       symbolic_constant50000010: {inst: inst50000057, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000011: {inst: inst50000057, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_decl6}}
+// CHECK:STDOUT:       symbolic_constant50000012: {inst: inst50000065, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000013: {inst: inst50000065, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_def0}}
+// CHECK:STDOUT:       symbolic_constant50000014: {inst: inst50000068, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000015: {inst: inst50000068, kind: checked, attached: {generic: generic50000003, index: generic_inst_in_def1}}
+// CHECK:STDOUT:       symbolic_constant50000016: {inst: inst5000006F, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000017: {inst: inst5000006F, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl0}}
+// CHECK:STDOUT:       symbolic_constant50000018: {inst: inst50000074, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000019: {inst: inst50000074, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl1}}
+// CHECK:STDOUT:       symbolic_constant5000001A: {inst: inst50000079, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000001B: {inst: inst5000007B, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000001C: {inst: inst50000079, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl2}}
+// CHECK:STDOUT:       symbolic_constant5000001D: {inst: inst5000007B, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl3}}
+// CHECK:STDOUT:       symbolic_constant5000001E: {inst: inst5000007E, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant5000001F: {inst: inst5000007E, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl4}}
+// CHECK:STDOUT:       symbolic_constant50000020: {inst: inst50000089, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000021: {inst: inst50000089, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl5}}
+// CHECK:STDOUT:       symbolic_constant50000022: {inst: inst5000008B, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000023: {inst: inst5000008B, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_decl6}}
+// CHECK:STDOUT:       symbolic_constant50000024: {inst: inst50000099, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000025: {inst: inst50000099, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_def0}}
+// CHECK:STDOUT:       symbolic_constant50000026: {inst: inst5000009C, kind: checked, attached: null}
+// CHECK:STDOUT:       symbolic_constant50000027: {inst: inst5000009C, kind: checked, attached: {generic: generic50000004, index: generic_inst_in_def1}}
+// CHECK:STDOUT:   inst_blocks:
+// CHECK:STDOUT:     inst_block_empty: {}
+// CHECK:STDOUT:     exports:
+// CHECK:STDOUT:       0:               inst50000012
+// CHECK:STDOUT:       1:               inst50000061
+// CHECK:STDOUT:       2:               inst50000095
+// CHECK:STDOUT:     generated:       {}
+// CHECK:STDOUT:     imports:
+// CHECK:STDOUT:       0:               inst50000011
+// CHECK:STDOUT:       1:               inst50000026
+// CHECK:STDOUT:       2:               inst50000027
+// CHECK:STDOUT:       3:               inst50000029
+// CHECK:STDOUT:       4:               inst5000002B
+// CHECK:STDOUT:       5:               inst5000002C
+// CHECK:STDOUT:       6:               inst5000002D
+// CHECK:STDOUT:       7:               inst5000002E
+// CHECK:STDOUT:       8:               inst5000002F
+// CHECK:STDOUT:       9:               inst50000030
+// CHECK:STDOUT:       10:              inst5000003D
+// CHECK:STDOUT:       11:              inst50000042
+// CHECK:STDOUT:       12:              inst5000004F
+// CHECK:STDOUT:       13:              inst50000053
+// CHECK:STDOUT:     global_init:     {}
+// CHECK:STDOUT:     inst_block50000005:
+// CHECK:STDOUT:       0:               inst50000014
+// CHECK:STDOUT:     inst_block50000006:
+// CHECK:STDOUT:       0:               inst50000015
+// CHECK:STDOUT:     inst_block50000007:
+// CHECK:STDOUT:       0:               inst50000014
+// CHECK:STDOUT:       1:               inst50000017
+// CHECK:STDOUT:     inst_block50000008:
+// CHECK:STDOUT:       0:               inst50000019
+// CHECK:STDOUT:       1:               inst5000001E
+// CHECK:STDOUT:     inst_block50000009:
+// CHECK:STDOUT:       0:               inst50000018
+// CHECK:STDOUT:     inst_block5000000A:
+// CHECK:STDOUT:       0:               inst5000001B
+// CHECK:STDOUT:     inst_block5000000B:
+// CHECK:STDOUT:       0:               inst5000001D
+// CHECK:STDOUT:     inst_block5000000C:
+// CHECK:STDOUT:       0:               inst5000001F
+// CHECK:STDOUT:     inst_block5000000D:
+// CHECK:STDOUT:       0:               inst50000019
+// CHECK:STDOUT:       1:               inst5000001E
+// CHECK:STDOUT:     inst_block5000000E:
+// CHECK:STDOUT:       0:               inst50000022
+// CHECK:STDOUT:       1:               inst50000024
+// CHECK:STDOUT:       2:               inst50000031
+// CHECK:STDOUT:     inst_block5000000F:
+// CHECK:STDOUT:       0:               inst5000002D
+// CHECK:STDOUT:       1:               inst5000002E
+// CHECK:STDOUT:     inst_block50000010:
+// CHECK:STDOUT:       0:               inst5000002F
+// CHECK:STDOUT:     inst_block50000011:
+// CHECK:STDOUT:       0:               inst5000002A
+// CHECK:STDOUT:     inst_block50000012:
+// CHECK:STDOUT:       0:               inst50000036
+// CHECK:STDOUT:     inst_block50000013:
+// CHECK:STDOUT:       0:               inst50000037
+// CHECK:STDOUT:       1:               inst50000038
+// CHECK:STDOUT:       2:               inst5000003B
+// CHECK:STDOUT:       3:               inst5000003F
+// CHECK:STDOUT:       4:               inst50000043
+// CHECK:STDOUT:     inst_block50000014:
+// CHECK:STDOUT:       0:               inst50000034
+// CHECK:STDOUT:     inst_block50000015:
+// CHECK:STDOUT:       0:               inst50000041
+// CHECK:STDOUT:     inst_block50000016:
+// CHECK:STDOUT:       0:               inst5000004C
+// CHECK:STDOUT:       1:               inst5000004D
+// CHECK:STDOUT:       2:               inst5000004E
+// CHECK:STDOUT:       3:               inst50000051
+// CHECK:STDOUT:       4:               inst50000054
+// CHECK:STDOUT:     inst_block50000017:
+// CHECK:STDOUT:       0:               inst5000004B
+// CHECK:STDOUT:       1:               inst5000005B
+// CHECK:STDOUT:     inst_block50000018:
+// CHECK:STDOUT:       0:               inst50000048
+// CHECK:STDOUT:       1:               inst50000058
+// CHECK:STDOUT:     inst_block50000019:
+// CHECK:STDOUT:       0:               inst5000005D
+// CHECK:STDOUT:       1:               inst5000005F
+// CHECK:STDOUT:     inst_block5000001A:
+// CHECK:STDOUT:       0:               inst50000036
+// CHECK:STDOUT:       1:               inst50000048
+// CHECK:STDOUT:       2:               inst5000004B
+// CHECK:STDOUT:       3:               inst50000058
+// CHECK:STDOUT:       4:               inst5000005B
+// CHECK:STDOUT:     inst_block5000001B:
+// CHECK:STDOUT:       0:               inst5000005C
+// CHECK:STDOUT:       1:               inst50000033
+// CHECK:STDOUT:       2:               inst5000005D
+// CHECK:STDOUT:       3:               inst5000005E
+// CHECK:STDOUT:       4:               inst5000004A
+// CHECK:STDOUT:       5:               inst5000005F
+// CHECK:STDOUT:       6:               inst50000060
+// CHECK:STDOUT:       7:               inst5000005A
+// CHECK:STDOUT:     inst_block5000001C:
+// CHECK:STDOUT:       0:               inst50000033
+// CHECK:STDOUT:     inst_block5000001D:
+// CHECK:STDOUT:       0:               inst50000035
+// CHECK:STDOUT:       1:               inst5000003A
+// CHECK:STDOUT:       2:               inst50000045
+// CHECK:STDOUT:       3:               inst50000046
+// CHECK:STDOUT:       4:               inst50000049
+// CHECK:STDOUT:       5:               inst50000056
+// CHECK:STDOUT:       6:               inst50000059
+// CHECK:STDOUT:     inst_block5000001E:
+// CHECK:STDOUT:       0:               inst50000034
+// CHECK:STDOUT:       1:               inst50000039
+// CHECK:STDOUT:       2:               inst50000041
+// CHECK:STDOUT:       3:               inst50000044
+// CHECK:STDOUT:       4:               inst50000047
+// CHECK:STDOUT:       5:               inst50000055
+// CHECK:STDOUT:       6:               inst50000057
+// CHECK:STDOUT:     inst_block5000001F:
+// CHECK:STDOUT:       0:               inst5000006A
+// CHECK:STDOUT:     inst_block50000020:
+// CHECK:STDOUT:       0:               inst50000066
+// CHECK:STDOUT:       1:               inst50000069
+// CHECK:STDOUT:     inst_block50000021:
+// CHECK:STDOUT:       0:               inst5000006B
+// CHECK:STDOUT:       1:               inst5000006C
+// CHECK:STDOUT:     inst_block50000022:
+// CHECK:STDOUT:       0:               inst50000071
+// CHECK:STDOUT:     inst_block50000023:
+// CHECK:STDOUT:       0:               inst50000072
+// CHECK:STDOUT:       1:               inst50000073
+// CHECK:STDOUT:       2:               inst50000076
+// CHECK:STDOUT:       3:               inst50000077
+// CHECK:STDOUT:       4:               inst5000007A
+// CHECK:STDOUT:     inst_block50000024:
+// CHECK:STDOUT:       0:               inst5000006F
+// CHECK:STDOUT:     inst_block50000025:
+// CHECK:STDOUT:       0:               inst50000079
+// CHECK:STDOUT:     inst_block50000026:
+// CHECK:STDOUT:       0:               inst50000083
+// CHECK:STDOUT:       1:               inst50000084
+// CHECK:STDOUT:       2:               inst50000085
+// CHECK:STDOUT:       3:               inst50000086
+// CHECK:STDOUT:       4:               inst50000088
+// CHECK:STDOUT:     inst_block50000027:
+// CHECK:STDOUT:       0:               inst50000082
+// CHECK:STDOUT:       1:               inst5000008F
+// CHECK:STDOUT:     inst_block50000028:
+// CHECK:STDOUT:       0:               inst5000007F
+// CHECK:STDOUT:       1:               inst5000008C
+// CHECK:STDOUT:     inst_block50000029:
+// CHECK:STDOUT:       0:               inst50000091
+// CHECK:STDOUT:       1:               inst50000093
+// CHECK:STDOUT:     inst_block5000002A:
+// CHECK:STDOUT:       0:               inst50000071
+// CHECK:STDOUT:       1:               inst5000007F
+// CHECK:STDOUT:       2:               inst50000082
+// CHECK:STDOUT:       3:               inst5000008C
+// CHECK:STDOUT:       4:               inst5000008F
+// CHECK:STDOUT:     inst_block5000002B:
+// CHECK:STDOUT:       0:               inst50000090
+// CHECK:STDOUT:       1:               inst5000006E
+// CHECK:STDOUT:       2:               inst50000091
+// CHECK:STDOUT:       3:               inst50000092
+// CHECK:STDOUT:       4:               inst50000081
+// CHECK:STDOUT:       5:               inst50000093
+// CHECK:STDOUT:       6:               inst50000094
+// CHECK:STDOUT:       7:               inst5000008E
+// CHECK:STDOUT:     inst_block5000002C:
+// CHECK:STDOUT:       0:               inst5000006E
+// CHECK:STDOUT:     inst_block5000002D:
+// CHECK:STDOUT:       0:               inst50000070
+// CHECK:STDOUT:       1:               inst50000075
+// CHECK:STDOUT:       2:               inst5000007C
+// CHECK:STDOUT:       3:               inst5000007D
+// CHECK:STDOUT:       4:               inst50000080
+// CHECK:STDOUT:       5:               inst5000008A
+// CHECK:STDOUT:       6:               inst5000008D
+// CHECK:STDOUT:     inst_block5000002E:
+// CHECK:STDOUT:       0:               inst5000006F
+// CHECK:STDOUT:       1:               inst50000074
+// CHECK:STDOUT:       2:               inst50000079
+// CHECK:STDOUT:       3:               inst5000007B
+// CHECK:STDOUT:       4:               inst5000007E
+// CHECK:STDOUT:       5:               inst50000089
+// CHECK:STDOUT:       6:               inst5000008B
+// CHECK:STDOUT:     inst_block5000002F:
+// CHECK:STDOUT:       0:               inst5000009E
+// CHECK:STDOUT:     inst_block50000030:
+// CHECK:STDOUT:       0:               inst5000009A
+// CHECK:STDOUT:       1:               inst5000009D
+// CHECK:STDOUT:     inst_block50000031:
+// CHECK:STDOUT:       0:               instF
+// CHECK:STDOUT:       1:               inst50000010
+// CHECK:STDOUT:       2:               inst50000012
+// CHECK:STDOUT:       3:               inst50000061
+// CHECK:STDOUT:       4:               inst50000095
+// CHECK:STDOUT:   value_stores:
+// CHECK:STDOUT:     shared_values:
+// CHECK:STDOUT:       ints:            {}
+// CHECK:STDOUT:       reals:           {}
+// CHECK:STDOUT:       floats:          {}
+// CHECK:STDOUT:       identifiers:
+// CHECK:STDOUT:         identifier0:     NonCore
+// CHECK:STDOUT:         identifier1:     Copy
+// CHECK:STDOUT:         identifier2:     T1
+// CHECK:STDOUT:         identifier3:     T2
+// CHECK:STDOUT:         identifier4:     UseNonCoreDestroy
+// CHECK:STDOUT:         identifier5:     T
+// CHECK:STDOUT:         identifier6:     Destroy
+// CHECK:STDOUT:         identifier7:     UseLocalCopy
+// CHECK:STDOUT:       strings:         {}
+// CHECK:STDOUT: ...

+ 1 - 1
toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon

@@ -345,7 +345,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     function78000005: {name: name4, parent_scope: name_scope7800000D, call_param_patterns_id: inst_block78000068, return_type_inst_id: inst78000131, return_form_inst_id: inst78000132, return_pattern_id: inst7800012D}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   interfaces:
-// CHECK:STDOUT:     interface78000000: {name: name3, parent_scope: name_scope78000001, require_impls_block_id: require_block_empty}
+// CHECK:STDOUT:     interface78000000: {name: name3, parent_scope: name_scope78000001, require_impls_block_id: require_block_empty, core_interface: Copy}
 // CHECK:STDOUT:   associated_constants: {}
 // CHECK:STDOUT:   impls:
 // CHECK:STDOUT:     impl78000000:    {self: inst7800009B, constraint: inst7800009C, witness: inst7800006F}

+ 3 - 0
toolchain/sem_ir/BUILD

@@ -85,6 +85,7 @@ cc_library(
         "builtin_function_kind.cpp",
         "class.cpp",
         "constant.cpp",
+        "core_interface.cpp",
         "cpp_initializer_list.cpp",
         "facet_type_info.cpp",
         "file.cpp",
@@ -106,6 +107,7 @@ cc_library(
         "class.h",
         "constant.h",
         "copy_on_write_block.h",
+        "core_interface.h",
         "cpp_global_var.h",
         "cpp_initializer_list.h",
         "cpp_overload_set.h",
@@ -133,6 +135,7 @@ cc_library(
     ],
     textual_hdrs = [
         "builtin_function_kind.def",
+        "core_interface_kind.def",
     ],
     deps = [
         ":clang_decl",

+ 15 - 0
toolchain/sem_ir/core_interface.cpp

@@ -0,0 +1,15 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "toolchain/sem_ir/core_interface.h"  // IWYU pragma: keep
+
+#include "toolchain/sem_ir/inst_kind.h"
+
+namespace Carbon::SemIR {
+CARBON_DEFINE_ENUM_CLASS_NAMES(CoreInterface) {
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name) \
+  CARBON_ENUM_CLASS_NAME_STRING(Name)
+#include "toolchain/sem_ir/core_interface_kind.def"
+};
+}  // namespace Carbon::SemIR

+ 49 - 0
toolchain/sem_ir/core_interface.h

@@ -0,0 +1,49 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef CARBON_TOOLCHAIN_SEM_IR_CORE_INTERFACE_H_
+#define CARBON_TOOLCHAIN_SEM_IR_CORE_INTERFACE_H_
+
+#include <cstdint>
+
+#include "common/enum_base.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace Carbon::SemIR {
+
+CARBON_DEFINE_RAW_ENUM_CLASS(CoreInterface, std::uint8_t) {
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
+#include "toolchain/sem_ir/core_interface_kind.def"
+};
+
+// Significant interfaces in `Core` which correspond to language features and
+// can have custom witnesses.
+class CoreInterface : public CARBON_ENUM_BASE(CoreInterface) {
+ public:
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name) CARBON_ENUM_CONSTANT_DECL(Name)
+#include "toolchain/sem_ir/core_interface_kind.def"
+
+  static const llvm::ArrayRef<CoreInterface> CoreInterfaces;
+  using EnumBase::AsInt;
+  using EnumBase::EnumBase;
+
+ private:
+  static const CoreInterface CoreInterfacesStorage[];
+  static const llvm::StringLiteral Spelling[];
+};
+
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name) \
+  CARBON_ENUM_CONSTANT_DEFINITION(CoreInterface, Name)
+#include "toolchain/sem_ir/core_interface_kind.def"
+
+inline constexpr CoreInterface CoreInterface::CoreInterfacesStorage[] = {
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name) CoreInterface::Name,
+#include "toolchain/sem_ir/core_interface_kind.def"
+};
+inline constexpr llvm::ArrayRef<CoreInterface> CoreInterface::CoreInterfaces =
+    CoreInterfacesStorage;
+
+}  // namespace Carbon::SemIR
+
+#endif  // CARBON_TOOLCHAIN_SEM_IR_CORE_INTERFACE_H_

+ 27 - 0
toolchain/sem_ir/core_interface_kind.def

@@ -0,0 +1,27 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// This is an X-macro header. It does not use `#include` guards, and instead is
+// designed to be `#include`ed after the x-macro is defined in order for its
+// inclusion to expand to the desired output. Macro definitions are cleaned up
+// at the end of this file.
+//
+// Supported x-macro is:
+// - CARBON_SEM_IR_CORE_INTERFACE_KIND(Name)
+//   Defines a core interface.
+
+#ifndef CARBON_SEM_IR_CORE_INTERFACE_KIND
+#error "Must define CARBON_SEM_IR_CORE_INTERFACE_KIND x-macro to use this file."
+#define CARBON_SEM_IR_CORE_INTERFACE_KIND(Name)
+#endif
+
+CARBON_SEM_IR_CORE_INTERFACE_KIND(Copy)
+CARBON_SEM_IR_CORE_INTERFACE_KIND(CppUnsafeDeref)
+CARBON_SEM_IR_CORE_INTERFACE_KIND(Default)
+CARBON_SEM_IR_CORE_INTERFACE_KIND(Destroy)
+CARBON_SEM_IR_CORE_INTERFACE_KIND(IntFitsIn)
+
+CARBON_SEM_IR_CORE_INTERFACE_KIND(Unknown)
+
+#undef CARBON_SEM_IR_CORE_INTERFACE_KIND

+ 6 - 0
toolchain/sem_ir/interface.h

@@ -6,6 +6,7 @@
 #define CARBON_TOOLCHAIN_SEM_IR_INTERFACE_H_
 
 #include "toolchain/base/value_store.h"
+#include "toolchain/sem_ir/core_interface.h"
 #include "toolchain/sem_ir/entity_with_params_base.h"
 #include "toolchain/sem_ir/ids.h"
 
@@ -33,6 +34,8 @@ struct InterfaceFields {
   InstBlockId body_block_with_self_id = InstBlockId::None;
   // The implicit `Self` parameter. This is a SymbolicBinding instruction.
   InstId self_param_id = InstId::None;
+  // Identifies whether the interface is a core interface.
+  CoreInterface core_interface = CoreInterface::Unknown;
 
   // The following members are set at the `}` of the interface definition.
 
@@ -48,6 +51,9 @@ struct Interface : public EntityWithParamsBase,
     out << "{";
     PrintBaseFields(out);
     out << ", require_impls_block_id: " << require_impls_block_id;
+    if (core_interface != CoreInterface::Unknown) {
+      out << ", core_interface: " << core_interface;
+    }
     out << "}";
   }