Rewrite generic binding imports to use AddLoadedImportRef (#6388)

This is part of trying to rewrite pending specific/generic code to make
use of the standard constant resolution flow. The LoadImportRef code was
a particular sticking point due to the recursion it does, which makes it
difficult to adapt over.
This commit is contained in:
Jon Ross-Perkins
2025-11-19 00:56:17 +00:00
committed by GitHub
parent eb0dcc8ce4
commit 4a8efd81e3
3 changed files with 81 additions and 64 deletions
+57 -40
View File
@@ -434,7 +434,6 @@ class ImportRefResolver : public ImportContext {
// Performs resolution for one instruction and then performs all work we
// deferred.
// NOLINTNEXTLINE(misc-no-recursion)
auto Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId {
auto const_id = ResolveOneInst(inst_id);
PerformPendingWork();
@@ -442,7 +441,6 @@ class ImportRefResolver : public ImportContext {
}
// Wraps constant evaluation with logic to handle constants.
// NOLINTNEXTLINE(misc-no-recursion)
auto ResolveConstant(SemIR::ConstantId import_const_id) -> SemIR::ConstantId {
return Resolve(GetInstWithConstantValue(import_ir(), import_const_id));
}
@@ -511,6 +509,18 @@ static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,
entity_name_id);
}
// Handles setting a constant on instructions related to an import.
static auto SetIndirectConstantValues(
Context& context, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
SemIR::ConstantId constant_id) -> void {
for (const auto& import_ir_inst : indirect_insts) {
auto ir_index =
context.sem_ir().import_irs().GetRawIndex(import_ir_inst.ir_id());
context.import_ir_constant_values()[ir_index].Set(import_ir_inst.inst_id(),
constant_id);
}
}
// Adds an import_ref instruction for an instruction that we have already loaded
// from an imported IR, with a known constant value. This is useful when the
// instruction has a symbolic constant value, in order to produce an instruction
@@ -622,7 +632,7 @@ static auto GetLocalTypeInstId(ImportRefResolver& resolver,
// The input instruction is a TypeInstId, and import does not change the type
// of instructions, so the result is also a valid TypeInstId.
return SemIR::TypeInstId::UnsafeMake(
GetLocalConstantInstId(resolver, static_cast<SemIR::InstId>(inst_id)));
GetLocalConstantInstId(resolver, inst_id));
}
// Returns the ConstantId for a TypeId. Adds unresolved constants to
@@ -777,31 +787,65 @@ static auto MakeIncompleteGeneric(ImportContext& context, SemIR::InstId decl_id,
namespace {
// Local information associated with an imported generic.
struct GenericData {
// TODO: Delete `GenericData` if we still don't use it once generic import is
// more stable.
struct Binding {
// The attached type's constant, which may differ from the type on the
// constant. This needs to be preserved for the ImportRef.
SemIR::ConstantId type_constant_id;
SemIR::ConstantId inst_constant_id;
};
llvm::SmallVector<Binding> bindings;
};
} // namespace
// Gets a local version of the data associated with a generic.
static auto GetLocalGenericData(ImportRefResolver& /*resolver*/,
SemIR::GenericId /*generic_id*/)
static auto GetLocalGenericData(ImportRefResolver& resolver,
SemIR::GenericId import_generic_id)
-> GenericData {
return {};
GenericData generic_data;
if (import_generic_id.has_value()) {
const auto& import_generic =
resolver.import_generics().Get(import_generic_id);
if (import_generic.bindings_id.has_value()) {
auto import_bindings =
resolver.import_inst_blocks().Get(import_generic.bindings_id);
generic_data.bindings.reserve(import_bindings.size());
for (auto import_inst_id : import_bindings) {
generic_data.bindings.push_back(
{.type_constant_id = GetLocalConstantId(
resolver,
resolver.import_insts().GetAttachedType(import_inst_id)),
.inst_constant_id = GetLocalConstantId(resolver, import_inst_id)});
}
}
}
return generic_data;
}
// Adds the given local generic data to the given generic.
static auto SetGenericData(ImportContext& context,
SemIR::GenericId import_generic_id,
SemIR::GenericId new_generic_id,
const GenericData& /*generic_data*/) -> void {
const GenericData& generic_data) -> void {
if (!import_generic_id.has_value()) {
return;
}
const auto& import_generic = context.import_generics().Get(import_generic_id);
auto& new_generic = context.local_generics().Get(new_generic_id);
new_generic.bindings_id =
GetLocalImportRefInstBlock(context, import_generic.bindings_id);
auto import_bindings =
context.import_inst_blocks().Get(import_generic.bindings_id);
llvm::SmallVector<SemIR::InstId> new_bindings;
new_bindings.reserve(import_bindings.size());
for (auto [import_binding_id, binding] :
llvm::zip_equal(import_bindings, generic_data.bindings)) {
auto local_type_id = context.local_types().GetTypeIdForTypeConstantId(
binding.type_constant_id);
new_bindings.push_back(AddLoadedImportRef(
context, local_type_id, import_binding_id, binding.inst_constant_id));
}
new_generic.bindings_id = context.local_inst_blocks().Add(new_bindings);
// Track that we need to fill in the remaining information in
// FinishPendingGeneric.
@@ -3400,10 +3444,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
// `None` if more has been added to the stack. This is the same as
// TryResolveInst, except that it may resolve symbolic constants as canonical
// constants instead of as constants associated with a particular generic.
//
// TODO: Consider refactoring the body to a helper in order to eliminate
// recursion.
// NOLINTNEXTLINE(misc-no-recursion)
static auto TryResolveInstCanonical(ImportRefResolver& resolver,
SemIR::InstId inst_id,
SemIR::ConstantId const_id)
@@ -3779,7 +3819,6 @@ auto ImportRefResolver::ResolveOneInst(SemIR::InstId inst_id)
return constant_id;
}
// NOLINTNEXTLINE(misc-no-recursion)
auto ImportRefResolver::ResolveType(SemIR::TypeId import_type_id)
-> SemIR::TypeId {
if (!import_type_id.has_value()) {
@@ -3877,13 +3916,7 @@ auto ImportRefResolver::SetResolvedConstId(
SemIR::InstId inst_id, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
SemIR::ConstantId const_id) -> void {
local_constant_values_for_import_insts().Set(inst_id, const_id);
for (auto indirect_inst : indirect_insts) {
local_context()
.import_ir_constant_values()
[local_context().sem_ir().import_irs().GetRawIndex(
indirect_inst.ir_id())]
.Set(indirect_inst.inst_id(), const_id);
}
SetIndirectConstantValues(local_context(), indirect_insts, const_id);
}
// Resolves and returns the local contents for an imported instruction block
@@ -3930,7 +3963,6 @@ static auto ResolveLocalEvalBlock(ImportRefResolver& resolver,
}
// Fills in the remaining information in a partially-imported generic.
// NOLINTNEXTLINE(misc-no-recursion)
static auto FinishPendingGeneric(ImportRefResolver& resolver,
ImportContext::PendingGeneric pending)
-> void {
@@ -3938,14 +3970,6 @@ static auto FinishPendingGeneric(ImportRefResolver& resolver,
resolver.import_generics().Get(pending.import_id);
auto& local_generic = resolver.local_generics().Get(pending.local_id);
// Load the bindings for the generic eagerly; they're used to form the self
// specific.
// TODO: Avoid recursion.
for (auto binding_id :
resolver.local_inst_blocks().Get(local_generic.bindings_id)) {
LoadImportRef(resolver.local_context(), binding_id);
}
local_generic.decl_block_id =
ResolveLocalEvalBlock(resolver, import_generic, pending.local_id,
SemIR::GenericInstIndex::Region::Declaration);
@@ -3995,7 +4019,6 @@ static auto FinishPendingSpecific(ImportRefResolver& resolver,
}
// Perform any work that we deferred until the end of the main Resolve loop.
// NOLINTNEXTLINE(misc-no-recursion)
auto ImportRefResolver::PerformPendingWork() -> void {
// Note that the individual Finish steps can add new pending work, so keep
// going until we have no more work to do.
@@ -4059,7 +4082,6 @@ static auto GetInstForLoad(Context& context,
}
}
// NOLINTNEXTLINE(misc-no-recursion)
auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
auto inst = context.insts().TryGetAs<SemIR::ImportRefUnloaded>(inst_id);
if (!inst) {
@@ -4104,12 +4126,7 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {
// Store the constant for both the ImportRefLoaded and indirect instructions.
context.constant_values().Set(inst_id, constant_id);
for (const auto& import_ir_inst : indirect_insts) {
context
.import_ir_constant_values()[context.sem_ir().import_irs().GetRawIndex(
import_ir_inst.ir_id())]
.Set(import_ir_inst.inst_id(), constant_id);
}
SetIndirectConstantValues(context, indirect_insts, constant_id);
}
auto ImportImplsFromApiFile(Context& context) -> void {
+23 -23
View File
@@ -264,8 +264,8 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: entity_name6000001B: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name6000001C: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name6000001D: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name6000001E: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name6000001F: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name6000001E: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name6000001F: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name60000020: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name60000021: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name60000022: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
@@ -280,9 +280,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: entity_name6000002B: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0}
// CHECK:STDOUT: entity_name6000002C: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name6000002D: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name6000002E: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name6000002E: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0}
// CHECK:STDOUT: entity_name6000002F: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name60000030: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0}
// CHECK:STDOUT: entity_name60000030: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name60000031: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0}
// CHECK:STDOUT: entity_name60000032: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0}
// CHECK:STDOUT: entity_name60000033: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0}
@@ -472,7 +472,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst60000063: {kind: SymbolicBindingType, arg0: entity_name60000001, arg1: inst60000062, type: type(TypeType)}
// CHECK:STDOUT: inst60000064: {kind: ConstType, arg0: inst60000063, type: type(TypeType)}
// CHECK:STDOUT: inst60000065: {kind: PatternType, arg0: inst6000004A, type: type(TypeType)}
// CHECK:STDOUT: inst60000066: {kind: SymbolicBindingPattern, arg0: entity_name6000000D, type: type(inst60000065)}
// CHECK:STDOUT: inst60000066: {kind: SymbolicBindingPattern, arg0: entity_name6000000E, type: type(inst60000065)}
// CHECK:STDOUT: inst60000067: {kind: ImportRefLoaded, arg0: import_ir_inst12, arg1: entity_name<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst60000068: {kind: ImportRefLoaded, arg0: import_ir_inst13, arg1: entity_name<none>, type: type(TypeType)}
// CHECK:STDOUT: inst60000069: {kind: ImportRefLoaded, arg0: import_ir_inst14, arg1: entity_name<none>, type: type(TypeType)}
@@ -529,7 +529,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst6000009C: {kind: ImportRefLoaded, arg0: import_ir_inst3C, arg1: entity_name<none>, type: type(TypeType)}
// CHECK:STDOUT: inst6000009D: {kind: ImportRefLoaded, arg0: import_ir_inst3D, arg1: entity_name<none>, type: type(inst(WitnessType))}
// CHECK:STDOUT: inst6000009E: {kind: ImplDecl, arg0: impl60000005, arg1: inst_block_empty}
// CHECK:STDOUT: inst6000009F: {kind: SymbolicBindingPattern, arg0: entity_name60000015, type: type(inst60000017)}
// CHECK:STDOUT: inst6000009F: {kind: SymbolicBindingPattern, arg0: entity_name60000016, type: type(inst60000017)}
// CHECK:STDOUT: inst600000A0: {kind: ImportRefLoaded, arg0: import_ir_inst40, arg1: entity_name<none>, type: type(TypeType)}
// CHECK:STDOUT: inst600000A1: {kind: ImportRefLoaded, arg0: import_ir_inst41, arg1: entity_name<none>, type: type(TypeType)}
// CHECK:STDOUT: inst600000A2: {kind: ImportRefLoaded, arg0: import_ir_inst42, arg1: entity_name<none>, type: type(TypeType)}
@@ -566,8 +566,8 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst600000C1: {kind: SymbolicBinding, arg0: entity_name6000001A, arg1: inst<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst600000C2: {kind: SymbolicBindingType, arg0: entity_name6000001A, arg1: inst600000C1, type: type(TypeType)}
// CHECK:STDOUT: inst600000C3: {kind: TupleType, arg0: inst_block6000003B, type: type(TypeType)}
// CHECK:STDOUT: inst600000C4: {kind: SymbolicBindingPattern, arg0: entity_name6000001C, type: type(inst60000065)}
// CHECK:STDOUT: inst600000C5: {kind: SymbolicBindingPattern, arg0: entity_name6000001D, type: type(inst60000065)}
// CHECK:STDOUT: inst600000C4: {kind: SymbolicBindingPattern, arg0: entity_name6000001E, type: type(inst60000065)}
// CHECK:STDOUT: inst600000C5: {kind: SymbolicBindingPattern, arg0: entity_name6000001F, type: type(inst60000065)}
// CHECK:STDOUT: inst600000C6: {kind: ImportRefLoaded, arg0: import_ir_inst60, arg1: entity_name<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst600000C7: {kind: ImportRefLoaded, arg0: import_ir_inst61, arg1: entity_name<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst600000C8: {kind: ImportRefLoaded, arg0: import_ir_inst62, arg1: entity_name<none>, type: type(TypeType)}
@@ -625,9 +625,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst600000FC: {kind: SymbolicBinding, arg0: entity_name60000029, arg1: inst<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst600000FD: {kind: SymbolicBindingType, arg0: entity_name60000029, arg1: inst600000FC, type: type(TypeType)}
// CHECK:STDOUT: inst600000FE: {kind: TupleType, arg0: inst_block60000053, type: type(TypeType)}
// CHECK:STDOUT: inst600000FF: {kind: SymbolicBindingPattern, arg0: entity_name6000002B, type: type(inst60000065)}
// CHECK:STDOUT: inst60000100: {kind: SymbolicBindingPattern, arg0: entity_name6000002C, type: type(inst60000065)}
// CHECK:STDOUT: inst60000101: {kind: SymbolicBindingPattern, arg0: entity_name6000002D, type: type(inst60000065)}
// CHECK:STDOUT: inst600000FF: {kind: SymbolicBindingPattern, arg0: entity_name6000002E, type: type(inst60000065)}
// CHECK:STDOUT: inst60000100: {kind: SymbolicBindingPattern, arg0: entity_name6000002F, type: type(inst60000065)}
// CHECK:STDOUT: inst60000101: {kind: SymbolicBindingPattern, arg0: entity_name60000030, type: type(inst60000065)}
// CHECK:STDOUT: inst60000102: {kind: ImportRefLoaded, arg0: import_ir_inst8C, arg1: entity_name<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst60000103: {kind: ImportRefLoaded, arg0: import_ir_inst8D, arg1: entity_name<none>, type: type(inst6000004A)}
// CHECK:STDOUT: inst60000104: {kind: ImportRefLoaded, arg0: import_ir_inst8E, arg1: entity_name<none>, type: type(inst6000004A)}
@@ -892,8 +892,8 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst600000C3: symbolic_constant60000066
// CHECK:STDOUT: inst600000C4: concrete_constant(inst600000C4)
// CHECK:STDOUT: inst600000C5: concrete_constant(inst600000C5)
// CHECK:STDOUT: inst600000C6: symbolic_constant60000068
// CHECK:STDOUT: inst600000C7: symbolic_constant60000069
// CHECK:STDOUT: inst600000C6: symbolic_constant60000069
// CHECK:STDOUT: inst600000C7: symbolic_constant60000068
// CHECK:STDOUT: inst600000C8: symbolic_constant60000067
// CHECK:STDOUT: inst600000C9: concrete_constant(inst6000004A)
// CHECK:STDOUT: inst600000CA: concrete_constant(inst600000CA)
@@ -916,8 +916,8 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst600000DB: concrete_constant(inst600000DB)
// CHECK:STDOUT: inst600000DC: concrete_constant(inst600000DC)
// CHECK:STDOUT: inst600000DD: concrete_constant(inst600000DD)
// CHECK:STDOUT: inst600000DE: symbolic_constant60000068
// CHECK:STDOUT: inst600000DF: symbolic_constant60000069
// CHECK:STDOUT: inst600000DE: symbolic_constant60000069
// CHECK:STDOUT: inst600000DF: symbolic_constant60000068
// CHECK:STDOUT: inst600000E0: symbolic_constant60000081
// CHECK:STDOUT: inst600000E1: symbolic_constant60000082
// CHECK:STDOUT: inst600000E2: symbolic_constant60000088
@@ -952,9 +952,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst600000FF: concrete_constant(inst600000FF)
// CHECK:STDOUT: inst60000100: concrete_constant(inst60000100)
// CHECK:STDOUT: inst60000101: concrete_constant(inst60000101)
// CHECK:STDOUT: inst60000102: symbolic_constant600000AF
// CHECK:STDOUT: inst60000102: symbolic_constant600000B1
// CHECK:STDOUT: inst60000103: symbolic_constant600000B0
// CHECK:STDOUT: inst60000104: symbolic_constant600000B1
// CHECK:STDOUT: inst60000104: symbolic_constant600000AF
// CHECK:STDOUT: inst60000105: symbolic_constant600000AE
// CHECK:STDOUT: inst60000106: concrete_constant(inst6000004A)
// CHECK:STDOUT: inst60000107: concrete_constant(inst60000107)
@@ -979,9 +979,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: inst6000011A: concrete_constant(inst6000011A)
// CHECK:STDOUT: inst6000011B: concrete_constant(inst6000011B)
// CHECK:STDOUT: inst6000011C: concrete_constant(inst6000011C)
// CHECK:STDOUT: inst6000011D: symbolic_constant600000AF
// CHECK:STDOUT: inst6000011D: symbolic_constant600000B1
// CHECK:STDOUT: inst6000011E: symbolic_constant600000B0
// CHECK:STDOUT: inst6000011F: symbolic_constant600000B1
// CHECK:STDOUT: inst6000011F: symbolic_constant600000AF
// CHECK:STDOUT: inst60000120: symbolic_constant600000CD
// CHECK:STDOUT: inst60000121: symbolic_constant600000CE
// CHECK:STDOUT: inst60000122: symbolic_constant600000D6
@@ -1135,8 +1135,8 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: symbolic_constant60000065: {inst: inst600000C2, generic: generic<none>, index: generic_inst<none>, kind: checked}
// CHECK:STDOUT: symbolic_constant60000066: {inst: inst600000C3, generic: generic<none>, index: generic_inst<none>, kind: checked}
// CHECK:STDOUT: symbolic_constant60000067: {inst: inst600000C3, generic: generic60000006, index: generic_inst_in_decl5, kind: checked}
// CHECK:STDOUT: symbolic_constant60000068: {inst: inst60000062, generic: generic60000006, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant60000069: {inst: inst600000C1, generic: generic60000006, index: generic_inst_in_decl1, kind: checked}
// CHECK:STDOUT: symbolic_constant60000068: {inst: inst600000C1, generic: generic60000006, index: generic_inst_in_decl1, kind: checked}
// CHECK:STDOUT: symbolic_constant60000069: {inst: inst60000062, generic: generic60000006, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant6000006A: {inst: inst60000062, generic: generic60000006, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant6000006B: {inst: inst600000C1, generic: generic60000006, index: generic_inst_in_decl1, kind: checked}
// CHECK:STDOUT: symbolic_constant6000006C: {inst: inst600000CB, generic: generic<none>, index: generic_inst<none>, kind: checked}
@@ -1206,9 +1206,9 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
// CHECK:STDOUT: symbolic_constant600000AC: {inst: inst600000FD, generic: generic<none>, index: generic_inst<none>, kind: checked}
// CHECK:STDOUT: symbolic_constant600000AD: {inst: inst600000FE, generic: generic<none>, index: generic_inst<none>, kind: checked}
// CHECK:STDOUT: symbolic_constant600000AE: {inst: inst600000FE, generic: generic60000008, index: generic_inst_in_decl7, kind: checked}
// CHECK:STDOUT: symbolic_constant600000AF: {inst: inst60000062, generic: generic60000008, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant600000AF: {inst: inst600000FC, generic: generic60000008, index: generic_inst_in_decl2, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B0: {inst: inst600000C1, generic: generic60000008, index: generic_inst_in_decl1, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B1: {inst: inst600000FC, generic: generic60000008, index: generic_inst_in_decl2, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B1: {inst: inst60000062, generic: generic60000008, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B2: {inst: inst60000062, generic: generic60000008, index: generic_inst_in_decl0, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B3: {inst: inst600000C1, generic: generic60000008, index: generic_inst_in_decl1, kind: checked}
// CHECK:STDOUT: symbolic_constant600000B4: {inst: inst600000FC, generic: generic60000008, index: generic_inst_in_decl2, kind: checked}
+1 -1
View File
@@ -229,8 +229,8 @@ var n: {} = i32;
// CHECK:STDOUT: %Int.type: type = fn_type @Int [concrete]
// CHECK:STDOUT: %Int: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %T: type = symbolic_binding T, 0 [symbolic]
// CHECK:STDOUT: %pattern_type.e68: type = pattern_type %T [symbolic]
// CHECK:STDOUT: %N: %T = symbolic_binding N, 1 [symbolic]
// CHECK:STDOUT: %pattern_type.e68: type = pattern_type %T [symbolic]
// CHECK:STDOUT: %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]
// CHECK:STDOUT: %Int.specific_fn: <specific function> = specific_function %Int, @Int(Core.IntLiteral, %int_32) [concrete]
// CHECK:STDOUT: }