From a9b43a222f7282664c92a4d9e37f9f14e36b7e02 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 1 Aug 2024 14:02:46 -0700 Subject: [PATCH] When importing symbolic constants and types, also import the associated generic and index. (#4180) A symbolic constant has an instruction to compute the constant value, as well as potentially also having a generic ID and an index within that generic to indicate where corresponding values can be found in a specific. Import those pieces of information when importing such a constant. We try to import the generic before we start the main work of importing the constant, and retry the import process if importing the generic adds work to the worklist. This means that the first time we import anything within a generic, we can now perform three passes calling `TryResolveInst` instead of two, but the first pass is very lightweight and only looks up and adds a single instruction, so the added overhead of the extra pass should be minimal. To avoid introducing cycles when importing a generic function, make the import of a function declaration build the new `Function`, `FunctionDecl`, and `FunctionType` in the first pass, like classes and interfaces do. --- toolchain/check/import_ref.cpp | 241 +++++++++++++----- .../testdata/class/generic/import.carbon | 191 +++----------- toolchain/check/testdata/class/import.carbon | 4 +- .../function/declaration/import.carbon | 6 +- .../fail_import_incomplete_return.carbon | 6 +- .../function/definition/import.carbon | 2 +- .../no_prelude/generic_import.carbon | 2 +- .../merging_with_indirections.carbon | 4 +- .../testdata/operators/overloaded/add.carbon | 2 +- .../operators/overloaded/bit_and.carbon | 2 +- .../operators/overloaded/bit_or.carbon | 2 +- .../operators/overloaded/bit_xor.carbon | 2 +- .../testdata/operators/overloaded/dec.carbon | 2 +- .../testdata/operators/overloaded/div.carbon | 2 +- .../overloaded/fail_assign_non_ref.carbon | 4 +- .../operators/overloaded/fail_no_impl.carbon | 4 +- .../overloaded/fail_no_impl_for_arg.carbon | 2 +- .../testdata/operators/overloaded/inc.carbon | 2 +- .../operators/overloaded/left_shift.carbon | 2 +- .../testdata/operators/overloaded/mod.carbon | 2 +- .../testdata/operators/overloaded/mul.carbon | 2 +- .../operators/overloaded/right_shift.carbon | 2 +- .../testdata/operators/overloaded/sub.carbon | 2 +- toolchain/check/testdata/struct/import.carbon | 8 +- toolchain/check/testdata/tuples/import.carbon | 8 +- 25 files changed, 247 insertions(+), 259 deletions(-) diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 2e07c156bbd3..de182c1baf5a 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -131,30 +131,38 @@ auto VerifySameCanonicalImportIRInst(Context& context, SemIR::InstId prev_id, // - If `retry` is set, we process it again, because it didn't complete last // time, even though we have a constant value already. // 2. Resolve the instruction: (TryResolveInst/TryResolveTypedInst) +// - For a symbolic constant within a generic, find the generic itself. If it +// needs to be imported, return Retry() to import the generic before we +// import the constant. // - For instructions that can be forward declared, if we don't already have // a constant value from a previous attempt at resolution, start by making // a forward declared constant value to address circular references. // - Gather all input constants. // - Gathering constants directly adds unresolved values to work_stack_. // - If any need to be resolved (HasNewWork), return Retry(): this -// instruction needs two calls to complete. +// instruction needs another call to complete. // - If the constant value is already known because we have made a forward // declaration, pass it to Retry(). It will be passed to future attempts // to resolve this instruction so the earlier work can be found, and will // be made available for other instructions to use. -// - The second attempt to resolve this instruction must produce the same -// constant, because the value may have already been used by resolved -// instructions. +// - The subsequent attempt to resolve this instruction must produce the +// same constant, because the value may have already been used by +// resolved instructions. // - Build any necessary IR structures, and return the output constant. // 3. If resolve didn't return Retry(), pop the work. Otherwise, it needs to // remain, and may no longer be at the top of the stack; set `retry` on it so // we'll make sure to run it again later. // -// TryResolveInst/TryResolveTypedInst can complete in one call for a given -// instruction, but should always complete within two calls. However, due to the -// chance of a second call, it's important to reserve all expensive logic until -// it's been established that input constants are available; this in particular -// includes GetTypeIdForTypeConstant calls which do a hash table lookup. +// TryResolveInst can complete in one call for a given instruction, but should +// always complete within three calls: +// +// - TryResolveInst can retry once if the generic is not yet loaded. +// - TryResolveTypedInst can retry once if its inputs are not yet loaded. +// - The third call should succeed. +// +// Due to the chance of a second call to TryResolveTypedInst, it's important to +// reserve all expensive logic until it's been established that input constants +// are available. // // TODO: Fix class `extern` handling and merging, rewrite tests. // - check/testdata/class/cross_package_import.carbon @@ -210,20 +218,52 @@ class ImportRefResolver { return constant_id; } + // Wraps constant evaluation with logic to handle constants. + auto ResolveConstant(SemIR::ConstantId import_const_id) -> SemIR::ConstantId { + if (!import_const_id.is_valid()) { + return import_const_id; + } + + // For template constants, the corresponding instruction has the desired + // constant value. + if (!import_const_id.is_symbolic()) { + return Resolve(import_ir_.constant_values().GetInstId(import_const_id)); + } + + // For abstract symbolic constants, the corresponding instruction has the + // desired constant value. + const auto& symbolic_const = + import_ir_.constant_values().GetSymbolicConstant(import_const_id); + if (!symbolic_const.generic_id.is_valid()) { + return Resolve(import_ir_.constant_values().GetInstId(import_const_id)); + } + + // For a symbolic constant in a generic, pick the corresponding instruction + // out of the eval block for the generic and resolve its constant value. + const auto& generic = import_ir_.generics().Get(symbolic_const.generic_id); + auto block = generic.GetEvalBlock(symbolic_const.index.region()); + return Resolve( + import_ir_.inst_blocks().Get(block)[symbolic_const.index.index()]); + } + // Wraps constant evaluation with logic to handle types. auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId { if (!import_type_id.is_valid()) { return import_type_id; } - auto import_type_inst_id = import_ir_.types().GetInstId(import_type_id); - CARBON_CHECK(import_type_inst_id.is_valid()); + auto import_type_const_id = + import_ir_.types().GetConstantId(import_type_id); + CARBON_CHECK(import_type_const_id.is_valid()); - if (import_type_inst_id.is_builtin()) { + if (auto import_type_inst_id = + import_ir_.constant_values().GetInstId(import_type_const_id); + import_type_inst_id.is_builtin()) { // Builtins don't require constant resolution; we can use them directly. return context_.GetBuiltinType(import_type_inst_id.builtin_inst_kind()); } else { - return context_.GetTypeIdForTypeConstant(Resolve(import_type_inst_id)); + return context_.GetTypeIdForTypeConstant( + ResolveConstant(import_type_id.AsConstantId())); } } @@ -847,6 +887,39 @@ class ImportRefResolver { // TODO: Error is returned when support is missing, but that should go away. auto TryResolveInst(SemIR::InstId inst_id, SemIR::ConstantId const_id) -> ResolveResult { + auto inst_const_id = import_ir_.constant_values().Get(inst_id); + if (!inst_const_id.is_valid() || !inst_const_id.is_symbolic() || + const_id.is_valid()) { + return TryResolveInstCanonical(inst_id, const_id); + } + + // Try to import the generic, and retry if it's not ready yet. Note that if + // this retries, we can require three passes to import an instruction. + const auto& symbolic_const = + import_ir_.constant_values().GetSymbolicConstant(inst_const_id); + auto initial_work = work_stack_.size(); + auto generic_const_id = GetLocalConstantId(symbolic_const.generic_id); + if (HasNewWork(initial_work)) { + return ResolveResult::Retry(); + } + + // Import the constant and rebuild the symbolic constant data. + auto result = TryResolveInstCanonical(inst_id, const_id); + if (result.const_id.is_valid()) { + result.const_id = context_.constant_values().AddSymbolicConstant( + {.inst_id = context_.constant_values().GetInstId(result.const_id), + .generic_id = GetLocalGenericId(generic_const_id), + .index = symbolic_const.index}); + } + return result; + } + + // Tries to resolve the InstId, returning a canonical constant when ready, or + // Invalid if more has been added to the stack. This is the same as + // TryResolveInst, except that it may resolve symbolic constants as canonical + // constants instead of as constants associated with a particular generic. + auto TryResolveInstCanonical(SemIR::InstId inst_id, + SemIR::ConstantId const_id) -> ResolveResult { if (inst_id.is_builtin()) { CARBON_CHECK(!const_id.is_valid()); // Constants for builtins can be directly copied. @@ -890,7 +963,7 @@ class ImportRefResolver { return TryResolveTypedInst(inst, inst_id); } case CARBON_KIND(SemIR::FunctionDecl inst): { - return TryResolveTypedInst(inst); + return TryResolveTypedInst(inst, const_id); } case CARBON_KIND(SemIR::FunctionType inst): { return TryResolveTypedInst(inst); @@ -1253,73 +1326,101 @@ class ImportRefResolver { return {.const_id = context_.constant_values().Get(inst_id)}; } - auto TryResolveTypedInst(SemIR::FunctionDecl inst) -> ResolveResult { - auto initial_work = work_stack_.size(); - - const auto& function = import_ir_.functions().Get(inst.function_id); - auto return_type_const_id = SemIR::ConstantId::Invalid; - if (function.return_storage_id.is_valid()) { - return_type_const_id = - GetLocalConstantId(function.GetDeclaredReturnType(import_ir_)); - } - auto parent_scope_id = GetLocalNameScopeId(function.parent_scope_id); - llvm::SmallVector implicit_param_const_ids = - GetLocalParamConstantIds(function.implicit_param_refs_id); - llvm::SmallVector param_const_ids = - GetLocalParamConstantIds(function.param_refs_id); - auto generic_data = GetLocalGenericData(function.generic_id); - - if (HasNewWork(initial_work)) { - return ResolveResult::Retry(); - } - - // Add the function declaration. + // Make a declaration of a function. This is done as a separate step from + // importing the function declaration in order to resolve cycles. + auto MakeFunctionDecl(const SemIR::Function& import_function) + -> std::pair { SemIR::FunctionDecl function_decl = { .type_id = SemIR::TypeId::Invalid, .function_id = SemIR::FunctionId::Invalid, .decl_block_id = SemIR::InstBlockId::Empty}; - auto import_ir_inst_id = AddImportIRInst(function.latest_decl_id()); - auto function_decl_id = context_.AddPlaceholderInstInNoBlock( - SemIR::LocIdAndInst(import_ir_inst_id, function_decl)); - // TODO: Implement import for generics. - auto generic_id = - MakeIncompleteGeneric(function_decl_id, function.generic_id); - SetGenericData(function.generic_id, generic_id, generic_data); + auto function_decl_id = + context_.AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst( + AddImportIRInst(import_function.latest_decl_id()), function_decl)); - auto new_return_storage = SemIR::InstId::Invalid; - if (function.return_storage_id.is_valid()) { - // Recreate the return slot from scratch. - // TODO: Once we import function definitions, we'll need to make sure we - // use the same return storage variable in the declaration and definition. - new_return_storage = context_.AddInstInNoBlock( - AddImportIRInst(function.return_storage_id), - {.type_id = context_.GetTypeIdForTypeConstant(return_type_const_id), - .name_id = SemIR::NameId::ReturnSlot}); - } + // Start with an incomplete function. function_decl.function_id = context_.functions().Add( - {{.name_id = GetLocalNameId(function.name_id), - .parent_scope_id = parent_scope_id, - .generic_id = generic_id, - .first_param_node_id = Parse::NodeId::Invalid, - .last_param_node_id = Parse::NodeId::Invalid, - .implicit_param_refs_id = GetLocalParamRefsId( - function.implicit_param_refs_id, implicit_param_const_ids), - .param_refs_id = - GetLocalParamRefsId(function.param_refs_id, param_const_ids), - .decl_id = function_decl_id, - .definition_id = function.definition_id.is_valid() - ? function_decl_id - : SemIR::InstId::Invalid}, - {.return_storage_id = new_return_storage, - .is_extern = function.is_extern, - .builtin_function_kind = function.builtin_function_kind}}); + {GetIncompleteLocalEntityBase(function_decl_id, import_function), + {.return_storage_id = SemIR::InstId::Invalid, + .is_extern = import_function.is_extern, + .builtin_function_kind = import_function.builtin_function_kind}}); + // TODO: Import this or recompute it. auto specific_id = SemIR::SpecificId::Invalid; function_decl.type_id = context_.GetFunctionType(function_decl.function_id, specific_id); - // Write the function ID into the FunctionDecl. + + // Write the function ID and type into the FunctionDecl. context_.ReplaceInstBeforeConstantUse(function_decl_id, function_decl); - return {.const_id = context_.constant_values().Get(function_decl_id)}; + return {function_decl.function_id, + context_.constant_values().Get(function_decl_id)}; + } + + auto TryResolveTypedInst(SemIR::FunctionDecl inst, + SemIR::ConstantId function_const_id) + -> ResolveResult { + const auto& import_function = import_ir_.functions().Get(inst.function_id); + + SemIR::FunctionId function_id = SemIR::FunctionId::Invalid; + if (!function_const_id.is_valid()) { + // On the first pass, create a forward declaration of the interface. + std::tie(function_id, function_const_id) = + MakeFunctionDecl(import_function); + } else { + // On the second pass, compute the function ID from the constant value of + // the declaration. + auto function_const_inst = context_.insts().Get( + context_.constant_values().GetInstId(function_const_id)); + auto function_type = context_.types().GetAs( + function_const_inst.type_id()); + function_id = function_type.function_id; + } + + auto initial_work = work_stack_.size(); + + auto return_type_const_id = SemIR::ConstantId::Invalid; + if (import_function.return_storage_id.is_valid()) { + return_type_const_id = + GetLocalConstantId(import_function.GetDeclaredReturnType(import_ir_)); + } + auto parent_scope_id = GetLocalNameScopeId(import_function.parent_scope_id); + llvm::SmallVector implicit_param_const_ids = + GetLocalParamConstantIds(import_function.implicit_param_refs_id); + llvm::SmallVector param_const_ids = + GetLocalParamConstantIds(import_function.param_refs_id); + auto generic_data = GetLocalGenericData(import_function.generic_id); + + if (HasNewWork(initial_work)) { + return ResolveResult::Retry(function_const_id); + } + + // Add the function declaration. + auto& new_function = context_.functions().Get(function_id); + new_function.parent_scope_id = parent_scope_id; + new_function.implicit_param_refs_id = GetLocalParamRefsId( + import_function.implicit_param_refs_id, implicit_param_const_ids); + new_function.param_refs_id = + GetLocalParamRefsId(import_function.param_refs_id, param_const_ids); + SetGenericData(import_function.generic_id, new_function.generic_id, + generic_data); + + if (import_function.return_storage_id.is_valid()) { + // Recreate the return slot from scratch. + // TODO: Once we import function definitions, we'll need to make sure we + // use the same return storage variable in the declaration and definition. + new_function.return_storage_id = + context_.AddInstInNoBlock( + AddImportIRInst(import_function.return_storage_id), + {.type_id = + context_.GetTypeIdForTypeConstant(return_type_const_id), + .name_id = SemIR::NameId::ReturnSlot}); + } + + if (import_function.definition_id.is_valid()) { + new_function.definition_id = new_function.decl_id; + } + + return {.const_id = function_const_id}; } auto TryResolveTypedInst(SemIR::FunctionType inst) -> ResolveResult { diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 30976b38b9bc..afd1eb3e4484 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -38,23 +38,13 @@ fn F() -> CompleteClass(i32) { library "use_foo"; import library "foo"; -fn Use() -> i32 { +fn UseMethod() -> i32 { var v: CompleteClass(i32) = F(); return v.F(); } -// --- fail_todo_use_foo.carbon - -library "fail_todo_use_foo"; -import library "foo"; - -fn Use() -> i32 { +fn UseField() -> i32 { var v: CompleteClass(i32) = F(); - // TODO: This should be accepted. - // CHECK:STDERR: fail_todo_use_foo.carbon:[[@LINE+4]]:10: ERROR: Cannot implicitly convert from `CompleteClass` to `CompleteClass`. - // CHECK:STDERR: return v.n; - // CHECK:STDERR: ^~~ - // CHECK:STDERR: return v.n; } @@ -387,8 +377,8 @@ class Class(U:! type) { // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %Use.type: type = fn_type @Use [template] -// CHECK:STDOUT: %Use: %Use.type = struct_value () [template] +// CHECK:STDOUT: %UseMethod.type: type = fn_type @UseMethod [template] +// CHECK:STDOUT: %UseMethod: %UseMethod.type = struct_value () [template] // CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] // CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] // CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] @@ -406,6 +396,8 @@ class Class(U:! type) { // CHECK:STDOUT: %.5: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] +// CHECK:STDOUT: %UseField.type: type = fn_type @UseField [template] +// CHECK:STDOUT: %UseField: %UseField.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -424,8 +416,8 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+18, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+28, unloaded -// CHECK:STDOUT: %import_ref.7: %F.type.2 = import_ref Main//foo, inst+35, loaded [template = constants.%F.1] +// CHECK:STDOUT: %import_ref.6: @CompleteClass.%.1 (%.3) = import_ref Main//foo, inst+28, loaded [template = %.1] +// CHECK:STDOUT: %import_ref.7: @CompleteClass.%F.type (%F.type.2) = import_ref Main//foo, inst+35, loaded [symbolic = @CompleteClass.%F (constants.%F.1)] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -434,15 +426,22 @@ class Class(U:! type) { // CHECK:STDOUT: .CompleteClass = imports.%import_ref.2 // CHECK:STDOUT: .F = imports.%import_ref.3 // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .Use = %Use.decl +// CHECK:STDOUT: .UseMethod = %UseMethod.decl +// CHECK:STDOUT: .UseField = %UseField.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc5_13.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc5_13.2: type = converted %int.make_type_32, %.loc5_13.1 [template = i32] -// CHECK:STDOUT: @Use.%return: ref i32 = var +// CHECK:STDOUT: %UseMethod.decl: %UseMethod.type = fn_decl @UseMethod [template = constants.%UseMethod] { +// CHECK:STDOUT: %int.make_type_32.loc5: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_19.1: type = value_of_initializer %int.make_type_32.loc5 [template = i32] +// CHECK:STDOUT: %.loc5_19.2: type = converted %int.make_type_32.loc5, %.loc5_19.1 [template = i32] +// CHECK:STDOUT: @UseMethod.%return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %UseField.decl: %UseField.type = fn_decl @UseField [template = constants.%UseField] { +// CHECK:STDOUT: %int.make_type_32.loc10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_18.1: type = value_of_initializer %int.make_type_32.loc10 [template = i32] +// CHECK:STDOUT: %.loc10_18.2: type = converted %int.make_type_32.loc10, %.loc10_18.1 [template = i32] +// CHECK:STDOUT: @UseField.%return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -465,7 +464,7 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Use() -> i32 { +// CHECK:STDOUT: fn @UseMethod() -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%import_ref.2 [template = constants.%CompleteClass.1] // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] @@ -481,7 +480,8 @@ class Class(U:! type) { // CHECK:STDOUT: %F.call.loc6: init %CompleteClass.3 = call %F.ref.loc6() to %.loc6_7 // CHECK:STDOUT: assign %v.var, %F.call.loc6 // CHECK:STDOUT: %v.ref: ref %CompleteClass.3 = name_ref v, %v -// CHECK:STDOUT: %F.ref.loc7: %F.type.2 = name_ref F, imports.%import_ref.7 [template = constants.%F.1] +// CHECK:STDOUT: %.loc7_11: %F.type.3 = specific_constant imports.%import_ref.7, @CompleteClass(i32) [template = constants.%F.3] +// CHECK:STDOUT: %F.ref.loc7: %F.type.3 = name_ref F, %.loc7_11 [template = constants.%F.3] // CHECK:STDOUT: %F.call.loc7: init i32 = call %F.ref.loc7() // CHECK:STDOUT: %.loc7_15.1: i32 = value_of_initializer %F.call.loc7 // CHECK:STDOUT: %.loc7_15.2: i32 = converted %F.call.loc7, %.loc7_15.1 @@ -496,145 +496,30 @@ class Class(U:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2() -> %CompleteClass.3; // CHECK:STDOUT: -// CHECK:STDOUT: specific @CompleteClass(constants.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @CompleteClass(i32) { -// CHECK:STDOUT: %T => i32 -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.3 -// CHECK:STDOUT: %.1 => constants.%.4 -// CHECK:STDOUT: %F.type => constants.%F.type.3 -// CHECK:STDOUT: %F => constants.%F.3 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_use_foo.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %Use.type: type = fn_type @Use [template] -// CHECK:STDOUT: %Use: %Use.type = struct_value () [template] -// CHECK:STDOUT: %CompleteClass.type: type = generic_class_type @CompleteClass [template] -// CHECK:STDOUT: %CompleteClass.1: %CompleteClass.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = struct_type {.n: i32} [template] -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] -// CHECK:STDOUT: %CompleteClass.2: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic] -// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] -// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @CompleteClass(%T) [symbolic] -// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] -// CHECK:STDOUT: %.3: type = unbound_element_type %CompleteClass.2, i32 [symbolic] -// CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(i32) [template] -// CHECK:STDOUT: %.4: type = unbound_element_type %CompleteClass.3, i32 [template] -// CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @CompleteClass(i32) [template] -// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %.2 [template] -// CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] -// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+6, unloaded -// CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+14, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.4 = import_ref Main//foo, inst+55, loaded [template = constants.%F.4] -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: .Int32 = %import_ref.4 -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] -// CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+18, unloaded -// CHECK:STDOUT: %import_ref.6: %.3 = import_ref Main//foo, inst+28, loaded [template = %.1] -// CHECK:STDOUT: %import_ref.7 = import_ref Main//foo, inst+35, unloaded -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Class = imports.%import_ref.1 -// CHECK:STDOUT: .CompleteClass = imports.%import_ref.2 -// CHECK:STDOUT: .F = imports.%import_ref.3 -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .Use = %Use.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %Use.decl: %Use.type = fn_decl @Use [template = constants.%Use] { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc5_13.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc5_13.2: type = converted %int.make_type_32, %.loc5_13.1 [template = i32] -// CHECK:STDOUT: @Use.%return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: generic class @CompleteClass(constants.%T: type) { -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.2)] -// CHECK:STDOUT: %.1: type = unbound_element_type @CompleteClass.%CompleteClass (%CompleteClass.2), i32 [symbolic = %.1 (constants.%.3)] -// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.2)] -// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.2) = struct_value () [symbolic = %F (constants.%F.2)] -// CHECK:STDOUT: -// CHECK:STDOUT: class { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 -// CHECK:STDOUT: .n = imports.%import_ref.6 -// CHECK:STDOUT: .F = imports.%import_ref.7 -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Use() -> i32 { +// CHECK:STDOUT: fn @UseField() -> i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%import_ref.2 [template = constants.%CompleteClass.1] // CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc6_23.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc6_23.2: type = converted %int.make_type_32, %.loc6_23.1 [template = i32] -// CHECK:STDOUT: %.loc6_23.3: init type = call %CompleteClass.ref(%.loc6_23.2) [template = constants.%CompleteClass.3] -// CHECK:STDOUT: %.loc6_27.1: type = value_of_initializer %.loc6_23.3 [template = constants.%CompleteClass.3] -// CHECK:STDOUT: %.loc6_27.2: type = converted %.loc6_23.3, %.loc6_27.1 [template = constants.%CompleteClass.3] +// CHECK:STDOUT: %.loc11_23.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc11_23.2: type = converted %int.make_type_32, %.loc11_23.1 [template = i32] +// CHECK:STDOUT: %.loc11_23.3: init type = call %CompleteClass.ref(%.loc11_23.2) [template = constants.%CompleteClass.3] +// CHECK:STDOUT: %.loc11_27.1: type = value_of_initializer %.loc11_23.3 [template = constants.%CompleteClass.3] +// CHECK:STDOUT: %.loc11_27.2: type = converted %.loc11_23.3, %.loc11_27.1 [template = constants.%CompleteClass.3] // CHECK:STDOUT: %v.var: ref %CompleteClass.3 = var v // CHECK:STDOUT: %v: ref %CompleteClass.3 = bind_name v, %v.var // CHECK:STDOUT: %F.ref: %F.type.4 = name_ref F, imports.%import_ref.3 [template = constants.%F.4] -// CHECK:STDOUT: %.loc6_7: ref %CompleteClass.3 = splice_block %v.var {} -// CHECK:STDOUT: %F.call: init %CompleteClass.3 = call %F.ref() to %.loc6_7 +// CHECK:STDOUT: %.loc11_7: ref %CompleteClass.3 = splice_block %v.var {} +// CHECK:STDOUT: %F.call: init %CompleteClass.3 = call %F.ref() to %.loc11_7 // CHECK:STDOUT: assign %v.var, %F.call // CHECK:STDOUT: %v.ref: ref %CompleteClass.3 = name_ref v, %v -// CHECK:STDOUT: %n.ref: %.3 = name_ref n, imports.%import_ref.6 [template = imports.%.1] -// CHECK:STDOUT: %.loc12: i32 = class_element_access , element0 [template = ] -// CHECK:STDOUT: return +// CHECK:STDOUT: %n.ref: %.4 = name_ref n, imports.%import_ref.6 [template = imports.%.1] +// CHECK:STDOUT: %.loc12_11.1: ref i32 = class_element_access %v.ref, element0 +// CHECK:STDOUT: %.loc12_11.2: i32 = bind_value %.loc12_11.1 +// CHECK:STDOUT: return %.loc12_11.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.1(constants.%T: type) { -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: -// CHECK:STDOUT: fn() -> i32; -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2() -> %CompleteClass.3; -// CHECK:STDOUT: // CHECK:STDOUT: specific @CompleteClass(constants.%T) { // CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %CompleteClass => constants.%CompleteClass.2 -// CHECK:STDOUT: %.1 => constants.%.3 -// CHECK:STDOUT: %F.type => constants.%F.type.2 -// CHECK:STDOUT: %F => constants.%F.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @CompleteClass(@CompleteClass.%T) { @@ -651,6 +536,8 @@ class Class(U:! type) { // CHECK:STDOUT: %F => constants.%F.3 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(i32) {} +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_generic_arg_mismatch.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -675,9 +562,9 @@ class Class(U:! type) { // CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @CompleteClass(%.4) [template] // CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] // CHECK:STDOUT: %.6: type = ptr_type %.2 [template] -// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, @CompleteClass(i32) [template] // CHECK:STDOUT: %F.type.4: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [template] +// CHECK:STDOUT: %CompleteClass.4: type = class_type @CompleteClass, @CompleteClass(i32) [template] // CHECK:STDOUT: %.7: type = unbound_element_type %CompleteClass.4, i32 [template] // CHECK:STDOUT: %F.type.5: type = fn_type @F.1, @CompleteClass(i32) [template] // CHECK:STDOUT: %F.5: %F.type.5 = struct_value () [template] diff --git a/toolchain/check/testdata/class/import.carbon b/toolchain/check/testdata/class/import.carbon index 8896ee5dce75..4b4c2936e88b 100644 --- a/toolchain/check/testdata/class/import.carbon +++ b/toolchain/check/testdata/class/import.carbon @@ -162,12 +162,12 @@ fn Run() { // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %ForwardDeclared.1: type = class_type @ForwardDeclared.1 [template] // CHECK:STDOUT: %struct.3: %ForwardDeclared.1 = struct_value () [template] -// CHECK:STDOUT: %ForwardDeclared.2: type = class_type @ForwardDeclared.2 [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.9: type = ptr_type %ForwardDeclared.1 [template] +// CHECK:STDOUT: %ForwardDeclared.2: type = class_type @ForwardDeclared.2 [template] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.9: type = ptr_type %ForwardDeclared.1 [template] // CHECK:STDOUT: %Incomplete: type = class_type @Incomplete [template] // CHECK:STDOUT: %.10: type = ptr_type %Incomplete [template] // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/declaration/import.carbon b/toolchain/check/testdata/function/declaration/import.carbon index e604e431f4a5..a83174da6636 100644 --- a/toolchain/check/testdata/function/declaration/import.carbon +++ b/toolchain/check/testdata/function/declaration/import.carbon @@ -559,9 +559,9 @@ import library "extern_api"; // CHECK:STDOUT: %B: %B.type = struct_value () [template] // CHECK:STDOUT: %.2: i32 = int_literal 1 [template] // CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %C.type: type = fn_type @C [template] // CHECK:STDOUT: %C: %C.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %tuple: %.4 = tuple_value (%.2) [template] // CHECK:STDOUT: %D.type: type = fn_type @D [template] // CHECK:STDOUT: %D: %D.type = struct_value () [template] @@ -989,9 +989,9 @@ import library "extern_api"; // CHECK:STDOUT: %B: %B.type = struct_value () [template] // CHECK:STDOUT: %.2: i32 = int_literal 1 [template] // CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %C.type: type = fn_type @C [template] // CHECK:STDOUT: %C: %C.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %tuple: %.4 = tuple_value (%.2) [template] // CHECK:STDOUT: %D.type: type = fn_type @D [template] // CHECK:STDOUT: %D: %D.type = struct_value () [template] @@ -1118,9 +1118,9 @@ import library "extern_api"; // CHECK:STDOUT: %B: %B.type = struct_value () [template] // CHECK:STDOUT: %.2: i32 = int_literal 1 [template] // CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %C.type: type = fn_type @C [template] // CHECK:STDOUT: %C: %C.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %tuple: %.4 = tuple_value (%.2) [template] // CHECK:STDOUT: %D.type: type = fn_type @D [template] // CHECK:STDOUT: %D: %D.type = struct_value () [template] diff --git a/toolchain/check/testdata/function/declaration/no_prelude/fail_import_incomplete_return.carbon b/toolchain/check/testdata/function/declaration/no_prelude/fail_import_incomplete_return.carbon index 0209183ce898..b55884ab7b38 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/fail_import_incomplete_return.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/fail_import_incomplete_return.carbon @@ -172,15 +172,15 @@ fn CallFAndGIncomplete() { // CHECK:STDOUT: %CallFAndGIncomplete.type: type = fn_type @CallFAndGIncomplete [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %CallFAndGIncomplete: %CallFAndGIncomplete.type = struct_value () [template] -// CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %ReturnCUnused.type: type = fn_type @ReturnCUnused [template] // CHECK:STDOUT: %ReturnCUnused: %ReturnCUnused.type = struct_value () [template] +// CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %ReturnCUsed.type: type = fn_type @ReturnCUsed [template] // CHECK:STDOUT: %ReturnCUsed: %ReturnCUsed.type = struct_value () [template] -// CHECK:STDOUT: %D: type = class_type @D [template] -// CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %ReturnDUnused.type: type = fn_type @ReturnDUnused [template] // CHECK:STDOUT: %ReturnDUnused: %ReturnDUnused.type = struct_value () [template] +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %ReturnDUsed.type: type = fn_type @ReturnDUsed [template] // CHECK:STDOUT: %ReturnDUsed: %ReturnDUsed.type = struct_value () [template] diff --git a/toolchain/check/testdata/function/definition/import.carbon b/toolchain/check/testdata/function/definition/import.carbon index 7adaffb91a32..a3abeb7761aa 100644 --- a/toolchain/check/testdata/function/definition/import.carbon +++ b/toolchain/check/testdata/function/definition/import.carbon @@ -235,9 +235,9 @@ fn D() {} // CHECK:STDOUT: %B: %B.type = struct_value () [template] // CHECK:STDOUT: %.2: i32 = int_literal 1 [template] // CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %C.type: type = fn_type @C [template] // CHECK:STDOUT: %C: %C.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] // CHECK:STDOUT: %tuple: %.4 = tuple_value (%.2) [template] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index 9fd2cdd0f2ea..3eb3de03f87b 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -118,7 +118,7 @@ impl C as AddWith(C) { // CHECK:STDOUT: %import_ref.2 = import_ref Main//a, inst+12, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref Main//a, inst+10, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//a, inst+16, unloaded -// CHECK:STDOUT: %import_ref.5: %F.type.2 = import_ref Main//a, inst+12, loaded [template = constants.%F.1] +// CHECK:STDOUT: %import_ref.5: @AddWith.%F.type (%F.type.2) = import_ref Main//a, inst+12, loaded [symbolic = @AddWith.%F (constants.%F.1)] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/namespace/merging_with_indirections.carbon b/toolchain/check/testdata/namespace/merging_with_indirections.carbon index 543ac104f145..106e7a312e52 100644 --- a/toolchain/check/testdata/namespace/merging_with_indirections.carbon +++ b/toolchain/check/testdata/namespace/merging_with_indirections.carbon @@ -153,10 +153,10 @@ fn Run() { // CHECK:STDOUT: %Run.type: type = fn_type @Run [template] // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Run: %Run.type = struct_value () [template] -// CHECK:STDOUT: %A: type = class_type @A [template] -// CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %A: type = class_type @A [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/operators/overloaded/add.carbon b/toolchain/check/testdata/operators/overloaded/add.carbon index 4f672f53accd..071b184ab640 100644 --- a/toolchain/check/testdata/operators/overloaded/add.carbon +++ b/toolchain/check/testdata/operators/overloaded/add.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/bit_and.carbon b/toolchain/check/testdata/operators/overloaded/bit_and.carbon index f24cb300430b..22d3a743dc73 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_and.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_and.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/bit_or.carbon b/toolchain/check/testdata/operators/overloaded/bit_or.carbon index b0272dbe820f..df1721eaa301 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_or.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_or.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/bit_xor.carbon b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon index 10a5918591ef..5dbd773d1133 100644 --- a/toolchain/check/testdata/operators/overloaded/bit_xor.carbon +++ b/toolchain/check/testdata/operators/overloaded/bit_xor.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/dec.carbon b/toolchain/check/testdata/operators/overloaded/dec.carbon index ae6fbe9ccbe8..e76ae309987f 100644 --- a/toolchain/check/testdata/operators/overloaded/dec.carbon +++ b/toolchain/check/testdata/operators/overloaded/dec.carbon @@ -34,9 +34,9 @@ fn TestOp() { // CHECK:STDOUT: %Op.type.1: type = fn_type @Op.1 [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %Self [symbolic] // CHECK:STDOUT: %Op.type.2: type = fn_type @Op.2 [template] // CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %Self [symbolic] // CHECK:STDOUT: %.6: = interface_witness (%Op.1) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/div.carbon b/toolchain/check/testdata/operators/overloaded/div.carbon index c121c27c4688..4a279f6a2274 100644 --- a/toolchain/check/testdata/operators/overloaded/div.carbon +++ b/toolchain/check/testdata/operators/overloaded/div.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon index a8634cc25aec..97c47cf84af5 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_assign_non_ref.carbon @@ -51,17 +51,17 @@ fn TestAddAssignNonRef(a: C, b: C) { // CHECK:STDOUT: %Op.type.1: type = fn_type @Op.1 [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %Self.1 [symbolic] // CHECK:STDOUT: %Op.type.2: type = fn_type @Op.2 [template] // CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %Self.1 [symbolic] // CHECK:STDOUT: %.6: = interface_witness (%Op.1) [template] // CHECK:STDOUT: %.7: type = interface_type @AddAssign [template] // CHECK:STDOUT: %Self.2: %.7 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestIncNonRef.type: type = fn_type @TestIncNonRef [template] // CHECK:STDOUT: %TestIncNonRef: %TestIncNonRef.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon index 57bb9d4eae84..a1db9fe4b42a 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl.carbon @@ -69,16 +69,16 @@ fn TestRef(b: C) { // CHECK:STDOUT: %struct: %C = struct_value () [template] // CHECK:STDOUT: %.10: type = interface_type @AddAssign [template] // CHECK:STDOUT: %Self.3: %.10 = bind_symbolic_name Self 0 [symbolic] -// CHECK:STDOUT: %.11: type = ptr_type %Self.3 [symbolic] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] +// CHECK:STDOUT: %.11: type = ptr_type %Self.3 [symbolic] // CHECK:STDOUT: %.12: type = assoc_entity_type @AddAssign, %Op.type.3 [template] // CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.15 [template] // CHECK:STDOUT: %.14: type = interface_type @Inc [template] // CHECK:STDOUT: %Self.4: %.14 = bind_symbolic_name Self 0 [symbolic] -// CHECK:STDOUT: %.15: type = ptr_type %Self.4 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.15: type = ptr_type %Self.4 [symbolic] // CHECK:STDOUT: %.16: type = assoc_entity_type @Inc, %Op.type.4 [template] // CHECK:STDOUT: %.17: %.16 = assoc_entity element0, imports.%import_ref.20 [template] // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon index a2298d865e9e..0c406ca515ef 100644 --- a/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon +++ b/toolchain/check/testdata/operators/overloaded/fail_no_impl_for_arg.carbon @@ -61,9 +61,9 @@ fn TestAssign(b: D) { // CHECK:STDOUT: %.6: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.7: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.7: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.8: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %Test.type: type = fn_type @Test [template] // CHECK:STDOUT: %Test: %Test.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/inc.carbon b/toolchain/check/testdata/operators/overloaded/inc.carbon index 1caaf7119230..95ac2945ccb5 100644 --- a/toolchain/check/testdata/operators/overloaded/inc.carbon +++ b/toolchain/check/testdata/operators/overloaded/inc.carbon @@ -34,9 +34,9 @@ fn TestOp() { // CHECK:STDOUT: %Op.type.1: type = fn_type @Op.1 [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %Self [symbolic] // CHECK:STDOUT: %Op.type.2: type = fn_type @Op.2 [template] // CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template] +// CHECK:STDOUT: %.5: type = ptr_type %Self [symbolic] // CHECK:STDOUT: %.6: = interface_witness (%Op.1) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/left_shift.carbon b/toolchain/check/testdata/operators/overloaded/left_shift.carbon index 7fcec7dff794..dcc1eabec122 100644 --- a/toolchain/check/testdata/operators/overloaded/left_shift.carbon +++ b/toolchain/check/testdata/operators/overloaded/left_shift.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/mod.carbon b/toolchain/check/testdata/operators/overloaded/mod.carbon index b399cbc84435..a61037c553a2 100644 --- a/toolchain/check/testdata/operators/overloaded/mod.carbon +++ b/toolchain/check/testdata/operators/overloaded/mod.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/mul.carbon b/toolchain/check/testdata/operators/overloaded/mul.carbon index 0cf4d35d18ab..2445bb3d8e55 100644 --- a/toolchain/check/testdata/operators/overloaded/mul.carbon +++ b/toolchain/check/testdata/operators/overloaded/mul.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/right_shift.carbon b/toolchain/check/testdata/operators/overloaded/right_shift.carbon index 5a9d0fab1af9..db0f61163f52 100644 --- a/toolchain/check/testdata/operators/overloaded/right_shift.carbon +++ b/toolchain/check/testdata/operators/overloaded/right_shift.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/operators/overloaded/sub.carbon b/toolchain/check/testdata/operators/overloaded/sub.carbon index 428224cd4a20..8559b85d65d9 100644 --- a/toolchain/check/testdata/operators/overloaded/sub.carbon +++ b/toolchain/check/testdata/operators/overloaded/sub.carbon @@ -51,9 +51,9 @@ fn TestAssign(a: C*, b: C) { // CHECK:STDOUT: %.7: type = ptr_type %C [template] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.3 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] -// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %Op.type.4: type = fn_type @Op.4 [template] // CHECK:STDOUT: %Op.4: %Op.type.4 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Self.2 [symbolic] // CHECK:STDOUT: %.9: = interface_witness (%Op.3) [template] // CHECK:STDOUT: %TestOp.type: type = fn_type @TestOp [template] // CHECK:STDOUT: %TestOp: %TestOp.type = struct_value () [template] diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 86ea05b7f85d..0f39e25334ee 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -380,10 +380,10 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %.5: i32 = int_literal 2 [template] // CHECK:STDOUT: %.6: type = struct_type {.c: i32, .d: i32} [template] // CHECK:STDOUT: %.7: type = ptr_type %.3 [template] -// CHECK:STDOUT: %struct: %.3 = struct_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %struct: %.3 = struct_value (%.4, %.5) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct) [template] // CHECK:STDOUT: %.8: type = ptr_type %.2 [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -475,12 +475,12 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: %struct.1: %.3 = struct_value (%.4, %.5) [template] // CHECK:STDOUT: %C.3: type = class_type @C, @C(%struct.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %struct.2: %.3 = struct_value (%.9, %.8) [template] // CHECK:STDOUT: %C.4: type = class_type @C, @C(%struct.2) [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { diff --git a/toolchain/check/testdata/tuples/import.carbon b/toolchain/check/testdata/tuples/import.carbon index ce160f8c773b..db4aa3851701 100644 --- a/toolchain/check/testdata/tuples/import.carbon +++ b/toolchain/check/testdata/tuples/import.carbon @@ -420,10 +420,10 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %.6: i32 = int_literal 3 [template] // CHECK:STDOUT: %.7: type = tuple_type (i32, i32, i32) [template] // CHECK:STDOUT: %.8: type = ptr_type %.3 [template] -// CHECK:STDOUT: %tuple: %.3 = tuple_value (%.4, %.5) [template] -// CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple) [template] // CHECK:STDOUT: %F.type: type = fn_type @F [template] // CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %tuple: %.3 = tuple_value (%.4, %.5) [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple) [template] // CHECK:STDOUT: %.9: type = ptr_type %.2 [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -516,12 +516,12 @@ var c_bad: C((3, 4)) = F(); // CHECK:STDOUT: %tuple.1: %.3 = tuple_value (%.4, %.5) [template] // CHECK:STDOUT: %C.3: type = class_type @C, @C(%tuple.1) [template] // CHECK:STDOUT: %.7: type = ptr_type %.2 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: %.8: i32 = int_literal 2 [template] // CHECK:STDOUT: %.9: i32 = int_literal 1 [template] // CHECK:STDOUT: %tuple.2: %.3 = tuple_value (%.9, %.8) [template] // CHECK:STDOUT: %C.4: type = class_type @C, @C(%tuple.2) [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports {