diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 995aa9e677975..f4672691eb994 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -651,7 +651,7 @@ class ImportRefResolver { return {.const_id = TryEvalInst(context_, inst_id, inst)}; } case CARBON_KIND(SemIR::BindSymbolicName inst): { - return TryResolveTypedInst(inst, inst_id); + return TryResolveTypedInst(inst); } case CARBON_KIND(SemIR::ClassDecl inst): { return TryResolveTypedInst(inst, const_id); @@ -721,6 +721,23 @@ class ImportRefResolver { } } + // Produce a resolve result for the given instruction that describes a + // constant value. This should only be used for instructions that describe + // constants, and not for instructions that represent declarations. For a + // declaration, we need an associated location, so AddInstInNoBlock should be + // used instead. + auto ResolveAsUntyped(SemIR::Inst inst) -> ResolveResult { + auto result = TryEvalInst(context_, SemIR::InstId::Invalid, inst); + CARBON_CHECK(result.is_constant()) << inst << " is not constant"; + return {.const_id = result}; + } + + // Same as ResolveAsUntyped, but with an explicit type for convenience. + template + auto ResolveAs(InstT inst) -> ResolveResult { + return ResolveAsUntyped(inst); + } + auto TryResolveTypedInst(SemIR::AssociatedEntity inst) -> ResolveResult { auto initial_work = work_stack_.size(); auto type_const_id = GetLocalConstantId(inst.type_id); @@ -733,12 +750,10 @@ class ImportRefResolver { context_, {.ir_id = import_ir_id_, .inst_id = inst.decl_id}, SemIR::BindNameId::Invalid); - auto inst_id = context_.AddInstInNoBlock( - AddImportIRInst(inst.decl_id), + return ResolveAs( {.type_id = context_.GetTypeIdForTypeConstant(type_const_id), .index = inst.index, .decl_id = decl_id}); - return {.const_id = context_.constant_values().Get(inst_id)}; } auto TryResolveTypedInst(SemIR::AssociatedEntityType inst) -> ResolveResult { @@ -752,17 +767,14 @@ class ImportRefResolver { return ResolveResult::Retry(); } - // TODO: Should this track the source? - auto inst_id = context_.AddInstInNoBlock( - SemIR::LocIdAndInst::NoLoc( - {.type_id = SemIR::TypeId::TypeType, - .interface_id = - context_.insts() - .GetAs(interface_const_id.inst_id()) - .interface_id, - .entity_type_id = - context_.GetTypeIdForTypeConstant(entity_type_const_id)})); - return {.const_id = context_.constant_values().Get(inst_id)}; + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .interface_id = + context_.insts() + .GetAs(interface_const_id.inst_id()) + .interface_id, + .entity_type_id = + context_.GetTypeIdForTypeConstant(entity_type_const_id)}); } auto TryResolveTypedInst(SemIR::BaseDecl inst, SemIR::InstId import_inst_id) @@ -774,7 +786,8 @@ class ImportRefResolver { return ResolveResult::Retry(); } - // Import the instruction in order to update contained base_type_id. + // Import the instruction in order to update contained base_type_id and + // track the import location. auto inst_id = context_.AddInstInNoBlock( AddImportIRInst(import_inst_id), {.type_id = context_.GetTypeIdForTypeConstant(type_const_id), @@ -792,8 +805,7 @@ class ImportRefResolver { return {.const_id = value_id}; } - auto TryResolveTypedInst(SemIR::BindSymbolicName inst, - SemIR::InstId import_inst_id) -> ResolveResult { + auto TryResolveTypedInst(SemIR::BindSymbolicName inst) -> ResolveResult { auto initial_work = work_stack_.size(); auto type_id = GetLocalConstantId(inst.type_id); if (HasNewWork(initial_work)) { @@ -807,12 +819,10 @@ class ImportRefResolver { {.name_id = name_id, .parent_scope_id = SemIR::NameScopeId::Invalid, .bind_index = import_bind_info.bind_index}); - auto new_bind_id = context_.AddInstInNoBlock( - AddImportIRInst(import_inst_id), + return ResolveAs( {.type_id = context_.GetTypeIdForTypeConstant(type_id), .bind_name_id = bind_name_id, .value_id = SemIR::InstId::Invalid}); - return {.const_id = context_.constant_values().Get(new_bind_id)}; } // Makes an incomplete class. This is necessary even with classes with a @@ -970,18 +980,17 @@ class ImportRefResolver { // type of the class declaration. For a generic class, build a class type // referencing this specialization of the generic class. auto class_const_inst = context_.insts().Get(class_const_id.inst_id()); - if (!class_const_inst.Is()) { + if (class_const_inst.Is()) { + return {.const_id = class_const_id}; + } else { auto generic_class_type = context_.types().GetAs( class_const_inst.type_id()); auto args_id = GetLocalCanonicalInstBlockId(inst.args_id, args); - class_const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, - SemIR::ClassType{.type_id = SemIR::TypeId::TypeType, - .class_id = generic_class_type.class_id, - .args_id = args_id}); + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .class_id = generic_class_type.class_id, + .args_id = args_id}); } - - return {.const_id = class_const_id}; } auto TryResolveTypedInst(SemIR::ConstType inst) -> ResolveResult { @@ -992,11 +1001,8 @@ class ImportRefResolver { return ResolveResult::Retry(); } auto inner_type_id = context_.GetTypeIdForTypeConstant(inner_const_id); - // TODO: Should ConstType have a wrapper for this similar to the others? - return {.const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, - SemIR::ConstType{.type_id = SemIR::TypeId::TypeType, - .inner_id = inner_type_id})}; + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, .inner_id = inner_type_id}); } auto TryResolveTypedInst(SemIR::ExportDecl inst) -> ResolveResult { @@ -1289,20 +1295,18 @@ class ImportRefResolver { // interface. auto interface_const_inst = context_.insts().Get(interface_const_id.inst_id()); - if (!interface_const_inst.Is()) { + if (interface_const_inst.Is()) { + return {.const_id = interface_const_id}; + } else { auto generic_interface_type = context_.types().GetAs( interface_const_inst.type_id()); auto args_id = GetLocalCanonicalInstBlockId(inst.args_id, args); - interface_const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, - SemIR::InterfaceType{ - .type_id = SemIR::TypeId::TypeType, - .interface_id = generic_interface_type.interface_id, - .args_id = args_id}); + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .interface_id = generic_interface_type.interface_id, + .args_id = args_id}); } - - return {.const_id = interface_const_id}; } auto TryResolveTypedInst(SemIR::InterfaceWitness inst) -> ResolveResult { @@ -1323,11 +1327,9 @@ class ImportRefResolver { << "Failed to import an element without adding new work."; auto elements_id = context_.inst_blocks().Add(elements); - SemIR::InterfaceWitness new_inst = { - .type_id = context_.GetBuiltinType(SemIR::BuiltinKind::WitnessType), - .elements_id = elements_id}; - return {.const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, new_inst)}; + return ResolveAs( + {.type_id = context_.GetBuiltinType(SemIR::BuiltinKind::WitnessType), + .elements_id = elements_id}); } auto TryResolveTypedInst(SemIR::IntLiteral inst) -> ResolveResult { @@ -1337,11 +1339,9 @@ class ImportRefResolver { return ResolveResult::Retry(); } - SemIR::IntLiteral new_inst = { - .type_id = context_.GetTypeIdForTypeConstant(type_id), - .int_id = context_.ints().Add(import_ir_.ints().Get(inst.int_id))}; - return {.const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, new_inst)}; + return ResolveAs( + {.type_id = context_.GetTypeIdForTypeConstant(type_id), + .int_id = context_.ints().Add(import_ir_.ints().Get(inst.int_id))}); } auto TryResolveTypedInst(SemIR::PointerType inst) -> ResolveResult { @@ -1353,8 +1353,8 @@ class ImportRefResolver { } auto pointee_type_id = context_.GetTypeIdForTypeConstant(pointee_const_id); - return {.const_id = context_.types().GetConstantId( - context_.GetPointerType(pointee_type_id))}; + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, .pointee_id = pointee_type_id}); } auto TryResolveTypedInst(SemIR::StructType inst, SemIR::InstId import_inst_id) @@ -1388,8 +1388,9 @@ class ImportRefResolver { {.name_id = name_id, .field_type_id = field_type_id})); } - return {.const_id = context_.types().GetConstantId( - context_.GetStructType(context_.inst_blocks().Add(fields)))}; + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .fields_id = context_.inst_blocks().AddCanonical(fields)}); } auto TryResolveTypedInst(SemIR::StructValue inst) -> ResolveResult { @@ -1400,11 +1401,9 @@ class ImportRefResolver { return ResolveResult::Retry(); } - SemIR::StructValue new_inst = { - .type_id = context_.GetTypeIdForTypeConstant(type_id), - .elements_id = GetLocalCanonicalInstBlockId(inst.elements_id, elems)}; - return {.const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, new_inst)}; + return ResolveAs( + {.type_id = context_.GetTypeIdForTypeConstant(type_id), + .elements_id = GetLocalCanonicalInstBlockId(inst.elements_id, elems)}); } auto TryResolveTypedInst(SemIR::TupleType inst) -> ResolveResult { @@ -1441,11 +1440,9 @@ class ImportRefResolver { return ResolveResult::Retry(); } - SemIR::TupleValue new_inst = { - .type_id = context_.GetTypeIdForTypeConstant(type_id), - .elements_id = GetLocalCanonicalInstBlockId(inst.elements_id, elems)}; - return {.const_id = - TryEvalInst(context_, SemIR::InstId::Invalid, new_inst)}; + return ResolveAs( + {.type_id = context_.GetTypeIdForTypeConstant(type_id), + .elements_id = GetLocalCanonicalInstBlockId(inst.elements_id, elems)}); } auto TryResolveTypedInst(SemIR::UnboundElementType inst) -> ResolveResult { @@ -1457,10 +1454,10 @@ class ImportRefResolver { return ResolveResult::Retry(); } - return {.const_id = - context_.types().GetConstantId(context_.GetUnboundElementType( - context_.GetTypeIdForTypeConstant(class_const_id), - context_.GetTypeIdForTypeConstant(elem_const_id)))}; + return ResolveAs( + {.type_id = SemIR::TypeId::TypeType, + .class_type_id = context_.GetTypeIdForTypeConstant(class_const_id), + .element_type_id = context_.GetTypeIdForTypeConstant(elem_const_id)}); } auto import_ir_constant_values() -> SemIR::ConstantValueStore& { diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 0986885675186..7953e0f180576 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -173,7 +173,7 @@ class Class(U:! type) { // CHECK:STDOUT: --- foo.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %Class.type: type = generic_class_type @Class [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] @@ -264,7 +264,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] @@ -344,7 +344,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, (i32) [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] @@ -417,7 +417,7 @@ class Class(U:! type) { // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %.3: type = ptr_type i32 [template] @@ -483,7 +483,7 @@ class Class(U:! type) { // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %.type: type = generic_class_type @.1 [template] // CHECK:STDOUT: %.2: %.type = struct_value () [template] // CHECK:STDOUT: %.3: type = class_type @.1 [template] diff --git a/toolchain/check/testdata/interface/no_prelude/export_name.carbon b/toolchain/check/testdata/interface/no_prelude/export_name.carbon index b3f5a3172ad68..4146e3f58e30f 100644 --- a/toolchain/check/testdata/interface/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/interface/no_prelude/export_name.carbon @@ -97,8 +97,8 @@ fn UseEmpty(i: I) {} // CHECK:STDOUT: .I = %import_ref.1 // CHECK:STDOUT: .UseEmpty = %UseEmpty.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+7, loaded [template = constants.%.1] -// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+6, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+6, loaded [template = constants.%.1] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+5, unloaded // CHECK:STDOUT: %UseEmpty.decl: %UseEmpty.type = fn_decl @UseEmpty [template = constants.%UseEmpty] { // CHECK:STDOUT: %I.ref: type = name_ref I, %import_ref.1 [template = constants.%.1] // CHECK:STDOUT: %i.loc6_13.1: %.1 = param i diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index d2f670acd0226..d9fd44d6c4965 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -74,7 +74,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: %AddWith.1: %AddWith.type = struct_value () [template] // CHECK:STDOUT: %AddWith.2: %AddWith.type = struct_value () [template] // CHECK:STDOUT: %Self: %AddWith.2 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %.3: type = interface_type @AddWith, (%C) [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] diff --git a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon index b4ae264825cbc..23020b6fc03e8 100644 --- a/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon +++ b/toolchain/check/testdata/packages/no_prelude/fail_export_name_params.carbon @@ -67,7 +67,7 @@ export C2(T:! type); // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %C1.1: %C1.type = struct_value () [template] // CHECK:STDOUT: %C1.2: type = class_type @C1 [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, [symbolic] // CHECK:STDOUT: %C2.type: type = generic_class_type @C2 [template] // CHECK:STDOUT: %C2.1: %C2.type = struct_value () [template] // CHECK:STDOUT: %C2.2: type = class_type @C2 [template] diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index f21392b41d639..e5f0183785465 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -205,7 +205,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.10: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] // CHECK:STDOUT: %.11: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.11 = bind_symbolic_name S 0, [symbolic] // CHECK:STDOUT: %.12: i32 = int_literal 1 [template] // CHECK:STDOUT: %.13: i32 = int_literal 2 [template] // CHECK:STDOUT: %.14: type = ptr_type %.11 [template] @@ -325,7 +325,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: type = struct_type {.c: i32, .d: i32} [template] @@ -386,7 +386,7 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] // CHECK:STDOUT: %.3: type = struct_type {.a: i32, .b: i32} [template] -// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] +// CHECK:STDOUT: %S: %.3 = bind_symbolic_name S 0, [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template] diff --git a/toolchain/check/testdata/tuples/import.carbon b/toolchain/check/testdata/tuples/import.carbon index b9230e2c4b473..d7e98a0f20900 100644 --- a/toolchain/check/testdata/tuples/import.carbon +++ b/toolchain/check/testdata/tuples/import.carbon @@ -230,7 +230,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %C.1: %C.type = struct_value () [template] // CHECK:STDOUT: %.14: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] -// CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.8 = bind_symbolic_name X 0, [symbolic] // CHECK:STDOUT: %.15: i32 = int_literal 1 [template] // CHECK:STDOUT: %.16: i32 = int_literal 2 [template] // CHECK:STDOUT: %tuple: %.8 = tuple_value (%.15, %.16) [template] @@ -366,7 +366,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 1 [template] // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: i32 = int_literal 3 [template] @@ -429,7 +429,7 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %C.2: type = class_type @C [template] // CHECK:STDOUT: %.3: type = tuple_type (i32, i32) [template] -// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] +// CHECK:STDOUT: %X: %.3 = bind_symbolic_name X 0, [symbolic] // CHECK:STDOUT: %.4: i32 = int_literal 3 [template] // CHECK:STDOUT: %.5: i32 = int_literal 4 [template] // CHECK:STDOUT: %.6: type = ptr_type %.3 [template]