diff --git a/toolchain/check/call.cpp b/toolchain/check/call.cpp index f185f9432bff..b7fb78549906 100644 --- a/toolchain/check/call.cpp +++ b/toolchain/check/call.cpp @@ -8,6 +8,8 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/function.h" +#include "toolchain/check/generic.h" +#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/typed_insts.h" @@ -22,11 +24,16 @@ static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id, -> SemIR::InstId { auto& class_info = context.classes().Get(class_id); + // TODO: Pass in information about the specific in which the generic class + // name was found. + // TODO: Perform argument deduction. + auto specific_id = SemIR::GenericInstanceId::Invalid; + // Convert the arguments to match the parameters. auto converted_args_id = ConvertCallArgs( context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids, /*return_storage_id=*/SemIR::InstId::Invalid, class_info.decl_id, - class_info.implicit_param_refs_id, class_info.param_refs_id); + specific_id, class_info.implicit_param_refs_id, class_info.param_refs_id); return context.AddInst(node_id, {.type_id = SemIR::TypeId::TypeType, .callee_id = callee_id, @@ -44,11 +51,17 @@ static auto PerformCallToGenericInterface(Context& context, -> SemIR::InstId { auto& interface_info = context.interfaces().Get(interface_id); + // TODO: Pass in information about the specific in which the generic interface + // name was found. + // TODO: Perform argument deduction. + auto specific_id = SemIR::GenericInstanceId::Invalid; + // Convert the arguments to match the parameters. auto converted_args_id = ConvertCallArgs( context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids, /*return_storage_id=*/SemIR::InstId::Invalid, interface_info.decl_id, - interface_info.implicit_param_refs_id, interface_info.param_refs_id); + specific_id, interface_info.implicit_param_refs_id, + interface_info.param_refs_id); return context.AddInst(node_id, {.type_id = SemIR::TypeId::TypeType, .callee_id = callee_id, @@ -87,15 +100,32 @@ auto PerformCall(Context& context, Parse::NodeId node_id, } auto& callable = context.functions().Get(callee_function.function_id); + // TODO: Properly determine the generic argument values for the call. For now, + // we do so only if the function introduces no generic parameters beyond those + // of the enclosing context. + auto specific_id = SemIR::GenericInstanceId::Invalid; + if (callee_function.instance_id.is_valid()) { + auto enclosing_args_id = + context.generic_instances().Get(callee_function.instance_id).args_id; + auto fn_params_id = context.generics().Get(callable.generic_id).bindings_id; + if (context.inst_blocks().Get(fn_params_id).size() == + context.inst_blocks().Get(enclosing_args_id).size()) { + specific_id = + MakeGenericInstance(context, callable.generic_id, enclosing_args_id); + } + } + // For functions with an implicit return type, the return type is the empty // tuple type. - SemIR::TypeId type_id = callable.declared_return_type(context.sem_ir()); + SemIR::TypeId type_id = + callable.GetDeclaredReturnType(context.sem_ir(), specific_id); if (!type_id.is_valid()) { type_id = context.GetTupleType({}); } // If there is a return slot, build storage for the result. SemIR::InstId return_storage_id = SemIR::InstId::Invalid; + SemIR::Function::ReturnSlot return_slot; { DiagnosticAnnotationScope annotate_diagnostics( &context.emitter(), [&](auto& builder) { @@ -103,9 +133,10 @@ auto PerformCall(Context& context, Parse::NodeId node_id, "Return type declared here."); builder.Note(callable.return_storage_id, IncompleteReturnTypeHere); }); - CheckFunctionReturnType(context, callee_id, callable); + return_slot = + CheckFunctionReturnType(context, callee_id, callable, specific_id); } - switch (callable.return_slot) { + switch (return_slot) { case SemIR::Function::ReturnSlot::Present: // Tentatively put storage for a temporary in the function's return slot. // This will be replaced if necessary when we perform initialization. @@ -125,7 +156,7 @@ auto PerformCall(Context& context, Parse::NodeId node_id, // Convert the arguments to match the parameters. auto converted_args_id = ConvertCallArgs(context, node_id, callee_function.self_id, arg_ids, - return_storage_id, callable.decl_id, + return_storage_id, callable.decl_id, specific_id, callable.implicit_param_refs_id, callable.param_refs_id); auto call_inst_id = context.AddInst(node_id, {.type_id = type_id, diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 7c871772ef46..abff033608e9 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -1084,8 +1084,10 @@ auto Context::GetBuiltinType(SemIR::BuiltinInstKind kind) -> SemIR::TypeId { return type_id; } -auto Context::GetFunctionType(SemIR::FunctionId fn_id) -> SemIR::TypeId { - return GetCompleteTypeImpl(*this, fn_id); +auto Context::GetFunctionType(SemIR::FunctionId fn_id, + SemIR::GenericInstanceId instance_id) + -> SemIR::TypeId { + return GetCompleteTypeImpl(*this, fn_id, instance_id); } auto Context::GetGenericClassType(SemIR::ClassId class_id) -> SemIR::TypeId { diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 508a5a8bd69a..a60047176255 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -288,7 +288,8 @@ class Context { auto GetBuiltinType(SemIR::BuiltinInstKind kind) -> SemIR::TypeId; // Gets a function type. The returned type will be complete. - auto GetFunctionType(SemIR::FunctionId fn_id) -> SemIR::TypeId; + auto GetFunctionType(SemIR::FunctionId fn_id, + SemIR::GenericInstanceId instance_id) -> SemIR::TypeId; // Gets a generic class type, which is the type of a name of a generic class, // such as the type of `Vector` given `class Vector(T:! type)`. The returned diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index f680379e3697..98d79e78d4da 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -14,6 +14,8 @@ #include "toolchain/check/context.h" #include "toolchain/sem_ir/copy_on_write_block.h" #include "toolchain/sem_ir/file.h" +#include "toolchain/sem_ir/generic.h" +#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/typed_insts.h" @@ -1117,6 +1119,7 @@ CARBON_DIAGNOSTIC(InCallToFunction, Note, "Calling function declared here."); // Convert the object argument in a method call to match the `self` parameter. static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id, SemIR::InstId callee_id, + SemIR::GenericInstanceId callee_specific_id, std::optional addr_pattern, SemIR::InstId self_param_id, SemIR::Param self_param, SemIR::InstId self_id) -> SemIR::InstId { @@ -1163,14 +1166,17 @@ static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id, .lvalue_id = self_or_addr_id}); } - return ConvertToValueOfType(context, call_loc_id, self_or_addr_id, - self_param.type_id); + return ConvertToValueOfType( + context, call_loc_id, self_or_addr_id, + SemIR::GetTypeInInstance(context.sem_ir(), callee_specific_id, + self_param.type_id)); } auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id, SemIR::InstId self_id, llvm::ArrayRef arg_refs, SemIR::InstId return_storage_id, SemIR::InstId callee_id, + SemIR::GenericInstanceId callee_specific_id, SemIR::InstBlockId implicit_param_refs_id, SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId { auto implicit_param_refs = @@ -1204,8 +1210,8 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id, context.sem_ir(), implicit_param_id); if (param.name_id == SemIR::NameId::SelfValue) { auto converted_self_id = - ConvertSelf(context, call_loc_id, callee_id, addr_pattern, param_id, - param, self_id); + ConvertSelf(context, call_loc_id, callee_id, callee_specific_id, + addr_pattern, param_id, param, self_id); if (converted_self_id == SemIR::InstId::BuiltinError) { return SemIR::InstBlockId::Invalid; } @@ -1230,7 +1236,9 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id, for (auto [i, arg_id, param_id] : llvm::enumerate(arg_refs, param_refs)) { diag_param_index = i; - auto param_type_id = context.insts().Get(param_id).type_id(); + auto param_type_id = + SemIR::GetTypeInInstance(context.sem_ir(), callee_specific_id, + context.insts().Get(param_id).type_id()); // TODO: Convert to the proper expression category. For now, we assume // parameters are all `let` bindings. auto converted_arg_id = diff --git a/toolchain/check/convert.h b/toolchain/check/convert.h index ac7cbf295dd4..1f49a309ef2c 100644 --- a/toolchain/check/convert.h +++ b/toolchain/check/convert.h @@ -7,6 +7,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/pending_block.h" +#include "toolchain/sem_ir/ids.h" namespace Carbon::Check { @@ -95,6 +96,7 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id, SemIR::InstId self_id, llvm::ArrayRef arg_refs, SemIR::InstId return_storage_id, SemIR::InstId callee_id, + SemIR::GenericInstanceId callee_specific_id, SemIR::InstBlockId implicit_param_refs_id, SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId; diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 3e83388c6170..7db8c621d46b 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1188,6 +1188,9 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, case SemIR::ClassType::Kind: return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::ClassType::instance_id); + case SemIR::FunctionType::Kind: + return RebuildIfFieldsAreConstant(eval_context, inst, + &SemIR::FunctionType::instance_id); case SemIR::InterfaceType::Kind: return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::InterfaceType::instance_id); @@ -1252,7 +1255,6 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id, return RebuildInitAsValue(eval_context, inst, SemIR::TupleValue::Kind); case SemIR::BuiltinInst::Kind: - case SemIR::FunctionType::Kind: case SemIR::GenericClassType::Kind: case SemIR::GenericInterfaceType::Kind: // Builtins are always template constants. diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index eeecf30c58e8..76fd8fb6ba85 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -21,9 +21,12 @@ auto CheckFunctionTypeMatches(Context& context, return false; } - auto new_return_type_id = new_function.declared_return_type(context.sem_ir()); - auto prev_return_type_id = - prev_function.declared_return_type(context.sem_ir()); + // TODO: Pass a specific ID for `prev_function` instead of substitutions and + // use it here. + auto new_return_type_id = + new_function.GetDeclaredReturnType(context.sem_ir()); + auto prev_return_type_id = prev_function.GetDeclaredReturnType( + context.sem_ir(), SemIR::GenericInstanceId::Invalid); if (new_return_type_id == SemIR::TypeId::Error || prev_return_type_id == SemIR::TypeId::Error) { return false; @@ -68,19 +71,23 @@ auto CheckFunctionTypeMatches(Context& context, } auto CheckFunctionReturnType(Context& context, SemIRLoc loc, - SemIR::Function& function) -> void { + SemIR::Function& function, + SemIR::GenericInstanceId specific_id) + -> SemIR::Function::ReturnSlot { // If we have already checked the return type, we have nothing to do. - if (function.return_slot != SemIR::Function::ReturnSlot::NotComputed) { - return; + if (function.return_slot != SemIR::Function::ReturnSlot::NotComputed && + !specific_id.is_valid()) { + return function.return_slot; } if (!function.return_storage_id.is_valid()) { // Implicit `-> ()` has no return slot. function.return_slot = SemIR::Function::ReturnSlot::Absent; - return; + return function.return_slot; } - auto return_type_id = function.declared_return_type(context.sem_ir()); + auto return_type_id = + function.GetDeclaredReturnType(context.sem_ir(), specific_id); CARBON_CHECK(return_type_id.is_valid()) << "Have return storage but no return type."; @@ -92,18 +99,23 @@ auto CheckFunctionReturnType(Context& context, SemIRLoc loc, return context.emitter().Build(loc, IncompleteTypeInFunctionReturnType, return_type_id); }; + SemIR::Function::ReturnSlot result; if (!context.TryToCompleteType( return_type_id, function.return_slot == SemIR::Function::ReturnSlot::Error ? std::nullopt : std::optional(diagnose_incomplete_return_type))) { - function.return_slot = SemIR::Function::ReturnSlot::Error; + result = SemIR::Function::ReturnSlot::Error; } else if (SemIR::GetInitRepr(context.sem_ir(), return_type_id) .has_return_slot()) { - function.return_slot = SemIR::Function::ReturnSlot::Present; + result = SemIR::Function::ReturnSlot::Present; } else { - function.return_slot = SemIR::Function::ReturnSlot::Absent; + result = SemIR::Function::ReturnSlot::Absent; } + if (!specific_id.is_valid()) { + function.return_slot = result; + } + return result; } } // namespace Carbon::Check diff --git a/toolchain/check/function.h b/toolchain/check/function.h index 44de24bc0928..caf93ada44e6 100644 --- a/toolchain/check/function.h +++ b/toolchain/check/function.h @@ -39,7 +39,9 @@ auto CheckFunctionTypeMatches(Context& context, // error if not. This computes the return slot usage for the function if // necessary. auto CheckFunctionReturnType(Context& context, SemIRLoc loc, - SemIR::Function& function) -> void; + SemIR::Function& function, + SemIR::GenericInstanceId specific_id) + -> SemIR::Function::ReturnSlot; } // namespace Carbon::Check diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 69b035f1be17..4b35f671f6ac 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -277,18 +277,8 @@ static auto BuildFunctionDecl(Context& context, FinishGenericRedecl(context, decl_id, function_info.generic_id); // TODO: Validate that the redeclaration doesn't set an access modifier. } - function_decl.type_id = context.GetFunctionType(function_decl.function_id); - - // TODO: Temporarily replace the return type with the canonical return type. - // This is a placeholder to avoid breaking tests before generic type - // substitution is ready. - if (return_storage_id.is_valid()) { - auto return_storage = context.insts().Get(return_storage_id); - return_storage.SetType(SemIR::GetTypeInInstance( - context.sem_ir(), SemIR::GenericInstanceId::Invalid, - return_storage.type_id())); - context.sem_ir().insts().Set(return_storage_id, return_storage); - } + function_decl.type_id = context.GetFunctionType( + function_decl.function_id, context.scope_stack().PeekSpecificId()); // Write the function ID into the FunctionDecl. context.ReplaceInstBeforeConstantUse(decl_id, function_decl); @@ -312,7 +302,7 @@ static auto BuildFunctionDecl(Context& context, } if (SemIR::IsEntryPoint(context.sem_ir(), function_decl.function_id)) { - auto return_type_id = function_info.declared_return_type(context.sem_ir()); + auto return_type_id = function_info.GetDeclaredReturnType(context.sem_ir()); // TODO: Update this once valid signatures for the entry point are decided. if (function_info.implicit_param_refs_id.is_valid() || !function_info.param_refs_id.is_valid() || @@ -357,7 +347,8 @@ static auto HandleFunctionDefinitionAfterSignature( context.AddCurrentCodeBlockToFunction(); // Check the return type is complete. - CheckFunctionReturnType(context, function.return_storage_id, function); + CheckFunctionReturnType(context, function.return_storage_id, function, + SemIR::GenericInstanceId::Invalid); // Check the parameter types are complete. for (auto param_id : llvm::concat( @@ -497,7 +488,7 @@ static auto IsValidBuiltinDeclaration(Context& context, } // Get the return type. This is `()` if none was specified. - auto return_type_id = function.declared_return_type(context.sem_ir()); + auto return_type_id = function.GetDeclaredReturnType(context.sem_ir()); if (!return_type_id.is_valid()) { return_type_id = context.GetTupleType({}); } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 289ccfc1c658..69c05ce2ed16 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -8,6 +8,7 @@ #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/eval.h" +#include "toolchain/check/generic.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/file.h" @@ -1104,7 +1105,7 @@ class ImportRefResolver { auto return_type_const_id = SemIR::ConstantId::Invalid; if (function.return_storage_id.is_valid()) { return_type_const_id = - GetLocalConstantId(function.declared_return_type(import_ir_)); + GetLocalConstantId(function.GetDeclaredReturnType(import_ir_)); } auto parent_scope_id = GetLocalNameScopeId(function.parent_scope_id); llvm::SmallVector implicit_param_const_ids = @@ -1158,7 +1159,10 @@ class ImportRefResolver { .definition_id = function.definition_id.is_valid() ? function_decl_id : SemIR::InstId::Invalid}); - function_decl.type_id = context_.GetFunctionType(function_decl.function_id); + // TODO: Import this or recompute it. + auto specific_id = SemIR::GenericInstanceId::Invalid; + function_decl.type_id = + context_.GetFunctionType(function_decl.function_id, specific_id); // Write the function ID into the FunctionDecl. context_.ReplaceInstBeforeConstantUse(function_decl_id, function_decl); return {.const_id = context_.constant_values().Get(function_decl_id)}; @@ -1174,6 +1178,8 @@ class ImportRefResolver { } auto fn_val = context_.insts().Get(fn_val_id); CARBON_CHECK(context_.types().Is(fn_val.type_id())); + // TODO: Import the correct generic instance and build a function type + // constant using it. return {.const_id = context_.types().GetConstantId(fn_val.type_id())}; } diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index e93966755da7..68f9a6d410d2 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -171,6 +171,8 @@ static auto CheckRedeclParam(Context& context, .Emit(); }; + // TODO: Pass in a specific ID for the previous declaration instead of + // substitutions. auto new_param_ref = context.insts().Get(new_param_ref_id); auto prev_param_ref = context.insts().Get(prev_param_ref_id); if (new_param_ref.kind() != prev_param_ref.kind() || diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index 9af50d88c9ab..33333eff97aa 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -58,7 +58,7 @@ auto CheckReturnedVar(Context& context, Parse::NodeId returned_node, -> SemIR::InstId { // A `returned var` requires an explicit return type. auto& function = GetCurrentFunction(context); - auto return_type_id = function.declared_return_type(context.sem_ir()); + auto return_type_id = function.GetDeclaredReturnType(context.sem_ir()); if (!return_type_id.is_valid()) { CARBON_DIAGNOSTIC(ReturnedVarWithNoReturnType, Error, "Cannot declare a `returned var` in this function."); @@ -106,7 +106,7 @@ auto RegisterReturnedVar(Context& context, SemIR::InstId bind_id) -> void { auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id) -> void { const auto& function = GetCurrentFunction(context); - auto return_type_id = function.declared_return_type(context.sem_ir()); + auto return_type_id = function.GetDeclaredReturnType(context.sem_ir()); if (return_type_id.is_valid()) { CARBON_DIAGNOSTIC(ReturnStatementMissingExpr, Error, @@ -124,7 +124,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, const auto& function = GetCurrentFunction(context); auto returned_var_id = GetCurrentReturnedVar(context); auto return_slot_id = SemIR::InstId::Invalid; - auto return_type_id = function.declared_return_type(context.sem_ir()); + auto return_type_id = function.GetDeclaredReturnType(context.sem_ir()); if (!return_type_id.is_valid()) { CARBON_DIAGNOSTIC( diff --git a/toolchain/check/scope_stack.cpp b/toolchain/check/scope_stack.cpp index ebb94fb5279b..0e0837fe97f6 100644 --- a/toolchain/check/scope_stack.cpp +++ b/toolchain/check/scope_stack.cpp @@ -16,12 +16,19 @@ auto ScopeStack::VerifyOnFinish() -> void { auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id, SemIR::GenericInstanceId instance_id, bool lexical_lookup_has_load_error) -> void { + // If this scope doesn't have a specific of its own, it lives in the enclosing + // scope's specific, if any. + auto enclosing_instance_id = instance_id; + if (!instance_id.is_valid() && !scope_stack_.empty()) { + enclosing_instance_id = PeekSpecificId(); + } + compile_time_binding_stack_.PushArray(); scope_stack_.push_back( {.index = next_scope_index_, .scope_inst_id = scope_inst_id, .scope_id = scope_id, - .instance_id = instance_id, + .instance_id = enclosing_instance_id, .next_compile_time_bind_index = SemIR::CompileTimeBindIndex( compile_time_binding_stack_.all_values_size()), .lexical_lookup_has_load_error = @@ -29,7 +36,7 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id, if (scope_id.is_valid()) { non_lexical_scope_stack_.push_back({.scope_index = next_scope_index_, .name_scope_id = scope_id, - .instance_id = instance_id}); + .instance_id = enclosing_instance_id}); } else { // For lexical lookups, unqualified lookup doesn't know how to find the // associated generic instance, so if we start adding lexical scopes with diff --git a/toolchain/check/scope_stack.h b/toolchain/check/scope_stack.h index a0a3fdea3724..473ab5421f40 100644 --- a/toolchain/check/scope_stack.h +++ b/toolchain/check/scope_stack.h @@ -88,6 +88,14 @@ class ScopeStack { // there is no such instruction, such as for a block scope. auto PeekInstId() const -> SemIR::InstId { return Peek().scope_inst_id; } + // Returns the specific associated with the innermost enclosing scope that is + // associated with a specific. This will generally be the self specific of the + // innermost enclosing generic, as there is no way to enter any other specific + // scope. + auto PeekSpecificId() const -> SemIR::GenericInstanceId { + return Peek().instance_id; + } + // Returns the current scope, if it is of the specified kind. Otherwise, // returns nullopt. template diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon index 6ffacea27876..51325d692b8f 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon @@ -51,7 +51,7 @@ fn B() { // CHECK:STDOUT: insts: // CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)} -// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType} // CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+5': {kind: Return} @@ -129,13 +129,13 @@ fn B() { // CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1} // CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)} -// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType} // CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)} // CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name0, type: type(inst+10)} // CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)} -// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, type: typeTypeType} +// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)} // CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)} // CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)} diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon index 5990fdffb75c..3b1b8a85ec6f 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon @@ -51,7 +51,7 @@ fn B() { // CHECK:STDOUT: insts: // CHECK:STDOUT: 'inst+0': {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+1': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+2)} -// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+2': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+3': {kind: TupleType, arg0: type_block0, type: typeTypeType} // CHECK:STDOUT: 'inst+4': {kind: StructValue, arg0: empty, type: type(inst+2)} // CHECK:STDOUT: 'inst+5': {kind: Return} @@ -108,13 +108,13 @@ fn B() { // CHECK:STDOUT: 'inst+1': {kind: ImportDecl, arg0: name1} // CHECK:STDOUT: 'inst+2': {kind: Namespace, arg0: name_scope1, arg1: inst+1, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+3': {kind: FunctionDecl, arg0: function0, arg1: empty, type: type(inst+4)} -// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+4': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+5': {kind: TupleType, arg0: type_block0, type: typeTypeType} // CHECK:STDOUT: 'inst+6': {kind: StructValue, arg0: empty, type: type(inst+4)} // CHECK:STDOUT: 'inst+7': {kind: NameRef, arg0: name1, arg1: inst+2, type: type(instNamespaceType)} // CHECK:STDOUT: 'inst+8': {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name0, type: type(inst+10)} // CHECK:STDOUT: 'inst+9': {kind: FunctionDecl, arg0: function1, arg1: empty, type: type(inst+10)} -// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, type: typeTypeType} +// CHECK:STDOUT: 'inst+10': {kind: FunctionType, arg0: function1, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+11': {kind: StructValue, arg0: empty, type: type(inst+10)} // CHECK:STDOUT: 'inst+12': {kind: NameRef, arg0: name1, arg1: inst+8, type: type(inst+10)} // CHECK:STDOUT: 'inst+13': {kind: Call, arg0: inst+12, arg1: block5, type: type(inst+5)} diff --git a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon index 9d0ab4655985..9d8735cb93f7 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon @@ -60,7 +60,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: 'inst+12': {kind: Converted, arg0: inst+9, arg1: inst+8, type: typeTypeType} // CHECK:STDOUT: 'inst+13': {kind: VarStorage, arg0: nameReturnSlot, type: type(inst+8)} // CHECK:STDOUT: 'inst+14': {kind: FunctionDecl, arg0: function0, arg1: block6, type: type(inst+15)} -// CHECK:STDOUT: 'inst+15': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+15': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+16': {kind: StructValue, arg0: empty, type: type(inst+15)} // CHECK:STDOUT: 'inst+17': {kind: PointerType, arg0: type(inst+8), type: typeTypeType} // CHECK:STDOUT: 'inst+18': {kind: NameRef, arg0: name1, arg1: inst+5, type: type(inst+1)} diff --git a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon index 0379f1b39a6b..0809d76490b5 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon @@ -72,12 +72,12 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: 'inst+12': {kind: Converted, arg0: inst+9, arg1: inst+8, type: typeTypeType} // CHECK:STDOUT: 'inst+13': {kind: TupleType, arg0: type_block2, type: typeTypeType} // CHECK:STDOUT: 'inst+14': {kind: Converted, arg0: inst+11, arg1: inst+13, type: typeTypeType} -// CHECK:STDOUT: 'inst+15': {kind: VarStorage, arg0: nameReturnSlot, type: type(symbolicConstant1)} +// CHECK:STDOUT: 'inst+15': {kind: VarStorage, arg0: nameReturnSlot, type: type(symbolicConstant3)} // CHECK:STDOUT: 'inst+16': {kind: FunctionDecl, arg0: function0, arg1: block7, type: type(inst+20)} // CHECK:STDOUT: 'inst+17': {kind: BindSymbolicName, arg0: entity_name0, arg1: inst, type: typeTypeType} // CHECK:STDOUT: 'inst+18': {kind: TupleType, arg0: type_block3, type: typeTypeType} // CHECK:STDOUT: 'inst+19': {kind: TupleType, arg0: type_block3, type: typeTypeType} -// CHECK:STDOUT: 'inst+20': {kind: FunctionType, arg0: function0, type: typeTypeType} +// CHECK:STDOUT: 'inst+20': {kind: FunctionType, arg0: function0, arg1: genericInstance, type: typeTypeType} // CHECK:STDOUT: 'inst+21': {kind: StructValue, arg0: empty, type: type(inst+20)} // CHECK:STDOUT: 'inst+22': {kind: PointerType, arg0: type(symbolicConstant1), type: typeTypeType} // CHECK:STDOUT: 'inst+23': {kind: NameRef, arg0: name2, arg1: inst+6, type: type(symbolicConstant2)} diff --git a/toolchain/check/testdata/builtins/int/make_type_signed.carbon b/toolchain/check/testdata/builtins/int/make_type_signed.carbon index b0c4a1778a3d..6e87379407cc 100644 --- a/toolchain/check/testdata/builtins/int/make_type_signed.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_signed.carbon @@ -208,7 +208,7 @@ var m: Int(1000000000); // CHECK:STDOUT: %int.make_type_signed.loc14_39: init type = call %Int.ref.loc14_36(%N.ref.loc14_40) [symbolic = @Symbolic.%.1 (constants.%.6)] // CHECK:STDOUT: %.loc14_41.1: type = value_of_initializer %int.make_type_signed.loc14_39 [symbolic = @Symbolic.%.1 (constants.%.6)] // CHECK:STDOUT: %.loc14_41.2: type = converted %int.make_type_signed.loc14_39, %.loc14_41.1 [symbolic = @Symbolic.%.1 (constants.%.6)] -// CHECK:STDOUT: @Symbolic.%return: ref %.6 = var +// CHECK:STDOUT: @Symbolic.%return: ref @Symbolic.%.1 (%.6) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -234,7 +234,7 @@ var m: Int(1000000000); // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn(%N.loc14: i32, %x: @Symbolic.%.1 (%.6)) -> %.6 { +// CHECK:STDOUT: fn(%N.loc14: i32, %x: @Symbolic.%.1 (%.6)) -> @Symbolic.%.1 (%.6) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: @Symbolic.%.1 (%.6) = name_ref x, %x // CHECK:STDOUT: return %x.ref diff --git a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon index 2cc311cfbd04..9fc169284367 100644 --- a/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon +++ b/toolchain/check/testdata/builtins/int/make_type_unsigned.carbon @@ -208,7 +208,7 @@ var m: UInt(1000000000); // CHECK:STDOUT: %int.make_type_unsigned.loc14_41: init type = call %UInt.ref.loc14_37(%N.ref.loc14_42) [symbolic = @Symbolic.%.1 (constants.%.6)] // CHECK:STDOUT: %.loc14_43.1: type = value_of_initializer %int.make_type_unsigned.loc14_41 [symbolic = @Symbolic.%.1 (constants.%.6)] // CHECK:STDOUT: %.loc14_43.2: type = converted %int.make_type_unsigned.loc14_41, %.loc14_43.1 [symbolic = @Symbolic.%.1 (constants.%.6)] -// CHECK:STDOUT: @Symbolic.%return: ref %.6 = var +// CHECK:STDOUT: @Symbolic.%return: ref @Symbolic.%.1 (%.6) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -234,7 +234,7 @@ var m: UInt(1000000000); // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn(%N.loc14: i32, %x: @Symbolic.%.1 (%.6)) -> %.6 { +// CHECK:STDOUT: fn(%N.loc14: i32, %x: @Symbolic.%.1 (%.6)) -> @Symbolic.%.1 (%.6) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %x.ref: @Symbolic.%.1 (%.6) = name_ref x, %x // CHECK:STDOUT: return %x.ref diff --git a/toolchain/check/testdata/class/fail_generic_method.carbon b/toolchain/check/testdata/class/fail_generic_method.carbon index e16cc13e1111..33e094c26ed8 100644 --- a/toolchain/check/testdata/class/fail_generic_method.carbon +++ b/toolchain/check/testdata/class/fail_generic_method.carbon @@ -40,8 +40,8 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic] +// CHECK:STDOUT: %F: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.a: %T} [symbolic] // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] @@ -95,11 +95,13 @@ fn Class(N:! i32).F[self: Self](n: T) {} // CHECK:STDOUT: !definition: // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @Class.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F)] // CHECK:STDOUT: // CHECK:STDOUT: class { // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc12: @Class.%.1 (%.2) = field_decl a, element0 [template] -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F)] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @F.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = @F.%Class (constants.%Class.2)] // CHECK:STDOUT: %self.loc13_8.1: @F.%Class (%Class.2) = param self diff --git a/toolchain/check/testdata/class/generic/basic.carbon b/toolchain/check/testdata/class/generic/basic.carbon index dedca54f1959..38963fc0eee8 100644 --- a/toolchain/check/testdata/class/generic/basic.carbon +++ b/toolchain/check/testdata/class/generic/basic.carbon @@ -33,12 +33,14 @@ class Declaration(T:! type); // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] // CHECK:STDOUT: %.2: type = ptr_type %Class.2 [symbolic] // CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] -// CHECK:STDOUT: %GetAddr.type: type = fn_type @GetAddr [template] -// CHECK:STDOUT: %GetAddr: %GetAddr.type = struct_value () [template] -// CHECK:STDOUT: %GetValue.type: type = fn_type @GetValue [template] -// CHECK:STDOUT: %GetValue: %GetValue.type = struct_value () [template] +// CHECK:STDOUT: %GetAddr.type: type = fn_type @GetAddr, @Class(%T) [symbolic] +// CHECK:STDOUT: %GetAddr.1: %GetAddr.type = struct_value () [symbolic] +// CHECK:STDOUT: %GetValue.type: type = fn_type @GetValue, @Class(%T) [symbolic] +// CHECK:STDOUT: %GetValue.1: %GetValue.type = struct_value () [symbolic] // CHECK:STDOUT: %.4: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.5: type = struct_type {.k: %T} [symbolic] +// CHECK:STDOUT: %GetAddr.2: %GetAddr.type = struct_value () [symbolic] +// CHECK:STDOUT: %GetValue.2: %GetValue.type = struct_value () [symbolic] // CHECK:STDOUT: %.6: type = ptr_type %.5 [symbolic] // CHECK:STDOUT: %Declaration.type: type = generic_class_type @Declaration [template] // CHECK:STDOUT: %Declaration.1: %Declaration.type = struct_value () [template] @@ -78,11 +80,15 @@ class Declaration(T:! type); // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %GetAddr.type: type = fn_type @GetAddr, @Class(%T) [symbolic = %GetAddr.type (constants.%GetAddr.type)] +// CHECK:STDOUT: %GetAddr: @Class.%GetAddr.type (%GetAddr.type) = struct_value () [symbolic = %GetAddr (constants.%GetAddr.1)] +// CHECK:STDOUT: %GetValue.type: type = fn_type @GetValue, @Class(%T) [symbolic = %GetValue.type (constants.%GetValue.type)] +// CHECK:STDOUT: %GetValue: @Class.%GetValue.type (%GetValue.type) = struct_value () [symbolic = %GetValue (constants.%GetValue.1)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %GetAddr.decl: %GetAddr.type = fn_decl @GetAddr [template = constants.%GetAddr] { +// CHECK:STDOUT: %GetAddr.decl: @Class.%GetAddr.type (%GetAddr.type) = fn_decl @GetAddr [symbolic = %GetAddr (constants.%GetAddr.1)] { // CHECK:STDOUT: %.loc12_25: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @GetAddr.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref.loc12: type = name_ref Self, %.loc12_25 [symbolic = @GetAddr.%Class (constants.%Class.2)] // CHECK:STDOUT: %.loc12_29: type = ptr_type %Class.2 [symbolic = @GetAddr.%.1 (constants.%.2)] @@ -91,15 +97,15 @@ class Declaration(T:! type); // CHECK:STDOUT: %.loc12_14: @GetAddr.%.1 (%.2) = addr_pattern %self.loc12_19.3 // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = @GetAddr.%T (constants.%T)] // CHECK:STDOUT: %.loc12_38: type = ptr_type %T [symbolic = @GetAddr.%.2 (constants.%.3)] -// CHECK:STDOUT: %return.var.loc12: ref %.3 = var +// CHECK:STDOUT: %return.var.loc12: ref @GetAddr.%.2 (%.3) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %GetValue.decl: %GetValue.type = fn_decl @GetValue [template = constants.%GetValue] { +// CHECK:STDOUT: %GetValue.decl: @Class.%GetValue.type (%GetValue.type) = fn_decl @GetValue [symbolic = %GetValue (constants.%GetValue.1)] { // CHECK:STDOUT: %.loc17: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @GetValue.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref.loc17: type = name_ref Self, %.loc17 [symbolic = @GetValue.%Class (constants.%Class.2)] // CHECK:STDOUT: %self.loc17_15.1: @GetValue.%Class (%Class.2) = param self // CHECK:STDOUT: %self.loc17_15.2: @GetValue.%Class (%Class.2) = bind_name self, %self.loc17_15.1 // CHECK:STDOUT: %T.ref.loc17: type = name_ref T, file.%T.loc11_13.2 [symbolic = @GetValue.%T (constants.%T)] -// CHECK:STDOUT: %return.var.loc17: ref %T = var +// CHECK:STDOUT: %return.var.loc17: ref @GetValue.%T (%T) = var // CHECK:STDOUT: } // CHECK:STDOUT: %T.ref.loc21: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc21: @Class.%.1 (%.4) = field_decl k, element0 [template] @@ -127,7 +133,7 @@ class Declaration(T:! type); // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.3: type = unbound_element_type @GetAddr.%Class (%Class.2), @GetAddr.%T (%T) [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[addr @Class.%self.loc12_19.3: @GetAddr.%.1 (%.2)]() -> %.3 { +// CHECK:STDOUT: fn[addr @Class.%self.loc12_19.3: @GetAddr.%.1 (%.2)]() -> @GetAddr.%.2 (%.3) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @GetAddr.%.1 (%.2) = name_ref self, @Class.%self.loc12_19.3 // CHECK:STDOUT: %.loc13_17.1: ref @GetAddr.%Class (%Class.2) = deref %self.ref @@ -145,7 +151,7 @@ class Declaration(T:! type); // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = unbound_element_type @GetValue.%Class (%Class.2), @GetValue.%T (%T) [symbolic = %.1 (constants.%.4)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@Class.%self.loc17_15.2: @GetValue.%Class (%Class.2)]() -> %T { +// CHECK:STDOUT: fn[@Class.%self.loc17_15.2: @GetValue.%Class (%Class.2)]() -> @GetValue.%T (%T) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @GetValue.%Class (%Class.2) = name_ref self, @Class.%self.loc17_15.2 // CHECK:STDOUT: %k.ref: @GetValue.%.1 (%.4) = name_ref k, @Class.%.loc21 [template = @Class.%.loc21] @@ -159,6 +165,10 @@ class Declaration(T:! type); // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %GetAddr.type => constants.%GetAddr.type +// CHECK:STDOUT: %GetAddr => constants.%GetAddr.2 +// CHECK:STDOUT: %GetValue.type => constants.%GetValue.type +// CHECK:STDOUT: %GetValue => constants.%GetValue.2 // CHECK:STDOUT: %Class => constants.%Class.2 // CHECK:STDOUT: %.1 => constants.%.4 // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/generic/call.carbon b/toolchain/check/testdata/class/generic/call.carbon index 0b1b9c341e5a..76d7459f7dd4 100644 --- a/toolchain/check/testdata/class/generic/call.carbon +++ b/toolchain/check/testdata/class/generic/call.carbon @@ -434,22 +434,34 @@ class Outer(T:! type) { // CHECK:STDOUT: %Inner.type: type = generic_class_type @Inner [template] // CHECK:STDOUT: %Inner.1: %Inner.type = struct_value () [template] // CHECK:STDOUT: %Inner.2: type = class_type @Inner, @Inner(%T, %U) [symbolic] -// CHECK:STDOUT: %A.type: type = fn_type @A [template] -// CHECK:STDOUT: %A: %A.type = struct_value () [template] +// CHECK:STDOUT: %A.type.1: type = fn_type @A, @Inner(%T, %U) [symbolic] +// CHECK:STDOUT: %A.1: %A.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %Outer.3: type = class_type @Outer, @Outer(%U) [symbolic] -// CHECK:STDOUT: %B.type: type = fn_type @B [template] -// CHECK:STDOUT: %B: %B.type = struct_value () [template] +// CHECK:STDOUT: %B.type.1: type = fn_type @B, @Inner(%T, %U) [symbolic] +// CHECK:STDOUT: %B.1: %B.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %Inner.3: type = class_type @Inner, @Inner(%T) [symbolic] -// CHECK:STDOUT: %C.type: type = fn_type @C [template] -// CHECK:STDOUT: %C: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.type.1: type = fn_type @C, @Inner(%T, %U) [symbolic] +// CHECK:STDOUT: %C.1: %C.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %Inner.4: type = class_type @Inner, @Inner(%U) [symbolic] -// CHECK:STDOUT: %D.type: type = fn_type @D [template] -// CHECK:STDOUT: %D: %D.type = struct_value () [template] +// CHECK:STDOUT: %D.type.1: type = fn_type @D, @Inner(%T, %U) [symbolic] +// CHECK:STDOUT: %D.1: %D.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: %struct.1: %Outer.2 = struct_value () [symbolic] // CHECK:STDOUT: %struct.2: %Outer.3 = struct_value () [symbolic] +// CHECK:STDOUT: %A.2: %A.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %B.2: %B.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %C.2: %C.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %D.2: %D.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %struct.3: %Inner.3 = struct_value () [symbolic] +// CHECK:STDOUT: %A.type.2: type = fn_type @A, @Inner(%U, %U) [symbolic] +// CHECK:STDOUT: %A.3: %A.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %B.type.2: type = fn_type @B, @Inner(%U, %U) [symbolic] +// CHECK:STDOUT: %B.3: %B.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %C.type.2: type = fn_type @C, @Inner(%U, %U) [symbolic] +// CHECK:STDOUT: %C.3: %C.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %D.type.2: type = fn_type @D, @Inner(%U, %U) [symbolic] +// CHECK:STDOUT: %D.3: %D.type.2 = struct_value () [symbolic] // CHECK:STDOUT: %struct.4: %Inner.4 = struct_value () [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -498,39 +510,48 @@ class Outer(T:! type) { // CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic = %U (constants.%U)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %A.type: type = fn_type @A, @Inner(%T, %U) [symbolic = %A.type (constants.%A.type.1)] +// CHECK:STDOUT: %A: @Inner.%A.type (%A.type.1) = struct_value () [symbolic = %A (constants.%A.1)] +// CHECK:STDOUT: %B.type: type = fn_type @B, @Inner(%T, %U) [symbolic = %B.type (constants.%B.type.1)] +// CHECK:STDOUT: %B: @Inner.%B.type (%B.type.1) = struct_value () [symbolic = %B (constants.%B.1)] +// CHECK:STDOUT: %C.type: type = fn_type @C, @Inner(%T, %U) [symbolic = %C.type (constants.%C.type.1)] +// CHECK:STDOUT: %C: @Inner.%C.type (%C.type.1) = struct_value () [symbolic = %C (constants.%C.1)] +// CHECK:STDOUT: %D.type: type = fn_type @D, @Inner(%T, %U) [symbolic = %D.type (constants.%D.type.1)] +// CHECK:STDOUT: %D: @Inner.%D.type (%D.type.1) = struct_value () [symbolic = %D (constants.%D.1)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] { +// CHECK:STDOUT: %A.decl: @Inner.%A.type (%A.type.1) = fn_decl @A [symbolic = %A (constants.%A.1)] { // CHECK:STDOUT: %Outer.ref.loc4: %Outer.type = name_ref Outer, file.%Outer.decl [template = constants.%Outer.1] // CHECK:STDOUT: %T.ref.loc4: type = name_ref T, file.%T.loc2_13.2 [symbolic = @A.%T (constants.%T)] // CHECK:STDOUT: %.loc4_20: init type = call %Outer.ref.loc4(%T.ref.loc4) [symbolic = @A.%Outer (constants.%Outer.2)] // CHECK:STDOUT: %.loc4_22.1: type = value_of_initializer %.loc4_20 [symbolic = @A.%Outer (constants.%Outer.2)] // CHECK:STDOUT: %.loc4_22.2: type = converted %.loc4_20, %.loc4_22.1 [symbolic = @A.%Outer (constants.%Outer.2)] -// CHECK:STDOUT: %return.var.loc4: ref %Outer.2 = var +// CHECK:STDOUT: %return.var.loc4: ref @A.%Outer (%Outer.2) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %B.decl: %B.type = fn_decl @B [template = constants.%B] { +// CHECK:STDOUT: %B.decl: @Inner.%B.type (%B.type.1) = fn_decl @B [symbolic = %B (constants.%B.1)] { // CHECK:STDOUT: %Outer.ref.loc7: %Outer.type = name_ref Outer, file.%Outer.decl [template = constants.%Outer.1] // CHECK:STDOUT: %U.ref.loc7: type = name_ref U, @Outer.%U.loc3_15.2 [symbolic = @B.%U (constants.%U)] // CHECK:STDOUT: %.loc7_20: init type = call %Outer.ref.loc7(%U.ref.loc7) [symbolic = @B.%Outer (constants.%Outer.3)] // CHECK:STDOUT: %.loc7_22.1: type = value_of_initializer %.loc7_20 [symbolic = @B.%Outer (constants.%Outer.3)] // CHECK:STDOUT: %.loc7_22.2: type = converted %.loc7_20, %.loc7_22.1 [symbolic = @B.%Outer (constants.%Outer.3)] -// CHECK:STDOUT: %return.var.loc7: ref %Outer.3 = var +// CHECK:STDOUT: %return.var.loc7: ref @B.%Outer (%Outer.3) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: %C.type = fn_decl @C [template = constants.%C] { +// CHECK:STDOUT: %C.decl: @Inner.%C.type (%C.type.1) = fn_decl @C [symbolic = %C (constants.%C.1)] { // CHECK:STDOUT: %Inner.ref.loc10: %Inner.type = name_ref Inner, @Outer.%Inner.decl [template = constants.%Inner.1] // CHECK:STDOUT: %T.ref.loc10: type = name_ref T, file.%T.loc2_13.2 [symbolic = @C.%T (constants.%T)] // CHECK:STDOUT: %.loc10_20: init type = call %Inner.ref.loc10(%T.ref.loc10) [symbolic = @C.%Inner (constants.%Inner.3)] // CHECK:STDOUT: %.loc10_22.1: type = value_of_initializer %.loc10_20 [symbolic = @C.%Inner (constants.%Inner.3)] // CHECK:STDOUT: %.loc10_22.2: type = converted %.loc10_20, %.loc10_22.1 [symbolic = @C.%Inner (constants.%Inner.3)] -// CHECK:STDOUT: %return.var.loc10: ref %Inner.3 = var +// CHECK:STDOUT: %return.var.loc10: ref @C.%Inner (%Inner.3) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %D.decl: %D.type = fn_decl @D [template = constants.%D] { +// CHECK:STDOUT: %D.decl: @Inner.%D.type (%D.type.1) = fn_decl @D [symbolic = %D (constants.%D.1)] { // CHECK:STDOUT: %Inner.ref.loc13: %Inner.type = name_ref Inner, @Outer.%Inner.decl [template = constants.%Inner.1] // CHECK:STDOUT: %U.ref.loc13: type = name_ref U, @Outer.%U.loc3_15.2 [symbolic = @D.%U (constants.%U)] // CHECK:STDOUT: %.loc13_20: init type = call %Inner.ref.loc13(%U.ref.loc13) [symbolic = @D.%Inner (constants.%Inner.4)] // CHECK:STDOUT: %.loc13_22.1: type = value_of_initializer %.loc13_20 [symbolic = @D.%Inner (constants.%Inner.4)] // CHECK:STDOUT: %.loc13_22.2: type = converted %.loc13_20, %.loc13_22.1 [symbolic = @D.%Inner (constants.%Inner.4)] -// CHECK:STDOUT: %return.var.loc13: ref %Inner.4 = var +// CHECK:STDOUT: %return.var.loc13: ref @D.%Inner (%Inner.4) = var // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -549,7 +570,7 @@ class Outer(T:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %struct: @A.%Outer (%Outer.2) = struct_value () [symbolic = %struct (constants.%struct.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> @Inner.%return.var.loc4: %Outer.2 { +// CHECK:STDOUT: fn() -> @Inner.%return.var.loc4: @A.%Outer (%Outer.2) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc5_15.1: %.2 = struct_literal () // CHECK:STDOUT: %.loc5_15.2: init @A.%Outer (%Outer.2) = class_init (), @Inner.%return.var.loc4 [symbolic = %struct (constants.%struct.1)] @@ -565,7 +586,7 @@ class Outer(T:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %struct: @B.%Outer (%Outer.3) = struct_value () [symbolic = %struct (constants.%struct.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> @Inner.%return.var.loc7: %Outer.3 { +// CHECK:STDOUT: fn() -> @Inner.%return.var.loc7: @B.%Outer (%Outer.3) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc8_15.1: %.2 = struct_literal () // CHECK:STDOUT: %.loc8_15.2: init @B.%Outer (%Outer.3) = class_init (), @Inner.%return.var.loc7 [symbolic = %struct (constants.%struct.2)] @@ -581,7 +602,7 @@ class Outer(T:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %struct: @C.%Inner (%Inner.3) = struct_value () [symbolic = %struct (constants.%struct.3)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> @Inner.%return.var.loc10: %Inner.3 { +// CHECK:STDOUT: fn() -> @Inner.%return.var.loc10: @C.%Inner (%Inner.3) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc11_15.1: %.2 = struct_literal () // CHECK:STDOUT: %.loc11_15.2: init @C.%Inner (%Inner.3) = class_init (), @Inner.%return.var.loc10 [symbolic = %struct (constants.%struct.3)] @@ -597,7 +618,7 @@ class Outer(T:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %struct: @D.%Inner (%Inner.4) = struct_value () [symbolic = %struct (constants.%struct.4)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> @Inner.%return.var.loc13: %Inner.4 { +// CHECK:STDOUT: fn() -> @Inner.%return.var.loc13: @D.%Inner (%Inner.4) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc14_15.1: %.2 = struct_literal () // CHECK:STDOUT: %.loc14_15.2: init @D.%Inner (%Inner.4) = class_init (), @Inner.%return.var.loc13 [symbolic = %struct (constants.%struct.4)] @@ -644,6 +665,15 @@ class Outer(T:! type) { // CHECK:STDOUT: %U => constants.%U // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %A.type => constants.%A.type.1 +// CHECK:STDOUT: %A => constants.%A.2 +// CHECK:STDOUT: %B.type => constants.%B.type.1 +// CHECK:STDOUT: %B => constants.%B.2 +// CHECK:STDOUT: %C.type => constants.%C.type.1 +// CHECK:STDOUT: %C => constants.%C.2 +// CHECK:STDOUT: %D.type => constants.%D.type.1 +// CHECK:STDOUT: %D => constants.%D.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Inner(@C.%T) { @@ -659,6 +689,15 @@ class Outer(T:! type) { // CHECK:STDOUT: %U => constants.%U // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T => constants.%U +// CHECK:STDOUT: %A.type => constants.%A.type.2 +// CHECK:STDOUT: %A => constants.%A.3 +// CHECK:STDOUT: %B.type => constants.%B.type.2 +// CHECK:STDOUT: %B => constants.%B.3 +// CHECK:STDOUT: %C.type => constants.%C.type.2 +// CHECK:STDOUT: %C => constants.%C.3 +// CHECK:STDOUT: %D.type => constants.%D.type.2 +// CHECK:STDOUT: %D => constants.%D.3 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Inner(@D.%U) { @@ -670,3 +709,11 @@ class Outer(T:! type) { // CHECK:STDOUT: %Inner => constants.%Inner.4 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(@Inner.%T, @Inner.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(constants.%U, constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/fail_todo_use.carbon b/toolchain/check/testdata/class/generic/fail_todo_use.carbon deleted file mode 100644 index 05780dabad80..000000000000 --- a/toolchain/check/testdata/class/generic/fail_todo_use.carbon +++ /dev/null @@ -1,201 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE -// TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/fail_todo_use.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/fail_todo_use.carbon - -class Class(T:! type) { - fn Get[addr self: Self*]() -> T* { - return &self->k; - } - - var k: T; -} - -// TODO: The following should work. -fn Run() -> i32 { - // CHECK:STDERR: fail_todo_use.carbon:[[@LINE+4]]:23: ERROR: Cannot implicitly convert from `i32` to `T`. - // CHECK:STDERR: var v: Class(i32) = {.k = 0}; - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: - var v: Class(i32) = {.k = 0}; - // CHECK:STDERR: fail_todo_use.carbon:[[@LINE+10]]:3: ERROR: Cannot implicitly convert from `T*` to `i32`. - // CHECK:STDERR: return v.Get(); - // CHECK:STDERR: ^~~~~~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_use.carbon:[[@LINE+6]]:10: ERROR: Cannot implicitly convert from `Class*` to `Class*`. - // CHECK:STDERR: return v.Get(); - // CHECK:STDERR: ^~~~~~ - // CHECK:STDERR: fail_todo_use.carbon:[[@LINE-21]]:15: Initializing `addr self` parameter of method declared here. - // CHECK:STDERR: fn Get[addr self: Self*]() -> T* { - // CHECK:STDERR: ^~~~ - return v.Get(); -} - -// CHECK:STDOUT: --- fail_todo_use.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, @Class(%T) [symbolic] -// CHECK:STDOUT: %.2: type = ptr_type %Class.2 [symbolic] -// CHECK:STDOUT: %.3: type = ptr_type %T [symbolic] -// CHECK:STDOUT: %Get.type: type = fn_type @Get [template] -// CHECK:STDOUT: %Get: %Get.type = struct_value () [template] -// CHECK:STDOUT: %.4: type = unbound_element_type %Class.2, %T [symbolic] -// CHECK:STDOUT: %.5: type = struct_type {.k: %T} [symbolic] -// CHECK:STDOUT: %.6: type = ptr_type %.5 [symbolic] -// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] -// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// 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, @Class(i32) [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 { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: .Int32 = %import_ref -// 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: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .Class = %Class.decl -// CHECK:STDOUT: .Run = %Run.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] { -// 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 = @Class.%T (constants.%T)] -// CHECK:STDOUT: } -// CHECK:STDOUT: %Run.decl: %Run.type = fn_decl @Run [template = constants.%Run] { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc20_13.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc20_13.2: type = converted %int.make_type_32, %.loc20_13.1 [template = i32] -// CHECK:STDOUT: @Run.%return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: generic class @Class(file.%T.loc11_13.2: type) { -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] -// CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.4)] -// CHECK:STDOUT: -// CHECK:STDOUT: class { -// CHECK:STDOUT: %Get.decl: %Get.type = fn_decl @Get [template = constants.%Get] { -// CHECK:STDOUT: %.loc12_21: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @Get.%Class (constants.%Class.2)] -// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc12_21 [symbolic = @Get.%Class (constants.%Class.2)] -// CHECK:STDOUT: %.loc12_25: type = ptr_type %Class.2 [symbolic = @Get.%.1 (constants.%.2)] -// CHECK:STDOUT: %self.loc12_15.1: @Get.%.1 (%.2) = param self -// CHECK:STDOUT: %self.loc12_15.3: @Get.%.1 (%.2) = bind_name self, %self.loc12_15.1 -// CHECK:STDOUT: %.loc12_10: @Get.%.1 (%.2) = addr_pattern %self.loc12_15.3 -// CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = @Get.%T (constants.%T)] -// CHECK:STDOUT: %.loc12_34: type = ptr_type %T [symbolic = @Get.%.2 (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 (constants.%T)] -// CHECK:STDOUT: %.loc16: @Class.%.1 (%.4) = field_decl k, element0 [template] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Class.2 -// CHECK:STDOUT: .Get = %Get.decl -// CHECK:STDOUT: .k = %.loc16 -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: generic fn @Get(file.%T.loc11_13.2: type) { -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] -// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] -// CHECK:STDOUT: %.1: type = ptr_type @Get.%Class (%Class.2) [symbolic = %.1 (constants.%.2)] -// CHECK:STDOUT: %.2: type = ptr_type @Get.%T (%T) [symbolic = %.2 (constants.%.3)] -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %.3: type = unbound_element_type @Get.%Class (%Class.2), @Get.%T (%T) [symbolic = %.3 (constants.%.4)] -// CHECK:STDOUT: -// CHECK:STDOUT: fn[addr @Class.%self.loc12_15.3: @Get.%.1 (%.2)]() -> %.3 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %self.ref: @Get.%.1 (%.2) = name_ref self, @Class.%self.loc12_15.3 -// CHECK:STDOUT: %.loc13_17.1: ref @Get.%Class (%Class.2) = deref %self.ref -// CHECK:STDOUT: %k.ref: @Get.%.3 (%.4) = name_ref k, @Class.%.loc16 [template = @Class.%.loc16] -// CHECK:STDOUT: %.loc13_17.2: ref @Get.%T (%T) = class_element_access %.loc13_17.1, element0 -// CHECK:STDOUT: %.loc13_12: @Get.%.2 (%.3) = addr_of %.loc13_17.2 -// CHECK:STDOUT: return %.loc13_12 -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Run() -> i32 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc25_15.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc25_15.2: type = converted %int.make_type_32, %.loc25_15.1 [template = i32] -// CHECK:STDOUT: %.loc25_15.3: init type = call %Class.ref(%.loc25_15.2) [template = constants.%Class.3] -// CHECK:STDOUT: %.loc25_19.1: type = value_of_initializer %.loc25_15.3 [template = constants.%Class.3] -// 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.%.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: %.10 = addr_of %v.ref -// CHECK:STDOUT: %Get.call: init %.3 = call %.loc36_11() [template = ] -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @Class(constants.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Class => constants.%Class.2 -// CHECK:STDOUT: %.1 => constants.%.4 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @Class(@Get.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @Get(constants.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: %Class => constants.%Class.2 -// CHECK:STDOUT: %.1 => constants.%.2 -// CHECK:STDOUT: %.2 => constants.%.3 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @Class(@Class.%T) { -// CHECK:STDOUT: %T => constants.%T -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: specific @Class(i32) { -// CHECK:STDOUT: %T => i32 -// CHECK:STDOUT: -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Class => constants.%Class.3 -// CHECK:STDOUT: %.1 => constants.%.7 -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/field.carbon b/toolchain/check/testdata/class/generic/field.carbon index 4c212a517688..51a8eb2a8d5d 100644 --- a/toolchain/check/testdata/class/generic/field.carbon +++ b/toolchain/check/testdata/class/generic/field.carbon @@ -103,7 +103,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: %c.loc19_16.1: @G.%Class (%Class.2) = param c // CHECK:STDOUT: @G.%c: @G.%Class (%Class.2) = bind_name c, %c.loc19_16.1 // CHECK:STDOUT: %T.ref.loc19_32: type = name_ref T, @G.%T.loc19 [symbolic = @G.%T.1 (constants.%T)] -// CHECK:STDOUT: @G.%return: ref %T = var +// CHECK:STDOUT: @G.%return: ref @G.%T.1 (%T) = var // CHECK:STDOUT: } // CHECK:STDOUT: %H.decl: %H.type = fn_decl @H [template = constants.%H] { // CHECK:STDOUT: %U.loc23_6.1: type = param U @@ -116,7 +116,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: %c.loc23_16.1: @H.%Class (%Class.4) = param c // CHECK:STDOUT: @H.%c: @H.%Class (%Class.4) = bind_name c, %c.loc23_16.1 // CHECK:STDOUT: %U.ref.loc23_32: type = name_ref U, @H.%U.loc23 [symbolic = @H.%U.1 (constants.%U)] -// CHECK:STDOUT: @H.%return: ref %U = var +// CHECK:STDOUT: @H.%return: ref @H.%U.1 (%U) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -155,7 +155,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = unbound_element_type @G.%Class (%Class.2), @G.%T.1 (%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc19: type, %c: @G.%Class (%Class.2)) -> %T { +// CHECK:STDOUT: fn(%T.loc19: type, %c: @G.%Class (%Class.2)) -> @G.%T.1 (%T) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: @G.%Class (%Class.2) = name_ref c, %c // CHECK:STDOUT: %x.ref: @G.%.1 (%.2) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] @@ -172,7 +172,7 @@ fn H(U:! type, c: Class(U)) -> U { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = unbound_element_type @H.%Class (%Class.4), @H.%U.1 (%U) [symbolic = %.1 (constants.%.6)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%U.loc23: type, %c: @H.%Class (%Class.4)) -> %U { +// CHECK:STDOUT: fn(%U.loc23: type, %c: @H.%Class (%Class.4)) -> @H.%U.1 (%U) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: @H.%Class (%Class.4) = name_ref c, %c // CHECK:STDOUT: %x.ref: @H.%.1 (%.6) = name_ref x, @Class.%.loc12 [template = @Class.%.loc12] diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 30ec7a59c58e..dffd54bf87a5 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -102,8 +102,8 @@ class Class(U:! type) { // CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %.2: type = unbound_element_type %CompleteClass.2, i32 [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.1: type = fn_type @F.1, @CompleteClass(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.n: i32} [template] // CHECK:STDOUT: %.4: i32 = int_literal 0 [template] // CHECK:STDOUT: %CompleteClass.3: type = class_type @CompleteClass, @CompleteClass(i32) [template] @@ -165,13 +165,15 @@ class Class(U:! type) { // 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.%.2)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @CompleteClass(%T) [symbolic = %F.type (constants.%F.type.1)] +// CHECK:STDOUT: %F: @CompleteClass.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)] // CHECK:STDOUT: // CHECK:STDOUT: class { // 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: @CompleteClass.%.1 (%.2) = field_decl n, element0 [template] -// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { +// CHECK:STDOUT: %F.decl: @CompleteClass.%F.type (%F.type.1) = fn_decl @F.1 [symbolic = %F (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] // CHECK:STDOUT: %.loc8_13.2: type = converted %int.make_type_32.loc8, %.loc8_13.1 [template = i32] @@ -244,7 +246,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref Main//foo, inst+6, loaded [template = constants.%Class.1] // 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 = import_ref Main//foo, inst+53, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -344,7 +346,7 @@ class Class(U:! type) { // 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.1 = import_ref Main//foo, inst+53, loaded [template = constants.%F.1] +// CHECK:STDOUT: %import_ref.3: %F.type.1 = import_ref Main//foo, inst+55, loaded [template = constants.%F.1] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.4 // CHECK:STDOUT: import Core//prelude @@ -442,7 +444,7 @@ class Class(U:! type) { // 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 = import_ref Main//foo, inst+53, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.4 // CHECK:STDOUT: import Core//prelude @@ -537,7 +539,7 @@ class Class(U:! type) { // 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 = import_ref Main//foo, inst+53, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.3: %F.type = import_ref Main//foo, inst+55, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -620,7 +622,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref Main//foo, inst+6, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2 = import_ref Main//foo, inst+14, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//foo, inst+53, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//foo, inst+55, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/operators diff --git a/toolchain/check/testdata/class/generic/init.carbon b/toolchain/check/testdata/class/generic/init.carbon new file mode 100644 index 000000000000..7a3101c79e17 --- /dev/null +++ b/toolchain/check/testdata/class/generic/init.carbon @@ -0,0 +1,266 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/init.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/init.carbon + +// --- init.carbon + +class Class(T:! type) { + var k: T; +} + +fn InitFromStructGeneric(T:! type, x: T) -> T { + var v: Class(T) = {.k = x}; + return v.k; +} + +// --- fail_todo_init.carbon + +library "fail_todo_init"; + +class Class(T:! type) { + var k: T; +} + +// TODO: The following should work. +fn InitFromStructSpecific() -> i32 { + // CHECK:STDERR: fail_todo_init.carbon:[[@LINE+3]]:23: ERROR: Cannot implicitly convert from `i32` to `T`. + // CHECK:STDERR: var v: Class(i32) = {.k = 0}; + // CHECK:STDERR: ^~~~~~~~ + var v: Class(i32) = {.k = 0}; + return v.k; +} + +// CHECK:STDOUT: --- init.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, @Class(%T) [symbolic] +// CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] +// CHECK:STDOUT: %.3: type = struct_type {.k: %T} [symbolic] +// CHECK:STDOUT: %InitFromStructGeneric.type: type = fn_type @InitFromStructGeneric [template] +// CHECK:STDOUT: %InitFromStructGeneric: %InitFromStructGeneric.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Class = %Class.decl +// CHECK:STDOUT: .InitFromStructGeneric = %InitFromStructGeneric.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// 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 = @Class.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %InitFromStructGeneric.decl: %InitFromStructGeneric.type = fn_decl @InitFromStructGeneric [template = constants.%InitFromStructGeneric] { +// CHECK:STDOUT: %T.loc6_26.1: type = param T +// CHECK:STDOUT: @InitFromStructGeneric.%T.loc6: type = bind_symbolic_name T 0, %T.loc6_26.1 [symbolic = @InitFromStructGeneric.%T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc6_39: type = name_ref T, @InitFromStructGeneric.%T.loc6 [symbolic = @InitFromStructGeneric.%T.1 (constants.%T)] +// CHECK:STDOUT: %x.loc6_36.1: @InitFromStructGeneric.%T.1 (%T) = param x +// CHECK:STDOUT: @InitFromStructGeneric.%x: @InitFromStructGeneric.%T.1 (%T) = bind_name x, %x.loc6_36.1 +// CHECK:STDOUT: %T.ref.loc6_45: type = name_ref T, @InitFromStructGeneric.%T.loc6 [symbolic = @InitFromStructGeneric.%T.1 (constants.%T)] +// CHECK:STDOUT: @InitFromStructGeneric.%return: ref @InitFromStructGeneric.%T.1 (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Class(file.%T.loc2_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc2_13.2 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc3: @Class.%.1 (%.2) = field_decl k, element0 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Class.2 +// CHECK:STDOUT: .k = %.loc3 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @InitFromStructGeneric(%T.loc6: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T.1) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = struct_type {.k: @InitFromStructGeneric.%T.1 (%T)} [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: type = unbound_element_type @InitFromStructGeneric.%Class (%Class.2), @InitFromStructGeneric.%T.1 (%T) [symbolic = %.2 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.loc6: type, %x: @InitFromStructGeneric.%T.1 (%T)) -> @InitFromStructGeneric.%T.1 (%T) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc6 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc7_15: init type = call %Class.ref(%T.ref) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc7_17.1: type = value_of_initializer %.loc7_15 [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc7_17.2: type = converted %.loc7_15, %.loc7_17.1 [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %v.var: ref @InitFromStructGeneric.%Class (%Class.2) = var v +// CHECK:STDOUT: %v: ref @InitFromStructGeneric.%Class (%Class.2) = bind_name v, %v.var +// CHECK:STDOUT: %x.ref: @InitFromStructGeneric.%T.1 (%T) = name_ref x, %x +// CHECK:STDOUT: %.loc7_28.1: @InitFromStructGeneric.%.1 (%.3) = struct_literal (%x.ref) +// CHECK:STDOUT: %.loc7_28.2: ref @InitFromStructGeneric.%T.1 (%T) = class_element_access %v.var, element0 +// CHECK:STDOUT: %.loc7_28.3: init @InitFromStructGeneric.%T.1 (%T) = initialize_from %x.ref to %.loc7_28.2 +// CHECK:STDOUT: %.loc7_28.4: init @InitFromStructGeneric.%Class (%Class.2) = class_init (%.loc7_28.3), %v.var +// CHECK:STDOUT: %.loc7_29: init @InitFromStructGeneric.%Class (%Class.2) = converted %.loc7_28.1, %.loc7_28.4 +// CHECK:STDOUT: assign %v.var, %.loc7_29 +// CHECK:STDOUT: %v.ref: ref @InitFromStructGeneric.%Class (%Class.2) = name_ref v, %v +// CHECK:STDOUT: %k.ref: @InitFromStructGeneric.%.2 (%.2) = name_ref k, @Class.%.loc3 [template = @Class.%.loc3] +// CHECK:STDOUT: %.loc8_11.1: ref @InitFromStructGeneric.%T.1 (%T) = class_element_access %v.ref, element0 +// CHECK:STDOUT: %.loc8_11.2: @InitFromStructGeneric.%T.1 (%T) = bind_value %.loc8_11.1 +// CHECK:STDOUT: return %.loc8_11.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @InitFromStructGeneric(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@InitFromStructGeneric.%T.1) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_init.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, @Class(%T) [symbolic] +// CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] +// CHECK:STDOUT: %.3: type = struct_type {.k: %T} [symbolic] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %InitFromStructSpecific.type: type = fn_type @InitFromStructSpecific [template] +// CHECK:STDOUT: %InitFromStructSpecific: %InitFromStructSpecific.type = struct_value () [template] +// CHECK:STDOUT: %Class.3: type = class_type @Class, @Class(i32) [template] +// CHECK:STDOUT: %.4: type = unbound_element_type %Class.3, i32 [template] +// CHECK:STDOUT: %.5: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %.6: i32 = int_literal 0 [template] +// CHECK:STDOUT: %.7: type = struct_type {.k: i32} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Class = %Class.decl +// CHECK:STDOUT: .InitFromStructSpecific = %InitFromStructSpecific.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] { +// CHECK:STDOUT: %T.loc4_13.1: type = param T +// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = @Class.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %InitFromStructSpecific.decl: %InitFromStructSpecific.type = fn_decl @InitFromStructSpecific [template = constants.%InitFromStructSpecific] { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc9_32.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc9_32.2: type = converted %int.make_type_32, %.loc9_32.1 [template = i32] +// CHECK:STDOUT: @InitFromStructSpecific.%return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Class(file.%T.loc4_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc4_13.2 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc5: @Class.%.1 (%.2) = field_decl k, element0 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Class.2 +// CHECK:STDOUT: .k = %.loc5 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @InitFromStructSpecific() -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_15.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc13_15.2: type = converted %int.make_type_32, %.loc13_15.1 [template = i32] +// CHECK:STDOUT: %.loc13_15.3: init type = call %Class.ref(%.loc13_15.2) [template = constants.%Class.3] +// CHECK:STDOUT: %.loc13_19.1: type = value_of_initializer %.loc13_15.3 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc13_19.2: type = converted %.loc13_15.3, %.loc13_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: %.loc13_29: i32 = int_literal 0 [template = constants.%.6] +// CHECK:STDOUT: %.loc13_30: %.7 = struct_literal (%.loc13_29) +// CHECK:STDOUT: assign %v.var, +// CHECK:STDOUT: %v.ref: ref %Class.3 = name_ref v, %v +// CHECK:STDOUT: %k.ref: %.4 = name_ref k, @Class.%.loc5 [template = @Class.%.loc5] +// CHECK:STDOUT: %.loc14_11.1: ref i32 = class_element_access %v.ref, element0 +// CHECK:STDOUT: %.loc14_11.2: i32 = bind_value %.loc14_11.1 +// CHECK:STDOUT: return %.loc14_11.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class => constants.%Class.3 +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/member_access.carbon b/toolchain/check/testdata/class/generic/member_access.carbon new file mode 100644 index 000000000000..15cc22c7554d --- /dev/null +++ b/toolchain/check/testdata/class/generic/member_access.carbon @@ -0,0 +1,480 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_access.carbon + +// --- member_access.carbon + +class Class(T:! type) { + var x: T; + + fn Get[self: Self]() -> T { return self.x; } + + fn GetAddr[addr self: Self*]() -> T* { return &self->x; } +} + +fn DirectFieldAccess(x: Class(i32)) -> i32 { + return x.x; +} + +fn MethodCall(x: Class(i32)) -> i32 { + return x.Get(); +} + +fn AddrMethodCall(p: Class(i32)*) -> i32 { + return *p->GetAddr(); +} + +// --- fail_todo_static_member_fn_call.carbon + +library "fail_todo_static_member_fn_call"; + +class Class(T:! type) { + fn Make() -> Class(T) { return {}; } +} + +fn StaticMemberFunctionCall(T:! type) -> Class(T) { + // CHECK:STDERR: fail_todo_static_member_fn_call.carbon:[[@LINE+3]]:3: ERROR: Cannot implicitly convert from `Class` to `Class`. + // CHECK:STDERR: return Class(T).Make(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ + return Class(T).Make(); +} + +// CHECK:STDOUT: --- member_access.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, @Class(%T) [symbolic] +// CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] +// CHECK:STDOUT: %Get.type.1: type = fn_type @Get, @Class(%T) [symbolic] +// CHECK:STDOUT: %Get.1: %Get.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = ptr_type %Class.2 [symbolic] +// CHECK:STDOUT: %.4: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %GetAddr.type.1: type = fn_type @GetAddr, @Class(%T) [symbolic] +// CHECK:STDOUT: %GetAddr.1: %GetAddr.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.5: type = struct_type {.x: %T} [symbolic] +// CHECK:STDOUT: %Get.2: %Get.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %GetAddr.2: %GetAddr.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.6: type = ptr_type %.5 [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, @Class(i32) [template] +// CHECK:STDOUT: %DirectFieldAccess.type: type = fn_type @DirectFieldAccess [template] +// CHECK:STDOUT: %DirectFieldAccess: %DirectFieldAccess.type = struct_value () [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %Class.3, i32 [template] +// CHECK:STDOUT: %Get.type.2: type = fn_type @Get, @Class(i32) [template] +// CHECK:STDOUT: %Get.3: %Get.type.2 = struct_value () [template] +// CHECK:STDOUT: %GetAddr.type.2: type = fn_type @GetAddr, @Class(i32) [template] +// CHECK:STDOUT: %GetAddr.3: %GetAddr.type.2 = struct_value () [template] +// CHECK:STDOUT: %MethodCall.type: type = fn_type @MethodCall [template] +// CHECK:STDOUT: %MethodCall: %MethodCall.type = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %Class.3 [template] +// CHECK:STDOUT: %AddrMethodCall.type: type = fn_type @AddrMethodCall [template] +// CHECK:STDOUT: %AddrMethodCall: %AddrMethodCall.type = struct_value () [template] +// CHECK:STDOUT: %.9: type = ptr_type i32 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Class = %Class.decl +// CHECK:STDOUT: .DirectFieldAccess = %DirectFieldAccess.decl +// CHECK:STDOUT: .MethodCall = %MethodCall.decl +// CHECK:STDOUT: .AddrMethodCall = %AddrMethodCall.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// 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 = @Class.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %DirectFieldAccess.decl: %DirectFieldAccess.type = fn_decl @DirectFieldAccess [template = constants.%DirectFieldAccess] { +// CHECK:STDOUT: %Class.ref.loc10: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %int.make_type_32.loc10_31: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_30.1: type = value_of_initializer %int.make_type_32.loc10_31 [template = i32] +// CHECK:STDOUT: %.loc10_30.2: type = converted %int.make_type_32.loc10_31, %.loc10_30.1 [template = i32] +// CHECK:STDOUT: %.loc10_30.3: init type = call %Class.ref.loc10(%.loc10_30.2) [template = constants.%Class.3] +// CHECK:STDOUT: %.loc10_34.1: type = value_of_initializer %.loc10_30.3 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc10_34.2: type = converted %.loc10_30.3, %.loc10_34.1 [template = constants.%Class.3] +// CHECK:STDOUT: %x.loc10_22.1: %Class.3 = param x +// CHECK:STDOUT: @DirectFieldAccess.%x: %Class.3 = bind_name x, %x.loc10_22.1 +// CHECK:STDOUT: %int.make_type_32.loc10_40: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_40.1: type = value_of_initializer %int.make_type_32.loc10_40 [template = i32] +// CHECK:STDOUT: %.loc10_40.2: type = converted %int.make_type_32.loc10_40, %.loc10_40.1 [template = i32] +// CHECK:STDOUT: @DirectFieldAccess.%return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %MethodCall.decl: %MethodCall.type = fn_decl @MethodCall [template = constants.%MethodCall] { +// CHECK:STDOUT: %Class.ref.loc14: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %int.make_type_32.loc14_24: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc14_23.1: type = value_of_initializer %int.make_type_32.loc14_24 [template = i32] +// CHECK:STDOUT: %.loc14_23.2: type = converted %int.make_type_32.loc14_24, %.loc14_23.1 [template = i32] +// CHECK:STDOUT: %.loc14_23.3: init type = call %Class.ref.loc14(%.loc14_23.2) [template = constants.%Class.3] +// CHECK:STDOUT: %.loc14_27.1: type = value_of_initializer %.loc14_23.3 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc14_27.2: type = converted %.loc14_23.3, %.loc14_27.1 [template = constants.%Class.3] +// CHECK:STDOUT: %x.loc14_15.1: %Class.3 = param x +// CHECK:STDOUT: @MethodCall.%x: %Class.3 = bind_name x, %x.loc14_15.1 +// CHECK:STDOUT: %int.make_type_32.loc14_33: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc14_33.1: type = value_of_initializer %int.make_type_32.loc14_33 [template = i32] +// CHECK:STDOUT: %.loc14_33.2: type = converted %int.make_type_32.loc14_33, %.loc14_33.1 [template = i32] +// CHECK:STDOUT: @MethodCall.%return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %AddrMethodCall.decl: %AddrMethodCall.type = fn_decl @AddrMethodCall [template = constants.%AddrMethodCall] { +// CHECK:STDOUT: %Class.ref.loc18: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %int.make_type_32.loc18_28: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc18_27.1: type = value_of_initializer %int.make_type_32.loc18_28 [template = i32] +// CHECK:STDOUT: %.loc18_27.2: type = converted %int.make_type_32.loc18_28, %.loc18_27.1 [template = i32] +// CHECK:STDOUT: %.loc18_27.3: init type = call %Class.ref.loc18(%.loc18_27.2) [template = constants.%Class.3] +// CHECK:STDOUT: %.loc18_32.1: type = value_of_initializer %.loc18_27.3 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc18_32.2: type = converted %.loc18_27.3, %.loc18_32.1 [template = constants.%Class.3] +// CHECK:STDOUT: %.loc18_32.3: type = ptr_type %Class.3 [template = constants.%.8] +// CHECK:STDOUT: %p.loc18_19.1: %.8 = param p +// CHECK:STDOUT: @AddrMethodCall.%p: %.8 = bind_name p, %p.loc18_19.1 +// CHECK:STDOUT: %int.make_type_32.loc18_38: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc18_38.1: type = value_of_initializer %int.make_type_32.loc18_38 [template = i32] +// CHECK:STDOUT: %.loc18_38.2: type = converted %int.make_type_32.loc18_38, %.loc18_38.1 [template = i32] +// CHECK:STDOUT: @AddrMethodCall.%return: ref i32 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Class(file.%T.loc2_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %Get.type: type = fn_type @Get, @Class(%T) [symbolic = %Get.type (constants.%Get.type.1)] +// CHECK:STDOUT: %Get: @Class.%Get.type (%Get.type.1) = struct_value () [symbolic = %Get (constants.%Get.1)] +// CHECK:STDOUT: %GetAddr.type: type = fn_type @GetAddr, @Class(%T) [symbolic = %GetAddr.type (constants.%GetAddr.type.1)] +// CHECK:STDOUT: %GetAddr: @Class.%GetAddr.type (%GetAddr.type.1) = struct_value () [symbolic = %GetAddr (constants.%GetAddr.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref.loc3: type = name_ref T, file.%T.loc2_13.2 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.loc3: @Class.%.1 (%.2) = field_decl x, element0 [template] +// CHECK:STDOUT: %Get.decl: @Class.%Get.type (%Get.type.1) = fn_decl @Get [symbolic = %Get (constants.%Get.1)] { +// CHECK:STDOUT: %.loc5: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @Get.%Class (constants.%Class.2)] +// CHECK:STDOUT: %Self.ref.loc5: type = name_ref Self, %.loc5 [symbolic = @Get.%Class (constants.%Class.2)] +// CHECK:STDOUT: %self.loc5_10.1: @Get.%Class (%Class.2) = param self +// CHECK:STDOUT: %self.loc5_10.2: @Get.%Class (%Class.2) = bind_name self, %self.loc5_10.1 +// CHECK:STDOUT: %T.ref.loc5: type = name_ref T, file.%T.loc2_13.2 [symbolic = @Get.%T (constants.%T)] +// CHECK:STDOUT: %return.var.loc5: ref @Get.%T (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %GetAddr.decl: @Class.%GetAddr.type (%GetAddr.type.1) = fn_decl @GetAddr [symbolic = %GetAddr (constants.%GetAddr.1)] { +// CHECK:STDOUT: %.loc7_25: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @GetAddr.%Class (constants.%Class.2)] +// CHECK:STDOUT: %Self.ref.loc7: type = name_ref Self, %.loc7_25 [symbolic = @GetAddr.%Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc7_29: type = ptr_type %Class.2 [symbolic = @GetAddr.%.1 (constants.%.3)] +// CHECK:STDOUT: %self.loc7_19.1: @GetAddr.%.1 (%.3) = param self +// CHECK:STDOUT: %self.loc7_19.3: @GetAddr.%.1 (%.3) = bind_name self, %self.loc7_19.1 +// CHECK:STDOUT: %.loc7_14: @GetAddr.%.1 (%.3) = addr_pattern %self.loc7_19.3 +// CHECK:STDOUT: %T.ref.loc7: type = name_ref T, file.%T.loc2_13.2 [symbolic = @GetAddr.%T (constants.%T)] +// CHECK:STDOUT: %.loc7_38: type = ptr_type %T [symbolic = @GetAddr.%.2 (constants.%.4)] +// CHECK:STDOUT: %return.var.loc7: ref @GetAddr.%.2 (%.4) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Class.2 +// CHECK:STDOUT: .x = %.loc3 +// CHECK:STDOUT: .Get = %Get.decl +// CHECK:STDOUT: .GetAddr = %GetAddr.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Get(file.%T.loc2_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = unbound_element_type @Get.%Class (%Class.2), @Get.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[@Class.%self.loc5_10.2: @Get.%Class (%Class.2)]() -> @Get.%T (%T) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: @Get.%Class (%Class.2) = name_ref self, @Class.%self.loc5_10.2 +// CHECK:STDOUT: %x.ref: @Get.%.1 (%.2) = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] +// CHECK:STDOUT: %.loc5_42.1: ref @Get.%T (%T) = class_element_access %self.ref, element0 +// CHECK:STDOUT: %.loc5_42.2: @Get.%T (%T) = bind_value %.loc5_42.1 +// CHECK:STDOUT: return %.loc5_42.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @GetAddr(file.%T.loc2_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.1: type = ptr_type @GetAddr.%Class (%Class.2) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: type = ptr_type @GetAddr.%T (%T) [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.3: type = unbound_element_type @GetAddr.%Class (%Class.2), @GetAddr.%T (%T) [symbolic = %.3 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[addr @Class.%self.loc7_19.3: @GetAddr.%.1 (%.3)]() -> @GetAddr.%.2 (%.4) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: @GetAddr.%.1 (%.3) = name_ref self, @Class.%self.loc7_19.3 +// CHECK:STDOUT: %.loc7_54.1: ref @GetAddr.%Class (%Class.2) = deref %self.ref +// CHECK:STDOUT: %x.ref: @GetAddr.%.3 (%.2) = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] +// CHECK:STDOUT: %.loc7_54.2: ref @GetAddr.%T (%T) = class_element_access %.loc7_54.1, element0 +// CHECK:STDOUT: %.loc7_49: @GetAddr.%.2 (%.4) = addr_of %.loc7_54.2 +// CHECK:STDOUT: return %.loc7_49 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @DirectFieldAccess(%x: %Class.3) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref.loc11_10: %Class.3 = name_ref x, %x +// CHECK:STDOUT: %x.ref.loc11_11: %.7 = name_ref x, @Class.%.loc3 [template = @Class.%.loc3] +// CHECK:STDOUT: %.loc11_11.1: ref i32 = class_element_access %x.ref.loc11_10, element0 +// CHECK:STDOUT: %.loc11_11.2: i32 = bind_value %.loc11_11.1 +// CHECK:STDOUT: return %.loc11_11.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MethodCall(%x: %Class.3) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref: %Class.3 = name_ref x, %x +// CHECK:STDOUT: %.loc15_11.1: %Get.type.2 = specific_constant @Class.%Get.decl, @Class(i32) [template = constants.%Get.3] +// CHECK:STDOUT: %Get.ref: %Get.type.2 = name_ref Get, %.loc15_11.1 [template = constants.%Get.3] +// CHECK:STDOUT: %.loc15_11.2: = bound_method %x.ref, %Get.ref +// CHECK:STDOUT: %Get.call: init i32 = call %.loc15_11.2(%x.ref) +// CHECK:STDOUT: %.loc15_17.1: i32 = value_of_initializer %Get.call +// CHECK:STDOUT: %.loc15_17.2: i32 = converted %Get.call, %.loc15_17.1 +// CHECK:STDOUT: return %.loc15_17.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @AddrMethodCall(%p: %.8) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %p.ref: %.8 = name_ref p, %p +// CHECK:STDOUT: %.loc19_12.1: ref %Class.3 = deref %p.ref +// CHECK:STDOUT: %.loc19_12.2: %GetAddr.type.2 = specific_constant @Class.%GetAddr.decl, @Class(i32) [template = constants.%GetAddr.3] +// CHECK:STDOUT: %GetAddr.ref: %GetAddr.type.2 = name_ref GetAddr, %.loc19_12.2 [template = constants.%GetAddr.3] +// CHECK:STDOUT: %.loc19_12.3: = bound_method %.loc19_12.1, %GetAddr.ref +// CHECK:STDOUT: %.loc19_12.4: %.8 = addr_of %.loc19_12.1 +// CHECK:STDOUT: %GetAddr.call: init %.9 = call %.loc19_12.3(%.loc19_12.4) +// CHECK:STDOUT: %.loc19_21.1: %.9 = value_of_initializer %GetAddr.call +// CHECK:STDOUT: %.loc19_21.2: %.9 = converted %GetAddr.call, %.loc19_21.1 +// CHECK:STDOUT: %.loc19_10.1: ref i32 = deref %.loc19_21.2 +// CHECK:STDOUT: %.loc19_10.2: i32 = bind_value %.loc19_10.1 +// CHECK:STDOUT: return %.loc19_10.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: %Get.type => constants.%Get.type.1 +// CHECK:STDOUT: %Get => constants.%Get.2 +// CHECK:STDOUT: %GetAddr.type => constants.%GetAddr.type.1 +// CHECK:STDOUT: %GetAddr => constants.%GetAddr.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Get.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Get(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@GetAddr.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GetAddr(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: %.1 => constants.%.3 +// CHECK:STDOUT: %.2 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Class => constants.%Class.3 +// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: %Get.type => constants.%Get.type.2 +// CHECK:STDOUT: %Get => constants.%Get.3 +// CHECK:STDOUT: %GetAddr.type => constants.%GetAddr.type.2 +// CHECK:STDOUT: %GetAddr => constants.%GetAddr.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Get(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: %Class => constants.%Class.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @GetAddr(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: %Class => constants.%Class.3 +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: %.2 => constants.%.9 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_static_member_fn_call.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, @Class(%T) [symbolic] +// CHECK:STDOUT: %Make.type: type = fn_type @Make, @Class(%T) [symbolic] +// CHECK:STDOUT: %Make.1: %Make.type = struct_value () [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %Make.2: %Make.type = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = ptr_type %.2 [template] +// CHECK:STDOUT: %struct: %Class.2 = struct_value () [symbolic] +// CHECK:STDOUT: %StaticMemberFunctionCall.type: type = fn_type @StaticMemberFunctionCall [template] +// CHECK:STDOUT: %StaticMemberFunctionCall: %StaticMemberFunctionCall.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// 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: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Class = %Class.decl +// CHECK:STDOUT: .StaticMemberFunctionCall = %StaticMemberFunctionCall.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Class.decl: %Class.type = class_decl @Class [template = constants.%Class.1] { +// CHECK:STDOUT: %T.loc4_13.1: type = param T +// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = @Class.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %StaticMemberFunctionCall.decl: %StaticMemberFunctionCall.type = fn_decl @StaticMemberFunctionCall [template = constants.%StaticMemberFunctionCall] { +// CHECK:STDOUT: %T.loc8_29.1: type = param T +// CHECK:STDOUT: @StaticMemberFunctionCall.%T.loc8: type = bind_symbolic_name T 0, %T.loc8_29.1 [symbolic = @StaticMemberFunctionCall.%T.1 (constants.%T)] +// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, %Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, @StaticMemberFunctionCall.%T.loc8 [symbolic = @StaticMemberFunctionCall.%T.1 (constants.%T)] +// CHECK:STDOUT: %.loc8_47: init type = call %Class.ref(%T.ref) [symbolic = @StaticMemberFunctionCall.%Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc8_49.1: type = value_of_initializer %.loc8_47 [symbolic = @StaticMemberFunctionCall.%Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc8_49.2: type = converted %.loc8_47, %.loc8_49.1 [symbolic = @StaticMemberFunctionCall.%Class (constants.%Class.2)] +// CHECK:STDOUT: @StaticMemberFunctionCall.%return: ref @StaticMemberFunctionCall.%Class (%Class.2) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Class(file.%T.loc4_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type: type = fn_type @Make, @Class(%T) [symbolic = %Make.type (constants.%Make.type)] +// CHECK:STDOUT: %Make: @Class.%Make.type (%Make.type) = struct_value () [symbolic = %Make (constants.%Make.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %Make.decl: @Class.%Make.type (%Make.type) = fn_decl @Make [symbolic = %Make (constants.%Make.1)] { +// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc4_13.2 [symbolic = @Make.%T (constants.%T)] +// CHECK:STDOUT: %.loc5_21: init type = call %Class.ref(%T.ref) [symbolic = @Make.%Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc5_23.1: type = value_of_initializer %.loc5_21 [symbolic = @Make.%Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc5_23.2: type = converted %.loc5_21, %.loc5_23.1 [symbolic = @Make.%Class (constants.%Class.2)] +// CHECK:STDOUT: %return.var: ref @Make.%Class (%Class.2) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Class.2 +// CHECK:STDOUT: .Make = %Make.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Make(file.%T.loc4_13.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %struct: @Make.%Class (%Class.2) = struct_value () [symbolic = %struct (constants.%struct)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @Class.%return.var: @Make.%Class (%Class.2) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_35.1: %.2 = struct_literal () +// CHECK:STDOUT: %.loc5_35.2: init @Make.%Class (%Class.2) = class_init (), @Class.%return.var [symbolic = %struct (constants.%struct)] +// CHECK:STDOUT: %.loc5_36: init @Make.%Class (%Class.2) = converted %.loc5_35.1, %.loc5_35.2 [symbolic = %struct (constants.%struct)] +// CHECK:STDOUT: return %.loc5_36 to @Class.%return.var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @StaticMemberFunctionCall(%T.loc8: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T.1) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type: type = fn_type @Make, @Class(%T.1) [symbolic = %Make.type (constants.%Make.type)] +// CHECK:STDOUT: %Make: @StaticMemberFunctionCall.%Make.type (%Make.type) = struct_value () [symbolic = %Make (constants.%Make.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.loc8: type) -> %return: @StaticMemberFunctionCall.%Class (%Class.2) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc8 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc12_15: init type = call %Class.ref(%T.ref) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %.loc12_18: @StaticMemberFunctionCall.%Make.type (%Make.type) = specific_constant @Class.%Make.decl, @Class(constants.%T) [symbolic = %Make (constants.%Make.2)] +// CHECK:STDOUT: %Make.ref: @StaticMemberFunctionCall.%Make.type (%Make.type) = name_ref Make, %.loc12_18 [symbolic = %Make (constants.%Make.2)] +// CHECK:STDOUT: %.loc12_23: ref @StaticMemberFunctionCall.%Class (%Class.2) = temporary_storage +// CHECK:STDOUT: %Make.call: init @StaticMemberFunctionCall.%Class (%Class.2) = call %Make.ref() to %.loc12_23 +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type => constants.%Make.type +// CHECK:STDOUT: %Make => constants.%Make.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Make.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Make(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@StaticMemberFunctionCall.%T.1) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @StaticMemberFunctionCall(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %Class => constants.%Class.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/member_inline.carbon b/toolchain/check/testdata/class/generic/member_inline.carbon index 6c985c02be81..884ec8e427aa 100644 --- a/toolchain/check/testdata/class/generic/member_inline.carbon +++ b/toolchain/check/testdata/class/generic/member_inline.carbon @@ -28,12 +28,14 @@ class Class(T:! type) { // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %G.type: type = fn_type @G [template] -// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %G.type: type = fn_type @G, @Class(%T) [symbolic] +// CHECK:STDOUT: %G.1: %G.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.n: %T} [symbolic] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %G.2: %G.type = struct_value () [symbolic] // CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -65,24 +67,28 @@ class Class(T:! type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @Class.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %G.type: type = fn_type @G, @Class(%T) [symbolic = %G.type (constants.%G.type)] +// CHECK:STDOUT: %G: @Class.%G.type (%G.type) = struct_value () [symbolic = %G (constants.%G.1)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %T.ref.loc12_11: type = name_ref T, file.%T.loc11_13.2 [symbolic = @F.%T (constants.%T)] // CHECK:STDOUT: %n.loc12_8.1: @F.%T (%T) = param n // CHECK:STDOUT: %n.loc12_8.2: @F.%T (%T) = bind_name n, %n.loc12_8.1 // CHECK:STDOUT: %T.ref.loc12_17: type = name_ref T, file.%T.loc11_13.2 [symbolic = @F.%T (constants.%T)] -// CHECK:STDOUT: %return.var.loc12: ref %T = var +// CHECK:STDOUT: %return.var.loc12: ref @F.%T (%T) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %G.decl: @Class.%G.type (%G.type) = fn_decl @G [symbolic = %G (constants.%G.1)] { // CHECK:STDOUT: %.loc16: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @G.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc16 [symbolic = @G.%Class (constants.%Class.2)] // CHECK:STDOUT: %self.loc16_8.1: @G.%Class (%Class.2) = param self // CHECK:STDOUT: %self.loc16_8.2: @G.%Class (%Class.2) = bind_name self, %self.loc16_8.1 // CHECK:STDOUT: %T.ref.loc16: type = name_ref T, file.%T.loc11_13.2 [symbolic = @G.%T (constants.%T)] -// CHECK:STDOUT: %return.var.loc16: ref %T = var +// CHECK:STDOUT: %return.var.loc16: ref @G.%T (%T) = var // CHECK:STDOUT: } // CHECK:STDOUT: %T.ref.loc20: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc20: @Class.%.1 (%.2) = field_decl n, element0 [template] @@ -100,7 +106,7 @@ class Class(T:! type) { // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn(@Class.%n.loc12_8.2: @F.%T (%T)) -> %T { +// CHECK:STDOUT: fn(@Class.%n.loc12_8.2: @F.%T (%T)) -> @F.%T (%T) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %n.ref: @F.%T (%T) = name_ref n, @Class.%n.loc12_8.2 // CHECK:STDOUT: return %n.ref @@ -114,7 +120,7 @@ class Class(T:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = unbound_element_type @G.%Class (%Class.2), @G.%T (%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@Class.%self.loc16_8.2: @G.%Class (%Class.2)]() -> %T { +// CHECK:STDOUT: fn[@Class.%self.loc16_8.2: @G.%Class (%Class.2)]() -> @G.%T (%T) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @G.%Class (%Class.2) = name_ref self, @Class.%self.loc16_8.2 // CHECK:STDOUT: %n.ref: @G.%.1 (%.2) = name_ref n, @Class.%.loc20 [template = @Class.%.loc20] @@ -128,6 +134,10 @@ class Class(T:! type) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: %G.type => constants.%G.type +// CHECK:STDOUT: %G => constants.%G.2 // CHECK:STDOUT: %Class => constants.%Class.2 // CHECK:STDOUT: %.1 => constants.%.2 // 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 cfadda690ce2..c7c5caabdf00 100644 --- a/toolchain/check/testdata/class/generic/member_out_of_line.carbon +++ b/toolchain/check/testdata/class/generic/member_out_of_line.carbon @@ -113,12 +113,14 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %G.type: type = fn_type @G [template] -// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %G.type: type = fn_type @G, @Class(%T) [symbolic] +// CHECK:STDOUT: %G.1: %G.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.n: %T} [symbolic] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %G.2: %G.type = struct_value () [symbolic] // CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -144,7 +146,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T.loc4_13.1: type = param T // CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T 0, %T.loc4_13.1 [symbolic = @Class.%T (constants.%T)] // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [symbolic = constants.%F.1] { // CHECK:STDOUT: %T.loc10_10.1: type = param T // CHECK:STDOUT: %T.loc10_10.2: type = bind_symbolic_name T 0, %T.loc10_10.1 [symbolic = constants.%T] // CHECK:STDOUT: %T.ref.loc10_25: type = name_ref T, %T.loc10_10.2 [symbolic = constants.%T] @@ -153,7 +155,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T.ref.loc10_31: type = name_ref T, %T.loc10_10.2 [symbolic = constants.%T] // CHECK:STDOUT: @F.%return: ref %T = var // CHECK:STDOUT: } -// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [symbolic = constants.%G.1] { // CHECK:STDOUT: %T.loc14_10.1: type = param T // CHECK:STDOUT: %T.loc14_10.2: type = bind_symbolic_name T 0, %T.loc14_10.1 [symbolic = constants.%T] // CHECK:STDOUT: %.loc14: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = constants.%Class.2] @@ -169,24 +171,28 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @Class.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %G.type: type = fn_type @G, @Class(%T) [symbolic = %G.type (constants.%G.type)] +// CHECK:STDOUT: %G: @Class.%G.type (%G.type) = struct_value () [symbolic = %G (constants.%G.1)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %T.ref.loc5_11: type = name_ref T, file.%T.loc4_13.2 [symbolic = @F.%T (constants.%T)] // CHECK:STDOUT: %n.loc5_8.1: @F.%T (%T) = param n // CHECK:STDOUT: %n.loc5_8.2: @F.%T (%T) = bind_name n, %n.loc5_8.1 // CHECK:STDOUT: %T.ref.loc5_17: type = name_ref T, file.%T.loc4_13.2 [symbolic = @F.%T (constants.%T)] -// CHECK:STDOUT: %return.var.loc5: ref %T = var +// CHECK:STDOUT: %return.var.loc5: ref @F.%T (%T) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %G.decl: @Class.%G.type (%G.type) = fn_decl @G [symbolic = %G (constants.%G.1)] { // CHECK:STDOUT: %.loc6: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @G.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc6 [symbolic = @G.%Class (constants.%Class.2)] // CHECK:STDOUT: %self.loc6_8.1: @G.%Class (%Class.2) = param self // CHECK:STDOUT: %self.loc6_8.2: @G.%Class (%Class.2) = bind_name self, %self.loc6_8.1 // CHECK:STDOUT: %T.ref.loc6: type = name_ref T, file.%T.loc4_13.2 [symbolic = @G.%T (constants.%T)] -// CHECK:STDOUT: %return.var.loc6: ref %T = var +// CHECK:STDOUT: %return.var.loc6: ref @G.%T (%T) = var // CHECK:STDOUT: } // CHECK:STDOUT: %T.ref.loc7: type = name_ref T, file.%T.loc4_13.2 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc7: @Class.%.1 (%.2) = field_decl n, element0 [template] @@ -232,6 +238,10 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: %G.type => constants.%G.type +// CHECK:STDOUT: %G => constants.%G.2 // CHECK:STDOUT: %Class => constants.%Class.2 // CHECK:STDOUT: %.1 => constants.%.2 // CHECK:STDOUT: } @@ -265,9 +275,10 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %B.type: type = generic_class_type @B [template] // CHECK:STDOUT: %B.1: %B.type = struct_value () [template] // CHECK:STDOUT: %B.2: type = class_type @B, @B(%T, %N) [symbolic] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @B(%T, %N) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -293,7 +304,7 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T.loc4_9.1: type = param T // CHECK:STDOUT: %T.loc4_9.2: type = bind_symbolic_name T 0, %T.loc4_9.1 [symbolic = @A.%T (constants.%T)] // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [symbolic = constants.%F.1] { // CHECK:STDOUT: %T.loc10_6.1: type = param T // CHECK:STDOUT: %T.loc10_6.2: type = bind_symbolic_name T 0, %T.loc10_6.1 [symbolic = constants.%T] // CHECK:STDOUT: %T.ref.loc10_22: type = name_ref T, %T.loc10_6.2 [symbolic = constants.%T] @@ -332,9 +343,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %N: %T = bind_symbolic_name N 1 [symbolic = %N (constants.%N)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type: type = fn_type @F, @B(%T, %N) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @B.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @B.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %.loc6: type = specific_constant constants.%B.2, @B(constants.%T, constants.%N) [symbolic = @F.%B (constants.%B.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc6 [symbolic = @F.%B (constants.%B.2)] // CHECK:STDOUT: %self.loc6_10.1: @F.%B (%B.2) = param self @@ -374,6 +387,8 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %N => constants.%N // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @B(@F.%T, @F.%N) { @@ -387,6 +402,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %B => constants.%B.2 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @B(@B.%T, @B.%N) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %N => constants.%N +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_not_generic_vs_generic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -458,8 +478,8 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] // CHECK:STDOUT: %Generic.2: type = class_type @Generic, @Generic(%T) [symbolic] -// CHECK:STDOUT: %TooFew.type: type = fn_type @TooFew [template] -// CHECK:STDOUT: %TooFew: %TooFew.type = struct_value () [template] +// CHECK:STDOUT: %TooFew.type: type = fn_type @TooFew, @Generic(%T) [symbolic] +// CHECK:STDOUT: %TooFew: %TooFew.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %.type: type = fn_type @.1 [template] // CHECK:STDOUT: %.3: %.type = struct_value () [template] @@ -494,9 +514,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %TooFew.type: type = fn_type @TooFew, @Generic(%T) [symbolic = %TooFew.type (constants.%TooFew.type)] +// CHECK:STDOUT: %TooFew: @Generic.%TooFew.type (%TooFew.type) = struct_value () [symbolic = %TooFew (constants.%TooFew)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %TooFew.decl: %TooFew.type = fn_decl @TooFew [template = constants.%TooFew] {} +// CHECK:STDOUT: %TooFew.decl: @Generic.%TooFew.type (%TooFew.type) = fn_decl @TooFew [symbolic = %TooFew (constants.%TooFew)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Generic.2 @@ -520,6 +542,10 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: // CHECK:STDOUT: specific @TooFew(constants.%T) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic(@Generic.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_mismatched_too_many_args.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -528,8 +554,8 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] // CHECK:STDOUT: %Generic.2: type = class_type @Generic, @Generic(%T) [symbolic] -// CHECK:STDOUT: %TooMany.type: type = fn_type @TooMany [template] -// CHECK:STDOUT: %TooMany: %TooMany.type = struct_value () [template] +// CHECK:STDOUT: %TooMany.type: type = fn_type @TooMany, @Generic(%T) [symbolic] +// CHECK:STDOUT: %TooMany: %TooMany.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %U: type = bind_symbolic_name U 1 [symbolic] // CHECK:STDOUT: %.type: type = fn_type @.1 [template] @@ -570,9 +596,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %TooMany.type: type = fn_type @TooMany, @Generic(%T) [symbolic = %TooMany.type (constants.%TooMany.type)] +// CHECK:STDOUT: %TooMany: @Generic.%TooMany.type (%TooMany.type) = struct_value () [symbolic = %TooMany (constants.%TooMany)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %TooMany.decl: %TooMany.type = fn_decl @TooMany [template = constants.%TooMany] {} +// CHECK:STDOUT: %TooMany.decl: @Generic.%TooMany.type (%TooMany.type) = fn_decl @TooMany [symbolic = %TooMany (constants.%TooMany)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Generic.2 @@ -603,6 +631,10 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: // CHECK:STDOUT: specific @TooMany(constants.%T) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic(@Generic.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @.1(constants.%T, constants.%U) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: %U => constants.%U @@ -616,8 +648,8 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Generic.1: %Generic.type = struct_value () [template] // CHECK:STDOUT: %Generic.2: type = class_type @Generic, @Generic(%T.1) [symbolic] -// CHECK:STDOUT: %WrongType.type: type = fn_type @WrongType [template] -// CHECK:STDOUT: %WrongType: %WrongType.type = struct_value () [template] +// CHECK:STDOUT: %WrongType.type: type = fn_type @WrongType, @Generic(%T.1) [symbolic] +// CHECK:STDOUT: %WrongType: %WrongType.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] // CHECK:STDOUT: %T.2: %.1 = bind_symbolic_name T 0 [symbolic] // CHECK:STDOUT: %.type: type = fn_type @.1 [template] @@ -658,9 +690,11 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T.1)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %WrongType.type: type = fn_type @WrongType, @Generic(%T) [symbolic = %WrongType.type (constants.%WrongType.type)] +// CHECK:STDOUT: %WrongType: @Generic.%WrongType.type (%WrongType.type) = struct_value () [symbolic = %WrongType (constants.%WrongType)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %WrongType.decl: %WrongType.type = fn_decl @WrongType [template = constants.%WrongType] {} +// CHECK:STDOUT: %WrongType.decl: @Generic.%WrongType.type (%WrongType.type) = fn_decl @WrongType [symbolic = %WrongType (constants.%WrongType)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Generic.2 @@ -690,6 +724,10 @@ fn Generic(T:! ()).WrongType() {} // CHECK:STDOUT: // CHECK:STDOUT: specific @WrongType(constants.%T.1) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @Generic(@Generic.%T) { +// CHECK:STDOUT: %T => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @.1(constants.%T.2) { // CHECK:STDOUT: %T => constants.%T.2 // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/generic/self.carbon b/toolchain/check/testdata/class/generic/self.carbon index d3d7e550f61e..c0a5d5b80ba3 100644 --- a/toolchain/check/testdata/class/generic/self.carbon +++ b/toolchain/check/testdata/class/generic/self.carbon @@ -27,13 +27,16 @@ class Class(T:! type) { // CHECK:STDOUT: %.1: type = tuple_type () [template] // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] -// CHECK:STDOUT: %MakeSelf.type: type = fn_type @MakeSelf [template] -// CHECK:STDOUT: %MakeSelf: %MakeSelf.type = struct_value () [template] -// CHECK:STDOUT: %MakeClass.type: type = fn_type @MakeClass [template] -// CHECK:STDOUT: %MakeClass: %MakeClass.type = struct_value () [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %MakeSelf.type: type = fn_type @MakeSelf, @Class(%T) [symbolic] +// CHECK:STDOUT: %MakeSelf.1: %MakeSelf.type = struct_value () [symbolic] +// CHECK:STDOUT: %MakeClass.type: type = fn_type @MakeClass, @Class(%T) [symbolic] +// CHECK:STDOUT: %MakeClass.1: %MakeClass.type = struct_value () [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %MakeSelf.2: %MakeSelf.type = struct_value () [symbolic] +// CHECK:STDOUT: %MakeClass.2: %MakeClass.type = struct_value () [symbolic] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.3: type = ptr_type %.2 [template] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -65,22 +68,28 @@ class Class(T:! type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %MakeSelf.type: type = fn_type @MakeSelf, @Class(%T) [symbolic = %MakeSelf.type (constants.%MakeSelf.type)] +// CHECK:STDOUT: %MakeSelf: @Class.%MakeSelf.type (%MakeSelf.type) = struct_value () [symbolic = %MakeSelf (constants.%MakeSelf.1)] +// CHECK:STDOUT: %MakeClass.type: type = fn_type @MakeClass, @Class(%T) [symbolic = %MakeClass.type (constants.%MakeClass.type)] +// CHECK:STDOUT: %MakeClass: @Class.%MakeClass.type (%MakeClass.type) = struct_value () [symbolic = %MakeClass (constants.%MakeClass.1)] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @Class.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] // CHECK:STDOUT: // CHECK:STDOUT: class { -// CHECK:STDOUT: %MakeSelf.decl: %MakeSelf.type = fn_decl @MakeSelf [template = constants.%MakeSelf] { +// CHECK:STDOUT: %MakeSelf.decl: @Class.%MakeSelf.type (%MakeSelf.type) = fn_decl @MakeSelf [symbolic = %MakeSelf (constants.%MakeSelf.1)] { // CHECK:STDOUT: %.loc14: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @MakeSelf.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc14 [symbolic = @MakeSelf.%Class (constants.%Class.2)] -// CHECK:STDOUT: %return.var.loc14: ref %Class.2 = var +// CHECK:STDOUT: %return.var.loc14: ref @MakeSelf.%Class (%Class.2) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %MakeClass.decl: %MakeClass.type = fn_decl @MakeClass [template = constants.%MakeClass] { +// CHECK:STDOUT: %MakeClass.decl: @Class.%MakeClass.type (%MakeClass.type) = fn_decl @MakeClass [symbolic = %MakeClass (constants.%MakeClass.1)] { // CHECK:STDOUT: %Class.ref: %Class.type = name_ref Class, file.%Class.decl [template = constants.%Class.1] // CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_13.2 [symbolic = @MakeClass.%T (constants.%T)] // CHECK:STDOUT: %.loc15_26: init type = call %Class.ref(%T.ref) [symbolic = @MakeClass.%Class (constants.%Class.2)] // CHECK:STDOUT: %.loc15_28.1: type = value_of_initializer %.loc15_26 [symbolic = @MakeClass.%Class (constants.%Class.2)] // CHECK:STDOUT: %.loc15_28.2: type = converted %.loc15_26, %.loc15_28.1 [symbolic = @MakeClass.%Class (constants.%Class.2)] -// CHECK:STDOUT: %return.var.loc15: ref %Class.2 = var +// CHECK:STDOUT: %return.var.loc15: ref @MakeClass.%Class (%Class.2) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Class.2 @@ -94,20 +103,24 @@ class Class(T:! type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> %Class.2; +// CHECK:STDOUT: fn() -> @MakeSelf.%Class (%Class.2); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @MakeClass(file.%T.loc11_13.2: type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> %Class.2; +// CHECK:STDOUT: fn() -> @MakeClass.%Class (%Class.2); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F(file.%T.loc11_13.2: type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] +// CHECK:STDOUT: %MakeSelf.type: type = fn_type @MakeSelf, @Class(%T) [symbolic = %MakeSelf.type (constants.%MakeSelf.type)] +// CHECK:STDOUT: %MakeSelf: @F.%MakeSelf.type (%MakeSelf.type) = struct_value () [symbolic = %MakeSelf (constants.%MakeSelf.2)] +// CHECK:STDOUT: %MakeClass.type: type = fn_type @MakeClass, @Class(%T) [symbolic = %MakeClass.type (constants.%MakeClass.type)] +// CHECK:STDOUT: %MakeClass: @F.%MakeClass.type (%MakeClass.type) = struct_value () [symbolic = %MakeClass (constants.%MakeClass.2)] // CHECK:STDOUT: // CHECK:STDOUT: fn() { // CHECK:STDOUT: !entry: @@ -118,7 +131,8 @@ class Class(T:! type) { // CHECK:STDOUT: %.loc17_19.2: type = converted %.loc17_17, %.loc17_19.1 [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %c.var: ref @F.%Class (%Class.2) = var c // CHECK:STDOUT: %c: ref @F.%Class (%Class.2) = bind_name c, %c.var -// CHECK:STDOUT: %MakeSelf.ref: %MakeSelf.type = name_ref MakeSelf, @Class.%MakeSelf.decl [template = constants.%MakeSelf] +// CHECK:STDOUT: %.loc17_23: @F.%MakeSelf.type (%MakeSelf.type) = specific_constant @Class.%MakeSelf.decl, @Class(constants.%T) [symbolic = %MakeSelf (constants.%MakeSelf.2)] +// CHECK:STDOUT: %MakeSelf.ref: @F.%MakeSelf.type (%MakeSelf.type) = name_ref MakeSelf, %.loc17_23 [symbolic = %MakeSelf (constants.%MakeSelf.2)] // CHECK:STDOUT: %.loc17_9: ref @F.%Class (%Class.2) = splice_block %c.var {} // CHECK:STDOUT: %MakeSelf.call: init @F.%Class (%Class.2) = call %MakeSelf.ref() to %.loc17_9 // CHECK:STDOUT: assign %c.var, %MakeSelf.call @@ -126,7 +140,8 @@ class Class(T:! type) { // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc18_12 [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %s.var: ref @F.%Class (%Class.2) = var s // CHECK:STDOUT: %s: ref @F.%Class (%Class.2) = bind_name s, %s.var -// CHECK:STDOUT: %MakeClass.ref: %MakeClass.type = name_ref MakeClass, @Class.%MakeClass.decl [template = constants.%MakeClass] +// CHECK:STDOUT: %.loc18_19: @F.%MakeClass.type (%MakeClass.type) = specific_constant @Class.%MakeClass.decl, @Class(constants.%T) [symbolic = %MakeClass (constants.%MakeClass.2)] +// CHECK:STDOUT: %MakeClass.ref: @F.%MakeClass.type (%MakeClass.type) = name_ref MakeClass, %.loc18_19 [symbolic = %MakeClass (constants.%MakeClass.2)] // CHECK:STDOUT: %.loc18_9: ref @F.%Class (%Class.2) = splice_block %s.var {} // CHECK:STDOUT: %MakeClass.call: init @F.%Class (%Class.2) = call %MakeClass.ref() to %.loc18_9 // CHECK:STDOUT: assign %s.var, %MakeClass.call @@ -138,6 +153,12 @@ class Class(T:! type) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: // CHECK:STDOUT: !definition: +// CHECK:STDOUT: %MakeSelf.type => constants.%MakeSelf.type +// CHECK:STDOUT: %MakeSelf => constants.%MakeSelf.2 +// CHECK:STDOUT: %MakeClass.type => constants.%MakeClass.type +// CHECK:STDOUT: %MakeClass => constants.%MakeClass.2 +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class(@MakeSelf.%T) { @@ -160,6 +181,10 @@ class Class(T:! type) { // CHECK:STDOUT: // CHECK:STDOUT: specific @F(constants.%T) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @Class(@Class.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @Class(@F.%T) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/generic_method.carbon b/toolchain/check/testdata/class/generic_method.carbon index 06afd84b419f..38ba96a16b03 100644 --- a/toolchain/check/testdata/class/generic_method.carbon +++ b/toolchain/check/testdata/class/generic_method.carbon @@ -24,9 +24,10 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: %Class.1: %Class.type = struct_value () [template] // CHECK:STDOUT: %Class.2: type = class_type @Class, @Class(%T) [symbolic] // CHECK:STDOUT: %.2: type = unbound_element_type %Class.2, %T [symbolic] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.3: type = struct_type {.a: %T} [symbolic] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] // CHECK:STDOUT: %.4: type = ptr_type %.3 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -52,7 +53,7 @@ fn Class(T:! type).F[self: Self](n: 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 = @Class.%T (constants.%T)] // CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [symbolic = constants.%F.1] { // CHECK:STDOUT: %T.loc16_10.1: type = param T // CHECK:STDOUT: %T.loc16_10.2: type = bind_symbolic_name T 0, %T.loc16_10.1 [symbolic = constants.%T] // CHECK:STDOUT: %.loc16: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = constants.%Class.2] @@ -71,11 +72,13 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: !definition: // CHECK:STDOUT: %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class.2)] // CHECK:STDOUT: %.1: type = unbound_element_type @Class.%Class (%Class.2), @Class.%T (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %F.type: type = fn_type @F, @Class(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @Class.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] // CHECK:STDOUT: // CHECK:STDOUT: class { // CHECK:STDOUT: %T.ref.loc12: type = name_ref T, file.%T.loc11_13.2 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %.loc12: @Class.%.1 (%.2) = field_decl a, element0 [template] -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %.loc13: type = specific_constant constants.%Class.2, @Class(constants.%T) [symbolic = @F.%Class (constants.%Class.2)] // CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc13 [symbolic = @F.%Class (constants.%Class.2)] // CHECK:STDOUT: %self.loc13_8.1: @F.%Class (%Class.2) = param self @@ -110,6 +113,8 @@ fn Class(T:! type).F[self: Self](n: T) {} // CHECK:STDOUT: !definition: // CHECK:STDOUT: %Class => constants.%Class.2 // CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Class(@F.%T) { diff --git a/toolchain/check/testdata/function/builtin/method.carbon b/toolchain/check/testdata/function/builtin/method.carbon index f637dc4f42c9..e677e05c3cf7 100644 --- a/toolchain/check/testdata/function/builtin/method.carbon +++ b/toolchain/check/testdata/function/builtin/method.carbon @@ -100,7 +100,7 @@ var arr: [i32; 1.(I.F)(2)]; // CHECK:STDOUT: %Self.ref.loc12_36: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_36.1: type = facet_type_access %Self.ref.loc12_36 [symbolic = @F.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_36.2: type = converted %Self.ref.loc12_36, %.loc12_36.1 [symbolic = @F.1.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @F.1.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc12_40: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -137,7 +137,7 @@ var arr: [i32; 1.(I.F)(2)]; // CHECK:STDOUT: generic fn @F.1(@I.%Self: %.1) { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@I.%self.loc12_8.2: @F.1.%Self (%Self)](@I.%other.loc12_20.2: @F.1.%Self (%Self)) -> %Self; +// CHECK:STDOUT: fn[@I.%self.loc12_8.2: @F.1.%Self (%Self)](@I.%other.loc12_20.2: @F.1.%Self (%Self)) -> @F.1.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon index 5f325e81f07f..53bfbfd84f45 100644 --- a/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon +++ b/toolchain/check/testdata/function/builtin/no_prelude/call_from_operator.carbon @@ -71,7 +71,7 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4); // CHECK:STDOUT: %Self.ref.loc7_37: %.2 = name_ref Self, %Self [symbolic = @Op.%Self (constants.%Self)] // CHECK:STDOUT: %.loc7_37.1: type = facet_type_access %Self.ref.loc7_37 [symbolic = @Op.%Self (constants.%Self)] // CHECK:STDOUT: %.loc7_37.2: type = converted %Self.ref.loc7_37, %.loc7_37.1 [symbolic = @Op.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @Op.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc7_41: %.3 = assoc_entity element0, %Op.decl [template = constants.%.4] // CHECK:STDOUT: @@ -86,7 +86,7 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4); // CHECK:STDOUT: generic fn @Op(@Add.%Self: %.2) { // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@Add.%self.loc7_9.2: @Op.%Self (%Self)](@Add.%other.loc7_21.2: @Op.%Self (%Self)) -> %Self; +// CHECK:STDOUT: fn[@Add.%self.loc7_9.2: @Op.%Self (%Self)](@Add.%other.loc7_21.2: @Op.%Self (%Self)) -> @Op.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Op(constants.%Self) { 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 05c47f7aa2ba..b0981e84e921 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 @@ -37,7 +37,7 @@ fn F(T:! type, p: T**) -> T* { // CHECK:STDOUT: @F.%p: @F.%.2 (%.2) = bind_name p, %p.loc11_16.1 // CHECK:STDOUT: %T.ref.loc11_27: type = name_ref T, @F.%T.loc11 [symbolic = @F.%T.1 (constants.%T)] // CHECK:STDOUT: %.loc11_28: type = ptr_type %T [symbolic = @F.%.1 (constants.%.1)] -// CHECK:STDOUT: @F.%return: ref %.1 = var +// CHECK:STDOUT: @F.%return: ref @F.%.1 (%.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -48,7 +48,7 @@ fn F(T:! type, p: T**) -> T* { // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc11: type, %p: @F.%.2 (%.2)) -> %.1 { +// CHECK:STDOUT: fn(%T.loc11: type, %p: @F.%.2 (%.2)) -> @F.%.1 (%.1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %p.ref: @F.%.2 (%.2) = name_ref p, %p // CHECK:STDOUT: %.loc12_10.1: ref @F.%.1 (%.1) = deref %p.ref 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 3abe924f333b..9980f745deb4 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 @@ -33,7 +33,7 @@ fn F(T:! type, n: T) -> T { // CHECK:STDOUT: %n.loc11_16.1: @F.%T.1 (%T) = param n // CHECK:STDOUT: @F.%n: @F.%T.1 (%T) = bind_name n, %n.loc11_16.1 // CHECK:STDOUT: %T.ref.loc11_25: type = name_ref T, @F.%T.loc11 [symbolic = @F.%T.1 (constants.%T)] -// CHECK:STDOUT: @F.%return: ref %T = var +// CHECK:STDOUT: @F.%return: ref @F.%T.1 (%T) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -42,7 +42,7 @@ fn F(T:! type, n: T) -> T { // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc11: type, %n: @F.%T.1 (%T)) -> %T { +// CHECK:STDOUT: fn(%T.loc11: type, %n: @F.%T.1 (%T)) -> @F.%T.1 (%T) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc11 [symbolic = %T.1 (constants.%T)] // CHECK:STDOUT: %n.ref: @F.%T.1 (%T) = name_ref n, %n diff --git a/toolchain/check/testdata/function/generic/redeclare.carbon b/toolchain/check/testdata/function/generic/redeclare.carbon index 4bdc042ca366..34338784032c 100644 --- a/toolchain/check/testdata/function/generic/redeclare.carbon +++ b/toolchain/check/testdata/function/generic/redeclare.carbon @@ -134,7 +134,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %T.loc4_6.2: type = bind_symbolic_name T 0, %T.loc4_6.1 [symbolic = @F.%T.1 (constants.%T)] // CHECK:STDOUT: %T.ref.loc4: type = name_ref T, %T.loc4_6.2 [symbolic = @F.%T.1 (constants.%T)] // CHECK:STDOUT: %.loc4: type = ptr_type %T [symbolic = @F.%.1 (constants.%.1)] -// CHECK:STDOUT: %return.var.loc4: ref %.1 = var +// CHECK:STDOUT: %return.var.loc4: ref @F.%.1 (%.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: %F.decl.loc6: %F.type = fn_decl @F [template = constants.%F] { // CHECK:STDOUT: %T.loc6_6.1: type = param T @@ -206,7 +206,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @F.%U.loc4: type = bind_symbolic_name U 1, %U.loc4_16.1 [symbolic = @F.%U.1 (constants.%U)] // CHECK:STDOUT: %T.ref: type = name_ref T, @F.%T.loc4 [symbolic = @F.%T.1 (constants.%T)] // CHECK:STDOUT: %.loc4: type = ptr_type %T [symbolic = @F.%.1 (constants.%.1)] -// CHECK:STDOUT: @F.%return: ref %.1 = var +// CHECK:STDOUT: @F.%return: ref @F.%.1 (%.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.4] { // CHECK:STDOUT: %T.loc13_6.1: type = param T @@ -215,7 +215,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @.1.%U.loc13: type = bind_symbolic_name U 1, %U.loc13_16.1 [symbolic = @.1.%U.1 (constants.%U)] // CHECK:STDOUT: %U.ref: type = name_ref U, @.1.%U.loc13 [symbolic = @.1.%U.1 (constants.%U)] // CHECK:STDOUT: %.loc13: type = ptr_type %U [symbolic = @.1.%.1 (constants.%.3)] -// CHECK:STDOUT: @.1.%return: ref %.3 = var +// CHECK:STDOUT: @.1.%return: ref @.1.%.1 (%.3) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -224,7 +224,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %U.1: type = bind_symbolic_name U 1 [symbolic = %U.1 (constants.%U)] // CHECK:STDOUT: %.1: type = ptr_type @F.%T.1 (%T) [symbolic = %.1 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> %.1; +// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> @F.%.1 (%.1); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @.1(%T.loc13: type, %U.loc13: type) { @@ -235,7 +235,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.2: type = ptr_type @.1.%T.1 (%T) [symbolic = %.2 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc13: type, %U.loc13: type) -> %.3 { +// CHECK:STDOUT: fn(%T.loc13: type, %U.loc13: type) -> @.1.%.1 (%.3) { // 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.loc13 [symbolic = %T.1 (constants.%T)] @@ -297,7 +297,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @F.%U.loc4: type = bind_symbolic_name U 1, %U.loc4_16.1 [symbolic = @F.%U.1 (constants.%U.1)] // CHECK:STDOUT: %T.ref.loc4: type = name_ref T, @F.%T.loc4 [symbolic = @F.%T.1 (constants.%T.1)] // CHECK:STDOUT: %.loc4: type = ptr_type %T.1 [symbolic = @F.%.1 (constants.%.1)] -// CHECK:STDOUT: @F.%return: ref %.1 = var +// CHECK:STDOUT: @F.%return: ref @F.%.1 (%.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.4] { // CHECK:STDOUT: %U.loc13_6.1: type = param U @@ -306,7 +306,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @.1.%T.loc13: type = bind_symbolic_name T 1, %T.loc13_16.1 [symbolic = @.1.%T.1 (constants.%T.2)] // CHECK:STDOUT: %T.ref.loc13: type = name_ref T, @.1.%T.loc13 [symbolic = @.1.%T.1 (constants.%T.2)] // CHECK:STDOUT: %.loc13: type = ptr_type %T.2 [symbolic = @.1.%.1 (constants.%.3)] -// CHECK:STDOUT: @.1.%return: ref %.3 = var +// CHECK:STDOUT: @.1.%return: ref @.1.%.1 (%.3) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -315,7 +315,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %U.1: type = bind_symbolic_name U 1 [symbolic = %U.1 (constants.%U.1)] // CHECK:STDOUT: %.1: type = ptr_type @F.%T.1 (%T.1) [symbolic = %.1 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> %.1; +// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> @F.%.1 (%.1); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @.1(%U.loc13: type, %T.loc13: type) { @@ -327,7 +327,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %T.2: type = bind_symbolic_name T 0 [symbolic = %T.2 (constants.%T.1)] // CHECK:STDOUT: %.2: type = ptr_type @.1.%T.2 (%T.1) [symbolic = %.2 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%U.loc13: type, %T.loc13: type) -> %.3 { +// CHECK:STDOUT: fn(%U.loc13: type, %T.loc13: type) -> @.1.%.1 (%.3) { // 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.loc13 [symbolic = %T.1 (constants.%T.2)] @@ -389,7 +389,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @F.%U.loc4: type = bind_symbolic_name U 1, %U.loc4_16.1 [symbolic = @F.%U.1 (constants.%U.1)] // CHECK:STDOUT: %T.ref: type = name_ref T, @F.%T.loc4 [symbolic = @F.%T.1 (constants.%T.1)] // CHECK:STDOUT: %.loc4: type = ptr_type %T.1 [symbolic = @F.%.1 (constants.%.1)] -// CHECK:STDOUT: @F.%return: ref %.1 = var +// CHECK:STDOUT: @F.%return: ref @F.%.1 (%.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.4] { // CHECK:STDOUT: %U.loc13_6.1: type = param U @@ -398,7 +398,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: @.1.%T.loc13: type = bind_symbolic_name T 1, %T.loc13_16.1 [symbolic = @.1.%T.1 (constants.%T.2)] // CHECK:STDOUT: %U.ref: type = name_ref U, @.1.%U.loc13 [symbolic = @.1.%U.1 (constants.%U.2)] // CHECK:STDOUT: %.loc13: type = ptr_type %U.2 [symbolic = @.1.%.1 (constants.%.3)] -// CHECK:STDOUT: @.1.%return: ref %.3 = var +// CHECK:STDOUT: @.1.%return: ref @.1.%.1 (%.3) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -407,7 +407,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %U.1: type = bind_symbolic_name U 1 [symbolic = %U.1 (constants.%U.1)] // CHECK:STDOUT: %.1: type = ptr_type @F.%T.1 (%T.1) [symbolic = %.1 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> %.1; +// CHECK:STDOUT: fn(%T.loc4: type, %U.loc4: type) -> @F.%.1 (%.1); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @.1(%U.loc13: type, %T.loc13: type) { @@ -419,7 +419,7 @@ fn F(U:! type, T:! type) -> U* { // CHECK:STDOUT: %T.2: type = bind_symbolic_name T 0 [symbolic = %T.2 (constants.%T.1)] // CHECK:STDOUT: %.2: type = ptr_type @.1.%T.2 (%T.1) [symbolic = %.2 (constants.%.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%U.loc13: type, %T.loc13: type) -> %.3 { +// CHECK:STDOUT: fn(%U.loc13: type, %T.loc13: type) -> @.1.%.1 (%.3) { // 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.loc13 [symbolic = %T.1 (constants.%T.2)] diff --git a/toolchain/check/testdata/function/generic/return_slot.carbon b/toolchain/check/testdata/function/generic/return_slot.carbon new file mode 100644 index 000000000000..c44afeff79b5 --- /dev/null +++ b/toolchain/check/testdata/function/generic/return_slot.carbon @@ -0,0 +1,217 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/return_slot.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/return_slot.carbon + +class Wrap(T:! type) { + fn Make() -> T; +} + +class C { var arr: [i32; 100]; } + +fn G() { + var a: i32 = Wrap(i32).Make(); + var b: () = Wrap(()).Make(); + var c: C = Wrap(C).Make(); +} + +// CHECK:STDOUT: --- return_slot.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %Wrap.type: type = generic_class_type @Wrap [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Wrap.1: %Wrap.type = struct_value () [template] +// CHECK:STDOUT: %Wrap.2: type = class_type @Wrap, @Wrap(%T) [symbolic] +// CHECK:STDOUT: %Make.type.1: type = fn_type @Make, @Wrap(%T) [symbolic] +// CHECK:STDOUT: %Make.1: %Make.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.3: i32 = int_literal 100 [template] +// CHECK:STDOUT: %.4: type = array_type %.3, i32 [template] +// CHECK:STDOUT: %.5: type = ptr_type %.4 [template] +// CHECK:STDOUT: %.6: type = unbound_element_type %C, %.4 [template] +// CHECK:STDOUT: %.7: type = struct_type {.arr: %.4} [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %Wrap.3: type = class_type @Wrap, @Wrap(i32) [template] +// CHECK:STDOUT: %Make.type.2: type = fn_type @Make, @Wrap(i32) [template] +// CHECK:STDOUT: %Make.2: %Make.type.2 = struct_value () [template] +// CHECK:STDOUT: %.8: type = ptr_type %.2 [template] +// CHECK:STDOUT: %Wrap.4: type = class_type @Wrap, @Wrap(%.1) [template] +// CHECK:STDOUT: %Make.type.3: type = fn_type @Make, @Wrap(%.1) [template] +// CHECK:STDOUT: %Make.3: %Make.type.3 = struct_value () [template] +// CHECK:STDOUT: %.9: type = struct_type {.arr: %.5} [template] +// CHECK:STDOUT: %.10: type = ptr_type %.7 [template] +// CHECK:STDOUT: %Wrap.5: type = class_type @Wrap, @Wrap(%C) [template] +// CHECK:STDOUT: %Make.type.4: type = fn_type @Make, @Wrap(%C) [template] +// CHECK:STDOUT: %Make.4: %Make.type.4 = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// 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: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Wrap = %Wrap.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Wrap.decl: %Wrap.type = class_decl @Wrap [template = constants.%Wrap.1] { +// CHECK:STDOUT: %T.loc11_12.1: type = param T +// CHECK:STDOUT: %T.loc11_12.2: type = bind_symbolic_name T 0, %T.loc11_12.1 [symbolic = @Wrap.%T (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Wrap(file.%T.loc11_12.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type: type = fn_type @Make, @Wrap(%T) [symbolic = %Make.type (constants.%Make.type.1)] +// CHECK:STDOUT: %Make: @Wrap.%Make.type (%Make.type.1) = struct_value () [symbolic = %Make (constants.%Make.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %Make.decl: @Wrap.%Make.type (%Make.type.1) = fn_decl @Make [symbolic = %Make (constants.%Make.1)] { +// CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_12.2 [symbolic = @Make.%T (constants.%T)] +// CHECK:STDOUT: %return.var: ref @Make.%T (%T) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Wrap.2 +// CHECK:STDOUT: .Make = %Make.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc15_26: i32 = int_literal 100 [template = constants.%.3] +// CHECK:STDOUT: %.loc15_21.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc15_21.2: type = converted %int.make_type_32, %.loc15_21.1 [template = i32] +// CHECK:STDOUT: %.loc15_29: type = array_type %.loc15_26, i32 [template = constants.%.4] +// CHECK:STDOUT: %.loc15_18: %.6 = field_decl arr, element0 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .arr = %.loc15_18 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Make(file.%T.loc11_12.2: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @Make.%T (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int.make_type_32.loc18_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc18_10.1: type = value_of_initializer %int.make_type_32.loc18_10 [template = i32] +// CHECK:STDOUT: %.loc18_10.2: type = converted %int.make_type_32.loc18_10, %.loc18_10.1 [template = i32] +// CHECK:STDOUT: %a.var: ref i32 = var a +// CHECK:STDOUT: %a: ref i32 = bind_name a, %a.var +// CHECK:STDOUT: %Wrap.ref.loc18: %Wrap.type = name_ref Wrap, file.%Wrap.decl [template = constants.%Wrap.1] +// CHECK:STDOUT: %int.make_type_32.loc18_21: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc18_20.1: type = value_of_initializer %int.make_type_32.loc18_21 [template = i32] +// CHECK:STDOUT: %.loc18_20.2: type = converted %int.make_type_32.loc18_21, %.loc18_20.1 [template = i32] +// CHECK:STDOUT: %.loc18_20.3: init type = call %Wrap.ref.loc18(%.loc18_20.2) [template = constants.%Wrap.3] +// CHECK:STDOUT: %.loc18_25: %Make.type.2 = specific_constant @Wrap.%Make.decl, @Wrap(i32) [template = constants.%Make.2] +// CHECK:STDOUT: %Make.ref.loc18: %Make.type.2 = name_ref Make, %.loc18_25 [template = constants.%Make.2] +// CHECK:STDOUT: %Make.call.loc18: init i32 = call %Make.ref.loc18() +// CHECK:STDOUT: assign %a.var, %Make.call.loc18 +// CHECK:STDOUT: %.loc19_11.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc19_11.2: type = converted %.loc19_11.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %b.var: ref %.1 = var b +// CHECK:STDOUT: %b: ref %.1 = bind_name b, %b.var +// CHECK:STDOUT: %Wrap.ref.loc19: %Wrap.type = name_ref Wrap, file.%Wrap.decl [template = constants.%Wrap.1] +// CHECK:STDOUT: %.loc19_21: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc19_19.1: type = converted %.loc19_21, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc19_19.2: init type = call %Wrap.ref.loc19(%.loc19_19.1) [template = constants.%Wrap.4] +// CHECK:STDOUT: %.loc19_23: %Make.type.3 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%.1) [template = constants.%Make.3] +// CHECK:STDOUT: %Make.ref.loc19: %Make.type.3 = name_ref Make, %.loc19_23 [template = constants.%Make.3] +// CHECK:STDOUT: %Make.call.loc19: init %.1 = call %Make.ref.loc19() +// CHECK:STDOUT: assign %b.var, %Make.call.loc19 +// CHECK:STDOUT: %C.ref.loc20_10: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %c.var: ref %C = var c +// CHECK:STDOUT: %c: ref %C = bind_name c, %c.var +// CHECK:STDOUT: %Wrap.ref.loc20: %Wrap.type = name_ref Wrap, file.%Wrap.decl [template = constants.%Wrap.1] +// CHECK:STDOUT: %C.ref.loc20_19: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc20_18: init type = call %Wrap.ref.loc20(%C.ref.loc20_19) [template = constants.%Wrap.5] +// CHECK:STDOUT: %.loc20_21: %Make.type.4 = specific_constant @Wrap.%Make.decl, @Wrap(constants.%C) [template = constants.%Make.4] +// CHECK:STDOUT: %Make.ref.loc20: %Make.type.4 = name_ref Make, %.loc20_21 [template = constants.%Make.4] +// CHECK:STDOUT: %.loc20_7: ref %C = splice_block %c.var {} +// CHECK:STDOUT: %Make.call.loc20: init %C = call %Make.ref.loc20() to %.loc20_7 +// CHECK:STDOUT: assign %c.var, %Make.call.loc20 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Wrap(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Make(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Wrap(@Wrap.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Wrap(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type => constants.%Make.type.2 +// CHECK:STDOUT: %Make => constants.%Make.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Make(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Wrap(constants.%.1) { +// CHECK:STDOUT: %T => constants.%.1 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type => constants.%Make.type.3 +// CHECK:STDOUT: %Make => constants.%Make.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Make(constants.%.1) { +// CHECK:STDOUT: %T => constants.%.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Wrap(constants.%C) { +// CHECK:STDOUT: %T => constants.%C +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Make.type => constants.%Make.type.4 +// CHECK:STDOUT: %Make => constants.%Make.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Make(constants.%C) { +// CHECK:STDOUT: %T => constants.%C +// CHECK:STDOUT: } +// 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 d6409e2523a0..c831663e34bb 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -30,10 +30,10 @@ class C { // CHECK:STDOUT: %GenericInterface: %GenericInterface.type = struct_value () [template] // CHECK:STDOUT: %.2: type = interface_type @GenericInterface, @GenericInterface(%T) [symbolic] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] -// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %.3: type = assoc_entity_type @GenericInterface, %F.type.1 [template] -// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @GenericInterface.%F.decl [template] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @GenericInterface(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @GenericInterface, %F.type.1 [symbolic] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @GenericInterface.%F.decl [symbolic] // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] @@ -73,15 +73,19 @@ class C { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = interface_type @GenericInterface, @GenericInterface(%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @GenericInterface(%T) [symbolic = %F.type (constants.%F.type.1)] +// CHECK:STDOUT: %F: @GenericInterface.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @GenericInterface, @GenericInterface.%F.type (%F.type.1) [symbolic = %.2 (constants.%.3)] +// CHECK:STDOUT: %.3: @GenericInterface.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: %Self.1: @GenericInterface.%.1 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] -// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { +// CHECK:STDOUT: %F.decl: @GenericInterface.%F.type (%F.type.1) = fn_decl @F.1 [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %T.ref: type = name_ref T, file.%T.loc11_28.2 [symbolic = @F.1.%T (constants.%T)] // CHECK:STDOUT: %x.loc12_8.1: @F.1.%T (%T) = param x // CHECK:STDOUT: %x.loc12_8.2: @F.1.%T (%T) = bind_name x, %x.loc12_8.1 // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc12: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] +// CHECK:STDOUT: %.loc12: @GenericInterface.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 diff --git a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon index 9eacbbbcb5d6..80b8cb7c9e75 100644 --- a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon +++ b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon @@ -422,7 +422,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %.loc188_45.1: type = facet_type_access %Self.ref.loc188_45 [symbolic = @F.13.%Self (constants.%Self.3)] // CHECK:STDOUT: %.loc188_45.2: type = converted %Self.ref.loc188_45, %.loc188_45.1 [symbolic = @F.13.%Self (constants.%Self.3)] // CHECK:STDOUT: %.loc188_52: type = array_type %.loc188_51, %Self.3 [symbolic = @F.13.%.4 (constants.%.15)] -// CHECK:STDOUT: %return.var: ref %.15 = var +// CHECK:STDOUT: %return.var: ref @F.13.%.4 (%.15) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc188_53: %.17 = assoc_entity element0, %F.decl [template = constants.%.18] // CHECK:STDOUT: @@ -880,7 +880,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %.3: type = tuple_type (@F.13.%.1 (%.10), @F.13.%.2 (%.11)) [symbolic = %.3 (constants.%.13)] // CHECK:STDOUT: %.4: type = array_type constants.%.14, @F.13.%Self (%Self.3) [symbolic = %.4 (constants.%.15)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(@SelfNested.%x.loc188_8.2: @F.13.%.3 (%.13)) -> %.15; +// CHECK:STDOUT: fn(@SelfNested.%x.loc188_8.2: @F.13.%.3 (%.13)) -> @F.13.%.4 (%.15); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.14(@impl.14.%x.loc200_10.2: %.21) -> %.22; diff --git a/toolchain/check/testdata/impl/no_prelude/import_self.carbon b/toolchain/check/testdata/impl/no_prelude/import_self.carbon index c2522058c45e..b0ad6b59ea54 100644 --- a/toolchain/check/testdata/impl/no_prelude/import_self.carbon +++ b/toolchain/check/testdata/impl/no_prelude/import_self.carbon @@ -65,7 +65,7 @@ fn F(x: (), y: ()) -> () { // CHECK:STDOUT: %Self.ref.loc5_37: %.1 = name_ref Self, %Self [symbolic = @Op.%Self (constants.%Self)] // CHECK:STDOUT: %.loc5_37.1: type = facet_type_access %Self.ref.loc5_37 [symbolic = @Op.%Self (constants.%Self)] // CHECK:STDOUT: %.loc5_37.2: type = converted %Self.ref.loc5_37, %.loc5_37.1 [symbolic = @Op.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @Op.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc5_41: %.3 = assoc_entity element0, %Op.decl [template = constants.%.4] // CHECK:STDOUT: @@ -78,7 +78,7 @@ fn F(x: (), y: ()) -> () { // CHECK:STDOUT: generic fn @Op(@Add.%Self: %.1) { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@Add.%self.loc5_9.2: @Op.%Self (%Self)](@Add.%other.loc5_21.2: @Op.%Self (%Self)) -> %Self; +// CHECK:STDOUT: fn[@Add.%self.loc5_9.2: @Op.%Self (%Self)](@Add.%other.loc5_21.2: @Op.%Self (%Self)) -> @Op.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Op(constants.%Self) { diff --git a/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon b/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon index 62c348569205..2ccedab47383 100644 --- a/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon +++ b/toolchain/check/testdata/impl/no_prelude/self_in_class.carbon @@ -59,7 +59,7 @@ class A { // CHECK:STDOUT: %Self.ref: %.1 = name_ref Self, %Self [symbolic = @Make.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_16.1: type = facet_type_access %Self.ref [symbolic = @Make.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_16.2: type = converted %Self.ref, %.loc12_16.1 [symbolic = @Make.1.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @Make.1.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc12_20: %.3 = assoc_entity element0, %Make.decl [template = constants.%.4] // CHECK:STDOUT: @@ -99,7 +99,7 @@ class A { // CHECK:STDOUT: generic fn @Make.1(@DefaultConstructible.%Self: %.1) { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> %Self; +// CHECK:STDOUT: fn() -> @Make.1.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Make.2() -> @impl.%return.var: %C { diff --git a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon index 1ea007cd1c81..15bd0344bbd7 100644 --- a/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon +++ b/toolchain/check/testdata/impl/no_prelude/self_in_signature.carbon @@ -128,7 +128,7 @@ impl D as SelfNested { // CHECK:STDOUT: %Self.ref.loc12_32: %.1 = name_ref Self, %Self [symbolic = @F.1.%Self (constants.%Self.1)] // CHECK:STDOUT: %.loc12_32.1: type = facet_type_access %Self.ref.loc12_32 [symbolic = @F.1.%Self (constants.%Self.1)] // CHECK:STDOUT: %.loc12_32.2: type = converted %Self.ref.loc12_32, %.loc12_32.1 [symbolic = @F.1.%Self (constants.%Self.1)] -// CHECK:STDOUT: %return.var: ref %Self.1 = var +// CHECK:STDOUT: %return.var: ref @F.1.%Self (%Self.1) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc12_36: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -253,7 +253,7 @@ impl D as SelfNested { // CHECK:STDOUT: generic fn @F.1(@UseSelf.%Self: %.1) { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self.1)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@UseSelf.%self.loc12_8.2: @F.1.%Self (%Self.1)](@UseSelf.%x.loc12_20.2: @F.1.%Self (%Self.1)) -> %Self.1; +// CHECK:STDOUT: fn[@UseSelf.%self.loc12_8.2: @F.1.%Self (%Self.1)](@UseSelf.%x.loc12_20.2: @F.1.%Self (%Self.1)) -> @F.1.%Self (%Self.1); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2[@impl.1.%self.loc20_8.2: %C](@impl.1.%x.loc20_17.2: %C) -> @impl.1.%return.var: %C { 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 ba3331c2feb4..88af674bf7ab 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 @@ -43,10 +43,11 @@ interface Outer { // CHECK:STDOUT: %Self.2: %.3 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %.4: type = interface_type @Inner [template] // CHECK:STDOUT: %Self.3: %.4 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %.type: type = fn_type @.1 [template] -// CHECK:STDOUT: %.5: %.type = struct_value () [template] -// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] -// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1, @Inner(%Self.2) [symbolic] +// CHECK:STDOUT: %.5: %.type = struct_value () [symbolic] +// CHECK:STDOUT: %.6: %.type = struct_value () [symbolic] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.2, @Inner(%Self.2) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -71,7 +72,7 @@ interface Outer { // CHECK:STDOUT: interface @Outer { // CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] // CHECK:STDOUT: %Inner.decl: type = interface_decl @Inner [template = constants.%.4] {} -// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {} +// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [symbolic = constants.%F.2] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -82,10 +83,13 @@ interface Outer { // CHECK:STDOUT: generic interface @Inner(@Outer.%Self: %.3) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] +// CHECK:STDOUT: %Self.3: %.3 = bind_symbolic_name Self 0 [symbolic = %Self.3 (constants.%Self.2)] +// CHECK:STDOUT: %.type: type = fn_type @.1, @Inner(%Self.3) [symbolic = %.type (constants.%.type)] +// CHECK:STDOUT: %.1: @Inner.%.type (%.type) = struct_value () [symbolic = %.1 (constants.%.5)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: %Self.1: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.3)] -// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] {} +// CHECK:STDOUT: %.decl: @Inner.%.type (%.type) = fn_decl @.1 [symbolic = %.1 (constants.%.5)] {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 @@ -112,9 +116,14 @@ interface Outer { // CHECK:STDOUT: specific @Inner(constants.%Self.2) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %Self.2 => constants.%Self.3 +// CHECK:STDOUT: %Self.3 => constants.%Self.2 +// CHECK:STDOUT: %.type => constants.%.type +// CHECK:STDOUT: %.1 => constants.%.6 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @.1(constants.%Self.2, constants.%Self.3) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @Inner(@Inner.%Self.3) {} +// CHECK:STDOUT: // CHECK:STDOUT: specific @F.2(constants.%Self.2) {} // 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 c532ecab40c5..1356aaefc10d 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 @@ -30,12 +30,13 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %I: %I.type = struct_value () [template] // CHECK:STDOUT: %.2: type = interface_type @I, @I(%T) [symbolic] // CHECK:STDOUT: %Self: %.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: %.type: type = fn_type @.1 [template] -// CHECK:STDOUT: %.5: %.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @I(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @I, %F.type [symbolic] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %F.2: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %.type: type = fn_type @.1, @I(%T) [symbolic] +// CHECK:STDOUT: %.5: %.type = struct_value () [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -46,7 +47,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // 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 = @I.%T (constants.%T)] // CHECK:STDOUT: } -// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.5] { +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [symbolic = 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 = @.1.%T (constants.%T)] // CHECK:STDOUT: %.loc22_24.1: @.1.%.1 (%.2) = specific_constant @I.%Self.1, @I(constants.%T) [symbolic = @.1.%Self (constants.%Self)] @@ -59,7 +60,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %Self.ref.loc22_35: @.1.%.1 (%.2) = name_ref Self, %.loc22_35.1 [symbolic = @.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc22_35.2: type = facet_type_access %Self.ref.loc22_35 [symbolic = @.1.%Self (constants.%Self)] // CHECK:STDOUT: %.loc22_35.3: type = converted %Self.ref.loc22_35, %.loc22_35.2 [symbolic = @.1.%Self (constants.%Self)] -// CHECK:STDOUT: @.1.%return: ref %Self = var +// CHECK:STDOUT: @.1.%return: ref @.1.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -69,10 +70,14 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = interface_type @I, @I(%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F, @I(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @I.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @I, @I.%F.type (%F.type) [symbolic = %.2 (constants.%.3)] +// CHECK:STDOUT: %.3: @I.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: %Self.1: @I.%.1 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %F.decl: @I.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %.loc13_14.1: @F.%.1 (%.2) = specific_constant %Self.1, @I(constants.%T) [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %Self.ref.loc13_14: @F.%.1 (%.2) = name_ref Self, %.loc13_14.1 [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %.loc13_14.2: type = facet_type_access %Self.ref.loc13_14 [symbolic = @F.%Self (constants.%Self)] @@ -83,9 +88,9 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %Self.ref.loc13_25: @F.%.1 (%.2) = name_ref Self, %.loc13_25.1 [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %.loc13_25.2: type = facet_type_access %Self.ref.loc13_25 [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %.loc13_25.3: type = converted %Self.ref.loc13_25, %.loc13_25.2 [symbolic = @F.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @F.%Self (%Self) = var // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_29: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] +// CHECK:STDOUT: %.loc13_29: @I.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 @@ -99,7 +104,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: %.1: type = interface_type @I, @I(%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@I.%self.loc13_8.2: @F.%Self (%Self)]() -> %Self; +// CHECK:STDOUT: fn[@I.%self.loc13_8.2: @F.%Self (%Self)]() -> @F.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @.1(file.%T.loc22_6.2: type) { @@ -109,7 +114,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn[%self: @.1.%Self (%Self)]() -> %Self { +// CHECK:STDOUT: fn[%self: @.1.%Self (%Self)]() -> @.1.%Self (%Self) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: @.1.%Self (%Self) = name_ref self, %self // CHECK:STDOUT: return %self.ref @@ -122,6 +127,10 @@ fn I(T:! type).F[self: Self]() -> Self { return self; } // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1 => constants.%.2 // CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: %.2 => constants.%.3 +// CHECK:STDOUT: %.3 => constants.%.4 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @I(@F.%T) { diff --git a/toolchain/check/testdata/interface/no_prelude/generic.carbon b/toolchain/check/testdata/interface/no_prelude/generic.carbon index ec0e3d36e5a4..706d5d656b7a 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic.carbon @@ -73,10 +73,10 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: %WithAssocFn: %WithAssocFn.type = struct_value () [template] // CHECK:STDOUT: %.4: type = interface_type @WithAssocFn, @WithAssocFn(%T.1) [symbolic] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] -// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] -// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %.5: type = assoc_entity_type @WithAssocFn, %F.type.1 [template] -// CHECK:STDOUT: %.6: %.5 = assoc_entity element0, @WithAssocFn.%F.decl [template] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @WithAssocFn(%T.1) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.5: type = assoc_entity_type @WithAssocFn, %F.type.1 [symbolic] +// CHECK:STDOUT: %.6: %.5 = assoc_entity element0, @WithAssocFn.%F.decl [symbolic] // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %.7: type = interface_type @Simple, @Simple(%C) [template] // CHECK:STDOUT: %.8: = interface_witness () [template] @@ -165,14 +165,18 @@ fn G(T:! Generic(B)) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = interface_type @WithAssocFn, @WithAssocFn(%T) [symbolic = %.1 (constants.%.4)] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.2)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @WithAssocFn(%T) [symbolic = %F.type (constants.%F.type.1)] +// CHECK:STDOUT: %F: @WithAssocFn.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @WithAssocFn, @WithAssocFn.%F.type (%F.type.1) [symbolic = %.2 (constants.%.5)] +// CHECK:STDOUT: %.3: @WithAssocFn.%.2 (%.5) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.6)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: %Self.1: @WithAssocFn.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self.2)] -// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] { +// CHECK:STDOUT: %F.decl: @WithAssocFn.%F.type (%F.type.1) = fn_decl @F.1 [symbolic = %F (constants.%F.1)] { // CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [template = constants.%X] // CHECK:STDOUT: %return.var: ref %X = var // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc10: %.5 = assoc_entity element0, %F.decl [template = constants.%.6] +// CHECK:STDOUT: %.loc10: @WithAssocFn.%.2 (%.5) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.6)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 diff --git a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon index 18cc86d3e096..b9b5a44d4f49 100644 --- a/toolchain/check/testdata/interface/no_prelude/generic_import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/generic_import.carbon @@ -36,10 +36,10 @@ impl C as AddWith(C) { // CHECK:STDOUT: %AddWith: %AddWith.type = struct_value () [template] // CHECK:STDOUT: %.2: type = interface_type @AddWith, @AddWith(%T) [symbolic] // CHECK:STDOUT: %Self: %.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 @AddWith, %F.type [template] -// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @AddWith.%F.decl [template] +// CHECK:STDOUT: %F.type: type = fn_type @F, @AddWith(%T) [symbolic] +// CHECK:STDOUT: %F: %F.type = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type @AddWith, %F.type [symbolic] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @AddWith.%F.decl [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -58,11 +58,15 @@ impl C as AddWith(C) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %.1: type = interface_type @AddWith, @AddWith(%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F, @AddWith(%T) [symbolic = %F.type (constants.%F.type)] +// CHECK:STDOUT: %F: @AddWith.%F.type (%F.type) = struct_value () [symbolic = %F (constants.%F)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @AddWith, @AddWith.%F.type (%F.type) [symbolic = %.2 (constants.%.3)] +// CHECK:STDOUT: %.3: @AddWith.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: %Self.1: @AddWith.%.1 (%.2) = bind_symbolic_name Self 1 [symbolic = %Self.2 (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: %F.decl: @AddWith.%F.type (%F.type) = fn_decl @F [symbolic = %F (constants.%F)] {} +// CHECK:STDOUT: %.loc5: @AddWith.%.2 (%.3) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.4)] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self.1 diff --git a/toolchain/check/testdata/interface/no_prelude/self.carbon b/toolchain/check/testdata/interface/no_prelude/self.carbon index 2306c2c3664c..f26031ba296e 100644 --- a/toolchain/check/testdata/interface/no_prelude/self.carbon +++ b/toolchain/check/testdata/interface/no_prelude/self.carbon @@ -42,7 +42,7 @@ interface UseSelf { // CHECK:STDOUT: %Self.ref.loc12_25: %.1 = name_ref Self, %Self [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_25.1: type = facet_type_access %Self.ref.loc12_25 [symbolic = @F.%Self (constants.%Self)] // CHECK:STDOUT: %.loc12_25.2: type = converted %Self.ref.loc12_25, %.loc12_25.1 [symbolic = @F.%Self (constants.%Self)] -// CHECK:STDOUT: %return.var: ref %Self = var +// CHECK:STDOUT: %return.var: ref @F.%Self (%Self) = var // CHECK:STDOUT: } // CHECK:STDOUT: %.loc12_29: %.3 = assoc_entity element0, %F.decl [template = constants.%.4] // CHECK:STDOUT: @@ -55,7 +55,7 @@ interface UseSelf { // CHECK:STDOUT: generic fn @F(@UseSelf.%Self: %.1) { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = %Self (constants.%Self)] // CHECK:STDOUT: -// CHECK:STDOUT: fn[@UseSelf.%self.loc12_8.2: @F.%Self (%Self)]() -> %Self; +// CHECK:STDOUT: fn[@UseSelf.%self.loc12_8.2: @F.%Self (%Self)]() -> @F.%Self (%Self); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @F(constants.%Self) { diff --git a/toolchain/check/testdata/return/fail_let_in_type.carbon b/toolchain/check/testdata/return/fail_let_in_type.carbon index d8288fd71694..3d39a037370b 100644 --- a/toolchain/check/testdata/return/fail_let_in_type.carbon +++ b/toolchain/check/testdata/return/fail_let_in_type.carbon @@ -59,7 +59,7 @@ fn FirstPerfectNumber() -> z { return 6; } // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: -// CHECK:STDOUT: fn() -> %y { +// CHECK:STDOUT: fn() -> @HalfDozen.%y (%y) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc24: i32 = int_literal 6 [template = constants.%.2] // CHECK:STDOUT: return diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index b7eea20c2e71..4c3635b5aeb8 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -146,7 +146,7 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id) sem_ir().inst_blocks().GetOrEmpty(function.implicit_param_refs_id); // TODO: Include parameters corresponding to positional parameters. auto param_refs = sem_ir().inst_blocks().GetOrEmpty(function.param_refs_id); - auto return_type_id = function.declared_return_type(sem_ir()); + auto return_type_id = function.GetDeclaredReturnType(sem_ir()); SemIR::InitRepr return_rep = return_type_id.is_valid() diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 5834b4742fb3..da1d5a9134ac 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -763,6 +763,14 @@ class FormatterImpl { FormatTrailingBlock(inst.decl_block_id); } + auto FormatInstRHS(FunctionType inst) -> void { + if (inst.instance_id.is_valid()) { + FormatArgs(inst.function_id, inst.instance_id); + } else { + FormatArgs(inst.function_id); + } + } + auto FormatInstRHS(ClassDecl inst) -> void { FormatArgs(inst.class_id); FormatTrailingBlock(inst.decl_block_id); diff --git a/toolchain/sem_ir/function.cpp b/toolchain/sem_ir/function.cpp index 3d921b9ba8ef..2b73eed5c514 100644 --- a/toolchain/sem_ir/function.cpp +++ b/toolchain/sem_ir/function.cpp @@ -5,11 +5,14 @@ #include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/file.h" +#include "toolchain/sem_ir/generic.h" +#include "toolchain/sem_ir/ids.h" namespace Carbon::SemIR { auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction { CalleeFunction result = {.function_id = FunctionId::Invalid, + .instance_id = GenericInstanceId::Invalid, .self_id = InstId::Invalid, .is_error = false}; @@ -35,14 +38,18 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction { } result.function_id = fn_type->function_id; + result.instance_id = fn_type->instance_id; return result; } -auto Function::declared_return_type(const File& file) const -> TypeId { +auto Function::GetDeclaredReturnType(const File& file, + GenericInstanceId specific_id) const + -> TypeId { if (!return_storage_id.is_valid()) { return TypeId::Invalid; } - return file.insts().Get(return_storage_id).type_id(); + return GetTypeInInstance(file, specific_id, + file.insts().Get(return_storage_id).type_id()); } } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index c9bbff17c561..e3d772004d98 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -62,13 +62,22 @@ struct Function : public Printable { static auto GetParamFromParamRefId(const File& sem_ir, InstId param_ref_id) -> std::pair; - // Gets the declared return type of the function. Returns `Invalid` if no - // return type was specified, - auto declared_return_type(const File& file) const -> TypeId; + // Gets the declared return type for a specific instance of this function, or + // the canonical return type for the original declaration no specific is + // specified. Returns `Invalid` if no return type was specified, in which + // case the effective return type is an empty tuple. + auto GetDeclaredReturnType(const File& file, + GenericInstanceId specific_id = + GenericInstanceId::Invalid) const -> TypeId; // Returns whether the function has a return slot. Can only be called for a // function that has either been called or defined, otherwise this is not // known. + // + // For a generic function, this only returns information about the generic + // itself, not a specific. Because a generic function can't be called (only a + // specific can be), this information is only available for generic functions + // that are defined. auto has_return_slot() const -> bool { CARBON_CHECK(return_slot != ReturnSlot::NotComputed); // On error, we assume no return slot is used. @@ -106,7 +115,8 @@ struct Function : public Printable { // The following member is set on the first call to the function, or at the // point where the function is defined. - // Whether the function uses a return slot. + // Whether the function uses a return slot. For a generic function, this + // tracks information about the generic, not a specific. ReturnSlot return_slot; // The following members are set at the end of a builtin function definition. @@ -133,6 +143,8 @@ class File; struct CalleeFunction { // The function. Invalid if not a function. SemIR::FunctionId function_id; + // The generic instance that contains the function. + SemIR::GenericInstanceId instance_id; // The bound `self` parameter. Invalid if not a method. SemIR::InstId self_id; // True if an error instruction was found. diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index d5c19a233cba..f0b69501c1c8 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -575,6 +575,7 @@ struct FunctionType { TypeId type_id; FunctionId function_id; + GenericInstanceId instance_id; }; // The type of the name of a generic class. The corresponding value is an empty