diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 7c80610035ed..b158b323d0ce 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -13,6 +13,7 @@ #include "toolchain/base/kind_switch.h" #include "toolchain/check/decl_name_stack.h" #include "toolchain/check/eval.h" +#include "toolchain/check/generic.h" #include "toolchain/check/generic_region_stack.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/inst_block_stack.h" @@ -797,7 +798,9 @@ class TypeCompleter { } return false; } - // TODO: Trigger generic resolution here for a generic class. + if (inst.instance_id.is_valid()) { + ResolveSpecificDefinition(context_, inst.instance_id); + } Push(class_info.object_repr_id); break; } @@ -1092,7 +1095,9 @@ auto Context::TryToDefineType( return false; } - // TODO: Trigger generic resolution here for a generic instance. + if (interface->instance_id.is_valid()) { + ResolveSpecificDefinition(*this, interface->instance_id); + } } return true; diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index 6b121338dda0..b328800a6d40 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -206,6 +206,11 @@ static auto PushNameQualifierScope(Context& context, // parameter scope. context.scope_stack().PopIfEmpty(); + // When declaring a member of a generic, resolve the self specific. + if (instance_id.is_valid()) { + ResolveSpecificDefinition(context, instance_id); + } + context.scope_stack().Push(scope_inst_id, scope_id, instance_id, has_error); // Enter a parameter scope in case the qualified name itself has parameters. diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 5535006979fe..31564a3aa9c3 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1332,12 +1332,16 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, const auto& specific = eval_context.generic_instances().Get(eval_context.specific_id); auto args = eval_context.inst_blocks().Get(specific.args_id); - CARBON_CHECK(static_cast(bind_name.bind_index.index) < - args.size()) - << "Use of binding " << bind_name.bind_index - << " with no corresponding value."; - return eval_context.context.constant_values().Get( - args[bind_name.bind_index.index]); + if (static_cast(bind_name.bind_index.index) >= args.size()) { + // TODO: For now we don't provide a mapping for the `Self` type in an + // interface, and fall back to the canonical constant type. + CARBON_CHECK(bind_name.name_id == SemIR::NameId::SelfType) + << "Use of binding " << bind_name.bind_index + << " with no corresponding value."; + } else { + return eval_context.context.constant_values().Get( + args[bind_name.bind_index.index]); + } } // The constant form of a symbolic binding is an idealized form of the diff --git a/toolchain/check/generic.cpp b/toolchain/check/generic.cpp index d734113cb830..e1d12999c78c 100644 --- a/toolchain/check/generic.cpp +++ b/toolchain/check/generic.cpp @@ -130,7 +130,16 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id, context.inst_block_stack().Push(); Map constants_in_generic; - // TODO: For the definition region, populate constants from the declaration. + + // For the definition region, populate constants from the declaration. + if (region == SemIR::GenericInstIndex::Region::Definition) { + auto decl_eval_block = context.inst_blocks().Get( + context.generics().Get(generic_id).decl_block_id); + for (auto inst_id : decl_eval_block) { + constants_in_generic.Insert( + context.constant_values().GetConstantInstId(inst_id), inst_id); + } + } // The work done in this loop might invalidate iterators into the generic // region stack, but shouldn't add new dependent instructions to the current @@ -293,6 +302,33 @@ auto MakeGenericSelfInstance(Context& context, SemIR::GenericId generic_id) return MakeGenericInstance(context, generic_id, args_id); } +auto ResolveSpecificDefinition(Context& context, + SemIR::GenericInstanceId specific_id) -> bool { + auto& specific = context.generic_instances().Get(specific_id); + auto generic_id = specific.generic_id; + + // TODO: Remove this once we import generics properly. + if (!generic_id.is_valid()) { + return true; + } + + if (!specific.definition_block_id.is_valid()) { + // Evaluate the eval block for the definition of the generic. + auto& generic = context.generics().Get(generic_id); + if (!generic.definition_block_id.is_valid()) { + // The generic is not defined yet. + return false; + } + auto definition_block_id = TryEvalBlockForSpecific( + context, specific_id, SemIR::GenericInstIndex::Region::Definition); + // Note that TryEvalBlockForSpecific may reallocate the list of generic + // instances, so re-lookup the instance here. + context.generic_instances().Get(specific_id).definition_block_id = + definition_block_id; + } + return true; +} + auto GetTypeInInstance(Context& context, SemIR::GenericInstanceId instance_id, SemIR::TypeId type_id) -> SemIR::TypeId { auto const_id = context.types().GetConstantId(type_id); diff --git a/toolchain/check/generic.h b/toolchain/check/generic.h index 10b8b537d845..e52e1c6ba8b3 100644 --- a/toolchain/check/generic.h +++ b/toolchain/check/generic.h @@ -46,6 +46,12 @@ auto MakeGenericInstance(Context& context, SemIR::GenericId generic_id, auto MakeGenericSelfInstance(Context& context, SemIR::GenericId generic_id) -> SemIR::GenericInstanceId; +// Attempts to resolve the definition of the given specific, by evaluating the +// eval block of the corresponding generic and storing a corresponding value +// block in the specific. Returns false if a definition is not available. +auto ResolveSpecificDefinition(Context& context, + SemIR::GenericInstanceId specific_id) -> bool; + // Gets the substituted value of a type within a specified instance of a // generic. Note that this does not perform substitution, and will return // `Invalid` if the substituted type is not yet known. diff --git a/toolchain/check/testdata/array/generic_empty.carbon b/toolchain/check/testdata/array/generic_empty.carbon index 034a1bda4439..11e60c250710 100644 --- a/toolchain/check/testdata/array/generic_empty.carbon +++ b/toolchain/check/testdata/array/generic_empty.carbon @@ -42,7 +42,7 @@ fn G(T:! type) { // CHECK:STDOUT: fn @G(%T: type) // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc13_16: i32 = int_literal 0 [template = constants.%.2] // CHECK:STDOUT: %.loc13_17: type = array_type %.loc13_16, %T [symbolic = %.loc13_17 (constants.%.3)] // CHECK:STDOUT: %arr.var: ref @G.%.loc13_17 (%.3) = var arr diff --git a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon index b1d00955cb3f..d645af2061ad 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon @@ -41,7 +41,7 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: type3: {constant: template inst+10, value_rep: {kind: unknown, type: type}} // CHECK:STDOUT: type4: {constant: symbolic 1, value_rep: {kind: pointer, type: type8}} // CHECK:STDOUT: type5: {constant: symbolic 2, value_rep: {kind: copy, type: type5}} -// CHECK:STDOUT: type6: {constant: symbolic 3, value_rep: {kind: unknown, type: type}} +// CHECK:STDOUT: type6: {constant: symbolic 3, value_rep: {kind: pointer, type: type8}} // CHECK:STDOUT: type7: {constant: template inst+17, value_rep: {kind: none, type: type2}} // CHECK:STDOUT: type8: {constant: symbolic 4, value_rep: {kind: copy, type: type8}} // CHECK:STDOUT: type_blocks: @@ -73,17 +73,17 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: 'inst+17': {kind: FunctionType, arg0: function0, type: typeTypeType} // CHECK:STDOUT: 'inst+18': {kind: StructValue, arg0: empty, type: type7} // CHECK:STDOUT: 'inst+19': {kind: PointerType, arg0: type4, type: typeTypeType} -// CHECK:STDOUT: 'inst+20': {kind: NameRef, arg0: name2, arg1: inst+6, type: type1} +// CHECK:STDOUT: 'inst+20': {kind: NameRef, arg0: name2, arg1: inst+6, type: type5} // CHECK:STDOUT: 'inst+21': {kind: TupleLiteral, arg0: empty, type: type2} -// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block13, type: type4} -// CHECK:STDOUT: 'inst+23': {kind: TupleAccess, arg0: inst+15, arg1: element0, type: type1} -// CHECK:STDOUT: 'inst+24': {kind: InitializeFrom, arg0: inst+20, arg1: inst+23, type: type1} +// CHECK:STDOUT: 'inst+22': {kind: TupleLiteral, arg0: block13, type: type6} +// CHECK:STDOUT: 'inst+23': {kind: TupleAccess, arg0: inst+15, arg1: element0, type: type5} +// CHECK:STDOUT: 'inst+24': {kind: InitializeFrom, arg0: inst+20, arg1: inst+23, type: type5} // CHECK:STDOUT: 'inst+25': {kind: TupleAccess, arg0: inst+15, arg1: element1, type: type2} // CHECK:STDOUT: 'inst+26': {kind: TupleInit, arg0: empty, arg1: inst+25, type: type2} // CHECK:STDOUT: 'inst+27': {kind: TupleValue, arg0: block15, type: type2} // CHECK:STDOUT: 'inst+28': {kind: Converted, arg0: inst+21, arg1: inst+26, type: type2} -// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block14, arg1: inst+15, type: type4} -// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+22, arg1: inst+29, type: type4} +// CHECK:STDOUT: 'inst+29': {kind: TupleInit, arg0: block14, arg1: inst+15, type: type6} +// CHECK:STDOUT: 'inst+30': {kind: Converted, arg0: inst+22, arg1: inst+29, type: type6} // CHECK:STDOUT: 'inst+31': {kind: ReturnExpr, arg0: inst+30, arg1: inst+15} // CHECK:STDOUT: constant_values: // CHECK:STDOUT: 'inst+0': template inst+0 diff --git a/toolchain/check/testdata/builtins/int/make_type_signed.carbon b/toolchain/check/testdata/builtins/int/make_type_signed.carbon index 8d1e64844382..188d9dc58b1d 100644 --- a/toolchain/check/testdata/builtins/int/make_type_signed.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_signed.carbon @@ -213,7 +213,7 @@ var m: Int(1000000000); // CHECK:STDOUT: fn @Symbolic(%N: i32, %x: file.%int.make_type_signed.loc14_28 (%.6)) -> %.6 // CHECK:STDOUT: generic [%N: i32] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %.6 = name_ref x, %x +// CHECK:STDOUT: %x.ref: file.%int.make_type_signed.loc14_28 (%.6) = name_ref x, %x // CHECK:STDOUT: return %x.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon index 8896cedf2624..fffced24ad0d 100644 --- a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon @@ -213,7 +213,7 @@ var m: UInt(1000000000); // CHECK:STDOUT: fn @Symbolic(%N: i32, %x: file.%int.make_type_unsigned.loc14_29 (%.6)) -> %.6 // CHECK:STDOUT: generic [%N: i32] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %.6 = name_ref x, %x +// CHECK:STDOUT: %x.ref: file.%int.make_type_unsigned.loc14_29 (%.6) = name_ref x, %x // CHECK:STDOUT: return %x.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_generic_method.carbon b/toolchain/check/testdata/class/fail_generic_method.carbon index 1e3ee32d2bc0..2de067d5cfbd 100644 --- a/toolchain/check/testdata/class/fail_generic_method.carbon +++ b/toolchain/check/testdata/class/fail_generic_method.carbon @@ -82,7 +82,7 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { -// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T.ref.loc12 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] // CHECK:STDOUT: %.loc12: (%.2) = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] @@ -122,7 +122,7 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: @Class.%T.ref.loc13 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref.loc12) { +// CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/generic/basic.carbon b/toolchain/check/testdata/class/generic/basic.carbon index 5d5441296daa..ba7e2326d20d 100644 --- a/toolchain/check/testdata/class/generic/basic.carbon +++ b/toolchain/check/testdata/class/generic/basic.carbon @@ -75,7 +75,7 @@ class Class(T:! type) { // CHECK:STDOUT: %T.ref.loc17: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T.ref.loc17 (constants.%T)] // CHECK:STDOUT: %return.var.loc17: ref %T = var // CHECK:STDOUT: } -// CHECK:STDOUT: %T.ref.loc21: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T.ref.loc21 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc21: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] // CHECK:STDOUT: %.loc21: (%.4) = field_decl k, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -88,27 +88,32 @@ class Class(T:! type) { // CHECK:STDOUT: fn @GetAddr[addr @Class.%self.loc12_19.3: @Class.%.loc12_29 (%.2)]() -> %.3 // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %self.ref: %.2 = name_ref self, @Class.%self.loc12_19.3 -// CHECK:STDOUT: %.loc13_17.1: ref %Class.2 = deref %self.ref -// CHECK:STDOUT: %k.ref: %.4 = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] -// CHECK:STDOUT: %.loc13_17.2: ref %T = class_element_access %.loc13_17.1, element0 -// CHECK:STDOUT: %.loc13_12: %.3 = addr_of %.loc13_17.2 +// CHECK:STDOUT: %self.ref: @Class.%.loc12_29 (%.2) = name_ref self, @Class.%self.loc12_19.3 +// CHECK:STDOUT: %.loc13_17.1: ref @Class.%.loc12_25 (%Class.2) = deref %self.ref +// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] +// CHECK:STDOUT: %.loc13_17.2: ref @Class.%T.ref.loc12 (%T) = class_element_access %.loc13_17.1, element0 +// CHECK:STDOUT: %.loc13_12: @Class.%.loc12_38 (%.3) = addr_of %.loc13_17.2 // CHECK:STDOUT: return %.loc13_12 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @GetValue[@Class.%self.loc17_15.2: @Class.%.loc17 (%Class.2)]() -> %T // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %self.ref: %Class.2 = name_ref self, @Class.%self.loc17_15.2 -// CHECK:STDOUT: %k.ref: %.4 = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] -// CHECK:STDOUT: %.loc18_16.1: ref %T = class_element_access %self.ref, element0 -// CHECK:STDOUT: %.loc18_16.2: %T = bind_value %.loc18_16.1 +// CHECK:STDOUT: %self.ref: @Class.%.loc17 (%Class.2) = name_ref self, @Class.%self.loc17_15.2 +// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] +// CHECK:STDOUT: %.loc18_16.1: ref @Class.%T.ref.loc17 (%T) = class_element_access %self.ref, element0 +// CHECK:STDOUT: %.loc18_16.2: @Class.%T.ref.loc17 (%T) = bind_value %.loc18_16.1 // CHECK:STDOUT: return %.loc18_16.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.2 +// CHECK:STDOUT: => constants.%.4 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%GetAddr.decl(constants.%T) { @@ -125,7 +130,7 @@ class Class(T:! type) { // CHECK:STDOUT: @Class.%T.ref.loc17 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref.loc21) { +// CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/generic/call.carbon b/toolchain/check/testdata/class/generic/call.carbon index 4c742d77377f..38e8600367c5 100644 --- a/toolchain/check/testdata/class/generic/call.carbon +++ b/toolchain/check/testdata/class/generic/call.carbon @@ -146,12 +146,16 @@ var a: Class(5, i32*); // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_13.2 => constants.%.3 // CHECK:STDOUT: file.%N.loc4_23.2 => constants.%.4 +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(constants.%.1, constants.%.6) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_13.2 => constants.%.1 // CHECK:STDOUT: file.%N.loc4_23.2 => constants.%.6 +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_too_few.carbon diff --git a/toolchain/check/testdata/class/generic/fail_todo_use.carbon b/toolchain/check/testdata/class/generic/fail_todo_use.carbon index aa121ada21ab..94e19241099b 100644 --- a/toolchain/check/testdata/class/generic/fail_todo_use.carbon +++ b/toolchain/check/testdata/class/generic/fail_todo_use.carbon @@ -56,9 +56,10 @@ fn Run() -> i32 { // CHECK:STDOUT: %Run.type: type = fn_type @Run [template] // CHECK:STDOUT: %Run: %Run.type = struct_value () [template] // CHECK:STDOUT: %Class.3: type = class_type @Class, file.%Class.decl(i32) [template] -// CHECK:STDOUT: %.7: i32 = int_literal 0 [template] -// CHECK:STDOUT: %.8: type = struct_type {.k: i32} [template] -// CHECK:STDOUT: %.9: type = ptr_type %Class.3 [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %Class.3, i32 [template] +// CHECK:STDOUT: %.8: i32 = int_literal 0 [template] +// CHECK:STDOUT: %.9: type = struct_type {.k: i32} [template] +// CHECK:STDOUT: %.10: type = ptr_type %Class.3 [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -99,7 +100,7 @@ fn Run() -> i32 { // CHECK:STDOUT: %.loc12_34: type = ptr_type %T [symbolic = %.loc12_34 (constants.%.3)] // CHECK:STDOUT: %return.var: ref %.3 = var // CHECK:STDOUT: } -// CHECK:STDOUT: %T.ref.loc16: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T.ref.loc16 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc16: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] // CHECK:STDOUT: %.loc16: (%.4) = field_decl k, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -111,11 +112,11 @@ fn Run() -> i32 { // CHECK:STDOUT: fn @Get[addr @Class.%self.loc12_15.3: @Class.%.loc12_25 (%.2)]() -> %.3 // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %self.ref: %.2 = name_ref self, @Class.%self.loc12_15.3 -// CHECK:STDOUT: %.loc13_17.1: ref %Class.2 = deref %self.ref -// CHECK:STDOUT: %k.ref: %.4 = name_ref k, @Class.%.loc16 [template = @Class.%.loc16] -// CHECK:STDOUT: %.loc13_17.2: ref %T = class_element_access %.loc13_17.1, element0 -// CHECK:STDOUT: %.loc13_12: %.3 = addr_of %.loc13_17.2 +// CHECK:STDOUT: %self.ref: @Class.%.loc12_25 (%.2) = name_ref self, @Class.%self.loc12_15.3 +// CHECK:STDOUT: %.loc13_17.1: ref @Class.%.loc12_21 (%Class.2) = deref %self.ref +// CHECK:STDOUT: %k.ref: (%.4) = name_ref k, @Class.%.loc16 [template = @Class.%.loc16] +// CHECK:STDOUT: %.loc13_17.2: ref @Class.%T.ref.loc12 (%T) = class_element_access %.loc13_17.1, element0 +// CHECK:STDOUT: %.loc13_12: @Class.%.loc12_34 (%.3) = addr_of %.loc13_17.2 // CHECK:STDOUT: return %.loc13_12 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -132,13 +133,13 @@ fn Run() -> i32 { // CHECK:STDOUT: %.loc25_19.2: type = converted %.loc25_15.3, %.loc25_19.1 [template = constants.%Class.3] // CHECK:STDOUT: %v.var: ref %Class.3 = var v // CHECK:STDOUT: %v: ref %Class.3 = bind_name v, %v.var -// CHECK:STDOUT: %.loc25_29: i32 = int_literal 0 [template = constants.%.7] -// CHECK:STDOUT: %.loc25_30: %.8 = struct_literal (%.loc25_29) +// CHECK:STDOUT: %.loc25_29: i32 = int_literal 0 [template = constants.%.8] +// CHECK:STDOUT: %.loc25_30: %.9 = struct_literal (%.loc25_29) // CHECK:STDOUT: assign %v.var, // CHECK:STDOUT: %v.ref: ref %Class.3 = name_ref v, %v // CHECK:STDOUT: %Get.ref: %Get.type = name_ref Get, @Class.%Get.decl [template = constants.%Get] // CHECK:STDOUT: %.loc36_11: = bound_method %v.ref, %Get.ref -// CHECK:STDOUT: %.loc36_10: %.9 = addr_of %v.ref +// CHECK:STDOUT: %.loc36_10: %.10 = addr_of %v.ref // CHECK:STDOUT: %Get.call: init %.3 = call %.loc36_11() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -146,6 +147,11 @@ fn Run() -> i32 { // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.2 +// CHECK:STDOUT: => constants.%.4 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%Get.decl(constants.%T) { @@ -156,7 +162,7 @@ fn Run() -> i32 { // CHECK:STDOUT: @Class.%.loc12_34 => constants.%.3 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref.loc16) { +// CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } @@ -164,5 +170,10 @@ fn Run() -> i32 { // CHECK:STDOUT: specific file.%Class.decl(i32) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.3 +// CHECK:STDOUT: => constants.%.7 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/field.carbon b/toolchain/check/testdata/class/generic/field.carbon index 6e394c2e2d12..6691820b430b 100644 --- a/toolchain/check/testdata/class/generic/field.carbon +++ b/toolchain/check/testdata/class/generic/field.carbon @@ -7,47 +7,20 @@ // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/field.carbon // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/field.carbon -// CHECK:STDERR: fail_todo_field.carbon: ERROR: Main//default previously provided by `field.carbon`. -// CHECK:STDERR: - -// --- field.carbon - -class Class(T:! type) { - var x: T; -} - -// TODO: This case only works because the parameters of Class and G have the -// same name and index, so canonicalize to the same type. -fn G(T:! type, c: Class(T)) -> T { - return c.x; -} - -// --- fail_todo_field.carbon class Class(T:! type) { var x: T; } fn F(c: Class(i32)) -> i32 { - // CHECK:STDERR: fail_todo_field.carbon:[[@LINE+8]]:3: ERROR: Cannot implicitly convert from `T` to `i32`. - // CHECK:STDERR: return c.x; - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_field.carbon:[[@LINE+4]]:10: ERROR: Cannot implicitly convert from `Class` to `Class`. - // CHECK:STDERR: return c.x; - // CHECK:STDERR: ^~~ - // CHECK:STDERR: + return c.x; +} + +fn G(T:! type, c: Class(T)) -> T { return c.x; } fn H(U:! type, c: Class(U)) -> U { - // CHECK:STDERR: fail_todo_field.carbon:[[@LINE+7]]:3: ERROR: Cannot implicitly convert from `T` to `U`. - // CHECK:STDERR: return c.x; - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_field.carbon:[[@LINE+3]]:10: ERROR: Cannot implicitly convert from `Class` to `Class`. - // CHECK:STDERR: return c.x; - // CHECK:STDERR: ^~~ return c.x; } @@ -61,94 +34,20 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] -// CHECK:STDOUT: %G.type: type = fn_type @G [template] -// CHECK:STDOUT: %G: %G.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .Class = %Class.decl -// CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %Core: = namespace %Core.import, [template] {} -// CHECK:STDOUT: %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] { -// CHECK:STDOUT: %T.loc2_13.1: type = param T -// CHECK:STDOUT: %T.loc2_13.2: type = bind_symbolic_name T 0, %T.loc2_13.1 [symbolic = %T.loc2_13.2 (constants.%T)] -// CHECK:STDOUT: } -// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { -// CHECK:STDOUT: %T.loc8_6.1: type = param T -// CHECK:STDOUT: @G.%T: type = bind_symbolic_name T 0, %T.loc8_6.1 [symbolic = @G.%T (constants.%T)] -// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] -// CHECK:STDOUT: %T.ref.loc8_25: type = name_ref T, @G.%T [symbolic = @G.%T (constants.%T)] -// CHECK:STDOUT: %.loc8_24: init type = call %Class.ref(%T.ref.loc8_25) [symbolic = %.loc8_24 (constants.%Class.2)] -// CHECK:STDOUT: %.loc8_26.1: type = value_of_initializer %.loc8_24 [symbolic = %.loc8_24 (constants.%Class.2)] -// CHECK:STDOUT: %.loc8_26.2: type = converted %.loc8_24, %.loc8_26.1 [symbolic = %.loc8_24 (constants.%Class.2)] -// CHECK:STDOUT: %c.loc8_16.1: file.%.loc8_24 (%Class.2) = param c -// CHECK:STDOUT: @G.%c: file.%.loc8_24 (%Class.2) = bind_name c, %c.loc8_16.1 -// CHECK:STDOUT: %T.ref.loc8_32: type = name_ref T, @G.%T [symbolic = @G.%T (constants.%T)] -// CHECK:STDOUT: @G.%return: ref %T = var -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @Class -// CHECK:STDOUT: generic [file.%T.loc2_13.2: type] { -// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc2_13.2 [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %.loc3: (%.2) = field_decl x, element0 [template] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Class.2 -// CHECK:STDOUT: .x = %.loc3 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @G(%T: type, %c: file.%.loc8_24 (%Class.2)) -> %T -// CHECK:STDOUT: generic [%T: type] { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %c.ref: %Class.2 = name_ref c, %c -// CHECK:STDOUT: %x.ref: %.2 = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] -// CHECK:STDOUT: %.loc9_11.1: ref %T = class_element_access %c.ref, element0 -// CHECK:STDOUT: %.loc9_11.2: %T = bind_value %.loc9_11.1 -// CHECK:STDOUT: return %.loc9_11.2 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(constants.%T) { -// CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref) { -// CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific file.%G.decl(constants.%T) { -// CHECK:STDOUT: declaration: -// CHECK:STDOUT: @G.%T => constants.%T -// CHECK:STDOUT: file.%.loc8_24 => constants.%Class.2 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_field.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// 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] -// CHECK:STDOUT: %Class.2: type = class_type @Class, file.%Class.decl(%T) [symbolic] -// CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] -// CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %Class.3: type = class_type @Class, file.%Class.decl(i32) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %.4: type = unbound_element_type %Class.3, i32 [template] +// CHECK:STDOUT: %.5: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] // CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic] // CHECK:STDOUT: %Class.4: type = class_type @Class, file.%Class.decl(%U) [symbolic] // CHECK:STDOUT: %H.type: type = fn_type @H [template] // CHECK:STDOUT: %H: %H.type = struct_value () [template] +// CHECK:STDOUT: %.6: type = unbound_element_type %Class.4, %U [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -161,52 +60,66 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: .Class = %Class.decl // CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .G = %G.decl // CHECK:STDOUT: .H = %H.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %Core: = namespace %Core.import, [template] {} // CHECK:STDOUT: %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] { -// CHECK:STDOUT: %T.loc2_13.1: type = param T -// CHECK:STDOUT: %T.loc2_13.2: type = bind_symbolic_name T 0, %T.loc2_13.1 [symbolic = %T.loc2_13.2 (constants.%T)] +// CHECK:STDOUT: %T.loc11_13.1: type = param T +// CHECK:STDOUT: %T.loc11_13.2: type = bind_symbolic_name T 0, %T.loc11_13.1 [symbolic = %T.loc11_13.2 (constants.%T)] // CHECK:STDOUT: } // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %Class.ref.loc6: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] -// CHECK:STDOUT: %int.make_type_32.loc6_15: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc6_14.1: type = value_of_initializer %int.make_type_32.loc6_15 [template = i32] -// CHECK:STDOUT: %.loc6_14.2: type = converted %int.make_type_32.loc6_15, %.loc6_14.1 [template = i32] -// CHECK:STDOUT: %.loc6_14.3: init type = call %Class.ref.loc6(%.loc6_14.2) [template = constants.%Class.3] -// CHECK:STDOUT: %.loc6_18.1: type = value_of_initializer %.loc6_14.3 [template = constants.%Class.3] -// CHECK:STDOUT: %.loc6_18.2: type = converted %.loc6_14.3, %.loc6_18.1 [template = constants.%Class.3] -// CHECK:STDOUT: %c.loc6_6.1: %Class.3 = param c -// CHECK:STDOUT: @F.%c: %Class.3 = bind_name c, %c.loc6_6.1 -// CHECK:STDOUT: %int.make_type_32.loc6_24: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc6_24.1: type = value_of_initializer %int.make_type_32.loc6_24 [template = i32] -// CHECK:STDOUT: %.loc6_24.2: type = converted %int.make_type_32.loc6_24, %.loc6_24.1 [template = i32] +// CHECK:STDOUT: %Class.ref.loc15: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %int.make_type_32.loc15_15: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc15_14.1: type = value_of_initializer %int.make_type_32.loc15_15 [template = i32] +// CHECK:STDOUT: %.loc15_14.2: type = converted %int.make_type_32.loc15_15, %.loc15_14.1 [template = i32] +// CHECK:STDOUT: %.loc15_14.3: init type = call %Class.ref.loc15(%.loc15_14.2) [template = constants.%Class.3] +// CHECK:STDOUT: %.loc15_18.1: type = value_of_initializer %.loc15_14.3 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc15_18.2: type = converted %.loc15_14.3, %.loc15_18.1 [template = constants.%Class.3] +// CHECK:STDOUT: %c.loc15_6.1: %Class.3 = param c +// CHECK:STDOUT: @F.%c: %Class.3 = bind_name c, %c.loc15_6.1 +// CHECK:STDOUT: %int.make_type_32.loc15_24: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc15_24.1: type = value_of_initializer %int.make_type_32.loc15_24 [template = i32] +// CHECK:STDOUT: %.loc15_24.2: type = converted %int.make_type_32.loc15_24, %.loc15_24.1 [template = i32] // CHECK:STDOUT: @F.%return: ref i32 = var // CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %T.loc19_6.1: type = param T +// CHECK:STDOUT: @G.%T: type = bind_symbolic_name T 0, %T.loc19_6.1 [symbolic = @G.%T (constants.%T)] +// CHECK:STDOUT: %Class.ref.loc19: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %T.ref.loc19_25: type = name_ref T, @G.%T [symbolic = @G.%T (constants.%T)] +// CHECK:STDOUT: %.loc19_24: init type = call %Class.ref.loc19(%T.ref.loc19_25) [symbolic = %.loc19_24 (constants.%Class.2)] +// CHECK:STDOUT: %.loc19_26.1: type = value_of_initializer %.loc19_24 [symbolic = %.loc19_24 (constants.%Class.2)] +// CHECK:STDOUT: %.loc19_26.2: type = converted %.loc19_24, %.loc19_26.1 [symbolic = %.loc19_24 (constants.%Class.2)] +// CHECK:STDOUT: %c.loc19_16.1: file.%.loc19_24 (%Class.2) = param c +// CHECK:STDOUT: @G.%c: file.%.loc19_24 (%Class.2) = bind_name c, %c.loc19_16.1 +// CHECK:STDOUT: %T.ref.loc19_32: type = name_ref T, @G.%T [symbolic = @G.%T (constants.%T)] +// CHECK:STDOUT: @G.%return: ref %T = var +// CHECK:STDOUT: } // CHECK:STDOUT: %H.decl: %H.type = fn_decl @H [template = constants.%H] { -// CHECK:STDOUT: %U.loc18_6.1: type = param U -// CHECK:STDOUT: @H.%U: type = bind_symbolic_name U 0, %U.loc18_6.1 [symbolic = @H.%U (constants.%U)] -// CHECK:STDOUT: %Class.ref.loc18: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] -// CHECK:STDOUT: %U.ref.loc18_25: type = name_ref U, @H.%U [symbolic = @H.%U (constants.%U)] -// CHECK:STDOUT: %.loc18_24: init type = call %Class.ref.loc18(%U.ref.loc18_25) [symbolic = %.loc18_24 (constants.%Class.4)] -// CHECK:STDOUT: %.loc18_26.1: type = value_of_initializer %.loc18_24 [symbolic = %.loc18_24 (constants.%Class.4)] -// CHECK:STDOUT: %.loc18_26.2: type = converted %.loc18_24, %.loc18_26.1 [symbolic = %.loc18_24 (constants.%Class.4)] -// CHECK:STDOUT: %c.loc18_16.1: file.%.loc18_24 (%Class.4) = param c -// CHECK:STDOUT: @H.%c: file.%.loc18_24 (%Class.4) = bind_name c, %c.loc18_16.1 -// CHECK:STDOUT: %U.ref.loc18_32: type = name_ref U, @H.%U [symbolic = @H.%U (constants.%U)] +// CHECK:STDOUT: %U.loc23_6.1: type = param U +// CHECK:STDOUT: @H.%U: type = bind_symbolic_name U 0, %U.loc23_6.1 [symbolic = @H.%U (constants.%U)] +// CHECK:STDOUT: %Class.ref.loc23: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %U.ref.loc23_25: type = name_ref U, @H.%U [symbolic = @H.%U (constants.%U)] +// CHECK:STDOUT: %.loc23_24: init type = call %Class.ref.loc23(%U.ref.loc23_25) [symbolic = %.loc23_24 (constants.%Class.4)] +// CHECK:STDOUT: %.loc23_26.1: type = value_of_initializer %.loc23_24 [symbolic = %.loc23_24 (constants.%Class.4)] +// CHECK:STDOUT: %.loc23_26.2: type = converted %.loc23_24, %.loc23_26.1 [symbolic = %.loc23_24 (constants.%Class.4)] +// CHECK:STDOUT: %c.loc23_16.1: file.%.loc23_24 (%Class.4) = param c +// CHECK:STDOUT: @H.%c: file.%.loc23_24 (%Class.4) = bind_name c, %c.loc23_16.1 +// CHECK:STDOUT: %U.ref.loc23_32: type = name_ref U, @H.%U [symbolic = @H.%U (constants.%U)] // CHECK:STDOUT: @H.%return: ref %U = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Class -// CHECK:STDOUT: generic [file.%T.loc2_13.2: type] { -// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc2_13.2 [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %.loc3: (%.2) = field_decl x, element0 [template] +// CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] +// CHECK:STDOUT: %.loc12: (%.2) = field_decl x, element0 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class.2 -// CHECK:STDOUT: .x = %.loc3 +// CHECK:STDOUT: .x = %.loc12 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -214,43 +127,76 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: fn @F(%c: %Class.3) -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: %Class.3 = name_ref c, %c -// CHECK:STDOUT: %x.ref: %.2 = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] -// CHECK:STDOUT: %.loc15: %T = class_element_access , element0 [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: %x.ref: %.4 = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] +// CHECK:STDOUT: %.loc16_11.1: ref i32 = class_element_access %c.ref, element0 +// CHECK:STDOUT: %.loc16_11.2: i32 = bind_value %.loc16_11.1 +// CHECK:STDOUT: return %.loc16_11.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @H(%U: type, %c: file.%.loc18_24 (%Class.4)) -> %U +// CHECK:STDOUT: fn @G(%T: type, %c: file.%.loc19_24 (%Class.2)) -> %T +// CHECK:STDOUT: generic [%T: type] { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %c.ref: file.%.loc19_24 (%Class.2) = name_ref c, %c +// CHECK:STDOUT: %x.ref: (%.2) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] +// CHECK:STDOUT: %.loc20_11.1: ref @G.%T (%T) = class_element_access %c.ref, element0 +// CHECK:STDOUT: %.loc20_11.2: @G.%T (%T) = bind_value %.loc20_11.1 +// CHECK:STDOUT: return %.loc20_11.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @H(%U: type, %c: file.%.loc23_24 (%Class.4)) -> %U // CHECK:STDOUT: generic [%U: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %c.ref: %Class.4 = name_ref c, %c -// CHECK:STDOUT: %x.ref: %.2 = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] -// CHECK:STDOUT: %.loc26: %T = class_element_access , element0 [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: %c.ref: file.%.loc23_24 (%Class.4) = name_ref c, %c +// CHECK:STDOUT: %x.ref: (%.6) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] +// CHECK:STDOUT: %.loc24_11.1: ref @H.%U (%U) = class_element_access %c.ref, element0 +// CHECK:STDOUT: %.loc24_11.2: @H.%U (%U) = bind_value %.loc24_11.1 +// CHECK:STDOUT: return %.loc24_11.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.2 +// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref) { +// CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%T +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(i32) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => i32 +// CHECK:STDOUT: file.%T.loc11_13.2 => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.3 +// CHECK:STDOUT: => constants.%.4 +// CHECK:STDOUT: => +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%G.decl(constants.%T) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: @G.%T => constants.%T +// CHECK:STDOUT: file.%.loc19_24 => constants.%Class.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(constants.%U) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: file.%T.loc2_13.2 => constants.%U +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.4 +// CHECK:STDOUT: => constants.%.6 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%H.decl(constants.%U) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: @H.%U => constants.%U -// CHECK:STDOUT: file.%.loc18_24 => constants.%Class.4 +// CHECK:STDOUT: file.%.loc23_24 => constants.%Class.4 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index cfcf89b8c46e..4644962104c7 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -154,7 +154,7 @@ class Class(U:! type) { // CHECK:STDOUT: %int.make_type_32.loc7: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc7_10.1: type = value_of_initializer %int.make_type_32.loc7 [template = i32] // CHECK:STDOUT: %.loc7_10.2: type = converted %int.make_type_32.loc7, %.loc7_10.1 [template = i32] -// CHECK:STDOUT: %.loc7_8: %.2 = field_decl n, element0 [template] +// CHECK:STDOUT: %.loc7_8: (%.2) = field_decl n, element0 [template] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %int.make_type_32.loc8: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc8_13.1: type = value_of_initializer %int.make_type_32.loc8 [template = i32] @@ -193,6 +193,11 @@ class Class(U:! type) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%CompleteClass.decl(file.%T.loc6_21.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc6_21.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific file.%CompleteClass.decl(i32) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc6_21.2 => i32 @@ -225,7 +230,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref ir0, inst+6, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref ir0, inst+13, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir0, inst+51, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir0, inst+53, loaded [template = constants.%F] // CHECK:STDOUT: %import_ref.4 = import_ref ir0, inst+16, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref ir0, inst+26, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref ir0, inst+34, unloaded @@ -316,7 +321,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref ir1, inst+13, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.1 = import_ref ir1, inst+51, loaded [template = constants.%F.1] +// CHECK:STDOUT: %import_ref.3: %F.type.1 = import_ref ir1, inst+53, loaded [template = constants.%F.1] // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref ir4, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+16, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+26, unloaded @@ -406,7 +411,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref ir1, inst+13, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir1, inst+51, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir1, inst+53, loaded [template = constants.%F] // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref ir4, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+16, unloaded // CHECK:STDOUT: %import_ref.6: %.4 = import_ref ir1, inst+26, loaded [template = %.1] @@ -493,7 +498,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+6, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref ir1, inst+13, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir1, inst+51, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref ir1, inst+53, loaded [template = constants.%F] // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+16, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+26, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+34, unloaded @@ -567,7 +572,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref ir0, inst+6, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2 = import_ref ir0, inst+13, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref ir0, inst+51, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir0, inst+53, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/class/generic/member_inline.carbon b/toolchain/check/testdata/class/generic/member_inline.carbon index af7b0e7f34bf..4be196734a30 100644 --- a/toolchain/check/testdata/class/generic/member_inline.carbon +++ b/toolchain/check/testdata/class/generic/member_inline.carbon @@ -58,7 +58,7 @@ class Class(T:! type) { // CHECK:STDOUT: fn @F(@Class.%n.loc12_8.2: @Class.%T.ref.loc12_11 (%T)) -> %T // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %n.ref: %T = name_ref n, @Class.%n.loc12_8.2 +// CHECK:STDOUT: %n.ref: @Class.%T.ref.loc12_11 (%T) = name_ref n, @Class.%n.loc12_8.2 // CHECK:STDOUT: return %n.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/member_out_of_line.carbon b/toolchain/check/testdata/class/generic/member_out_of_line.carbon index 5074f37c173a..83aa57763b32 100644 --- a/toolchain/check/testdata/class/generic/member_out_of_line.carbon +++ b/toolchain/check/testdata/class/generic/member_out_of_line.carbon @@ -152,13 +152,15 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: fn @F(%n: %T) -> %T // CHECK:STDOUT: generic [file.%T.loc4_13.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %n.ref: %T = name_ref n, %n +// CHECK:STDOUT: %n.ref: @Class.%T.ref.loc5_11 (%T) = name_ref n, %n // CHECK:STDOUT: return %n.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { @@ -250,12 +252,16 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: specific file.%A.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_9.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @A.%B.decl(constants.%T, constants.%N) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: @A.%T.ref => constants.%T // CHECK:STDOUT: @A.%N.loc5_11.2 => constants.%N +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @B.%F.decl(constants.%T, constants.%N) { diff --git a/toolchain/check/testdata/class/generic/self.carbon b/toolchain/check/testdata/class/generic/self.carbon index 48f12c7149e8..52036287b7ca 100644 --- a/toolchain/check/testdata/class/generic/self.carbon +++ b/toolchain/check/testdata/class/generic/self.carbon @@ -108,6 +108,8 @@ class Class(T:! type) { // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%MakeSelf.decl(constants.%T) { diff --git a/toolchain/check/testdata/class/generic_method.carbon b/toolchain/check/testdata/class/generic_method.carbon index ffca2fd596c1..cb8bc1faad41 100644 --- a/toolchain/check/testdata/class/generic_method.carbon +++ b/toolchain/check/testdata/class/generic_method.carbon @@ -56,7 +56,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: // CHECK:STDOUT: class @Class // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { -// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T.ref.loc12 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = file.%T.loc11_13.2 (constants.%T)] // CHECK:STDOUT: %.loc12: (%.2) = field_decl a, element0 [template] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, file.%Class.decl(constants.%T) [symbolic = %.loc13 (constants.%Class.2)] @@ -83,6 +83,11 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: specific file.%Class.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%Class.2 +// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: => // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class.%F.decl(constants.%T) { @@ -91,7 +96,7 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: @Class.%T.ref.loc13 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific file.%Class.decl(@Class.%T.ref.loc12) { +// CHECK:STDOUT: specific file.%Class.decl(file.%T.loc11_13.2) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/eval/fail_symbolic.carbon b/toolchain/check/testdata/eval/fail_symbolic.carbon index a573a9f93938..ac9e8ecf6146 100644 --- a/toolchain/check/testdata/eval/fail_symbolic.carbon +++ b/toolchain/check/testdata/eval/fail_symbolic.carbon @@ -54,7 +54,7 @@ fn G(N:! i32) { // CHECK:STDOUT: generic [%N: i32] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %N.ref: i32 = name_ref N, %N [symbolic = %N.ref (constants.%N)] +// CHECK:STDOUT: %N.ref: i32 = name_ref N, %N [symbolic = %N (constants.%N)] // CHECK:STDOUT: %.loc16_11.1: type = value_of_initializer %int.make_type_32 [template = i32] // CHECK:STDOUT: %.loc16_11.2: type = converted %int.make_type_32, %.loc16_11.1 [template = i32] // CHECK:STDOUT: %.loc16_17: type = array_type %N.ref, i32 [template = ] diff --git a/toolchain/check/testdata/eval/symbolic.carbon b/toolchain/check/testdata/eval/symbolic.carbon index 42c920d377db..c75cb76c5806 100644 --- a/toolchain/check/testdata/eval/symbolic.carbon +++ b/toolchain/check/testdata/eval/symbolic.carbon @@ -50,19 +50,19 @@ fn F(T:! type) { // CHECK:STDOUT: fn @F(%T: type) // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref.loc13_11: type = name_ref T, %T [symbolic = %T.ref.loc13_11 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc13_11: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc13_12: type = ptr_type %T [symbolic = %.loc13_12 (constants.%.2)] -// CHECK:STDOUT: %T.ref.loc13_21: type = name_ref T, %T [symbolic = %T.ref.loc13_11 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc13_21: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc13_15: type = const_type %T [symbolic = %.loc13_15 (constants.%.3)] // CHECK:STDOUT: %.loc13_22.1: %.4 = tuple_literal (%.loc13_12, %.loc13_15) // CHECK:STDOUT: %.loc13_22.2: type = converted %.loc13_22.1, constants.%.5 [symbolic = %.loc13_22.2 (constants.%.5)] // CHECK:STDOUT: %u.var: ref @F.%.loc13_22.2 (%.5) = var u // CHECK:STDOUT: %u: ref @F.%.loc13_22.2 (%.5) = bind_name u, %u.var -// CHECK:STDOUT: %T.ref.loc14: type = name_ref T, %T [symbolic = %T.ref.loc13_11 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc14: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc14: type = struct_type {.a: %T} [symbolic = %.loc14 (constants.%.8)] // CHECK:STDOUT: %v.var: ref @F.%.loc14 (%.8) = var v // CHECK:STDOUT: %v: ref @F.%.loc14 (%.8) = bind_name v, %v.var -// CHECK:STDOUT: %T.ref.loc15: type = name_ref T, %T [symbolic = %T.ref.loc13_11 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc15: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc15_14: i32 = int_literal 5 [template = constants.%.9] // CHECK:STDOUT: %.loc15_15: type = array_type %.loc15_14, %T [symbolic = %.loc15_15 (constants.%.10)] // CHECK:STDOUT: %w.var: ref @F.%.loc15_15 (%.10) = var w diff --git a/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon b/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon index 556853141cf6..79e8e70a75db 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/fail_type_param_mismatch.carbon @@ -42,15 +42,15 @@ fn F(T:! type, U:! type) { // CHECK:STDOUT: fn @F(%T: type, %U: type) // CHECK:STDOUT: generic [%T: type, %U: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc12: type = ptr_type %T [symbolic = %.loc12 (constants.%.2)] // CHECK:STDOUT: %p.var: ref @F.%.loc12 (%.2) = var p // CHECK:STDOUT: %p: ref @F.%.loc12 (%.2) = bind_name p, %p.var -// CHECK:STDOUT: %U.ref: type = name_ref U, %U [symbolic = %U.ref (constants.%U)] +// CHECK:STDOUT: %U.ref: type = name_ref U, %U [symbolic = %U (constants.%U)] // CHECK:STDOUT: %p.ref: ref @F.%.loc12 (%.2) = name_ref p, %p // CHECK:STDOUT: %.loc16_15: @F.%.loc12 (%.2) = bind_value %p.ref -// CHECK:STDOUT: %.loc16_14: ref @F.%T.ref (%T) = deref %.loc16_15 -// CHECK:STDOUT: %n: @F.%U.ref (%U) = bind_name n, +// CHECK:STDOUT: %.loc16_14: ref @F.%T (%T) = deref %.loc16_15 +// CHECK:STDOUT: %n: @F.%U (%U) = bind_name n, // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon b/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon index 76c41a0bf73b..19d759e857f9 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/indirect_generic_type.carbon @@ -44,9 +44,9 @@ fn F(T:! type, p: T**) -> T* { // CHECK:STDOUT: fn @F(%T: type, %p: file.%.loc11_21 (%.2)) -> %.1 // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %p.ref: %.2 = name_ref p, %p -// CHECK:STDOUT: %.loc12_10.1: ref %.1 = deref %p.ref -// CHECK:STDOUT: %.loc12_10.2: %.1 = bind_value %.loc12_10.1 +// CHECK:STDOUT: %p.ref: file.%.loc11_21 (%.2) = name_ref p, %p +// CHECK:STDOUT: %.loc12_10.1: ref file.%.loc11_20 (%.1) = deref %p.ref +// CHECK:STDOUT: %.loc12_10.2: file.%.loc11_20 (%.1) = bind_value %.loc12_10.1 // CHECK:STDOUT: return %.loc12_10.2 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon b/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon index 5b9a3c98ae3c..c5f71fcf7ea3 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/type_param.carbon @@ -36,16 +36,16 @@ fn F(T:! type) { // CHECK:STDOUT: fn @F(%T: type) // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, %T [symbolic = %T.ref.loc12 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc12: type = ptr_type %T [symbolic = %.loc12 (constants.%.2)] // CHECK:STDOUT: %p.var: ref @F.%.loc12 (%.2) = var p // CHECK:STDOUT: %p: ref @F.%.loc12 (%.2) = bind_name p, %p.var -// CHECK:STDOUT: %T.ref.loc13: type = name_ref T, %T [symbolic = %T.ref.loc12 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc13: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %p.ref: ref @F.%.loc12 (%.2) = name_ref p, %p // CHECK:STDOUT: %.loc13_15: @F.%.loc12 (%.2) = bind_value %p.ref -// CHECK:STDOUT: %.loc13_14.1: ref @F.%T.ref.loc12 (%T) = deref %.loc13_15 -// CHECK:STDOUT: %.loc13_14.2: @F.%T.ref.loc12 (%T) = bind_value %.loc13_14.1 -// CHECK:STDOUT: %n: @F.%T.ref.loc12 (%T) = bind_name n, %.loc13_14.2 +// CHECK:STDOUT: %.loc13_14.1: ref @F.%T (%T) = deref %.loc13_15 +// CHECK:STDOUT: %.loc13_14.2: @F.%T (%T) = bind_value %.loc13_14.1 +// CHECK:STDOUT: %n: @F.%T (%T) = bind_name n, %.loc13_14.2 // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon b/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon index 0c150fedf204..6ca0870630ce 100644 --- a/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon +++ b/toolchain/check/testdata/function/generic/no_prelude/type_param_scope.carbon @@ -40,10 +40,10 @@ fn F(T:! type, n: T) -> T { // CHECK:STDOUT: fn @F(%T: type, %n: @F.%T (%T)) -> %T // CHECK:STDOUT: generic [%T: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %n.ref: @F.%T.ref (%T) = name_ref n, %n -// CHECK:STDOUT: %m: @F.%T.ref (%T) = bind_name m, %n.ref -// CHECK:STDOUT: %m.ref: @F.%T.ref (%T) = name_ref m, %m +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %n.ref: @F.%T (%T) = name_ref n, %n +// CHECK:STDOUT: %m: @F.%T (%T) = bind_name m, %n.ref +// CHECK:STDOUT: %m.ref: @F.%T (%T) = name_ref m, %m // CHECK:STDOUT: return %m.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/generic/redeclare.carbon b/toolchain/check/testdata/function/generic/redeclare.carbon index 9ee50b07c79a..255f8071dc2e 100644 --- a/toolchain/check/testdata/function/generic/redeclare.carbon +++ b/toolchain/check/testdata/function/generic/redeclare.carbon @@ -138,10 +138,10 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: generic [file.%T.loc4_6.2: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl.loc4 [template = constants.%F] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %F.call: init (%.1) = call %F.ref(%T.ref) -// CHECK:STDOUT: %.loc7_14.1: (%.1) = value_of_initializer %F.call -// CHECK:STDOUT: %.loc7_14.2: (%.1) = converted %F.call, %.loc7_14.1 +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = file.%T.loc4_6.2 (constants.%T)] +// CHECK:STDOUT: %F.call: init file.%.loc4 (%.1) = call %F.ref(%T.ref) +// CHECK:STDOUT: %.loc7_14.1: file.%.loc4 (%.1) = value_of_initializer %F.call +// CHECK:STDOUT: %.loc7_14.2: file.%.loc4 (%.1) = converted %F.call, %.loc7_14.1 // CHECK:STDOUT: return %.loc7_14.2 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -199,7 +199,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: generic [%T: type, %U: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %F.call: init (%.1) = call %F.ref() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -268,7 +268,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: generic [%U: type, %T: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T.2)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T.2)] // CHECK:STDOUT: %F.call: init %.1 = call %F.ref() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -337,7 +337,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: generic [%U: type, %T: type] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T.ref (constants.%T.2)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = %T (constants.%T.2)] // CHECK:STDOUT: %F.call: init %.1 = call %F.ref() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon index 871116c1c2e4..d80a947b486e 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -58,7 +58,7 @@ class C { // CHECK:STDOUT: // CHECK:STDOUT: interface @GenericInterface // CHECK:STDOUT: generic [file.%T.loc11_28.2: type] { -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_28.2 [symbolic = %T.ref (constants.%T)] // CHECK:STDOUT: %x.loc12_8.1: @GenericInterface.%T.ref (%T) = param x @@ -102,7 +102,7 @@ class C { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1(@GenericInterface.%x.loc12_8.2: @GenericInterface.%T.ref (%T)) -// CHECK:STDOUT: generic [file.%T.loc11_28.2: type, @GenericInterface.%Self: %.2]; +// CHECK:STDOUT: generic [file.%T.loc11_28.2: type, @GenericInterface.%Self: (%.2)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(@impl.%x.loc20_10.2: @impl.%T.ref (%T)) // CHECK:STDOUT: generic [@C.%T.loc19_23.2: type] { @@ -120,6 +120,11 @@ class C { // CHECK:STDOUT: @GenericInterface.%T.ref => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%GenericInterface.decl(file.%T.loc11_28.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_28.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @impl.%F.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: @impl.%T.ref => constants.%T diff --git a/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon b/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon index 611758a229c5..10ff048bc2e6 100644 --- a/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon +++ b/toolchain/check/testdata/interface/no_prelude/as_type_of_type.carbon @@ -49,11 +49,11 @@ fn F(T:! Empty) { // CHECK:STDOUT: fn @F(%T: %.1) // CHECK:STDOUT: generic [%T: %.1] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %.loc14_10.1: type = facet_type_access %T.ref [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %.loc14_10.2: type = converted %T.ref, %.loc14_10.1 [symbolic = %T.ref (constants.%T)] -// CHECK:STDOUT: %x.var: ref @F.%T.ref (%T) = var x -// CHECK:STDOUT: %x: ref @F.%T.ref (%T) = bind_name x, %x.var +// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc14_10.1: type = facet_type_access %T.ref [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc14_10.2: type = converted %T.ref, %.loc14_10.1 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %x.var: ref @F.%T (%T) = var x +// CHECK:STDOUT: %x: ref @F.%T (%T) = bind_name x, %x.var // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon index fd235bd65674..1185b273feff 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_add_member_outside_definition.carbon @@ -103,6 +103,9 @@ interface Outer { // CHECK:STDOUT: // CHECK:STDOUT: specific @Outer.%Inner.decl(constants.%Self.2) { // CHECK:STDOUT: declaration: +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: @Inner.%Self => constants.%Self.3 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Inner.%.decl(constants.%Self.2, constants.%Self.3) { diff --git a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon index 1c4243094733..e736aa31bf0e 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_generic_redeclaration.carbon @@ -92,7 +92,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: // CHECK:STDOUT: interface @.1 // CHECK:STDOUT: generic [file.%T.loc19_22.2: type] { -// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %Self: (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -115,7 +115,7 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: // CHECK:STDOUT: interface @.3 // CHECK:STDOUT: generic [file.%T.loc38_27.2: %.2] { -// CHECK:STDOUT: %Self: %.7 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] +// CHECK:STDOUT: %Self: (%.7) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -127,6 +127,11 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: file.%T.loc19_22.2 => constants.%T.1 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl.loc19(file.%T.loc19_22.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc19_22.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific file.%Generic.decl(constants.%T.1) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc21_19.2 => constants.%T.1 @@ -142,3 +147,8 @@ interface DifferentParams(T:! ()) {} // CHECK:STDOUT: file.%T.loc38_27.2 => constants.%T.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%.decl.loc38(file.%T.loc38_27.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc38_27.2 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon index 06e4b3d9b3e1..3ce38eb46166 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_facet_lookup.carbon @@ -83,7 +83,7 @@ fn CallFacet(T:! Interface, x: T) { // CHECK:STDOUT: fn @CallStatic(%T: %.1) // CHECK:STDOUT: generic [%T: %.1] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T [symbolic = %T.ref (constants.%T)] +// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T [symbolic = %T (constants.%T)] // CHECK:STDOUT: %F.ref: %.3 = name_ref F, @Interface.%.loc11 [template = constants.%.4] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -91,7 +91,7 @@ fn CallFacet(T:! Interface, x: T) { // CHECK:STDOUT: fn @CallFacet(%T: %.1, %x: @CallFacet.%T (%T)) // CHECK:STDOUT: generic [%T: %.1] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %x.ref: %T = name_ref x, %x +// CHECK:STDOUT: %x.ref: @CallFacet.%T (%T) = name_ref x, %x // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon index 463f6a1cec3e..40d8a0aff8a0 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon @@ -29,11 +29,12 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %I: %I.type = struct_value () [template] // CHECK:STDOUT: %.2: type = interface_type @I, file.%I.decl(%T) [symbolic] -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %Self.1: %.2 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.3: type = assoc_entity_type @I, %F.type [template] // CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [template] +// CHECK:STDOUT: %Self.2: (%.2) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.type: type = fn_type @.1 [template] // CHECK:STDOUT: %.5: %.type = struct_value () [template] // CHECK:STDOUT: } @@ -49,35 +50,35 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] { // CHECK:STDOUT: %T.loc22_6.1: type = param T // CHECK:STDOUT: %T.loc22_6.2: type = bind_symbolic_name T 0, %T.loc22_6.1 [symbolic = %T.loc22_6.2 (constants.%T)] -// CHECK:STDOUT: %.loc22_24.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %Self.ref.loc22_24: (%.2) = name_ref Self, %.loc22_24.1 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %.loc22_24.2: type = facet_type_access %Self.ref.loc22_24 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %.loc22_24.3: type = converted %Self.ref.loc22_24, %.loc22_24.2 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %self.loc22_18.1: file.%.loc22_24.1 (%Self) = param self -// CHECK:STDOUT: @.1.%self: file.%.loc22_24.1 (%Self) = bind_name self, %self.loc22_18.1 -// CHECK:STDOUT: %.loc22_35.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %Self.ref.loc22_35: (%.2) = name_ref Self, %.loc22_35.1 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %.loc22_35.2: type = facet_type_access %Self.ref.loc22_35 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: %.loc22_35.3: type = converted %Self.ref.loc22_35, %.loc22_35.2 [symbolic = %.loc22_24.1 (constants.%Self)] -// CHECK:STDOUT: @.1.%return: ref %Self = var +// CHECK:STDOUT: %.loc22_24.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %Self.ref.loc22_24: (%.2) = name_ref Self, %.loc22_24.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_24.2: type = facet_type_access %Self.ref.loc22_24 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_24.3: type = converted %Self.ref.loc22_24, %.loc22_24.2 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %self.loc22_18.1: file.%.loc22_24.1 (%Self.2) = param self +// CHECK:STDOUT: @.1.%self: file.%.loc22_24.1 (%Self.2) = bind_name self, %self.loc22_18.1 +// CHECK:STDOUT: %.loc22_35.1: (%.2) = specific_constant @I.%Self, %I.decl(constants.%T) [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %Self.ref.loc22_35: (%.2) = name_ref Self, %.loc22_35.1 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_35.2: type = facet_type_access %Self.ref.loc22_35 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: %.loc22_35.3: type = converted %Self.ref.loc22_35, %.loc22_35.2 [symbolic = %.loc22_24.1 (constants.%Self.2)] +// CHECK:STDOUT: @.1.%return: ref %Self.2 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @I // CHECK:STDOUT: generic [file.%T.loc11_13.2: type] { -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %.loc13_14.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %Self.ref.loc13_14: %.2 = name_ref Self, %.loc13_14.1 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %.loc13_14.2: type = facet_type_access %Self.ref.loc13_14 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %.loc13_14.3: type = converted %Self.ref.loc13_14, %.loc13_14.2 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %self.loc13_8.1: @I.%.loc13_14.1 (%Self) = param self -// CHECK:STDOUT: %self.loc13_8.2: @I.%.loc13_14.1 (%Self) = bind_name self, %self.loc13_8.1 -// CHECK:STDOUT: %.loc13_25.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %Self.ref.loc13_25: %.2 = name_ref Self, %.loc13_25.1 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %.loc13_25.2: type = facet_type_access %Self.ref.loc13_25 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %.loc13_25.3: type = converted %Self.ref.loc13_25, %.loc13_25.2 [symbolic = %.loc13_14.1 (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %.loc13_14.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %Self.ref.loc13_14: %.2 = name_ref Self, %.loc13_14.1 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %.loc13_14.2: type = facet_type_access %Self.ref.loc13_14 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %.loc13_14.3: type = converted %Self.ref.loc13_14, %.loc13_14.2 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %self.loc13_8.1: @I.%.loc13_14.1 (%Self.1) = param self +// CHECK:STDOUT: %self.loc13_8.2: @I.%.loc13_14.1 (%Self.1) = bind_name self, %self.loc13_8.1 +// CHECK:STDOUT: %.loc13_25.1: %.2 = specific_constant %Self, file.%I.decl(constants.%T) [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %Self.ref.loc13_25: %.2 = name_ref Self, %.loc13_25.1 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %.loc13_25.2: type = facet_type_access %Self.ref.loc13_25 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %.loc13_25.3: type = converted %Self.ref.loc13_25, %.loc13_25.2 [symbolic = %.loc13_14.1 (constants.%Self.1)] +// CHECK:STDOUT: %return.var: ref %Self.1 = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc13_29: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -87,24 +88,33 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: witness = (%F.decl) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F[@I.%self.loc13_8.2: @I.%.loc13_14.1 (%Self)]() -> %Self -// CHECK:STDOUT: generic [file.%T.loc11_13.2: type, @I.%Self: %.2]; +// CHECK:STDOUT: fn @F[@I.%self.loc13_8.2: @I.%.loc13_14.1 (%Self.1)]() -> %Self.1 +// CHECK:STDOUT: generic [file.%T.loc11_13.2: type, @I.%Self: (%.2)]; // CHECK:STDOUT: -// CHECK:STDOUT: fn @.1[%self: file.%.loc22_24.1 (%Self)]() -> %Self +// CHECK:STDOUT: fn @.1[%self: file.%.loc22_24.1 (%Self.2)]() -> %Self.2 // CHECK:STDOUT: generic [file.%T.loc22_6.2: type] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %self.ref: %Self = name_ref self, %self +// CHECK:STDOUT: %self.ref: file.%.loc22_24.1 (%Self.2) = name_ref self, %self // CHECK:STDOUT: return %self.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%I.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: definition: +// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: @I.%Self => constants.%Self.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @I.%F.decl(constants.%T, constants.%Self) { +// CHECK:STDOUT: specific @I.%F.decl(constants.%T, constants.%Self.1) { // CHECK:STDOUT: declaration: -// CHECK:STDOUT: @I.%.loc13_14.1 => constants.%Self +// CHECK:STDOUT: @I.%.loc13_14.1 => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific file.%I.decl(file.%T.loc11_13.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc11_13.2 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific file.%I.decl(file.%T.loc22_6.2) { @@ -115,7 +125,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: specific file.%.decl(constants.%T) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc22_6.2 => constants.%T -// CHECK:STDOUT: => constants.%.2 -// CHECK:STDOUT: file.%.loc22_24.1 => constants.%Self +// CHECK:STDOUT: => constants.%.2 +// CHECK:STDOUT: file.%.loc22_24.1 => constants.%Self.2 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic.carbon b/toolchain/check/testdata/interface/no_prelude/generic.carbon index 09e6e51ef7f5..00c9a2e40ac0 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic.carbon @@ -145,7 +145,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @Simple // CHECK:STDOUT: generic [file.%T.loc4_18.2: type] { -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] +// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -154,7 +154,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @WithAssocFn // CHECK:STDOUT: generic [file.%T.loc8_23.2: type] { -// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Self: (%.4) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] // CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { // CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [template = constants.%X] // CHECK:STDOUT: %return.var: ref %X = var @@ -215,7 +215,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1() -> %X -// CHECK:STDOUT: generic [file.%T.loc8_23.2: type, @WithAssocFn.%Self: %.4]; +// CHECK:STDOUT: generic [file.%T.loc8_23.2: type, @WithAssocFn.%Self: (%.4)]; // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2() -> @impl.2.%return.var: %X { // CHECK:STDOUT: !entry: @@ -232,7 +232,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: generic [%T: %.7] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Receive.ref: %Receive.type = name_ref Receive, file.%Receive.decl [template = constants.%Receive] -// CHECK:STDOUT: %T.ref: %.7 = name_ref T, %T [symbolic = %T.ref (constants.%T.2)] +// CHECK:STDOUT: %T.ref: %.7 = name_ref T, %T [symbolic = %T (constants.%T.2)] // CHECK:STDOUT: %Receive.call: init %.1 = call %Receive.ref(%T.ref) // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -242,6 +242,11 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: file.%T.loc4_18.2 => constants.%T.1 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Simple.decl(file.%T.loc4_18.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_18.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific file.%WithAssocFn.decl(constants.%T.1) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc8_23.2 => constants.%T.1 @@ -251,6 +256,11 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%WithAssocFn.decl(file.%T.loc8_23.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc8_23.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific file.%Simple.decl(constants.%C) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_18.2 => constants.%C @@ -335,7 +345,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: // CHECK:STDOUT: interface @Generic // CHECK:STDOUT: generic [file.%T.loc4_19.2: type] { -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -359,7 +369,7 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: generic [%T: %.5] { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F] -// CHECK:STDOUT: %T.ref: %.5 = name_ref T, %T [symbolic = %T.ref (constants.%T.3)] +// CHECK:STDOUT: %T.ref: %.5 = name_ref T, %T [symbolic = %T (constants.%T.3)] // CHECK:STDOUT: %F.call: init %.1 = call %F.ref() [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -369,6 +379,11 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: file.%T.loc4_19.2 => constants.%T.1 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%Generic.decl(file.%T.loc4_19.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific file.%Generic.decl(constants.%A) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: file.%T.loc4_19.2 => constants.%A diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index c6ec7ee5bd39..f6315d812c94 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -54,7 +54,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: // CHECK:STDOUT: interface @AddWith // CHECK:STDOUT: generic [file.%T.loc4_19.2: type] { -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self: (%.2) = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} // CHECK:STDOUT: %.loc5: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -65,7 +65,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -// CHECK:STDOUT: generic [file.%T.loc4_19.2: type, @AddWith.%Self: %.2]; +// CHECK:STDOUT: generic [file.%T.loc4_19.2: type, @AddWith.%Self: (%.2)]; // CHECK:STDOUT: // CHECK:STDOUT: specific file.%AddWith.decl(constants.%T) { // CHECK:STDOUT: declaration: @@ -76,6 +76,11 @@ impl C as AddWith(C) { // CHECK:STDOUT: declaration: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific file.%AddWith.decl(file.%T.loc4_19.2) { +// CHECK:STDOUT: declaration: +// CHECK:STDOUT: file.%T.loc4_19.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- b.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/sem_ir/constant.cpp b/toolchain/sem_ir/constant.cpp index 80387dbff33b..4a68947ec28c 100644 --- a/toolchain/sem_ir/constant.cpp +++ b/toolchain/sem_ir/constant.cpp @@ -29,7 +29,9 @@ auto ConstantStore::GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId { return const_id; }); CARBON_CHECK(result.value() != ConstantId::Invalid); - CARBON_CHECK(result.value().is_symbolic() == is_symbolic); + CARBON_CHECK(result.value().is_symbolic() == is_symbolic) + << "Constant " << inst + << " registered as both symbolic and template constant."; return result.value(); } diff --git a/toolchain/sem_ir/generic.cpp b/toolchain/sem_ir/generic.cpp index 470cd1022b8a..8c4d1a9816ec 100644 --- a/toolchain/sem_ir/generic.cpp +++ b/toolchain/sem_ir/generic.cpp @@ -53,8 +53,7 @@ auto GenericInstanceStore::CollectMemUsage(MemUsage& mem_usage, KeyContext(generic_instances_.array_ref())); } -auto GetConstantInInstance(const File& sem_ir, - GenericInstanceId /*instance_id*/, +auto GetConstantInInstance(const File& sem_ir, GenericInstanceId instance_id, ConstantId const_id) -> ConstantId { if (!const_id.is_symbolic()) { // Type does not depend on a generic parameter. @@ -67,9 +66,26 @@ auto GetConstantInInstance(const File& sem_ir, return const_id; } - // TODO: Look up the value in the generic instance. For now, return the - // canonical constant value. - return sem_ir.constant_values().Get(symbolic.inst_id); + if (!instance_id.is_valid()) { + // TODO: We have a generic constant but no instance. Investigate whether we + // can CHECK-fail here. For now, produce the canonical value of the + // constant. + return sem_ir.constant_values().Get(symbolic.inst_id); + } + + const auto& specific = sem_ir.generic_instances().Get(instance_id); + if (specific.generic_id != symbolic.generic_id) { + // TODO: Given an instance for the wrong generic. If the symbolic constant + // is from an enclosing generic, take the value from the corresponding + // instance. Otherwise, CHECK-fail. + return sem_ir.constant_values().Get(symbolic.inst_id); + } + + auto value_block_id = specific.GetValueBlock(symbolic.index.region()); + CARBON_CHECK(value_block_id.is_valid()) + << "Queried region of " << instance_id << " before it was resolved."; + return sem_ir.constant_values().Get( + sem_ir.inst_blocks().Get(value_block_id)[symbolic.index.index()]); } auto GetConstantValueInInstance(const File& sem_ir,