From 95903dc624993f7f40ebabe65470331201ab11af Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 1 May 2025 15:17:55 -0700 Subject: [PATCH] Generate thunks for functions in `impl`s (#5390) Generate a thunk when a function in an `impl` has a different signature than the function in the interface. This follows the design in [#3763](https://docs.carbon-lang.dev/proposals/p3763.html#impl-members-vs-interface-members), although some of the checks described there are not yet implemented. --------- Co-authored-by: Jon Ross-Perkins --- toolchain/check/BUILD | 24 +- toolchain/check/function.cpp | 87 +- toolchain/check/function.h | 25 +- toolchain/check/handle_binding_pattern.cpp | 52 +- toolchain/check/handle_function.cpp | 58 +- toolchain/check/handle_impl.cpp | 4 +- toolchain/check/handle_let_and_var.cpp | 2 +- toolchain/check/handle_pattern_list.cpp | 2 +- toolchain/check/impl.cpp | 17 +- toolchain/check/impl.h | 2 +- toolchain/check/inst.h | 11 +- toolchain/check/pattern.cpp | 99 + toolchain/check/{subpattern.h => pattern.h} | 19 +- toolchain/check/pattern_match.cpp | 2 +- toolchain/check/pointer_dereference.cpp | 7 +- toolchain/check/pointer_dereference.h | 3 +- toolchain/check/return.cpp | 19 +- toolchain/check/return.h | 5 +- toolchain/check/subpattern.cpp | 48 - .../testdata/impl/fail_call_invalid.carbon | 34 +- .../impl/fail_impl_bad_assoc_fn.carbon | 933 ++++++--- .../impl/fail_self_type_mismatch.carbon | 140 +- .../impl/no_prelude/impl_thunk.carbon | 1843 +++++++++++++++++ .../testdata/impl/use_assoc_const.carbon | 217 +- toolchain/check/thunk.cpp | 410 ++++ toolchain/check/thunk.h | 22 + toolchain/diagnostics/diagnostic_kind.def | 2 + toolchain/sem_ir/block_value_store.h | 8 + toolchain/sem_ir/function.cpp | 17 +- toolchain/sem_ir/inst.h | 17 + toolchain/sem_ir/typed_insts.h | 19 +- 31 files changed, 3438 insertions(+), 710 deletions(-) create mode 100644 toolchain/check/pattern.cpp rename toolchain/check/{subpattern.h => pattern.h} (66%) delete mode 100644 toolchain/check/subpattern.cpp create mode 100644 toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon create mode 100644 toolchain/check/thunk.cpp create mode 100644 toolchain/check/thunk.h diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index aeb610c9b3f2..3fd65943d845 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -44,10 +44,12 @@ cc_library( "name_component.cpp", "name_lookup.cpp", "operator.cpp", + "pattern.cpp", "pattern_match.cpp", + "pointer_dereference.cpp", "return.cpp", - "subpattern.cpp", "subst.cpp", + "thunk.cpp", "type.cpp", "type_completion.cpp", "type_structure.cpp", @@ -86,12 +88,14 @@ cc_library( "name_lookup.h", "operator.h", "param_and_arg_refs_stack.h", + "pattern.h", "pattern_match.h", "pending_block.h", + "pointer_dereference.h", "region_stack.h", "return.h", - "subpattern.h", "subst.h", + "thunk.h", "type.h", "type_completion.h", "type_structure.h", @@ -100,6 +104,7 @@ cc_library( ":node_stack", "//common:array_stack", "//common:check", + "//common:find", "//common:map", "//common:ostream", "//common:raw_string_ostream", @@ -167,7 +172,6 @@ cc_library( ":context", ":diagnostic_emitter", ":dump", - ":pointer_dereference", "//common:check", "//common:error", "//common:find", @@ -238,20 +242,6 @@ cc_library( ], ) -cc_library( - name = "pointer_dereference", - srcs = ["pointer_dereference.cpp"], - hdrs = ["pointer_dereference.h"], - deps = [ - ":context", - "//common:check", - "//toolchain/parse:node_kind", - "//toolchain/sem_ir:file", - "//toolchain/sem_ir:typed_insts", - "@llvm-project//llvm:Support", - ], -) - cc_library( name = "scope_stack", srcs = ["scope_stack.cpp"], diff --git a/toolchain/check/function.cpp b/toolchain/check/function.cpp index d9b7421c1a7c..a8638450f772 100644 --- a/toolchain/check/function.cpp +++ b/toolchain/check/function.cpp @@ -4,29 +4,29 @@ #include "toolchain/check/function.h" +#include "common/find.h" #include "toolchain/check/merge.h" #include "toolchain/check/type_completion.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/pattern.h" namespace Carbon::Check { -auto CheckFunctionTypeMatches(Context& context, - const SemIR::Function& new_function, - const SemIR::Function& prev_function, - SemIR::SpecificId prev_specific_id, - bool check_syntax, bool check_self) -> bool { - // TODO: When check_syntax is false, the functions should be allowed to have - // different signatures as long as we can synthesize a suitable thunk. i.e., - // when there's an implicit conversion from the original parameter types to - // the overriding parameter types, and from the overriding return type to the - // original return type. - // Also, build that thunk. - if (!CheckRedeclParamsMatch(context, DeclParams(new_function), - DeclParams(prev_function), prev_specific_id, - /*diagnose=*/true, check_syntax, check_self)) { - return false; - } +auto FindSelfPattern(Context& context, + SemIR::InstBlockId implicit_param_patterns_id) + -> SemIR::InstId { + auto implicit_param_patterns = + context.inst_blocks().GetOrEmpty(implicit_param_patterns_id); + return FindIfOrNone(implicit_param_patterns, [&](auto implicit_param_id) { + return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id); + }); +} +auto CheckFunctionReturnTypeMatches(Context& context, + const SemIR::Function& new_function, + const SemIR::Function& prev_function, + SemIR::SpecificId prev_specific_id, + bool diagnose) -> bool { // TODO: Pass a specific ID for `prev_function` instead of substitutions and // use it here. auto new_return_type_id = @@ -39,6 +39,10 @@ auto CheckFunctionTypeMatches(Context& context, } if (!context.types().AreEqualAcrossDeclarations(new_return_type_id, prev_return_type_id)) { + if (!diagnose) { + return false; + } + CARBON_DIAGNOSTIC( FunctionRedeclReturnTypeDiffers, Error, "function redeclaration differs because return type is {0}", @@ -72,6 +76,21 @@ auto CheckFunctionTypeMatches(Context& context, return true; } +auto CheckFunctionTypeMatches(Context& context, + const SemIR::Function& new_function, + const SemIR::Function& prev_function, + SemIR::SpecificId prev_specific_id, + bool check_syntax, bool check_self, bool diagnose) + -> bool { + if (!CheckRedeclParamsMatch(context, DeclParams(new_function), + DeclParams(prev_function), prev_specific_id, + diagnose, check_syntax, check_self)) { + return false; + } + return CheckFunctionReturnTypeMatches(context, new_function, prev_function, + prev_specific_id, diagnose); +} + auto CheckFunctionReturnType(Context& context, SemIR::LocId loc_id, const SemIR::Function& function, SemIR::SpecificId specific_id) @@ -108,4 +127,40 @@ auto CheckFunctionReturnType(Context& context, SemIR::LocId loc_id, return return_info; } +auto CheckFunctionDefinitionSignature(Context& context, + SemIR::FunctionId function_id) -> void { + auto& function = context.functions().Get(function_id); + + auto params_to_complete = + context.inst_blocks().GetOrEmpty(function.call_params_id); + + // Check the return type is complete. + if (function.return_slot_pattern_id.has_value()) { + CheckFunctionReturnType(context, + SemIR::LocId(function.return_slot_pattern_id), + function, SemIR::SpecificId::None); + // Don't re-check the return type below. + params_to_complete = params_to_complete.drop_back(); + } + + // Check the parameter types are complete. + for (auto param_ref_id : params_to_complete) { + if (param_ref_id == SemIR::ErrorInst::InstId) { + continue; + } + + // The parameter types need to be complete. + RequireCompleteType( + context, context.insts().GetAs(param_ref_id).type_id, + SemIR::LocId(param_ref_id), [&] { + CARBON_DIAGNOSTIC( + IncompleteTypeInFunctionParam, Error, + "parameter has incomplete type {0} in function definition", + TypeOfInstId); + return context.emitter().Build( + param_ref_id, IncompleteTypeInFunctionParam, param_ref_id); + }); + } +} + } // namespace Carbon::Check diff --git a/toolchain/check/function.h b/toolchain/check/function.h index c7eb4145fa69..3b7f7566c99f 100644 --- a/toolchain/check/function.h +++ b/toolchain/check/function.h @@ -26,6 +26,22 @@ struct SuspendedFunction { DeclNameStack::SuspendedName saved_name_state; }; +// Returns the ID of the self parameter pattern, or None. +// TODO: Do this during initial traversal of implicit params. +auto FindSelfPattern(Context& context, + SemIR::InstBlockId implicit_param_patterns_id) + -> SemIR::InstId; + +// Checks that `new_function` has the same return type as `prev_function`, or if +// `prev_function_id` is specified, a specific version of `prev_function`. +// Prints a suitable diagnostic and returns false if not. Never checks for a +// syntactic match. +auto CheckFunctionReturnTypeMatches(Context& context, + const SemIR::Function& new_function, + const SemIR::Function& prev_function, + SemIR::SpecificId prev_specific_id, + bool diagnose = true) -> bool; + // Checks that `new_function` has the same parameter types and return type as // `prev_function`, or if `prev_function_id` is specified, a specific version of // `prev_function`. Prints a suitable diagnostic and returns false if not. @@ -38,7 +54,8 @@ auto CheckFunctionTypeMatches(Context& context, const SemIR::Function& new_function, const SemIR::Function& prev_function, SemIR::SpecificId prev_specific_id, - bool check_syntax, bool check_self) -> bool; + bool check_syntax, bool check_self, + bool diagnose = true) -> bool; inline auto CheckFunctionTypeMatches(Context& context, const SemIR::Function& new_function, @@ -58,6 +75,12 @@ auto CheckFunctionReturnType(Context& context, SemIR::LocId loc_id, SemIR::SpecificId specific_id) -> SemIR::ReturnTypeInfo; +// Checks that a function declaration's signature is suitable to support a +// function definition. This requires the parameter types to be complete and the +// return type to be concrete. +auto CheckFunctionDefinitionSignature(Context& context, + SemIR::FunctionId function_id) -> void; + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_FUNCTION_H_ diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index de0d21c181ac..ac04a7baffa2 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -8,8 +8,8 @@ #include "toolchain/check/inst.h" #include "toolchain/check/interface.h" #include "toolchain/check/name_lookup.h" +#include "toolchain/check/pattern.h" #include "toolchain/check/return.h" -#include "toolchain/check/subpattern.h" #include "toolchain/check/type.h" #include "toolchain/check/type_completion.h" #include "toolchain/diagnostics/format_providers.h" @@ -51,62 +51,24 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, context.decl_introducer_state_stack().innermost(); auto make_binding_pattern = [&]() -> SemIR::InstId { - // bind_id and entity_name_id are not populated if name_id is Underscore. - auto bind_id = SemIR::InstId::None; // TODO: Eventually the name will need to support associations with other // scopes, but right now we don't support qualified names here. - auto entity_name_id = SemIR::EntityNameId::None; - entity_name_id = context.entity_names().AddSymbolicBindingName( - name_id, context.scope_stack().PeekNameScopeId(), - is_generic ? context.scope_stack().AddCompileTimeBinding() - : SemIR::CompileTimeBindIndex::None, - is_template); - if (is_generic) { - bind_id = AddInstInNoBlock( - context, name_node, - SemIR::BindSymbolicName{.type_id = cast_type_id, - .entity_name_id = entity_name_id, - .value_id = SemIR::InstId::None}); - } else { - bind_id = - AddInstInNoBlock(context, name_node, - SemIR::BindName{.type_id = cast_type_id, - .entity_name_id = entity_name_id, - .value_id = SemIR::InstId::None}); - } + auto binding = + AddBindingPattern(context, name_node, name_id, cast_type_id, + type_expr_region_id, is_generic, is_template); - auto pattern_type_id = GetPatternType(context, cast_type_id); - auto binding_pattern_id = SemIR::InstId::None; - if (is_generic) { - binding_pattern_id = AddPatternInst( - context, name_node, - {.type_id = pattern_type_id, .entity_name_id = entity_name_id}); - } else { - binding_pattern_id = AddPatternInst( - context, name_node, - {.type_id = pattern_type_id, .entity_name_id = entity_name_id}); - } - - if (is_generic) { - context.scope_stack().PushCompileTimeBinding(bind_id); - } if (name_id != SemIR::NameId::Underscore) { // Add name to lookup immediately, so it can be used in the rest of the // enclosing pattern. auto name_context = context.decl_name_stack().MakeUnqualifiedName(name_node, name_id); context.decl_name_stack().AddNameOrDiagnose( - name_context, bind_id, introducer.modifier_set.GetAccessKind()); + name_context, binding.bind_id, + introducer.modifier_set.GetAccessKind()); context.full_pattern_stack().AddBindName(name_id); } - bool inserted = context.bind_name_map() - .Insert(binding_pattern_id, - {.bind_name_id = bind_id, - .type_expr_region_id = type_expr_region_id}) - .is_inserted(); - CARBON_CHECK(inserted); - return binding_pattern_id; + return binding.pattern_id; }; // A `self` binding can only appear in an implicit parameter list. diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 6d50b31da525..24236d8f535f 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -5,7 +5,6 @@ #include #include -#include "common/find.h" #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" @@ -34,7 +33,6 @@ #include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" -#include "toolchain/sem_ir/pattern.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -85,18 +83,6 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool { return true; } -// Returns the ID of the self parameter pattern, or None. -// TODO: Do this during initial traversal of implicit params. -static auto FindSelfPattern(Context& context, - SemIR::InstBlockId implicit_param_patterns_id) - -> SemIR::InstId { - auto implicit_param_patterns = - context.inst_blocks().GetOrEmpty(implicit_param_patterns_id); - return FindIfOrNone(implicit_param_patterns, [&](auto implicit_param_id) { - return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id); - }); -} - // Diagnoses issues with the modifiers, removing modifiers that shouldn't be // present. static auto DiagnoseModifiers(Context& context, @@ -577,55 +563,20 @@ auto HandleParseNode(Context& context, Parse::FunctionDeclId node_id) -> bool { return true; } -static auto CheckFunctionDefinitionSignature(Context& context, - SemIR::Function& function) - -> void { - auto params_to_complete = - context.inst_blocks().GetOrEmpty(function.call_params_id); - - // Check the return type is complete. - if (function.return_slot_pattern_id.has_value()) { - CheckFunctionReturnType(context, - SemIR::LocId(function.return_slot_pattern_id), - function, SemIR::SpecificId::None); - params_to_complete = params_to_complete.drop_back(); - } - - // Check the parameter types are complete. - for (auto param_ref_id : params_to_complete) { - if (param_ref_id == SemIR::ErrorInst::InstId) { - continue; - } - - // The parameter types need to be complete. - RequireCompleteType( - context, context.insts().GetAs(param_ref_id).type_id, - SemIR::LocId(param_ref_id), [&] { - CARBON_DIAGNOSTIC( - IncompleteTypeInFunctionParam, Error, - "parameter has incomplete type {0} in function definition", - TypeOfInstId); - return context.emitter().Build( - param_ref_id, IncompleteTypeInFunctionParam, param_ref_id); - }); - } -} - // Processes a function definition after a signature for which we have already // built a function ID. This logic is shared between processing regular function // definitions and delayed parsing of inline method definitions. static auto HandleFunctionDefinitionAfterSignature( Context& context, Parse::FunctionDefinitionStartId node_id, SemIR::FunctionId function_id, SemIR::InstId decl_id) -> void { - auto& function = context.functions().Get(function_id); - // Create the function scope and the entry block. context.scope_stack().PushForFunctionBody(decl_id); context.inst_block_stack().Push(); context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd()); - StartGenericDefinition(context, function.generic_id); + StartGenericDefinition(context, + context.functions().Get(function_id).generic_id); - CheckFunctionDefinitionSignature(context, function); + CheckFunctionDefinitionSignature(context, function_id); context.node_stack().Push(node_id, function_id); } @@ -765,8 +716,9 @@ auto HandleParseNode(Context& context, auto builtin_kind = LookupBuiltinFunctionKind(context, name_id); if (builtin_kind != SemIR::BuiltinFunctionKind::None) { + CheckFunctionDefinitionSignature(context, function_id); + auto& function = context.functions().Get(function_id); - CheckFunctionDefinitionSignature(context, function); if (IsValidBuiltinDeclaration(context, function, builtin_kind)) { function.builtin_function_kind = builtin_kind; // Build an empty generic definition if this is a generic builtin. diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index f1fa8d188dd9..9e40f3e7b0d7 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -564,9 +564,9 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionId /*node_id*/) auto impl_id = context.node_stack().Pop(); + FinishImplWitness(context, impl_id); + auto& impl_info = context.impls().Get(impl_id); - CARBON_CHECK(!impl_info.is_complete()); - FinishImplWitness(context, impl_info); impl_info.defined = true; FinishGenericDefinition(context, impl_info.generic_id); diff --git a/toolchain/check/handle_let_and_var.cpp b/toolchain/check/handle_let_and_var.cpp index 9d8ad209f038..d230c69b1f67 100644 --- a/toolchain/check/handle_let_and_var.cpp +++ b/toolchain/check/handle_let_and_var.cpp @@ -14,9 +14,9 @@ #include "toolchain/check/interface.h" #include "toolchain/check/keyword_modifier_set.h" #include "toolchain/check/modifiers.h" +#include "toolchain/check/pattern.h" #include "toolchain/check/pattern_match.h" #include "toolchain/check/return.h" -#include "toolchain/check/subpattern.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/diagnostics/format_providers.h" #include "toolchain/lex/token_kind.h" diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index c595c8e8c939..2f28bca48c88 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -5,7 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/handle.h" #include "toolchain/check/inst.h" -#include "toolchain/check/subpattern.h" +#include "toolchain/check/pattern.h" #include "toolchain/check/type.h" namespace Carbon::Check { diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 5e03ec2c1af1..c98a46f4374d 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -14,6 +14,7 @@ #include "toolchain/check/inst.h" #include "toolchain/check/interface.h" #include "toolchain/check/name_lookup.h" +#include "toolchain/check/thunk.h" #include "toolchain/check/type.h" #include "toolchain/check/type_completion.h" #include "toolchain/diagnostics/diagnostic_emitter.h" @@ -76,14 +77,8 @@ static auto CheckAssociatedFunctionImplementation( .generic_id, impl_enclosing_specific_id, self_type_id, witness_inst_id); - if (!CheckFunctionTypeMatches( - context, context.functions().Get(impl_function_decl->function_id), - context.functions().Get(interface_function_type.function_id), - interface_function_specific_id, /*check_syntax=*/false, - /*check_self=*/true)) { - return SemIR::ErrorInst::InstId; - } - return impl_decl_id; + return BuildThunk(context, interface_function_type.function_id, + interface_function_specific_id, impl_decl_id); } // Builds an initial witness from the rewrites in the facet type, if any. @@ -168,7 +163,11 @@ auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void { // Adds functions to the witness that the specified impl implements the given // interface. -auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void { +auto FinishImplWitness(Context& context, SemIR::ImplId impl_id) -> void { + // Make a copy of the impl. We're going to reference it a lot, and `impl`s + // could get invalidated by some of the things we do. + const auto impl = context.impls().Get(impl_id); + CARBON_CHECK(impl.is_being_defined()); CARBON_CHECK(impl.witness_id.has_value()); if (impl.witness_id == SemIR::ErrorInst::InstId) { diff --git a/toolchain/check/impl.h b/toolchain/check/impl.h index 886eb8a62484..99d7632265cb 100644 --- a/toolchain/check/impl.h +++ b/toolchain/check/impl.h @@ -21,7 +21,7 @@ auto ImplWitnessForDeclaration(Context& context, const SemIR::Impl& impl, auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void; // Adds the function members to the witness for `impl`. -auto FinishImplWitness(Context& context, SemIR::Impl& impl) -> void; +auto FinishImplWitness(Context& context, SemIR::ImplId impl_id) -> void; // Sets all unset members of the witness for `impl` to the error instruction. auto FillImplWitnessWithErrors(Context& context, SemIR::Impl& impl) -> void; diff --git a/toolchain/check/inst.h b/toolchain/check/inst.h index 1bec317db0a4..b92a117bd684 100644 --- a/toolchain/check/inst.h +++ b/toolchain/check/inst.h @@ -132,12 +132,11 @@ auto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) // Convenience for AddPatternInst with typed nodes. // // As a safety check, prevent use with storage insts (see `AddInstWithCleanup`). -template - requires(SemIR::Internal::HasNodeId && !InstT::Kind.has_cleanup()) -auto AddPatternInst(Context& context, - typename decltype(InstT::Kind)::TypedNodeId node_id, - InstT inst) -> SemIR::InstId { - return AddPatternInst(context, SemIR::LocIdAndInst(node_id, inst)); +template + requires(!InstT::Kind.has_cleanup() && + std::convertible_to) +auto AddPatternInst(Context& context, LocT loc, InstT inst) -> SemIR::InstId { + return AddPatternInst(context, SemIR::LocIdAndInst(loc, inst)); } // Adds an instruction to the current block, returning the produced ID. The diff --git a/toolchain/check/pattern.cpp b/toolchain/check/pattern.cpp new file mode 100644 index 000000000000..5c49fbb7d0cd --- /dev/null +++ b/toolchain/check/pattern.cpp @@ -0,0 +1,99 @@ +// 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 + +#include "toolchain/check/pattern.h" + +#include "toolchain/check/inst.h" +#include "toolchain/check/type.h" + +namespace Carbon::Check { + +auto BeginSubpattern(Context& context) -> void { + context.inst_block_stack().Push(); + context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd()); +} + +auto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id) + -> SemIR::ExprRegionId { + if (context.region_stack().PeekRegion().size() > 1) { + // End the exit block with a branch to a successor block, whose contents + // will be determined later. + AddInst(context, + SemIR::LocIdAndInst::NoLoc( + {.target_id = context.inst_blocks().AddPlaceholder()})); + } else { + // This single-block region will be inserted as a SpliceBlock, so we don't + // need control flow out of it. + } + auto block_id = context.inst_block_stack().Pop(); + CARBON_CHECK(block_id == context.region_stack().PeekRegion().back()); + + // TODO: Is it possible to validate that this region is genuinely + // single-entry, single-exit? + return context.sem_ir().expr_regions().Add( + {.block_ids = context.region_stack().PopRegion(), + .result_id = result_id}); +} + +auto EndSubpatternAsNonExpr(Context& context) -> void { + auto block_id = context.inst_block_stack().Pop(); + CARBON_CHECK(block_id == context.region_stack().PeekRegion().back()); + CARBON_CHECK(context.region_stack().PeekRegion().size() == 1); + // TODO: Add `CARBON_CHECK(inst_blocks().Get(block_id).empty())`. + // Currently that can fail when ending a tuple pattern in a name binding + // decl in a class or interface. + context.region_stack().PopAndDiscardRegion(); +} + +auto AddBindingPattern(Context& context, SemIR::LocId name_loc, + SemIR::NameId name_id, SemIR::TypeId type_id, + SemIR::ExprRegionId type_region_id, bool is_generic, + bool is_template) -> BindingPatternInfo { + auto entity_name_id = context.entity_names().AddSymbolicBindingName( + name_id, context.scope_stack().PeekNameScopeId(), + is_generic ? context.scope_stack().AddCompileTimeBinding() + : SemIR::CompileTimeBindIndex::None, + is_template); + + auto bind_id = SemIR::InstId::None; + if (is_generic) { + bind_id = AddInstInNoBlock( + context, name_loc, + {.type_id = type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None}); + } else { + bind_id = + AddInstInNoBlock(context, name_loc, + {.type_id = type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None}); + } + + auto pattern_type_id = GetPatternType(context, type_id); + auto binding_pattern_id = SemIR::InstId::None; + if (is_generic) { + binding_pattern_id = AddPatternInst( + context, name_loc, + {.type_id = pattern_type_id, .entity_name_id = entity_name_id}); + } else { + binding_pattern_id = AddPatternInst( + context, name_loc, + {.type_id = pattern_type_id, .entity_name_id = entity_name_id}); + } + + if (is_generic) { + context.scope_stack().PushCompileTimeBinding(bind_id); + } + + bool inserted = + context.bind_name_map() + .Insert(binding_pattern_id, {.bind_name_id = bind_id, + .type_expr_region_id = type_region_id}) + .is_inserted(); + CARBON_CHECK(inserted); + return {.pattern_id = binding_pattern_id, .bind_id = bind_id}; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/subpattern.h b/toolchain/check/pattern.h similarity index 66% rename from toolchain/check/subpattern.h rename to toolchain/check/pattern.h index 56bbb892487f..efb3c634e291 100644 --- a/toolchain/check/subpattern.h +++ b/toolchain/check/pattern.h @@ -2,8 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef CARBON_TOOLCHAIN_CHECK_SUBPATTERN_H_ -#define CARBON_TOOLCHAIN_CHECK_SUBPATTERN_H_ +#ifndef CARBON_TOOLCHAIN_CHECK_PATTERN_H_ +#define CARBON_TOOLCHAIN_CHECK_PATTERN_H_ #include "toolchain/check/context.h" #include "toolchain/sem_ir/ids.h" @@ -27,8 +27,21 @@ auto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id) // it had no expression content. auto EndSubpatternAsNonExpr(Context& context) -> void; +// Information about a created binding pattern. +struct BindingPatternInfo { + SemIR::InstId pattern_id; + SemIR::InstId bind_id; +}; + // TODO: Add EndSubpatternAsPattern, when needed. +// Creates a binding pattern. Returns the binding pattern and the bind name +// instruction. +auto AddBindingPattern(Context& context, SemIR::LocId name_loc, + SemIR::NameId name_id, SemIR::TypeId type_id, + SemIR::ExprRegionId type_region_id, bool is_generic, + bool is_template) -> BindingPatternInfo; + } // namespace Carbon::Check -#endif // CARBON_TOOLCHAIN_CHECK_SUBPATTERN_H_ +#endif // CARBON_TOOLCHAIN_CHECK_PATTERN_H_ diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index f97840d1c336..58c5581cbc50 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -14,7 +14,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" -#include "toolchain/check/subpattern.h" +#include "toolchain/check/pattern.h" #include "toolchain/check/type.h" #include "toolchain/diagnostics/format_providers.h" #include "toolchain/sem_ir/expr_info.h" diff --git a/toolchain/check/pointer_dereference.cpp b/toolchain/check/pointer_dereference.cpp index 4c2ff82d64a8..5824d0f366ea 100644 --- a/toolchain/check/pointer_dereference.cpp +++ b/toolchain/check/pointer_dereference.cpp @@ -14,13 +14,12 @@ namespace Carbon::Check { auto PerformPointerDereference( - Context& context, Parse::AnyPointerDeferenceExprId node_id, - SemIR::InstId base_id, + Context& context, SemIR::LocId loc_id, SemIR::InstId base_id, llvm::function_refvoid> diagnose_not_pointer) -> SemIR::InstId { // TODO: Once we have a finalized design for a pointer interface, use // - // HandleUnaryOperator(context, node_id, {"Pointer", "Dereference"}); + // HandleUnaryOperator(context, loc_id, {"Pointer", "Dereference"}); // // to convert to a pointer value. base_id = ConvertToValueExpr(context, base_id); @@ -35,7 +34,7 @@ auto PerformPointerDereference( diagnose_not_pointer(type_id); } return AddInst( - context, node_id, {.type_id = result_type_id, .pointer_id = base_id}); + context, loc_id, {.type_id = result_type_id, .pointer_id = base_id}); } } // namespace Carbon::Check diff --git a/toolchain/check/pointer_dereference.h b/toolchain/check/pointer_dereference.h index aa281d99a1bf..d63ecdc2cd32 100644 --- a/toolchain/check/pointer_dereference.h +++ b/toolchain/check/pointer_dereference.h @@ -15,8 +15,7 @@ namespace Carbon::Check { // Creates SemIR to perform a pointer dereference with base expression // `base_id`. Returns the result of the access. auto PerformPointerDereference( - Context& context, Parse::AnyPointerDeferenceExprId node_id, - SemIR::InstId base_i, + Context& context, SemIR::LocId loc_id, SemIR::InstId base_i, llvm::function_refvoid> diagnose_not_pointer) -> SemIR::InstId; diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index 791b0faa1365..62b91ffa0b60 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -113,23 +113,22 @@ auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node, } } -auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id) - -> void { +auto BuildReturnWithNoExpr(Context& context, SemIR::LocId loc_id) -> void { const auto& function = GetCurrentFunctionForReturn(context); auto return_type_id = function.GetDeclaredReturnType(context.sem_ir()); if (return_type_id.has_value()) { CARBON_DIAGNOSTIC(ReturnStatementMissingExpr, Error, "missing return value"); - auto diag = context.emitter().Build(node_id, ReturnStatementMissingExpr); + auto diag = context.emitter().Build(loc_id, ReturnStatementMissingExpr); NoteReturnType(context, diag, function); diag.Emit(); } - AddInst(context, node_id, {}); + AddInst(context, loc_id, {}); } -auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, +auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id) -> void { const auto& function = GetCurrentFunctionForReturn(context); auto returned_var_id = GetCurrentReturnedVar(context); @@ -141,7 +140,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, CARBON_DIAGNOSTIC( ReturnStatementDisallowExpr, Error, "no return expression should be provided in this context"); - auto diag = context.emitter().Build(node_id, ReturnStatementDisallowExpr); + auto diag = context.emitter().Build(loc_id, ReturnStatementDisallowExpr); NoteNoReturnTypeProvided(diag, function); diag.Emit(); expr_id = SemIR::ErrorInst::InstId; @@ -149,7 +148,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, CARBON_DIAGNOSTIC( ReturnExprWithReturnedVar, Error, "can only `return var;` in the scope of a `returned var`"); - auto diag = context.emitter().Build(node_id, ReturnExprWithReturnedVar); + auto diag = context.emitter().Build(loc_id, ReturnExprWithReturnedVar); NoteReturnedVar(diag, returned_var_id); diag.Emit(); expr_id = SemIR::ErrorInst::InstId; @@ -161,13 +160,13 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, return_slot_id = GetCurrentReturnSlot(context); CARBON_CHECK(return_slot_id.has_value()); // Note that this can import a function and invalidate `function`. - expr_id = Initialize(context, node_id, return_slot_id, expr_id); + expr_id = Initialize(context, loc_id, return_slot_id, expr_id); } else { expr_id = - ConvertToValueOfType(context, node_id, expr_id, return_info.type_id); + ConvertToValueOfType(context, loc_id, expr_id, return_info.type_id); } - AddInst(context, node_id, + AddInst(context, loc_id, {.expr_id = expr_id, .dest_id = return_slot_id}); } diff --git a/toolchain/check/return.h b/toolchain/check/return.h index 0748850f32b6..810f7f64d93d 100644 --- a/toolchain/check/return.h +++ b/toolchain/check/return.h @@ -25,11 +25,10 @@ auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node, SemIR::InstId bind_id) -> void; // Checks and builds SemIR for a `return;` statement. -auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id) - -> void; +auto BuildReturnWithNoExpr(Context& context, SemIR::LocId loc_id) -> void; // Checks and builds SemIR for a `return ;` statement. -auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, +auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id) -> void; // Checks and builds SemIR for a `return var;` statement. diff --git a/toolchain/check/subpattern.cpp b/toolchain/check/subpattern.cpp deleted file mode 100644 index a99507193992..000000000000 --- a/toolchain/check/subpattern.cpp +++ /dev/null @@ -1,48 +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 - -#include "toolchain/check/subpattern.h" - -#include "toolchain/check/inst.h" - -namespace Carbon::Check { - -auto BeginSubpattern(Context& context) -> void { - context.inst_block_stack().Push(); - context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd()); -} - -auto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id) - -> SemIR::ExprRegionId { - if (context.region_stack().PeekRegion().size() > 1) { - // End the exit block with a branch to a successor block, whose contents - // will be determined later. - AddInst(context, - SemIR::LocIdAndInst::NoLoc( - {.target_id = context.inst_blocks().AddPlaceholder()})); - } else { - // This single-block region will be inserted as a SpliceBlock, so we don't - // need control flow out of it. - } - auto block_id = context.inst_block_stack().Pop(); - CARBON_CHECK(block_id == context.region_stack().PeekRegion().back()); - - // TODO: Is it possible to validate that this region is genuinely - // single-entry, single-exit? - return context.sem_ir().expr_regions().Add( - {.block_ids = context.region_stack().PopRegion(), - .result_id = result_id}); -} - -auto EndSubpatternAsNonExpr(Context& context) -> void { - auto block_id = context.inst_block_stack().Pop(); - CARBON_CHECK(block_id == context.region_stack().PeekRegion().back()); - CARBON_CHECK(context.region_stack().PeekRegion().size() == 1); - // TODO: Add `CARBON_CHECK(inst_blocks().Get(block_id).empty())`. - // Currently that can fail when ending a tuple pattern in a name binding - // decl in a class or interface. - context.region_stack().PopAndDiscardRegion(); -} - -} // namespace Carbon::Check diff --git a/toolchain/check/testdata/impl/fail_call_invalid.carbon b/toolchain/check/testdata/impl/fail_call_invalid.carbon index 71a712fed3f2..9bbb1f9d426a 100644 --- a/toolchain/check/testdata/impl/fail_call_invalid.carbon +++ b/toolchain/check/testdata/impl/fail_call_invalid.carbon @@ -32,6 +32,7 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: %Self.as_type.716: type = facet_access_type %Self.3c9 [symbolic] // CHECK:STDOUT: %pattern_type.f88: type = pattern_type %Self.as_type.716 [symbolic] // CHECK:STDOUT: %G.type.b60: type = fn_type @G.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %G.cb0: %G.type.b60 = struct_value () [concrete] // CHECK:STDOUT: %Simple.assoc_type: type = assoc_entity_type @Simple [concrete] // CHECK:STDOUT: %assoc0.db2: %Simple.assoc_type = assoc_entity element0, @Simple.%G.decl [concrete] @@ -40,13 +41,15 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %Simple.impl_witness: = impl_witness file.%Simple.impl_witness_table [concrete] -// CHECK:STDOUT: %G.type.c98: type = fn_type @G.2 [concrete] -// CHECK:STDOUT: %G.e73: %G.type.c98 = struct_value () [concrete] +// CHECK:STDOUT: %G.type.c9825d.1: type = fn_type @G.2 [concrete] +// CHECK:STDOUT: %G.e73e91.1: %G.type.c9825d.1 = struct_value () [concrete] // CHECK:STDOUT: %Simple.facet: %Simple.type = facet_value %i32, (%Simple.impl_witness) [concrete] // CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %G.type.c9825d.2: type = fn_type @G.3 [concrete] +// CHECK:STDOUT: %G.e73e91.2: %G.type.c9825d.2 = struct_value () [concrete] // CHECK:STDOUT: %InstanceCall.type: type = fn_type @InstanceCall [concrete] // CHECK:STDOUT: %InstanceCall: %InstanceCall.type = struct_value () [concrete] -// CHECK:STDOUT: %.0aa: type = fn_type_with_self_type %G.type.b60, %Simple.facet [concrete] +// CHECK:STDOUT: %.8e6: type = fn_type_with_self_type %G.type.b60, %Simple.facet [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -72,7 +75,7 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %Simple.impl_witness_table = impl_witness_table (), @impl.006 [concrete] +// CHECK:STDOUT: %Simple.impl_witness_table = impl_witness_table (@impl.006.%G.decl.loc20_27.2), @impl.006 [concrete] // CHECK:STDOUT: %Simple.impl_witness: = impl_witness %Simple.impl_witness_table [concrete = constants.%Simple.impl_witness] // CHECK:STDOUT: %InstanceCall.decl: %InstanceCall.type = fn_decl @InstanceCall [concrete = constants.%InstanceCall] { // CHECK:STDOUT: %n.patt: %pattern_type.7ce = binding_pattern n [concrete] @@ -110,7 +113,7 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.006: %i32 as %Simple.ref { -// CHECK:STDOUT: %G.decl: %G.type.c98 = fn_decl @G.2 [concrete = constants.%G.e73] { +// CHECK:STDOUT: %G.decl.loc20_27.1: %G.type.c9825d.1 = fn_decl @G.2 [concrete = constants.%G.e73e91.1] { // CHECK:STDOUT: %self.patt: = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: } { @@ -118,10 +121,17 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: %Undeclared.ref: = name_ref Undeclared, [concrete = ] // CHECK:STDOUT: %self: = bind_name self, %self.param // CHECK:STDOUT: } +// CHECK:STDOUT: %G.decl.loc20_27.2: %G.type.c9825d.2 = fn_decl @G.3 [concrete = constants.%G.e73e91.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.7ce = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.7ce = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %i32 = value_param call_param0 +// CHECK:STDOUT: %self: %i32 = bind_name self, %self.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Undeclared = -// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: .G = %G.decl.loc20_27.1 // CHECK:STDOUT: witness = file.%Simple.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: @@ -135,12 +145,22 @@ fn InstanceCall(n: i32) { // CHECK:STDOUT: // CHECK:STDOUT: fn @G.2(%self.param: ); // CHECK:STDOUT: +// CHECK:STDOUT: fn @G.3(%self.param: %i32) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %i32 = name_ref self, %self.param +// CHECK:STDOUT: %G.bound: = bound_method %self.ref, @impl.006.%G.decl.loc20_27.1 +// CHECK:STDOUT: %G.call: init %empty_tuple.type = call %G.bound() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: fn @InstanceCall(%n.param: %i32) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %n.ref: %i32 = name_ref n, %n // CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type] // CHECK:STDOUT: %G.ref: %Simple.assoc_type = name_ref G, @Simple.%assoc0 [concrete = constants.%assoc0.db2] -// CHECK:STDOUT: %impl.elem0: %.0aa = impl_witness_access constants.%Simple.impl_witness, element0 [concrete = ] +// CHECK:STDOUT: %impl.elem0: %.8e6 = impl_witness_access constants.%Simple.impl_witness, element0 [concrete = constants.%G.e73e91.2] +// CHECK:STDOUT: %bound_method: = bound_method %n.ref, %impl.elem0 +// CHECK:STDOUT: %G.call: init %empty_tuple.type = call %bound_method(%n.ref) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: 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 011593c735fe..3dc095c40855 100644 --- a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon +++ b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon @@ -52,10 +52,13 @@ class FAlias { class FExtraParam { impl as I { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: 0 arguments passed to function expecting 1 argument [CallArgCountMismatch] // CHECK:STDERR: fn F(b: bool); // CHECK:STDERR: ^~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-47]]:15: note: previously declared with parameter count of 0 [RedeclParamCountPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToEntity] + // CHECK:STDERR: fn F(b: bool); + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-50]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface I { fn F(); } // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -65,10 +68,13 @@ class FExtraParam { class FExtraImplicitParam { impl as I { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: redeclaration differs because of implicit parameter list [RedeclParamListDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: missing object argument in method call [MissingObjectInMethodCall] // CHECK:STDERR: fn F[self: Self](); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-60]]:15: note: previously declared without implicit parameter list [RedeclParamListPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToFunction] + // CHECK:STDERR: fn F[self: Self](); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-66]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface I { fn F(); } // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -82,7 +88,7 @@ class FExtraReturnType { // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: function redeclaration differs because return type is `bool` [FunctionRedeclReturnTypeDiffers] // CHECK:STDERR: fn F() -> bool; // CHECK:STDERR: ^~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-74]]:15: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-80]]:15: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn] // CHECK:STDERR: interface I { fn F(); } // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -94,10 +100,13 @@ interface J { fn F[self: bool](b: bool) -> bool; } class FMissingParam { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: redeclaration differs because of parameter count of 0 [RedeclParamCountDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: 1 argument passed to function expecting 0 arguments [CallArgCountMismatch] // CHECK:STDERR: fn F[self: bool]() -> bool; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-7]]:15: note: previously declared with parameter count of 1 [RedeclParamCountPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToEntity] + // CHECK:STDERR: fn F[self: bool]() -> bool; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-10]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -107,10 +116,10 @@ class FMissingParam { class FMissingImplicitParam { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: redeclaration differs because of missing implicit parameter list [RedeclParamListDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: member name of type `` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase] // CHECK:STDERR: fn F(b: bool) -> bool; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-20]]:15: note: previously declared with implicit parameter list [RedeclParamListPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-23]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -120,38 +129,53 @@ class FMissingImplicitParam { class FMissingReturnType { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: function redeclaration differs because no return type is provided [FunctionRedeclReturnTypeDiffersNoReturn] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+13]]:5: error: cannot implicitly convert expression of type `()` to `bool` [ConversionFailure] // CHECK:STDERR: fn F[self: bool](b: bool); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-33]]:15: note: previously declared with return type `bool` [FunctionRedeclReturnTypePrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: note: type `()` does not implement interface `Core.ImplicitAs(bool)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: fn F[self: bool](b: bool); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-39]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-43]]:32: error: forming value of incomplete type `FDifferentParamType` [IncompleteTypeInValueConversion] + // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } + // CHECK:STDERR: ^~~~~~~ fn F[self: bool](b: bool); } } +// CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] +// CHECK:STDERR: class FDifferentParamType { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ class FDifferentParamType { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:22: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:22: note: initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: fn F[self: bool](b: Self) -> bool; // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-46]]:32: note: previous declaration's corresponding parameter here [RedeclParamPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-58]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } - // CHECK:STDERR: ^~~~~~~ + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-62]]:20: error: forming value of incomplete type `FDifferentImplicitParamType` [IncompleteTypeInValueConversion] + // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } + // CHECK:STDERR: ^~~~~~~~~~ fn F[self: bool](b: Self) -> bool; } } +// CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] +// CHECK:STDERR: class FDifferentImplicitParamType { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class FDifferentImplicitParamType { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: error: type `` of implicit parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: fn F[self: Self](b: bool) -> bool; // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-59]]:20: note: previous declaration's corresponding implicit parameter here [RedeclParamPrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-77]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } - // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fn F[self: Self](b: bool) -> bool; } @@ -159,10 +183,16 @@ class FDifferentImplicitParamType { class FDifferentReturnType { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: function redeclaration differs because return type is `FDifferentReturnType` [FunctionRedeclReturnTypeDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+13]]:5: error: function returns incomplete type `FDifferentReturnType` [IncompleteTypeInFunctionReturnType] // CHECK:STDERR: fn F[self: bool](b: bool) -> Self; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-72]]:15: note: previously declared with return type `bool` [FunctionRedeclReturnTypePrevious] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-5]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class FDifferentReturnType { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:31: note: return type declared here [IncompleteReturnTypeHere] + // CHECK:STDERR: fn F[self: bool](b: bool) -> Self; + // CHECK:STDERR: ^~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-96]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -170,43 +200,94 @@ class FDifferentReturnType { } } -// TODO: This should probably be permitted. -class FDifferentParamName { - impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:22: error: redeclaration differs at parameter 1 [RedeclParamDiffers] - // CHECK:STDERR: fn F[self: bool](not_b: bool) -> bool; - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-86]]:32: note: previous declaration's corresponding parameter here [RedeclParamPrevious] - // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; } - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: - fn F[self: bool](not_b: bool) -> bool; - } -} - interface SelfNested { + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:41: error: function returns incomplete type `array(SelfNestedBadParam, 4)` [IncompleteTypeInFunctionReturnType] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); } +// CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] +// CHECK:STDERR: class SelfNestedBadParam { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~ class SelfNestedBadParam { impl as SelfNested { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+43]]:5: note: while building thunk calling this function [ThunkCallee] // CHECK:STDERR: fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-8]]:8: note: previous declaration's corresponding parameter here [RedeclParamPrevious] + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-12]]:8: error: parameter has incomplete type `(SelfNestedBadParam*, {.x: SelfNestedBadParam, .y: i32})` in function definition [IncompleteTypeInFunctionParam] // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-9]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class SelfNestedBadParam { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+33]]:5: note: while building thunk calling this function [ThunkCallee] + // CHECK:STDERR: fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+29]]:5: error: function returns incomplete type `array(SelfNestedBadParam, 4)` [IncompleteTypeInFunctionReturnType] + // CHECK:STDERR: fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-19]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class SelfNestedBadParam { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+23]]:56: note: return type declared here [IncompleteReturnTypeHere] + // CHECK:STDERR: fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-31]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-35]]:8: error: cannot implicitly convert expression of type `SelfNestedBadParam` to `i32` [ConversionFailure] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-38]]:8: note: type `SelfNestedBadParam` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:10: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-44]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-48]]:41: error: function returns incomplete type `array(SelfNestedBadReturnType, 4)` [IncompleteTypeInFunctionReturnType] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4); } } +// CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] +// CHECK:STDERR: class SelfNestedBadReturnType { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class SelfNestedBadReturnType { impl as SelfNested { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: function redeclaration differs because return type is `array(SelfNestedBadParam, 4)` [FunctionRedeclReturnTypeDiffers] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+27]]:5: note: while building thunk calling this function [ThunkCallee] // CHECK:STDERR: fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-21]]:3: note: previously declared with return type `array(SelfNestedBadReturnType, 4)` [FunctionRedeclReturnTypePrevious] + // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-64]]:8: error: parameter has incomplete type `(SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})` in function definition [IncompleteTypeInFunctionParam] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-9]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class SelfNestedBadReturnType { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+17]]:5: note: while building thunk calling this function [ThunkCallee] + // CHECK:STDERR: fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-74]]:8: error: forming value of incomplete type `(SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})` [IncompleteTypeInValueConversion] + // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-19]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class SelfNestedBadReturnType { + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-83]]:3: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -220,6 +301,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] // CHECK:STDOUT: %Self.826: %I.type = bind_symbolic_name Self, 0 [symbolic] // CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] // CHECK:STDOUT: %assoc0.82e: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] @@ -229,128 +311,147 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %FNotFunction: type = class_type @FNotFunction [concrete] // CHECK:STDOUT: %I.impl_witness.44e: = impl_witness @FNotFunction.%I.impl_witness_table [concrete] -// CHECK:STDOUT: %F.70c: type = class_type @F.16 [concrete] +// CHECK:STDOUT: %F.70c: type = class_type @F.25 [concrete] // CHECK:STDOUT: %PossiblyF.type: type = fn_type @PossiblyF [concrete] // CHECK:STDOUT: %PossiblyF: %PossiblyF.type = struct_value () [concrete] // CHECK:STDOUT: %FAlias: type = class_type @FAlias [concrete] // CHECK:STDOUT: %I.impl_witness.c80: = impl_witness @FAlias.%I.impl_witness_table [concrete] // CHECK:STDOUT: %FExtraParam: type = class_type @FExtraParam [concrete] -// CHECK:STDOUT: %I.impl_witness.f6b: = impl_witness @FExtraParam.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %I.impl_witness.1f3: = impl_witness @FExtraParam.%I.impl_witness_table [concrete] // CHECK:STDOUT: %Bool.type: type = fn_type @Bool [concrete] // CHECK:STDOUT: %Bool: %Bool.type = struct_value () [concrete] // CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] -// CHECK:STDOUT: %F.type.44e: type = fn_type @F.2 [concrete] -// CHECK:STDOUT: %F.424: %F.type.44e = struct_value () [concrete] -// CHECK:STDOUT: %I.facet.86d: %I.type = facet_value %FExtraParam, (%I.impl_witness.f6b) [concrete] +// CHECK:STDOUT: %F.type.44ef8c.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.424e9e.1: %F.type.44ef8c.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet.fa4: %I.type = facet_value %FExtraParam, (%I.impl_witness.1f3) [concrete] +// CHECK:STDOUT: %F.type.44ef8c.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.424e9e.2: %F.type.44ef8c.2 = struct_value () [concrete] // CHECK:STDOUT: %FExtraImplicitParam: type = class_type @FExtraImplicitParam [concrete] -// CHECK:STDOUT: %I.impl_witness.e58: = impl_witness @FExtraImplicitParam.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %I.impl_witness.a7b: = impl_witness @FExtraImplicitParam.%I.impl_witness_table [concrete] // CHECK:STDOUT: %pattern_type.8ae: type = pattern_type %FExtraImplicitParam [concrete] -// CHECK:STDOUT: %F.type.e1a: type = fn_type @F.3 [concrete] -// CHECK:STDOUT: %F.6ff: %F.type.e1a = struct_value () [concrete] -// CHECK:STDOUT: %I.facet.919: %I.type = facet_value %FExtraImplicitParam, (%I.impl_witness.e58) [concrete] +// CHECK:STDOUT: %F.type.e1abdd.1: type = fn_type @F.4 [concrete] +// CHECK:STDOUT: %F.6ff574.1: %F.type.e1abdd.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet.ee5: %I.type = facet_value %FExtraImplicitParam, (%I.impl_witness.a7b) [concrete] +// CHECK:STDOUT: %F.type.e1abdd.2: type = fn_type @F.5 [concrete] +// CHECK:STDOUT: %F.6ff574.2: %F.type.e1abdd.2 = struct_value () [concrete] // CHECK:STDOUT: %FExtraReturnType: type = class_type @FExtraReturnType [concrete] // CHECK:STDOUT: %I.impl_witness.59a: = impl_witness @FExtraReturnType.%I.impl_witness_table [concrete] -// CHECK:STDOUT: %F.type.387: type = fn_type @F.4 [concrete] +// CHECK:STDOUT: %F.type.387: type = fn_type @F.6 [concrete] // CHECK:STDOUT: %F.df5: %F.type.387 = struct_value () [concrete] // CHECK:STDOUT: %I.facet.d5c: %I.type = facet_value %FExtraReturnType, (%I.impl_witness.59a) [concrete] // CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete] // CHECK:STDOUT: %Self.ccd: %J.type = bind_symbolic_name Self, 0 [symbolic] -// CHECK:STDOUT: %F.type.c14: type = fn_type @F.5 [concrete] +// CHECK:STDOUT: %F.type.c14: type = fn_type @F.7 [concrete] // CHECK:STDOUT: %F.b71: %F.type.c14 = struct_value () [concrete] // CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete] // CHECK:STDOUT: %assoc0.922: %J.assoc_type = assoc_entity element0, @J.%F.decl [concrete] // CHECK:STDOUT: %FMissingParam: type = class_type @FMissingParam [concrete] -// CHECK:STDOUT: %J.impl_witness.b4b: = impl_witness @FMissingParam.%J.impl_witness_table [concrete] -// CHECK:STDOUT: %F.type.695: type = fn_type @F.6 [concrete] -// CHECK:STDOUT: %F.738: %F.type.695 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.97d: %J.type = facet_value %FMissingParam, (%J.impl_witness.b4b) [concrete] +// CHECK:STDOUT: %J.impl_witness.4e9: = impl_witness @FMissingParam.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %F.type.69596c.1: type = fn_type @F.8 [concrete] +// CHECK:STDOUT: %F.738f31.1: %F.type.69596c.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.94c: %J.type = facet_value %FMissingParam, (%J.impl_witness.4e9) [concrete] +// CHECK:STDOUT: %F.type.69596c.2: type = fn_type @F.9 [concrete] +// CHECK:STDOUT: %F.738f31.2: %F.type.69596c.2 = struct_value () [concrete] // CHECK:STDOUT: %FMissingImplicitParam: type = class_type @FMissingImplicitParam [concrete] -// CHECK:STDOUT: %J.impl_witness.c79: = impl_witness @FMissingImplicitParam.%J.impl_witness_table [concrete] -// CHECK:STDOUT: %F.type.d97: type = fn_type @F.7 [concrete] -// CHECK:STDOUT: %F.01d: %F.type.d97 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.0d0: %J.type = facet_value %FMissingImplicitParam, (%J.impl_witness.c79) [concrete] +// CHECK:STDOUT: %J.impl_witness.841: = impl_witness @FMissingImplicitParam.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %F.type.d97cef.1: type = fn_type @F.10 [concrete] +// CHECK:STDOUT: %F.01de92.1: %F.type.d97cef.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.e7e: %J.type = facet_value %FMissingImplicitParam, (%J.impl_witness.841) [concrete] +// CHECK:STDOUT: %F.type.d97cef.2: type = fn_type @F.11 [concrete] +// CHECK:STDOUT: %F.01de92.2: %F.type.d97cef.2 = struct_value () [concrete] // CHECK:STDOUT: %FMissingReturnType: type = class_type @FMissingReturnType [concrete] -// CHECK:STDOUT: %J.impl_witness.39b: = impl_witness @FMissingReturnType.%J.impl_witness_table [concrete] -// CHECK:STDOUT: %F.type.123: type = fn_type @F.8 [concrete] -// CHECK:STDOUT: %F.c7d: %F.type.123 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.97a: %J.type = facet_value %FMissingReturnType, (%J.impl_witness.39b) [concrete] +// CHECK:STDOUT: %J.impl_witness.e75: = impl_witness @FMissingReturnType.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %F.type.123d7a.1: type = fn_type @F.12 [concrete] +// CHECK:STDOUT: %F.c7d02d.1: %F.type.123d7a.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.974: %J.type = facet_value %FMissingReturnType, (%J.impl_witness.e75) [concrete] +// CHECK:STDOUT: %F.type.123d7a.2: type = fn_type @F.13 [concrete] +// CHECK:STDOUT: %F.c7d02d.2: %F.type.123d7a.2 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete] +// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete] // CHECK:STDOUT: %FDifferentParamType: type = class_type @FDifferentParamType [concrete] -// CHECK:STDOUT: %J.impl_witness.eab: = impl_witness @FDifferentParamType.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %J.impl_witness.cbe: = impl_witness @FDifferentParamType.%J.impl_witness_table [concrete] // CHECK:STDOUT: %pattern_type.b90: type = pattern_type %FDifferentParamType [concrete] -// CHECK:STDOUT: %F.type.6b5: type = fn_type @F.9 [concrete] -// CHECK:STDOUT: %F.043: %F.type.6b5 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.955: %J.type = facet_value %FDifferentParamType, (%J.impl_witness.eab) [concrete] +// CHECK:STDOUT: %F.type.6b537d.1: type = fn_type @F.14 [concrete] +// CHECK:STDOUT: %F.04313a.1: %F.type.6b537d.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.37e: %J.type = facet_value %FDifferentParamType, (%J.impl_witness.cbe) [concrete] +// CHECK:STDOUT: %F.type.6b537d.2: type = fn_type @F.15 [concrete] +// CHECK:STDOUT: %F.04313a.2: %F.type.6b537d.2 = struct_value () [concrete] // CHECK:STDOUT: %FDifferentImplicitParamType: type = class_type @FDifferentImplicitParamType [concrete] -// CHECK:STDOUT: %J.impl_witness.103: = impl_witness @FDifferentImplicitParamType.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %J.impl_witness.af2: = impl_witness @FDifferentImplicitParamType.%J.impl_witness_table [concrete] // CHECK:STDOUT: %pattern_type.9cc: type = pattern_type %FDifferentImplicitParamType [concrete] -// CHECK:STDOUT: %F.type.d62: type = fn_type @F.10 [concrete] -// CHECK:STDOUT: %F.886: %F.type.d62 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.130: %J.type = facet_value %FDifferentImplicitParamType, (%J.impl_witness.103) [concrete] +// CHECK:STDOUT: %F.type.d6232a.1: type = fn_type @F.16 [concrete] +// CHECK:STDOUT: %F.886f70.1: %F.type.d6232a.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.bf1: %J.type = facet_value %FDifferentImplicitParamType, (%J.impl_witness.af2) [concrete] +// CHECK:STDOUT: %F.type.d6232a.2: type = fn_type @F.17 [concrete] +// CHECK:STDOUT: %F.886f70.2: %F.type.d6232a.2 = struct_value () [concrete] // CHECK:STDOUT: %FDifferentReturnType: type = class_type @FDifferentReturnType [concrete] -// CHECK:STDOUT: %J.impl_witness.6f7: = impl_witness @FDifferentReturnType.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %J.impl_witness.bc1: = impl_witness @FDifferentReturnType.%J.impl_witness_table [concrete] // CHECK:STDOUT: %pattern_type.8ee: type = pattern_type %FDifferentReturnType [concrete] -// CHECK:STDOUT: %F.type.d3b: type = fn_type @F.11 [concrete] -// CHECK:STDOUT: %F.be8: %F.type.d3b = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.1a7: %J.type = facet_value %FDifferentReturnType, (%J.impl_witness.6f7) [concrete] -// CHECK:STDOUT: %FDifferentParamName: type = class_type @FDifferentParamName [concrete] -// CHECK:STDOUT: %J.impl_witness.3ab: = impl_witness @FDifferentParamName.%J.impl_witness_table [concrete] -// CHECK:STDOUT: %F.type.d19: type = fn_type @F.12 [concrete] -// CHECK:STDOUT: %F.669: %F.type.d19 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.366: %J.type = facet_value %FDifferentParamName, (%J.impl_witness.3ab) [concrete] +// CHECK:STDOUT: %F.type.d3b58f.1: type = fn_type @F.18 [concrete] +// CHECK:STDOUT: %F.be86c9.1: %F.type.d3b58f.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.67f: %J.type = facet_value %FDifferentReturnType, (%J.impl_witness.bc1) [concrete] +// CHECK:STDOUT: %F.type.d3b58f.2: type = fn_type @F.19 [concrete] +// CHECK:STDOUT: %F.be86c9.2: %F.type.d3b58f.2 = struct_value () [concrete] // CHECK:STDOUT: %SelfNested.type: type = facet_type <@SelfNested> [concrete] // CHECK:STDOUT: %Self.2ff: %SelfNested.type = bind_symbolic_name Self, 0 [symbolic] -// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.2ff [symbolic] -// CHECK:STDOUT: %ptr.e87: type = ptr_type %Self.as_type [symbolic] +// CHECK:STDOUT: %Self.as_type.e1e: type = facet_access_type %Self.2ff [symbolic] +// CHECK:STDOUT: %ptr.e87: type = ptr_type %Self.as_type.e1e [symbolic] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete] // CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %struct_type.x.y.81e: type = struct_type {.x: %Self.as_type, .y: %i32} [symbolic] +// CHECK:STDOUT: %struct_type.x.y.81e: type = struct_type {.x: %Self.as_type.e1e, .y: %i32} [symbolic] // CHECK:STDOUT: %tuple.type.24b: type = tuple_type (type, type) [concrete] // CHECK:STDOUT: %tuple.type.229: type = tuple_type (%ptr.e87, %struct_type.x.y.81e) [symbolic] // CHECK:STDOUT: %pattern_type.ced: type = pattern_type %tuple.type.229 [symbolic] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete] -// CHECK:STDOUT: %array_type.873: type = array_type %int_4, %Self.as_type [symbolic] +// CHECK:STDOUT: %array_type.873: type = array_type %int_4, %Self.as_type.e1e [symbolic] // CHECK:STDOUT: %pattern_type.c7e: type = pattern_type %array_type.873 [symbolic] -// CHECK:STDOUT: %F.type.6ed: type = fn_type @F.13 [concrete] +// CHECK:STDOUT: %F.type.6ed: type = fn_type @F.20 [concrete] // CHECK:STDOUT: %F.998: %F.type.6ed = struct_value () [concrete] // CHECK:STDOUT: %SelfNested.assoc_type: type = assoc_entity_type @SelfNested [concrete] // CHECK:STDOUT: %assoc0.beb: %SelfNested.assoc_type = assoc_entity element0, @SelfNested.%F.decl [concrete] // CHECK:STDOUT: %SelfNestedBadParam: type = class_type @SelfNestedBadParam [concrete] -// CHECK:STDOUT: %SelfNested.impl_witness.21a: = impl_witness @SelfNestedBadParam.%SelfNested.impl_witness_table [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness.e31: = impl_witness @SelfNestedBadParam.%SelfNested.impl_witness_table [concrete] // CHECK:STDOUT: %ptr.4cd: type = ptr_type %SelfNestedBadParam [concrete] // CHECK:STDOUT: %struct_type.x.y.871: type = struct_type {.x: %i32, .y: %i32} [concrete] // CHECK:STDOUT: %tuple.type.a7d: type = tuple_type (%ptr.4cd, %struct_type.x.y.871) [concrete] // CHECK:STDOUT: %pattern_type.714: type = pattern_type %tuple.type.a7d [concrete] // CHECK:STDOUT: %array_type.a41: type = array_type %int_4, %SelfNestedBadParam [concrete] // CHECK:STDOUT: %pattern_type.1f1: type = pattern_type %array_type.a41 [concrete] -// CHECK:STDOUT: %F.type.f90: type = fn_type @F.14 [concrete] -// CHECK:STDOUT: %F.fa8: %F.type.f90 = struct_value () [concrete] -// CHECK:STDOUT: %SelfNested.facet.9f5: %SelfNested.type = facet_value %SelfNestedBadParam, (%SelfNested.impl_witness.21a) [concrete] +// CHECK:STDOUT: %F.type.f90165.1: type = fn_type @F.21 [concrete] +// CHECK:STDOUT: %F.fa8d04.1: %F.type.f90165.1 = struct_value () [concrete] +// CHECK:STDOUT: %SelfNested.facet.608: %SelfNested.type = facet_value %SelfNestedBadParam, (%SelfNested.impl_witness.e31) [concrete] // CHECK:STDOUT: %struct_type.x.y.a89: type = struct_type {.x: %SelfNestedBadParam, .y: %i32} [concrete] // CHECK:STDOUT: %tuple.type.9c9: type = tuple_type (%ptr.4cd, %struct_type.x.y.a89) [concrete] // CHECK:STDOUT: %pattern_type.a5c: type = pattern_type %tuple.type.9c9 [concrete] +// CHECK:STDOUT: %F.type.f90165.2: type = fn_type @F.22 [concrete] +// CHECK:STDOUT: %F.fa8d04.2: %F.type.f90165.2 = struct_value () [concrete] // CHECK:STDOUT: %SelfNestedBadReturnType: type = class_type @SelfNestedBadReturnType [concrete] -// CHECK:STDOUT: %SelfNested.impl_witness.b10: = impl_witness @SelfNestedBadReturnType.%SelfNested.impl_witness_table [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness.d5e: = impl_witness @SelfNestedBadReturnType.%SelfNested.impl_witness_table [concrete] // CHECK:STDOUT: %ptr.612: type = ptr_type %SelfNestedBadReturnType [concrete] // CHECK:STDOUT: %struct_type.x.y.ac5: type = struct_type {.x: %SelfNestedBadReturnType, .y: %i32} [concrete] // CHECK:STDOUT: %tuple.type.eb9: type = tuple_type (%ptr.612, %struct_type.x.y.ac5) [concrete] // CHECK:STDOUT: %pattern_type.23f: type = pattern_type %tuple.type.eb9 [concrete] -// CHECK:STDOUT: %F.type.0e7: type = fn_type @F.15 [concrete] -// CHECK:STDOUT: %F.0bc: %F.type.0e7 = struct_value () [concrete] -// CHECK:STDOUT: %SelfNested.facet.3bd: %SelfNested.type = facet_value %SelfNestedBadReturnType, (%SelfNested.impl_witness.b10) [concrete] +// CHECK:STDOUT: %F.type.0e7d1d.1: type = fn_type @F.23 [concrete] +// CHECK:STDOUT: %F.0bc78a.1: %F.type.0e7d1d.1 = struct_value () [concrete] +// CHECK:STDOUT: %SelfNested.facet.766: %SelfNested.type = facet_value %SelfNestedBadReturnType, (%SelfNested.impl_witness.d5e) [concrete] // CHECK:STDOUT: %array_type.126: type = array_type %int_4, %SelfNestedBadReturnType [concrete] // CHECK:STDOUT: %pattern_type.f56: type = pattern_type %array_type.126 [concrete] +// CHECK:STDOUT: %F.type.0e7d1d.2: type = fn_type @F.24 [concrete] +// CHECK:STDOUT: %F.0bc78a.2: %F.type.0e7d1d.2 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { // CHECK:STDOUT: .Bool = %Core.Bool +// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs // CHECK:STDOUT: .Int = %Core.Int // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } // CHECK:STDOUT: %Core.Bool: %Bool.type = import_ref Core//prelude/types/bool, Bool, loaded [concrete = constants.%Bool] +// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -372,7 +473,6 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: .FDifferentParamType = %FDifferentParamType.decl // CHECK:STDOUT: .FDifferentImplicitParamType = %FDifferentImplicitParamType.decl // CHECK:STDOUT: .FDifferentReturnType = %FDifferentReturnType.decl -// CHECK:STDOUT: .FDifferentParamName = %FDifferentParamName.decl // CHECK:STDOUT: .SelfNested = %SelfNested.decl // CHECK:STDOUT: .SelfNestedBadParam = %SelfNestedBadParam.decl // CHECK:STDOUT: .SelfNestedBadReturnType = %SelfNestedBadReturnType.decl @@ -393,7 +493,6 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %FDifferentParamType.decl: type = class_decl @FDifferentParamType [concrete = constants.%FDifferentParamType] {} {} // CHECK:STDOUT: %FDifferentImplicitParamType.decl: type = class_decl @FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType] {} {} // CHECK:STDOUT: %FDifferentReturnType.decl: type = class_decl @FDifferentReturnType [concrete = constants.%FDifferentReturnType] {} {} -// CHECK:STDOUT: %FDifferentParamName.decl: type = class_decl @FDifferentParamName [concrete = constants.%FDifferentParamName] {} {} // CHECK:STDOUT: %SelfNested.decl: type = interface_decl @SelfNested [concrete = constants.%SelfNested.type] {} {} // CHECK:STDOUT: %SelfNestedBadParam.decl: type = class_decl @SelfNestedBadParam [concrete = constants.%SelfNestedBadParam] {} {} // CHECK:STDOUT: %SelfNestedBadReturnType.decl: type = class_decl @SelfNestedBadReturnType [concrete = constants.%SelfNestedBadReturnType] {} {} @@ -412,7 +511,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: interface @J { // CHECK:STDOUT: %Self: %J.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.ccd] -// CHECK:STDOUT: %F.decl: %F.type.c14 = fn_decl @F.5 [concrete = constants.%F.b71] { +// CHECK:STDOUT: %F.decl: %F.type.c14 = fn_decl @F.7 [concrete = constants.%F.b71] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] @@ -420,21 +519,21 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc93_44: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc93_44.1: type = value_of_initializer %bool.make_type.loc93_44 [concrete = bool] -// CHECK:STDOUT: %.loc93_44.2: type = converted %bool.make_type.loc93_44, %.loc93_44.1 [concrete = bool] +// CHECK:STDOUT: %bool.make_type.loc99_44: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc99_44.1: type = value_of_initializer %bool.make_type.loc99_44 [concrete = bool] +// CHECK:STDOUT: %.loc99_44.2: type = converted %bool.make_type.loc99_44, %.loc99_44.1 [concrete = bool] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc93_26.1: type = splice_block %.loc93_26.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc93_26: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc93_26.2: type = value_of_initializer %bool.make_type.loc93_26 [concrete = bool] -// CHECK:STDOUT: %.loc93_26.3: type = converted %bool.make_type.loc93_26, %.loc93_26.2 [concrete = bool] +// CHECK:STDOUT: %.loc99_26.1: type = splice_block %.loc99_26.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc99_26: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc99_26.2: type = value_of_initializer %bool.make_type.loc99_26 [concrete = bool] +// CHECK:STDOUT: %.loc99_26.3: type = converted %bool.make_type.loc99_26, %.loc99_26.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param // CHECK:STDOUT: %b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc93_35.1: type = splice_block %.loc93_35.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc93_35: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc93_35.2: type = value_of_initializer %bool.make_type.loc93_35 [concrete = bool] -// CHECK:STDOUT: %.loc93_35.3: type = converted %bool.make_type.loc93_35, %.loc93_35.2 [concrete = bool] +// CHECK:STDOUT: %.loc99_35.1: type = splice_block %.loc99_35.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc99_35: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc99_35.2: type = value_of_initializer %bool.make_type.loc99_35 [concrete = bool] +// CHECK:STDOUT: %.loc99_35.3: type = converted %bool.make_type.loc99_35, %.loc99_35.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: %return.param: ref bool = out_param call_param2 @@ -450,35 +549,35 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: interface @SelfNested { // CHECK:STDOUT: %Self: %SelfNested.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.2ff] -// CHECK:STDOUT: %F.decl: %F.type.6ed = fn_decl @F.13 [concrete = constants.%F.998] { -// CHECK:STDOUT: %x.patt: @F.13.%pattern_type.loc188_8 (%pattern_type.ced) = binding_pattern x [concrete] -// CHECK:STDOUT: %x.param_patt: @F.13.%pattern_type.loc188_8 (%pattern_type.ced) = value_param_pattern %x.patt, call_param0 [concrete] -// CHECK:STDOUT: %return.patt: @F.13.%pattern_type.loc188_41 (%pattern_type.c7e) = return_slot_pattern [concrete] -// CHECK:STDOUT: %return.param_patt: @F.13.%pattern_type.loc188_41 (%pattern_type.c7e) = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: %F.decl: %F.type.6ed = fn_decl @F.20 [concrete = constants.%F.998] { +// CHECK:STDOUT: %x.patt: @F.20.%pattern_type.loc207_8 (%pattern_type.ced) = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: @F.20.%pattern_type.loc207_8 (%pattern_type.ced) = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: @F.20.%pattern_type.loc207_41 (%pattern_type.c7e) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @F.20.%pattern_type.loc207_41 (%pattern_type.c7e) = out_param_pattern %return.patt, call_param1 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %Self.ref.loc188_50: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] +// CHECK:STDOUT: %Self.ref.loc207_50: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %Self.as_type.loc188_50: type = facet_access_type %Self.ref.loc188_50 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %.loc188_50: type = converted %Self.ref.loc188_50, %Self.as_type.loc188_50 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %array_type.loc188_57.2: type = array_type %int_4, %.loc188_50 [symbolic = %array_type.loc188_57.1 (constants.%array_type.873)] -// CHECK:STDOUT: %x.param: @F.13.%tuple.type (%tuple.type.229) = value_param call_param0 -// CHECK:STDOUT: %.loc188_38.1: type = splice_block %.loc188_38.3 [symbolic = %tuple.type (constants.%tuple.type.229)] { -// CHECK:STDOUT: %Self.ref.loc188_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] -// CHECK:STDOUT: %Self.as_type.loc188_16.2: type = facet_access_type %Self.ref.loc188_12 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %.loc188_16: type = converted %Self.ref.loc188_12, %Self.as_type.loc188_16.2 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %ptr.loc188_16.2: type = ptr_type %.loc188_16 [symbolic = %ptr.loc188_16.1 (constants.%ptr.e87)] -// CHECK:STDOUT: %Self.ref.loc188_24: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] -// CHECK:STDOUT: %Self.as_type.loc188_24: type = facet_access_type %Self.ref.loc188_24 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %.loc188_24: type = converted %Self.ref.loc188_24, %Self.as_type.loc188_24 [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %Self.as_type.loc207_50: type = facet_access_type %Self.ref.loc207_50 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %.loc207_50: type = converted %Self.ref.loc207_50, %Self.as_type.loc207_50 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %array_type.loc207_57.2: type = array_type %int_4, %.loc207_50 [symbolic = %array_type.loc207_57.1 (constants.%array_type.873)] +// CHECK:STDOUT: %x.param: @F.20.%tuple.type (%tuple.type.229) = value_param call_param0 +// CHECK:STDOUT: %.loc207_38.1: type = splice_block %.loc207_38.3 [symbolic = %tuple.type (constants.%tuple.type.229)] { +// CHECK:STDOUT: %Self.ref.loc207_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] +// CHECK:STDOUT: %Self.as_type.loc207_16.2: type = facet_access_type %Self.ref.loc207_12 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %.loc207_16: type = converted %Self.ref.loc207_12, %Self.as_type.loc207_16.2 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %ptr.loc207_16.2: type = ptr_type %.loc207_16 [symbolic = %ptr.loc207_16.1 (constants.%ptr.e87)] +// CHECK:STDOUT: %Self.ref.loc207_24: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.2ff)] +// CHECK:STDOUT: %Self.as_type.loc207_24: type = facet_access_type %Self.ref.loc207_24 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %.loc207_24: type = converted %Self.ref.loc207_24, %Self.as_type.loc207_24 [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %struct_type.x.y.loc188_37.2: type = struct_type {.x: @F.13.%Self.as_type.loc188_16.1 (%Self.as_type), .y: %i32} [symbolic = %struct_type.x.y.loc188_37.1 (constants.%struct_type.x.y.81e)] -// CHECK:STDOUT: %.loc188_38.2: %tuple.type.24b = tuple_literal (%ptr.loc188_16.2, %struct_type.x.y.loc188_37.2) -// CHECK:STDOUT: %.loc188_38.3: type = converted %.loc188_38.2, constants.%tuple.type.229 [symbolic = %tuple.type (constants.%tuple.type.229)] +// CHECK:STDOUT: %struct_type.x.y.loc207_37.2: type = struct_type {.x: @F.20.%Self.as_type.loc207_16.1 (%Self.as_type.e1e), .y: %i32} [symbolic = %struct_type.x.y.loc207_37.1 (constants.%struct_type.x.y.81e)] +// CHECK:STDOUT: %.loc207_38.2: %tuple.type.24b = tuple_literal (%ptr.loc207_16.2, %struct_type.x.y.loc207_37.2) +// CHECK:STDOUT: %.loc207_38.3: type = converted %.loc207_38.2, constants.%tuple.type.229 [symbolic = %tuple.type (constants.%tuple.type.229)] // CHECK:STDOUT: } -// CHECK:STDOUT: %x: @F.13.%tuple.type (%tuple.type.229) = bind_name x, %x.param -// CHECK:STDOUT: %return.param: ref @F.13.%array_type.loc188_57.1 (%array_type.873) = out_param call_param1 -// CHECK:STDOUT: %return: ref @F.13.%array_type.loc188_57.1 (%array_type.873) = return_slot %return.param +// CHECK:STDOUT: %x: @F.20.%tuple.type (%tuple.type.229) = bind_name x, %x.param +// CHECK:STDOUT: %return.param: ref @F.20.%array_type.loc207_57.1 (%array_type.873) = out_param call_param1 +// CHECK:STDOUT: %return: ref @F.20.%array_type.loc207_57.1 (%array_type.873) = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: %assoc0: %SelfNested.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0.beb] // CHECK:STDOUT: @@ -495,7 +594,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.b55: %Self.ref as %I.ref { -// CHECK:STDOUT: %F.decl: type = class_decl @F.16 [concrete = constants.%F.70c] {} {} +// CHECK:STDOUT: %F.decl: type = class_decl @F.25 [concrete = constants.%F.70c] {} {} // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .F = %F.decl @@ -513,26 +612,27 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.ddd: %Self.ref as %I.ref { -// CHECK:STDOUT: %F.decl: %F.type.44e = fn_decl @F.2 [concrete = constants.%F.424] { +// CHECK:STDOUT: %F.decl.loc65_18.1: %F.type.44ef8c.1 = fn_decl @F.2 [concrete = constants.%F.424e9e.1] { // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] // CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %b.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc62_13.1: type = splice_block %.loc62_13.3 [concrete = bool] { +// CHECK:STDOUT: %.loc65_13.1: type = splice_block %.loc65_13.3 [concrete = bool] { // CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc62_13.2: type = value_of_initializer %bool.make_type [concrete = bool] -// CHECK:STDOUT: %.loc62_13.3: type = converted %bool.make_type, %.loc62_13.2 [concrete = bool] +// CHECK:STDOUT: %.loc65_13.2: type = value_of_initializer %bool.make_type [concrete = bool] +// CHECK:STDOUT: %.loc65_13.3: type = converted %bool.make_type, %.loc65_13.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc65_18.2: %F.type.44ef8c.2 = fn_decl @F.3 [concrete = constants.%F.424e9e.2] {} {} // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc65_18.1 // CHECK:STDOUT: witness = @FExtraParam.%I.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.698: %Self.ref as %I.ref { -// CHECK:STDOUT: %F.decl: %F.type.e1a = fn_decl @F.3 [concrete = constants.%F.6ff] { +// CHECK:STDOUT: %F.decl.loc81_23.1: %F.type.e1abdd.1 = fn_decl @F.4 [concrete = constants.%F.6ff574.1] { // CHECK:STDOUT: %self.patt: %pattern_type.8ae = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.8ae = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: } { @@ -540,20 +640,21 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FExtraImplicitParam [concrete = constants.%FExtraImplicitParam] // CHECK:STDOUT: %self: %FExtraImplicitParam = bind_name self, %self.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc81_23.2: %F.type.e1abdd.2 = fn_decl @F.5 [concrete = constants.%F.6ff574.2] {} {} // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc81_23.1 // CHECK:STDOUT: witness = @FExtraImplicitParam.%I.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.77b: %Self.ref as %I.ref { -// CHECK:STDOUT: %F.decl: %F.type.387 = fn_decl @F.4 [concrete = constants.%F.df5] { +// CHECK:STDOUT: %F.decl: %F.type.387 = fn_decl @F.6 [concrete = constants.%F.df5] { // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc89_15.1: type = value_of_initializer %bool.make_type [concrete = bool] -// CHECK:STDOUT: %.loc89_15.2: type = converted %bool.make_type, %.loc89_15.1 [concrete = bool] +// CHECK:STDOUT: %.loc95_15.1: type = value_of_initializer %bool.make_type [concrete = bool] +// CHECK:STDOUT: %.loc95_15.2: type = converted %bool.make_type, %.loc95_15.1 [concrete = bool] // CHECK:STDOUT: %return.param: ref bool = out_param call_param0 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } @@ -564,87 +665,132 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.5cf: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.695 = fn_decl @F.6 [concrete = constants.%F.738] { +// CHECK:STDOUT: %F.decl.loc113_31.1: %F.type.69596c.1 = fn_decl @F.8 [concrete = constants.%F.738f31.1] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param1 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc104_27: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc104_27.1: type = value_of_initializer %bool.make_type.loc104_27 [concrete = bool] -// CHECK:STDOUT: %.loc104_27.2: type = converted %bool.make_type.loc104_27, %.loc104_27.1 [concrete = bool] +// CHECK:STDOUT: %bool.make_type.loc113_27: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc113_27.1: type = value_of_initializer %bool.make_type.loc113_27 [concrete = bool] +// CHECK:STDOUT: %.loc113_27.2: type = converted %bool.make_type.loc113_27, %.loc113_27.1 [concrete = bool] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc104_16.1: type = splice_block %.loc104_16.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc104_16: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc104_16.2: type = value_of_initializer %bool.make_type.loc104_16 [concrete = bool] -// CHECK:STDOUT: %.loc104_16.3: type = converted %bool.make_type.loc104_16, %.loc104_16.2 [concrete = bool] +// CHECK:STDOUT: %.loc113_16.1: type = splice_block %.loc113_16.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc113_16: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc113_16.2: type = value_of_initializer %bool.make_type.loc113_16 [concrete = bool] +// CHECK:STDOUT: %.loc113_16.3: type = converted %bool.make_type.loc113_16, %.loc113_16.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param // CHECK:STDOUT: %return.param: ref bool = out_param call_param1 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc113_31.2: %F.type.69596c.2 = fn_decl @F.9 [concrete = constants.%F.738f31.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: bool = value_param call_param0 +// CHECK:STDOUT: %self: bool = bind_name self, %self.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc113_31.1 // CHECK:STDOUT: witness = @FMissingParam.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.bac: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.d97 = fn_decl @F.7 [concrete = constants.%F.01d] { +// CHECK:STDOUT: %F.decl.loc126_26.1: %F.type.d97cef.1 = fn_decl @F.10 [concrete = constants.%F.01de92.1] { // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] // CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param0 [concrete] // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param1 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc117_22: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc117_22.1: type = value_of_initializer %bool.make_type.loc117_22 [concrete = bool] -// CHECK:STDOUT: %.loc117_22.2: type = converted %bool.make_type.loc117_22, %.loc117_22.1 [concrete = bool] +// CHECK:STDOUT: %bool.make_type.loc126_22: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc126_22.1: type = value_of_initializer %bool.make_type.loc126_22 [concrete = bool] +// CHECK:STDOUT: %.loc126_22.2: type = converted %bool.make_type.loc126_22, %.loc126_22.1 [concrete = bool] // CHECK:STDOUT: %b.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc117_13.1: type = splice_block %.loc117_13.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc117_13: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc117_13.2: type = value_of_initializer %bool.make_type.loc117_13 [concrete = bool] -// CHECK:STDOUT: %.loc117_13.3: type = converted %bool.make_type.loc117_13, %.loc117_13.2 [concrete = bool] +// CHECK:STDOUT: %.loc126_13.1: type = splice_block %.loc126_13.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc126_13: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc126_13.2: type = value_of_initializer %bool.make_type.loc126_13 [concrete = bool] +// CHECK:STDOUT: %.loc126_13.3: type = converted %bool.make_type.loc126_13, %.loc126_13.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: %return.param: ref bool = out_param call_param1 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc126_26.2: %F.type.d97cef.2 = fn_decl @F.11 [concrete = constants.%F.01de92.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: bool = value_param call_param0 +// CHECK:STDOUT: %self: bool = bind_name self, %self.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc126_26.1 // CHECK:STDOUT: witness = @FMissingImplicitParam.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.1a7: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.123 = fn_decl @F.8 [concrete = constants.%F.c7d] { +// CHECK:STDOUT: %F.decl.loc145_30.1: %F.type.123d7a.1 = fn_decl @F.12 [concrete = constants.%F.c7d02d.1] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] // CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc130_16.1: type = splice_block %.loc130_16.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc130_16: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc130_16.2: type = value_of_initializer %bool.make_type.loc130_16 [concrete = bool] -// CHECK:STDOUT: %.loc130_16.3: type = converted %bool.make_type.loc130_16, %.loc130_16.2 [concrete = bool] +// CHECK:STDOUT: %.loc145_16.1: type = splice_block %.loc145_16.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc145_16: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc145_16.2: type = value_of_initializer %bool.make_type.loc145_16 [concrete = bool] +// CHECK:STDOUT: %.loc145_16.3: type = converted %bool.make_type.loc145_16, %.loc145_16.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param // CHECK:STDOUT: %b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc130_25.1: type = splice_block %.loc130_25.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc130_25: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc130_25.2: type = value_of_initializer %bool.make_type.loc130_25 [concrete = bool] -// CHECK:STDOUT: %.loc130_25.3: type = converted %bool.make_type.loc130_25, %.loc130_25.2 [concrete = bool] +// CHECK:STDOUT: %.loc145_25.1: type = splice_block %.loc145_25.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc145_25: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc145_25.2: type = value_of_initializer %bool.make_type.loc145_25 [concrete = bool] +// CHECK:STDOUT: %.loc145_25.3: type = converted %bool.make_type.loc145_25, %.loc145_25.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc145_30.2: %F.type.123d7a.2 = fn_decl @F.13 [concrete = constants.%F.c7d02d.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: bool = value_param call_param0 +// CHECK:STDOUT: %self: bool = bind_name self, %self.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc145_30.1 // CHECK:STDOUT: witness = @FMissingReturnType.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.f2b: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.6b5 = fn_decl @F.9 [concrete = constants.%F.043] { +// CHECK:STDOUT: %F.decl.loc164_38.1: %F.type.6b537d.1 = fn_decl @F.14 [concrete = constants.%F.04313a.1] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %b.patt: %pattern_type.b90 = binding_pattern b [concrete] @@ -652,14 +798,14 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc143_34: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc143_34.1: type = value_of_initializer %bool.make_type.loc143_34 [concrete = bool] -// CHECK:STDOUT: %.loc143_34.2: type = converted %bool.make_type.loc143_34, %.loc143_34.1 [concrete = bool] +// CHECK:STDOUT: %bool.make_type.loc164_34: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc164_34.1: type = value_of_initializer %bool.make_type.loc164_34 [concrete = bool] +// CHECK:STDOUT: %.loc164_34.2: type = converted %bool.make_type.loc164_34, %.loc164_34.1 [concrete = bool] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc143_16.1: type = splice_block %.loc143_16.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc143_16: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc143_16.2: type = value_of_initializer %bool.make_type.loc143_16 [concrete = bool] -// CHECK:STDOUT: %.loc143_16.3: type = converted %bool.make_type.loc143_16, %.loc143_16.2 [concrete = bool] +// CHECK:STDOUT: %.loc164_16.1: type = splice_block %.loc164_16.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc164_16: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc164_16.2: type = value_of_initializer %bool.make_type.loc164_16 [concrete = bool] +// CHECK:STDOUT: %.loc164_16.3: type = converted %bool.make_type.loc164_16, %.loc164_16.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param // CHECK:STDOUT: %b.param: %FDifferentParamType = value_param call_param1 @@ -668,14 +814,29 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.param: ref bool = out_param call_param2 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc164_38.2: %F.type.6b537d.2 = fn_decl @F.15 [concrete = constants.%F.04313a.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: bool = value_param call_param0 +// CHECK:STDOUT: %self: bool = bind_name self, %self.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc164_38.1 // CHECK:STDOUT: witness = @FDifferentParamType.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.db4: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.d62 = fn_decl @F.10 [concrete = constants.%F.886] { +// CHECK:STDOUT: %F.decl.loc180_38.1: %F.type.d6232a.1 = fn_decl @F.16 [concrete = constants.%F.886f70.1] { // CHECK:STDOUT: %self.patt: %pattern_type.9cc = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.9cc = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] @@ -683,30 +844,45 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc156_34: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc156_34.1: type = value_of_initializer %bool.make_type.loc156_34 [concrete = bool] -// CHECK:STDOUT: %.loc156_34.2: type = converted %bool.make_type.loc156_34, %.loc156_34.1 [concrete = bool] +// CHECK:STDOUT: %bool.make_type.loc180_34: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc180_34.1: type = value_of_initializer %bool.make_type.loc180_34 [concrete = bool] +// CHECK:STDOUT: %.loc180_34.2: type = converted %bool.make_type.loc180_34, %.loc180_34.1 [concrete = bool] // CHECK:STDOUT: %self.param: %FDifferentImplicitParamType = value_param call_param0 // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType] // CHECK:STDOUT: %self: %FDifferentImplicitParamType = bind_name self, %self.param // CHECK:STDOUT: %b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc156_25.1: type = splice_block %.loc156_25.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc156_25: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc156_25.2: type = value_of_initializer %bool.make_type.loc156_25 [concrete = bool] -// CHECK:STDOUT: %.loc156_25.3: type = converted %bool.make_type.loc156_25, %.loc156_25.2 [concrete = bool] +// CHECK:STDOUT: %.loc180_25.1: type = splice_block %.loc180_25.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc180_25: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc180_25.2: type = value_of_initializer %bool.make_type.loc180_25 [concrete = bool] +// CHECK:STDOUT: %.loc180_25.3: type = converted %bool.make_type.loc180_25, %.loc180_25.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: %return.param: ref bool = out_param call_param2 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc180_38.2: %F.type.d6232a.2 = fn_decl @F.17 [concrete = constants.%F.886f70.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: bool = value_param call_param0 +// CHECK:STDOUT: %self: bool = bind_name self, %self.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc180_38.1 // CHECK:STDOUT: witness = @FDifferentImplicitParamType.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.fcc: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.d3b = fn_decl @F.11 [concrete = constants.%F.be8] { +// CHECK:STDOUT: %F.decl.loc199_38.1: %F.type.d3b58f.1 = fn_decl @F.18 [concrete = constants.%F.be86c9.1] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] @@ -716,98 +892,89 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: } { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentReturnType [concrete = constants.%FDifferentReturnType] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc169_16.1: type = splice_block %.loc169_16.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc169_16: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc169_16.2: type = value_of_initializer %bool.make_type.loc169_16 [concrete = bool] -// CHECK:STDOUT: %.loc169_16.3: type = converted %bool.make_type.loc169_16, %.loc169_16.2 [concrete = bool] +// CHECK:STDOUT: %.loc199_16.1: type = splice_block %.loc199_16.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc199_16: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc199_16.2: type = value_of_initializer %bool.make_type.loc199_16 [concrete = bool] +// CHECK:STDOUT: %.loc199_16.3: type = converted %bool.make_type.loc199_16, %.loc199_16.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param // CHECK:STDOUT: %b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc169_25.1: type = splice_block %.loc169_25.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc169_25: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc169_25.2: type = value_of_initializer %bool.make_type.loc169_25 [concrete = bool] -// CHECK:STDOUT: %.loc169_25.3: type = converted %bool.make_type.loc169_25, %.loc169_25.2 [concrete = bool] +// CHECK:STDOUT: %.loc199_25.1: type = splice_block %.loc199_25.3 [concrete = bool] { +// CHECK:STDOUT: %bool.make_type.loc199_25: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc199_25.2: type = value_of_initializer %bool.make_type.loc199_25 [concrete = bool] +// CHECK:STDOUT: %.loc199_25.3: type = converted %bool.make_type.loc199_25, %.loc199_25.2 [concrete = bool] // CHECK:STDOUT: } // CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: %return.param: ref %FDifferentReturnType = out_param call_param2 // CHECK:STDOUT: %return: ref %FDifferentReturnType = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = @FDifferentReturnType.%J.impl_witness -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: impl @impl.c5d: %Self.ref as %J.ref { -// CHECK:STDOUT: %F.decl: %F.type.d19 = fn_decl @F.12 [concrete = constants.%F.669] { +// CHECK:STDOUT: %F.decl.loc199_38.2: %F.type.d3b58f.2 = fn_decl @F.19 [concrete = constants.%F.be86c9.2] { // CHECK:STDOUT: %self.patt: %pattern_type.831 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt, call_param0 [concrete] -// CHECK:STDOUT: %not_b.patt: %pattern_type.831 = binding_pattern not_b [concrete] -// CHECK:STDOUT: %not_b.param_patt: %pattern_type.831 = value_param_pattern %not_b.patt, call_param1 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.831 = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt, call_param1 [concrete] // CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %bool.make_type.loc183_38: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc183_38.1: type = value_of_initializer %bool.make_type.loc183_38 [concrete = bool] -// CHECK:STDOUT: %.loc183_38.2: type = converted %bool.make_type.loc183_38, %.loc183_38.1 [concrete = bool] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc183_16.1: type = splice_block %.loc183_16.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc183_16: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc183_16.2: type = value_of_initializer %bool.make_type.loc183_16 [concrete = bool] -// CHECK:STDOUT: %.loc183_16.3: type = converted %bool.make_type.loc183_16, %.loc183_16.2 [concrete = bool] -// CHECK:STDOUT: } // CHECK:STDOUT: %self: bool = bind_name self, %self.param -// CHECK:STDOUT: %not_b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc183_29.1: type = splice_block %.loc183_29.3 [concrete = bool] { -// CHECK:STDOUT: %bool.make_type.loc183_29: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc183_29.2: type = value_of_initializer %bool.make_type.loc183_29 [concrete = bool] -// CHECK:STDOUT: %.loc183_29.3: type = converted %bool.make_type.loc183_29, %.loc183_29.2 [concrete = bool] -// CHECK:STDOUT: } -// CHECK:STDOUT: %not_b: bool = bind_name not_b, %not_b.param +// CHECK:STDOUT: %b.param: bool = value_param call_param1 +// CHECK:STDOUT: %b: bool = bind_name b, %b.param // CHECK:STDOUT: %return.param: ref bool = out_param call_param2 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = @FDifferentParamName.%J.impl_witness +// CHECK:STDOUT: .F = %F.decl.loc199_38.1 +// CHECK:STDOUT: witness = @FDifferentReturnType.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.6a5: %Self.ref as %SelfNested.ref { -// CHECK:STDOUT: %F.decl: %F.type.f90 = fn_decl @F.14 [concrete = constants.%F.fa8] { +// CHECK:STDOUT: %F.decl.loc258_87.1: %F.type.f90165.1 = fn_decl @F.21 [concrete = constants.%F.fa8d04.1] { // CHECK:STDOUT: %x.patt: %pattern_type.714 = binding_pattern x [concrete] // CHECK:STDOUT: %x.param_patt: %pattern_type.714 = value_param_pattern %x.patt, call_param0 [concrete] // CHECK:STDOUT: %return.patt: %pattern_type.1f1 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.1f1 = out_param_pattern %return.patt, call_param1 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %SelfNestedBadParam.ref.loc200_65: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] +// CHECK:STDOUT: %SelfNestedBadParam.ref.loc258_65: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref.loc200_65 [concrete = constants.%array_type.a41] +// CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref.loc258_65 [concrete = constants.%array_type.a41] // CHECK:STDOUT: %x.param: %tuple.type.a7d = value_param call_param0 -// CHECK:STDOUT: %.loc200_53.1: type = splice_block %.loc200_53.3 [concrete = constants.%tuple.type.a7d] { -// CHECK:STDOUT: %SelfNestedBadParam.ref.loc200_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] -// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadParam.ref.loc200_14 [concrete = constants.%ptr.4cd] -// CHECK:STDOUT: %int_32.loc200_40: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %i32.loc200_40: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %int_32.loc200_49: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %i32.loc200_49: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: %.loc258_53.1: type = splice_block %.loc258_53.3 [concrete = constants.%tuple.type.a7d] { +// CHECK:STDOUT: %SelfNestedBadParam.ref.loc258_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] +// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadParam.ref.loc258_14 [concrete = constants.%ptr.4cd] +// CHECK:STDOUT: %int_32.loc258_40: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.loc258_40: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: %int_32.loc258_49: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.loc258_49: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %struct_type.x.y: type = struct_type {.x: %i32, .y: %i32} [concrete = constants.%struct_type.x.y.871] -// CHECK:STDOUT: %.loc200_53.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) -// CHECK:STDOUT: %.loc200_53.3: type = converted %.loc200_53.2, constants.%tuple.type.a7d [concrete = constants.%tuple.type.a7d] +// CHECK:STDOUT: %.loc258_53.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) +// CHECK:STDOUT: %.loc258_53.3: type = converted %.loc258_53.2, constants.%tuple.type.a7d [concrete = constants.%tuple.type.a7d] // CHECK:STDOUT: } // CHECK:STDOUT: %x: %tuple.type.a7d = bind_name x, %x.param // CHECK:STDOUT: %return.param: ref %array_type.a41 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.a41 = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc258_87.2: %F.type.f90165.2 = fn_decl @F.22 [concrete = constants.%F.fa8d04.2] { +// CHECK:STDOUT: %x.patt: %pattern_type.a5c = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type.a5c = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.1f1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.1f1 = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %tuple.type.9c9 = value_param call_param0 +// CHECK:STDOUT: %x: %tuple.type.9c9 = bind_name x, %x.param +// CHECK:STDOUT: %return.param: ref %array_type.a41 = out_param call_param1 +// CHECK:STDOUT: %return: ref %array_type.a41 = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .SelfNestedBadParam = -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc258_87.1 // CHECK:STDOUT: witness = @SelfNestedBadParam.%SelfNested.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.bfc: %Self.ref as %SelfNested.ref { -// CHECK:STDOUT: %F.decl: %F.type.0e7 = fn_decl @F.15 [concrete = constants.%F.0bc] { +// CHECK:STDOUT: %F.decl.loc294_112.1: %F.type.0e7d1d.1 = fn_decl @F.23 [concrete = constants.%F.0bc78a.1] { // CHECK:STDOUT: %x.patt: %pattern_type.23f = binding_pattern x [concrete] // CHECK:STDOUT: %x.param_patt: %pattern_type.23f = value_param_pattern %x.patt, call_param0 [concrete] // CHECK:STDOUT: %return.patt: %pattern_type.1f1 = return_slot_pattern [concrete] @@ -817,25 +984,36 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] // CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref [concrete = constants.%array_type.a41] // CHECK:STDOUT: %x.param: %tuple.type.eb9 = value_param call_param0 -// CHECK:STDOUT: %.loc213_78.1: type = splice_block %.loc213_78.3 [concrete = constants.%tuple.type.eb9] { -// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc213_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] -// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadReturnType.ref.loc213_14 [concrete = constants.%ptr.612] -// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc213_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] +// CHECK:STDOUT: %.loc294_78.1: type = splice_block %.loc294_78.3 [concrete = constants.%tuple.type.eb9] { +// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc294_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] +// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadReturnType.ref.loc294_14 [concrete = constants.%ptr.612] +// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc294_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %struct_type.x.y: type = struct_type {.x: %SelfNestedBadReturnType, .y: %i32} [concrete = constants.%struct_type.x.y.ac5] -// CHECK:STDOUT: %.loc213_78.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) -// CHECK:STDOUT: %.loc213_78.3: type = converted %.loc213_78.2, constants.%tuple.type.eb9 [concrete = constants.%tuple.type.eb9] +// CHECK:STDOUT: %.loc294_78.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) +// CHECK:STDOUT: %.loc294_78.3: type = converted %.loc294_78.2, constants.%tuple.type.eb9 [concrete = constants.%tuple.type.eb9] // CHECK:STDOUT: } // CHECK:STDOUT: %x: %tuple.type.eb9 = bind_name x, %x.param // CHECK:STDOUT: %return.param: ref %array_type.a41 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.a41 = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc294_112.2: %F.type.0e7d1d.2 = fn_decl @F.24 [concrete = constants.%F.0bc78a.2] { +// CHECK:STDOUT: %x.patt: %pattern_type.23f = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type.23f = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.f56 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.f56 = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %tuple.type.eb9 = value_param call_param0 +// CHECK:STDOUT: %x: %tuple.type.eb9 = bind_name x, %x.param +// CHECK:STDOUT: %return.param: ref %array_type.126 = out_param call_param1 +// CHECK:STDOUT: %return: ref %array_type.126 = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .SelfNestedBadReturnType = // CHECK:STDOUT: .SelfNestedBadParam = -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc294_112.1 // CHECK:STDOUT: witness = @SelfNestedBadReturnType.%SelfNested.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: @@ -871,7 +1049,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: .I = // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @F.16; +// CHECK:STDOUT: class @F.25; // CHECK:STDOUT: // CHECK:STDOUT: class @FAlias { // CHECK:STDOUT: impl_decl @impl.199 [concrete] {} { @@ -895,8 +1073,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FExtraParam [concrete = constants.%FExtraParam] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (), @impl.ddd [concrete] -// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.f6b] +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.ddd.%F.decl.loc65_18.2), @impl.ddd [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.1f3] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -911,8 +1089,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FExtraImplicitParam [concrete = constants.%FExtraImplicitParam] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (), @impl.698 [concrete] -// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.e58] +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.698.%F.decl.loc81_23.2), @impl.698 [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.a7b] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -943,8 +1121,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FMissingParam [concrete = constants.%FMissingParam] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.5cf [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.b4b] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.5cf.%F.decl.loc113_31.2), @impl.5cf [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.4e9] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -959,8 +1137,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FMissingImplicitParam [concrete = constants.%FMissingImplicitParam] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.bac [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.c79] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.bac.%F.decl.loc126_26.2), @impl.bac [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.841] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -975,8 +1153,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FMissingReturnType [concrete = constants.%FMissingReturnType] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.1a7 [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.39b] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.1a7.%F.decl.loc145_30.2), @impl.1a7 [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.e75] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -991,8 +1169,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentParamType [concrete = constants.%FDifferentParamType] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.f2b [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.eab] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.f2b.%F.decl.loc164_38.2), @impl.f2b [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.cbe] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -1007,8 +1185,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.db4 [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.103] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.db4.%F.decl.loc180_38.2), @impl.db4 [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.af2] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -1023,8 +1201,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentReturnType [concrete = constants.%FDifferentReturnType] // CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.fcc [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.6f7] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (@impl.fcc.%F.decl.loc199_38.2), @impl.fcc [concrete] +// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.bc1] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -1034,29 +1212,13 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: .J = // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @FDifferentParamName { -// CHECK:STDOUT: impl_decl @impl.c5d [concrete] {} { -// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentParamName [concrete = constants.%FDifferentParamName] -// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type] -// CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (), @impl.c5d [concrete] -// CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.3ab] -// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] -// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] -// CHECK:STDOUT: complete_type_witness = %complete_type -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%FDifferentParamName -// CHECK:STDOUT: .J = -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: class @SelfNestedBadParam { // CHECK:STDOUT: impl_decl @impl.6a5 [concrete] {} { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%SelfNestedBadParam [concrete = constants.%SelfNestedBadParam] // CHECK:STDOUT: %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (), @impl.6a5 [concrete] -// CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.21a] +// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (@impl.6a5.%F.decl.loc258_87.2), @impl.6a5 [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.e31] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -1072,8 +1234,8 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%SelfNestedBadReturnType [concrete = constants.%SelfNestedBadReturnType] // CHECK:STDOUT: %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (), @impl.bfc [concrete] -// CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.b10] +// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (@impl.bfc.%F.decl.loc294_112.2), @impl.bfc [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.d5e] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -1093,99 +1255,184 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(%b.param: bool); // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.3(%self.param: %FExtraImplicitParam); +// CHECK:STDOUT: fn @F.3() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.4() -> bool; +// CHECK:STDOUT: fn @F.4(%self.param: %FExtraImplicitParam); // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.5(@J.%Self: %J.type) { +// CHECK:STDOUT: fn @F.5() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call @impl.698.%F.decl.loc81_23.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.6() -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.7(@J.%Self: %J.type) { // CHECK:STDOUT: fn(%self.param: bool, %b.param: bool) -> bool; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.6(%self.param: bool) -> bool; +// CHECK:STDOUT: fn @F.8(%self.param: bool) -> bool; // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.7(%b.param: bool) -> bool; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.8(%self.param: bool, %b.param: bool); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.9(%self.param: bool, %b.param: %FDifferentParamType) -> bool; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.10(%self.param: %FDifferentImplicitParamType, %b.param: bool) -> bool; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.11(%self.param: bool, %b.param: bool) -> %FDifferentReturnType; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.12(%self.param: bool, %not_b.param: bool) -> bool; -// CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.13(@SelfNested.%Self: %SelfNested.type) { -// CHECK:STDOUT: %Self: %SelfNested.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.2ff)] -// CHECK:STDOUT: %Self.as_type.loc188_16.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc188_16.1 (constants.%Self.as_type)] -// CHECK:STDOUT: %ptr.loc188_16.1: type = ptr_type %Self.as_type.loc188_16.1 [symbolic = %ptr.loc188_16.1 (constants.%ptr.e87)] -// CHECK:STDOUT: %struct_type.x.y.loc188_37.1: type = struct_type {.x: @F.13.%Self.as_type.loc188_16.1 (%Self.as_type), .y: %i32} [symbolic = %struct_type.x.y.loc188_37.1 (constants.%struct_type.x.y.81e)] -// CHECK:STDOUT: %tuple.type: type = tuple_type (%ptr.loc188_16.1, %struct_type.x.y.loc188_37.1) [symbolic = %tuple.type (constants.%tuple.type.229)] -// CHECK:STDOUT: %pattern_type.loc188_8: type = pattern_type %tuple.type [symbolic = %pattern_type.loc188_8 (constants.%pattern_type.ced)] -// CHECK:STDOUT: %array_type.loc188_57.1: type = array_type constants.%int_4, %Self.as_type.loc188_16.1 [symbolic = %array_type.loc188_57.1 (constants.%array_type.873)] -// CHECK:STDOUT: %pattern_type.loc188_41: type = pattern_type %array_type.loc188_57.1 [symbolic = %pattern_type.loc188_41 (constants.%pattern_type.c7e)] -// CHECK:STDOUT: -// CHECK:STDOUT: fn(%x.param: @F.13.%tuple.type (%tuple.type.229)) -> @F.13.%array_type.loc188_57.1 (%array_type.873); +// CHECK:STDOUT: fn @F.9(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.5cf.%F.decl.loc113_31.1 +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.14(%x.param: %tuple.type.a7d) -> %array_type.a41; +// CHECK:STDOUT: fn @F.10(%b.param: bool) -> bool; // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.15(%x.param: %tuple.type.eb9) -> %array_type.a41; +// CHECK:STDOUT: fn @F.11(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: %F.call: init bool = call @impl.bac.%F.decl.loc126_26.1(%b.ref) +// CHECK:STDOUT: %.loc126_26.1: bool = value_of_initializer %F.call +// CHECK:STDOUT: %.loc126_26.2: bool = converted %F.call, %.loc126_26.1 +// CHECK:STDOUT: return %.loc126_26.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.12(%self.param: bool, %b.param: bool); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.13(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.1a7.%F.decl.loc145_30.1 +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.bound(%self.ref, %b.ref) +// CHECK:STDOUT: %.loc145: bool = converted %F.call, [concrete = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.14(%self.param: bool, %b.param: %FDifferentParamType) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.15(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.f2b.%F.decl.loc164_38.1 +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: %F.call: init bool = call %F.bound(%self.ref, ) +// CHECK:STDOUT: %.loc164_38.1: bool = value_of_initializer %F.call +// CHECK:STDOUT: %.loc164_38.2: bool = converted %F.call, %.loc164_38.1 +// CHECK:STDOUT: return %.loc164_38.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.16(%self.param: %FDifferentImplicitParamType, %b.param: bool) -> bool; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.17(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.db4.%F.decl.loc180_38.1 +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: %F.call: init bool = call %F.bound(, %b.ref) +// CHECK:STDOUT: %.loc180_38.1: bool = value_of_initializer %F.call +// CHECK:STDOUT: %.loc180_38.2: bool = converted %F.call, %.loc180_38.1 +// CHECK:STDOUT: return %.loc180_38.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.18(%self.param: bool, %b.param: bool) -> %FDifferentReturnType; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.19(%self.param: bool, %b.param: bool) -> bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.fcc.%F.decl.loc199_38.1 +// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param +// CHECK:STDOUT: %F.call: init = call %F.bound(%self.ref, %b.ref) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.20(@SelfNested.%Self: %SelfNested.type) { +// CHECK:STDOUT: %Self: %SelfNested.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.2ff)] +// CHECK:STDOUT: %Self.as_type.loc207_16.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc207_16.1 (constants.%Self.as_type.e1e)] +// CHECK:STDOUT: %ptr.loc207_16.1: type = ptr_type %Self.as_type.loc207_16.1 [symbolic = %ptr.loc207_16.1 (constants.%ptr.e87)] +// CHECK:STDOUT: %struct_type.x.y.loc207_37.1: type = struct_type {.x: @F.20.%Self.as_type.loc207_16.1 (%Self.as_type.e1e), .y: %i32} [symbolic = %struct_type.x.y.loc207_37.1 (constants.%struct_type.x.y.81e)] +// CHECK:STDOUT: %tuple.type: type = tuple_type (%ptr.loc207_16.1, %struct_type.x.y.loc207_37.1) [symbolic = %tuple.type (constants.%tuple.type.229)] +// CHECK:STDOUT: %pattern_type.loc207_8: type = pattern_type %tuple.type [symbolic = %pattern_type.loc207_8 (constants.%pattern_type.ced)] +// CHECK:STDOUT: %array_type.loc207_57.1: type = array_type constants.%int_4, %Self.as_type.loc207_16.1 [symbolic = %array_type.loc207_57.1 (constants.%array_type.873)] +// CHECK:STDOUT: %pattern_type.loc207_41: type = pattern_type %array_type.loc207_57.1 [symbolic = %pattern_type.loc207_41 (constants.%pattern_type.c7e)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%x.param: @F.20.%tuple.type (%tuple.type.229)) -> @F.20.%array_type.loc207_57.1 (%array_type.873); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.21(%x.param: %tuple.type.a7d) -> %return.param: %array_type.a41; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.22(%x.param: %tuple.type.9c9) -> %return.param: %array_type.a41 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref: %tuple.type.9c9 = name_ref x, %x.param +// CHECK:STDOUT: %tuple.elem0: %ptr.4cd = tuple_access %x.ref, element0 +// CHECK:STDOUT: %tuple.elem1: %struct_type.x.y.a89 = tuple_access %x.ref, element1 +// CHECK:STDOUT: %.loc207_9.1: %SelfNestedBadParam = struct_access %tuple.elem1, element0 +// CHECK:STDOUT: %.loc207_9.2: %i32 = converted %.loc207_9.1, [concrete = ] +// CHECK:STDOUT: %F.call: init = call @impl.6a5.%F.decl.loc258_87.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.23(%x.param: %tuple.type.eb9) -> %return.param: %array_type.a41; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.24(%x.param: %tuple.type.eb9) -> %array_type.126 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref: %tuple.type.eb9 = name_ref x, %x.param +// CHECK:STDOUT: %.loc294: ref %array_type.a41 = temporary_storage +// CHECK:STDOUT: %F.call: init %array_type.a41 = call @impl.bfc.%F.decl.loc294_112.1() to %.loc294 +// CHECK:STDOUT: return +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%Self.826) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%I.facet.86d) {} +// CHECK:STDOUT: specific @F.1(constants.%I.facet.fa4) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%I.facet.919) {} +// CHECK:STDOUT: specific @F.1(constants.%I.facet.ee5) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%I.facet.d5c) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%Self.ccd) {} +// CHECK:STDOUT: specific @F.7(constants.%Self.ccd) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.97d) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.94c) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.0d0) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.e7e) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.97a) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.974) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.955) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.37e) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.130) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.bf1) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.1a7) {} +// CHECK:STDOUT: specific @F.7(constants.%J.facet.67f) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.5(constants.%J.facet.366) {} -// CHECK:STDOUT: -// CHECK:STDOUT: specific @F.13(constants.%Self.2ff) { +// CHECK:STDOUT: specific @F.20(constants.%Self.2ff) { // CHECK:STDOUT: %Self => constants.%Self.2ff -// CHECK:STDOUT: %Self.as_type.loc188_16.1 => constants.%Self.as_type -// CHECK:STDOUT: %ptr.loc188_16.1 => constants.%ptr.e87 -// CHECK:STDOUT: %struct_type.x.y.loc188_37.1 => constants.%struct_type.x.y.81e +// CHECK:STDOUT: %Self.as_type.loc207_16.1 => constants.%Self.as_type.e1e +// CHECK:STDOUT: %ptr.loc207_16.1 => constants.%ptr.e87 +// CHECK:STDOUT: %struct_type.x.y.loc207_37.1 => constants.%struct_type.x.y.81e // CHECK:STDOUT: %tuple.type => constants.%tuple.type.229 -// CHECK:STDOUT: %pattern_type.loc188_8 => constants.%pattern_type.ced -// CHECK:STDOUT: %array_type.loc188_57.1 => constants.%array_type.873 -// CHECK:STDOUT: %pattern_type.loc188_41 => constants.%pattern_type.c7e +// CHECK:STDOUT: %pattern_type.loc207_8 => constants.%pattern_type.ced +// CHECK:STDOUT: %array_type.loc207_57.1 => constants.%array_type.873 +// CHECK:STDOUT: %pattern_type.loc207_41 => constants.%pattern_type.c7e // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.13(constants.%SelfNested.facet.9f5) { -// CHECK:STDOUT: %Self => constants.%SelfNested.facet.9f5 -// CHECK:STDOUT: %Self.as_type.loc188_16.1 => constants.%SelfNestedBadParam -// CHECK:STDOUT: %ptr.loc188_16.1 => constants.%ptr.4cd -// CHECK:STDOUT: %struct_type.x.y.loc188_37.1 => constants.%struct_type.x.y.a89 +// CHECK:STDOUT: specific @F.20(constants.%SelfNested.facet.608) { +// CHECK:STDOUT: %Self => constants.%SelfNested.facet.608 +// CHECK:STDOUT: %Self.as_type.loc207_16.1 => constants.%SelfNestedBadParam +// CHECK:STDOUT: %ptr.loc207_16.1 => constants.%ptr.4cd +// CHECK:STDOUT: %struct_type.x.y.loc207_37.1 => constants.%struct_type.x.y.a89 // CHECK:STDOUT: %tuple.type => constants.%tuple.type.9c9 -// CHECK:STDOUT: %pattern_type.loc188_8 => constants.%pattern_type.a5c -// CHECK:STDOUT: %array_type.loc188_57.1 => constants.%array_type.a41 -// CHECK:STDOUT: %pattern_type.loc188_41 => constants.%pattern_type.1f1 +// CHECK:STDOUT: %pattern_type.loc207_8 => constants.%pattern_type.a5c +// CHECK:STDOUT: %array_type.loc207_57.1 => constants.%array_type.a41 +// CHECK:STDOUT: %pattern_type.loc207_41 => constants.%pattern_type.1f1 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.13(constants.%SelfNested.facet.3bd) { -// CHECK:STDOUT: %Self => constants.%SelfNested.facet.3bd -// CHECK:STDOUT: %Self.as_type.loc188_16.1 => constants.%SelfNestedBadReturnType -// CHECK:STDOUT: %ptr.loc188_16.1 => constants.%ptr.612 -// CHECK:STDOUT: %struct_type.x.y.loc188_37.1 => constants.%struct_type.x.y.ac5 +// CHECK:STDOUT: specific @F.20(constants.%SelfNested.facet.766) { +// CHECK:STDOUT: %Self => constants.%SelfNested.facet.766 +// CHECK:STDOUT: %Self.as_type.loc207_16.1 => constants.%SelfNestedBadReturnType +// CHECK:STDOUT: %ptr.loc207_16.1 => constants.%ptr.612 +// CHECK:STDOUT: %struct_type.x.y.loc207_37.1 => constants.%struct_type.x.y.ac5 // CHECK:STDOUT: %tuple.type => constants.%tuple.type.eb9 -// CHECK:STDOUT: %pattern_type.loc188_8 => constants.%pattern_type.23f -// CHECK:STDOUT: %array_type.loc188_57.1 => constants.%array_type.126 -// CHECK:STDOUT: %pattern_type.loc188_41 => constants.%pattern_type.f56 +// CHECK:STDOUT: %pattern_type.loc207_8 => constants.%pattern_type.23f +// CHECK:STDOUT: %array_type.loc207_57.1 => constants.%array_type.126 +// CHECK:STDOUT: %pattern_type.loc207_41 => constants.%pattern_type.f56 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_self_type_mismatch.carbon b/toolchain/check/testdata/impl/fail_self_type_mismatch.carbon index e061edb9ab26..7579cbcc1102 100644 --- a/toolchain/check/testdata/impl/fail_self_type_mismatch.carbon +++ b/toolchain/check/testdata/impl/fail_self_type_mismatch.carbon @@ -12,6 +12,12 @@ class C[T:! type](X:! T) {} interface I { // Uses of `Self` inside the definition of `I` have type `I`. + // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE+6]]:8: error: cannot implicitly convert expression of type `C(i32 as I)` to `C(i32)` [ConversionFailure] + // CHECK:STDERR: fn F(c: C(Self)); + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE+3]]:8: note: type `C(i32 as I)` does not implement interface `Core.ImplicitAs(C(i32))` [MissingImplInMemberAccessNote] + // CHECK:STDERR: fn F(c: C(Self)); + // CHECK:STDERR: ^~~~~~~~~~ fn F(c: C(Self)); } @@ -23,12 +29,12 @@ impl bool as I { } impl i32 as I { - // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE+7]]:8: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE+7]]:8: note: initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: fn F(c: C(i32)); // CHECK:STDERR: ^~~~~~~~~ - // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE-14]]:8: note: previous declaration's corresponding parameter here [RedeclParamPrevious] + // CHECK:STDERR: fail_self_type_mismatch.carbon:[[@LINE-14]]:3: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: fn F(c: C(Self)); - // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: fn F(c: C(i32)); } @@ -39,24 +45,25 @@ impl i32 as I { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] // CHECK:STDOUT: %pattern_type.98f: type = pattern_type type [concrete] // CHECK:STDOUT: %X: %T = bind_symbolic_name X, 1 [symbolic] -// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic] +// CHECK:STDOUT: %pattern_type.7dcd0a.1: type = pattern_type %T [symbolic] // CHECK:STDOUT: %C.type: type = generic_class_type @C [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %C.generic: %C.type = struct_value () [concrete] // CHECK:STDOUT: %C.b36: type = class_type @C, @C(%T, %X) [symbolic] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] -// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.826: %I.type = bind_symbolic_name Self, 0 [symbolic] // CHECK:STDOUT: %pattern_type.2b5: type = pattern_type %I.type [concrete] -// CHECK:STDOUT: %C.dbb: type = class_type @C, @C(%I.type, %Self) [symbolic] +// CHECK:STDOUT: %C.dbb: type = class_type @C, @C(%I.type, %Self.826) [symbolic] // CHECK:STDOUT: %pattern_type.4fb: type = pattern_type %C.dbb [symbolic] // CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] // CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] +// CHECK:STDOUT: %assoc0.82e: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] // CHECK:STDOUT: %Bool.type: type = fn_type @Bool [concrete] // CHECK:STDOUT: %Bool: %Bool.type = struct_value () [concrete] -// CHECK:STDOUT: %I.impl_witness.c21: = impl_witness file.%I.impl_witness_table.loc18 [concrete] +// CHECK:STDOUT: %I.impl_witness.c21: = impl_witness file.%I.impl_witness_table.loc24 [concrete] // CHECK:STDOUT: %I.facet.e8a: %I.type = facet_value bool, (%I.impl_witness.c21) [concrete] // CHECK:STDOUT: %C.7db: type = class_type @C, @C(%I.type, %I.facet.e8a) [concrete] // CHECK:STDOUT: %pattern_type.225: type = pattern_type %C.7db [concrete] @@ -66,25 +73,31 @@ impl i32 as I { // CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete] // CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %I.impl_witness.d39: = impl_witness file.%I.impl_witness_table.loc25 [concrete] +// CHECK:STDOUT: %I.impl_witness.863: = impl_witness file.%I.impl_witness_table.loc31 [concrete] // CHECK:STDOUT: %C.6fb: type = class_type @C, @C(type, %i32) [concrete] // CHECK:STDOUT: %pattern_type.52b: type = pattern_type %C.6fb [concrete] -// CHECK:STDOUT: %F.type.066: type = fn_type @F.3 [concrete] -// CHECK:STDOUT: %F.9ec: %F.type.066 = struct_value () [concrete] -// CHECK:STDOUT: %I.facet.8b2: %I.type = facet_value %i32, (%I.impl_witness.d39) [concrete] -// CHECK:STDOUT: %C.835: type = class_type @C, @C(%I.type, %I.facet.8b2) [concrete] -// CHECK:STDOUT: %pattern_type.023: type = pattern_type %C.835 [concrete] +// CHECK:STDOUT: %F.type.066a53.1: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.9ec58f.1: %F.type.066a53.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet.118: %I.type = facet_value %i32, (%I.impl_witness.863) [concrete] +// CHECK:STDOUT: %C.d88: type = class_type @C, @C(%I.type, %I.facet.118) [concrete] +// CHECK:STDOUT: %pattern_type.c65: type = pattern_type %C.d88 [concrete] +// CHECK:STDOUT: %F.type.066a53.2: type = fn_type @F.4 [concrete] +// CHECK:STDOUT: %F.9ec58f.2: %F.type.066a53.2 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete] +// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { // CHECK:STDOUT: .Bool = %Core.Bool // CHECK:STDOUT: .Int = %Core.Int +// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } // CHECK:STDOUT: %Core.Bool: %Bool.type = import_ref Core//prelude/types/bool, Bool, loaded [concrete = constants.%Bool] // CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic] +// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -96,7 +109,7 @@ impl i32 as I { // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] { // CHECK:STDOUT: %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete] -// CHECK:STDOUT: %X.patt: @C.%pattern_type (%pattern_type.7dc) = symbolic_binding_pattern X, 1 [concrete] +// CHECK:STDOUT: %X.patt: @C.%pattern_type (%pattern_type.7dcd0a.1) = symbolic_binding_pattern X, 1 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %T.loc11_9.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc11_9.2 (constants.%T)] // CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc11_9.1 [symbolic = %T.loc11_9.2 (constants.%T)] @@ -105,36 +118,36 @@ impl i32 as I { // CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} // CHECK:STDOUT: impl_decl @impl.049 [concrete] {} { // CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [concrete = bool] -// CHECK:STDOUT: %.loc18_6.1: type = value_of_initializer %bool.make_type [concrete = bool] -// CHECK:STDOUT: %.loc18_6.2: type = converted %bool.make_type, %.loc18_6.1 [concrete = bool] +// CHECK:STDOUT: %.loc24_6.1: type = value_of_initializer %bool.make_type [concrete = bool] +// CHECK:STDOUT: %.loc24_6.2: type = converted %bool.make_type, %.loc24_6.1 [concrete = bool] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %I.impl_witness_table.loc18 = impl_witness_table (@impl.049.%F.decl), @impl.049 [concrete] -// CHECK:STDOUT: %I.impl_witness.loc18: = impl_witness %I.impl_witness_table.loc18 [concrete = constants.%I.impl_witness.c21] +// CHECK:STDOUT: %I.impl_witness_table.loc24 = impl_witness_table (@impl.049.%F.decl), @impl.049 [concrete] +// CHECK:STDOUT: %I.impl_witness.loc24: = impl_witness %I.impl_witness_table.loc24 [concrete = constants.%I.impl_witness.c21] // CHECK:STDOUT: impl_decl @impl.a9a [concrete] {} { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %I.impl_witness_table.loc25 = impl_witness_table (), @impl.a9a [concrete] -// CHECK:STDOUT: %I.impl_witness.loc25: = impl_witness %I.impl_witness_table.loc25 [concrete = constants.%I.impl_witness.d39] +// CHECK:STDOUT: %I.impl_witness_table.loc31 = impl_witness_table (@impl.a9a.%F.decl.loc39_18.2), @impl.a9a [concrete] +// CHECK:STDOUT: %I.impl_witness.loc31: = impl_witness %I.impl_witness_table.loc31 [concrete = constants.%I.impl_witness.863] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @I { -// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.826] // CHECK:STDOUT: %F.decl: %F.type.cf0 = fn_decl @F.1 [concrete = constants.%F.bc6] { // CHECK:STDOUT: %c.patt: @F.1.%pattern_type (%pattern_type.4fb) = binding_pattern c [concrete] // CHECK:STDOUT: %c.param_patt: @F.1.%pattern_type (%pattern_type.4fb) = value_param_pattern %c.patt, call_param0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %c.param: @F.1.%C.loc15_17.1 (%C.dbb) = value_param call_param0 -// CHECK:STDOUT: %.loc15: type = splice_block %C.loc15_17.2 [symbolic = %C.loc15_17.1 (constants.%C.dbb)] { +// CHECK:STDOUT: %c.param: @F.1.%C.loc21_17.1 (%C.dbb) = value_param call_param0 +// CHECK:STDOUT: %.loc21: type = splice_block %C.loc21_17.2 [symbolic = %C.loc21_17.1 (constants.%C.dbb)] { // CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic] -// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] -// CHECK:STDOUT: %C.loc15_17.2: type = class_type @C, @C(constants.%I.type, constants.%Self) [symbolic = %C.loc15_17.1 (constants.%C.dbb)] +// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.826)] +// CHECK:STDOUT: %C.loc21_17.2: type = class_type @C, @C(constants.%I.type, constants.%Self.826) [symbolic = %C.loc21_17.1 (constants.%C.dbb)] // CHECK:STDOUT: } -// CHECK:STDOUT: %c: @F.1.%C.loc15_17.1 (%C.dbb) = bind_name c, %c.param +// CHECK:STDOUT: %c: @F.1.%C.loc21_17.1 (%C.dbb) = bind_name c, %c.param // CHECK:STDOUT: } -// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0.82e] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self @@ -143,18 +156,18 @@ impl i32 as I { // CHECK:STDOUT: witness = (%F.decl) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl.049: %.loc18_6.2 as %I.ref { +// CHECK:STDOUT: impl @impl.049: %.loc24_6.2 as %I.ref { // CHECK:STDOUT: %F.decl: %F.type.8ba = fn_decl @F.2 [concrete = constants.%F.2cf] { // CHECK:STDOUT: %c.patt: %pattern_type.225 = binding_pattern c [concrete] // CHECK:STDOUT: %c.param_patt: %pattern_type.225 = value_param_pattern %c.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %c.param: %C.7db = value_param call_param0 -// CHECK:STDOUT: %.loc22_22: type = splice_block %C [concrete = constants.%C.7db] { +// CHECK:STDOUT: %.loc28_22: type = splice_block %C [concrete = constants.%C.7db] { // CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic] // CHECK:STDOUT: %bool.make_type: init type = call constants.%Bool() [concrete = bool] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: %I.facet: %I.type = facet_value bool, (constants.%I.impl_witness.c21) [concrete = constants.%I.facet.e8a] -// CHECK:STDOUT: %.loc22_18: %I.type = converted %bool.make_type, %I.facet [concrete = constants.%I.facet.e8a] +// CHECK:STDOUT: %.loc28_18: %I.type = converted %bool.make_type, %I.facet [concrete = constants.%I.facet.e8a] // CHECK:STDOUT: %C: type = class_type @C, @C(constants.%I.type, constants.%I.facet.e8a) [concrete = constants.%C.7db] // CHECK:STDOUT: } // CHECK:STDOUT: %c: %C.7db = bind_name c, %c.param @@ -164,16 +177,16 @@ impl i32 as I { // CHECK:STDOUT: .C = // CHECK:STDOUT: .I = // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = file.%I.impl_witness.loc18 +// CHECK:STDOUT: witness = file.%I.impl_witness.loc24 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.a9a: %i32 as %I.ref { -// CHECK:STDOUT: %F.decl: %F.type.066 = fn_decl @F.3 [concrete = constants.%F.9ec] { +// CHECK:STDOUT: %F.decl.loc39_18.1: %F.type.066a53.1 = fn_decl @F.3 [concrete = constants.%F.9ec58f.1] { // CHECK:STDOUT: %c.patt: %pattern_type.52b = binding_pattern c [concrete] // CHECK:STDOUT: %c.param_patt: %pattern_type.52b = value_param_pattern %c.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %c.param: %C.6fb = value_param call_param0 -// CHECK:STDOUT: %.loc33: type = splice_block %C [concrete = constants.%C.6fb] { +// CHECK:STDOUT: %.loc39: type = splice_block %C [concrete = constants.%C.6fb] { // CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] @@ -181,17 +194,24 @@ impl i32 as I { // CHECK:STDOUT: } // CHECK:STDOUT: %c: %C.6fb = bind_name c, %c.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc39_18.2: %F.type.066a53.2 = fn_decl @F.4 [concrete = constants.%F.9ec58f.2] { +// CHECK:STDOUT: %c.patt: %pattern_type.c65 = binding_pattern c [concrete] +// CHECK:STDOUT: %c.param_patt: %pattern_type.c65 = value_param_pattern %c.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %c.param: %C.d88 = value_param call_param0 +// CHECK:STDOUT: %c: %C.d88 = bind_name c, %c.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .C = -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = file.%I.impl_witness.loc25 +// CHECK:STDOUT: .F = %F.decl.loc39_18.1 +// CHECK:STDOUT: witness = file.%I.impl_witness.loc31 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic class @C(%T.loc11_9.1: type, %X.loc11_19.1: @C.%T.loc11_9.2 (%T)) { // CHECK:STDOUT: %T.loc11_9.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc11_9.2 (constants.%T)] // CHECK:STDOUT: %X.loc11_19.2: @C.%T.loc11_9.2 (%T) = bind_symbolic_name X, 1 [symbolic = %X.loc11_19.2 (constants.%X)] -// CHECK:STDOUT: %pattern_type: type = pattern_type %T.loc11_9.2 [symbolic = %pattern_type (constants.%pattern_type.7dc)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %T.loc11_9.2 [symbolic = %pattern_type (constants.%pattern_type.7dcd0a.1)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: @@ -206,32 +226,40 @@ impl i32 as I { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { -// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] -// CHECK:STDOUT: %C.loc15_17.1: type = class_type @C, @C(constants.%I.type, %Self) [symbolic = %C.loc15_17.1 (constants.%C.dbb)] -// CHECK:STDOUT: %pattern_type: type = pattern_type %C.loc15_17.1 [symbolic = %pattern_type (constants.%pattern_type.4fb)] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.826)] +// CHECK:STDOUT: %C.loc21_17.1: type = class_type @C, @C(constants.%I.type, %Self) [symbolic = %C.loc21_17.1 (constants.%C.dbb)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %C.loc21_17.1 [symbolic = %pattern_type (constants.%pattern_type.4fb)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%c.param: @F.1.%C.loc15_17.1 (%C.dbb)); +// CHECK:STDOUT: fn(%c.param: @F.1.%C.loc21_17.1 (%C.dbb)); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.2(%c.param: %C.7db); // CHECK:STDOUT: // CHECK:STDOUT: fn @F.3(%c.param: %C.6fb); // CHECK:STDOUT: +// CHECK:STDOUT: fn @F.4(%c.param: %C.d88) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %c.ref: %C.d88 = name_ref c, %c.param +// CHECK:STDOUT: %.loc21: %C.6fb = converted %c.ref, [concrete = ] +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call @impl.a9a.%F.decl.loc39_18.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @C(constants.%T, constants.%X) { // CHECK:STDOUT: %T.loc11_9.2 => constants.%T // CHECK:STDOUT: %X.loc11_19.2 => constants.%X -// CHECK:STDOUT: %pattern_type => constants.%pattern_type.7dc +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.7dcd0a.1 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @C(constants.%I.type, constants.%Self) { +// CHECK:STDOUT: specific @C(constants.%I.type, constants.%Self.826) { // CHECK:STDOUT: %T.loc11_9.2 => constants.%I.type -// CHECK:STDOUT: %X.loc11_19.2 => constants.%Self +// CHECK:STDOUT: %X.loc11_19.2 => constants.%Self.826 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.2b5 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%Self) { -// CHECK:STDOUT: %Self => constants.%Self -// CHECK:STDOUT: %C.loc15_17.1 => constants.%C.dbb +// CHECK:STDOUT: specific @F.1(constants.%Self.826) { +// CHECK:STDOUT: %Self => constants.%Self.826 +// CHECK:STDOUT: %C.loc21_17.1 => constants.%C.dbb // CHECK:STDOUT: %pattern_type => constants.%pattern_type.4fb // CHECK:STDOUT: } // CHECK:STDOUT: @@ -243,7 +271,7 @@ impl i32 as I { // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%I.facet.e8a) { // CHECK:STDOUT: %Self => constants.%I.facet.e8a -// CHECK:STDOUT: %C.loc15_17.1 => constants.%C.7db +// CHECK:STDOUT: %C.loc21_17.1 => constants.%C.7db // CHECK:STDOUT: %pattern_type => constants.%pattern_type.225 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -251,17 +279,21 @@ impl i32 as I { // CHECK:STDOUT: %T.loc11_9.2 => type // CHECK:STDOUT: %X.loc11_19.2 => constants.%i32 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.98f +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%I.facet.8b2) { -// CHECK:STDOUT: %Self => constants.%I.facet.8b2 -// CHECK:STDOUT: %C.loc15_17.1 => constants.%C.835 -// CHECK:STDOUT: %pattern_type => constants.%pattern_type.023 +// CHECK:STDOUT: specific @F.1(constants.%I.facet.118) { +// CHECK:STDOUT: %Self => constants.%I.facet.118 +// CHECK:STDOUT: %C.loc21_17.1 => constants.%C.d88 +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.c65 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @C(constants.%I.type, constants.%I.facet.8b2) { +// CHECK:STDOUT: specific @C(constants.%I.type, constants.%I.facet.118) { // CHECK:STDOUT: %T.loc11_9.2 => constants.%I.type -// CHECK:STDOUT: %X.loc11_19.2 => constants.%I.facet.8b2 +// CHECK:STDOUT: %X.loc11_19.2 => constants.%I.facet.118 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.2b5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon b/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon new file mode 100644 index 000000000000..0e32fcb99eb6 --- /dev/null +++ b/toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon @@ -0,0 +1,1843 @@ +// 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/impl/no_prelude/impl_thunk.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/impl_thunk.carbon + +// --- fail_todo_param_name_differs.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+3]]:20: error: parameter has incomplete type `C` in function definition [IncompleteTypeInFunctionParam] +// CHECK:STDERR: interface I { fn F(x: Self); } +// CHECK:STDERR: ^~~~~~~ +interface I { fn F(x: Self); } + +// TODO: This currently uses a thunk due to the parameter name mismatch, but shouldn't! +// TODO: This then fails because we attempt to build the thunk before `C` is complete. +// CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+3]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +class C { + impl as I { + // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+17]]:5: note: while building thunk calling this function [ThunkCallee] + // CHECK:STDERR: fn F(not_x: C); + // CHECK:STDERR: ^~~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-13]]:20: error: forming value of incomplete type `C` [IncompleteTypeInValueConversion] + // CHECK:STDERR: interface I { fn F(x: Self); } + // CHECK:STDERR: ^~~~~~~ + // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-9]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition] + // CHECK:STDERR: class C { + // CHECK:STDERR: ^~~~~~~~~ + // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fn F(not_x: C); + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_todo_param_name_differs.carbon:[[@LINE-22]]:15: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: interface I { fn F(x: Self); } + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + fn F(not_x: C); + } +} + +// --- struct_conversion.carbon + +library "[[@TEST_NAME]]"; + +interface I { + fn F(x: {.a: (), .b: {}}) -> {.c: (), .d: {}}; +} + +impl () as I { + fn F(y: {.b: {}, .a: ()}) -> {.d: {}, .c: ()}; +} + +// --- inheritance_conversion.carbon + +library "[[@TEST_NAME]]"; + +base class A {} +base class B { extend base: A; } +class C { extend base: B; } + +interface X { + fn F[addr self: Self*](other: Self*) -> Self*; +} + +impl B as X { + fn F[addr self: A*](other: A*) -> C*; +} + +// --- inheritance_value_conversion.carbon + +library "[[@TEST_NAME]]"; + +base class A {} +class B { extend base: A; } + +interface X { + fn F[self: Self](other: Self); +} + +impl B as X { + fn F[self: A](other: A); +} + +// --- inheritance_value_conversion_pointer.carbon + +library "[[@TEST_NAME]]"; + +base class A {} +base class B { extend base: A; } +class C { extend base: B; } + +interface X { + fn F[addr self: Self*](other: Self*) -> Self*; +} + +impl B as X { + fn F[addr self: A*](other: A*) -> C*; +} + +// --- fail_inheritance_value_conversion_copy_return.carbon + +library "[[@TEST_NAME]]"; + +base class A {} +class B { extend base: A; } + +interface X { + fn F() -> Self; +} + +impl A as X { + // CHECK:STDERR: fail_inheritance_value_conversion_copy_return.carbon:[[@LINE+7]]:3: error: cannot copy value of type `A` [CopyOfUncopyableType] + // CHECK:STDERR: fn F() -> B; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_inheritance_value_conversion_copy_return.carbon:[[@LINE-7]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F() -> Self; + // CHECK:STDERR: ^~~~~~~~~~~~~~~ + // CHECK:STDERR: + fn F() -> B; +} + +// --- fail_param_type_mismatch.carbon + +library "[[@TEST_NAME]]"; + +interface I { + // CHECK:STDERR: fail_param_type_mismatch.carbon:[[@LINE+3]]:8: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound] + // CHECK:STDERR: fn F(a: Self); + // CHECK:STDERR: ^~~~~~~ + fn F(a: Self); +} + +class A {} +class B {} + +impl A as I { + // CHECK:STDERR: fail_param_type_mismatch.carbon:[[@LINE+7]]:8: note: initializing function parameter [InCallToFunctionParam] + // CHECK:STDERR: fn F(a: B); + // CHECK:STDERR: ^~~~ + // CHECK:STDERR: fail_param_type_mismatch.carbon:[[@LINE-10]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F(a: Self); + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + fn F(a: B); +} + +// --- fail_return_mismatch.carbon + +library "[[@TEST_NAME]]"; + +interface I { + fn F() -> Self; +} + +class A {} +class B {} + +impl A as I { + // CHECK:STDERR: fail_return_mismatch.carbon:[[@LINE+7]]:3: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound] + // CHECK:STDERR: fn F() -> B; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_return_mismatch.carbon:[[@LINE-10]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F() -> Self; + // CHECK:STDERR: ^~~~~~~~~~~~~~~ + // CHECK:STDERR: + fn F() -> B; +} + +// --- return_empty_tuple_mismatch_allowed.carbon + +library "[[@TEST_NAME]]"; + +interface I { + fn HasReturn() -> Self; + fn NoReturn(); + fn EmptyTupleReturn() -> (); +} + +impl () as I { + // OK, can `return HasReturn();` in thunk. + fn HasReturn(); + + // OK, exact match. + fn NoReturn(); + + // OK, same as `HasReturn`. + fn EmptyTupleReturn(); +} + +// --- fail_return_empty_tuple_mismatch.carbon + +library "[[@TEST_NAME]]"; + +interface I { + fn NoReturn(); +} + +impl () as I { + // TODO: The proposal says to reject this. But should we really do so? + // CHECK:STDERR: fail_return_empty_tuple_mismatch.carbon:[[@LINE+7]]:3: error: function redeclaration differs because return type is `()` [FunctionRedeclReturnTypeDiffers] + // CHECK:STDERR: fn NoReturn() -> (); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_return_empty_tuple_mismatch.carbon:[[@LINE-8]]:3: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn] + // CHECK:STDERR: fn NoReturn(); + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + fn NoReturn() -> (); +} + +class C {} + +impl C as I { + // CHECK:STDERR: fail_return_empty_tuple_mismatch.carbon:[[@LINE+7]]:3: error: function redeclaration differs because return type is `C` [FunctionRedeclReturnTypeDiffers] + // CHECK:STDERR: fn NoReturn() -> C; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_return_empty_tuple_mismatch.carbon:[[@LINE-21]]:3: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn] + // CHECK:STDERR: fn NoReturn(); + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + fn NoReturn() -> C; +} + +// CHECK:STDOUT: --- fail_todo_param_name_differs.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.6de: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness @C.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.c48: type = pattern_type %C [concrete] +// CHECK:STDOUT: %F.type.f3605c.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.4c32b3.1: %F.type.f3605c.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %F.type.f3605c.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.4c32b3.2: %F.type.f3605c.2 = struct_value () [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.cf0 = fn_decl @F.1 [concrete = constants.%F.bc6] { +// CHECK:STDOUT: %x.patt: @F.1.%pattern_type (%pattern_type.6de) = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: @F.1.%pattern_type (%pattern_type.6de) = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type) = value_param call_param0 +// CHECK:STDOUT: %.loc7_23.1: type = splice_block %.loc7_23.2 [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] { +// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc7_23.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc7_23.2: type = converted %Self.ref, %Self.as_type.loc7_23.2 [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %Self.ref as %I.ref { +// CHECK:STDOUT: %F.decl.loc33_19.1: %F.type.f3605c.1 = fn_decl @F.2 [concrete = constants.%F.4c32b3.1] { +// CHECK:STDOUT: %not_x.patt: %pattern_type.c48 = binding_pattern not_x [concrete] +// CHECK:STDOUT: %not_x.param_patt: %pattern_type.c48 = value_param_pattern %not_x.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %not_x.param: %C = value_param call_param0 +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %not_x: %C = bind_name not_x, %not_x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc33_19.2: %F.type.f3605c.2 = fn_decl @F.3 [concrete = constants.%F.4c32b3.2] { +// CHECK:STDOUT: %x.patt: %pattern_type.c48 = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type.c48 = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %C = value_param call_param0 +// CHECK:STDOUT: %x: %C = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .C = +// CHECK:STDOUT: .F = %F.decl.loc33_19.1 +// CHECK:STDOUT: witness = @C.%I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc33_19.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .I = +// CHECK:STDOUT: .C = +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc7_23.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc7_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc7_23.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%x.param: @F.1.%Self.as_type.loc7_23.1 (%Self.as_type)); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%not_x.param: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%x.param: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref: %C = name_ref x, %x.param +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call @impl.%F.decl.loc33_19.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc7_23.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6de +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%I.facet) { +// CHECK:STDOUT: %Self => constants.%I.facet +// CHECK:STDOUT: %Self.as_type.loc7_23.1 => constants.%C +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.c48 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- struct_conversion.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %struct_type.a.b.391: type = struct_type {.a: %empty_tuple.type, .b: %empty_struct_type} [concrete] +// CHECK:STDOUT: %pattern_type.bec: type = pattern_type %struct_type.a.b.391 [concrete] +// CHECK:STDOUT: %struct_type.c.d.15a: type = struct_type {.c: %empty_tuple.type, .d: %empty_struct_type} [concrete] +// CHECK:STDOUT: %pattern_type.d63: type = pattern_type %struct_type.c.d.15a [concrete] +// CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness file.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %struct_type.b.a.40c: type = struct_type {.b: %empty_struct_type, .a: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.231: type = pattern_type %struct_type.b.a.40c [concrete] +// CHECK:STDOUT: %struct_type.d.c.b36: type = struct_type {.d: %empty_struct_type, .c: %empty_tuple.type} [concrete] +// CHECK:STDOUT: %pattern_type.844: type = pattern_type %struct_type.d.c.b36 [concrete] +// CHECK:STDOUT: %F.type.39e918.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.c04b92.1: %F.type.39e918.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %empty_tuple.type, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %F.type.39e918.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.c04b92.2: %F.type.39e918.2 = struct_value () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] +// CHECK:STDOUT: %struct: %struct_type.c.d.15a = struct_value (%empty_tuple, %empty_struct) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %.loc8_7.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc8_7.2: type = converted %.loc8_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc9_48.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.cf0 = fn_decl @F.1 [concrete = constants.%F.bc6] { +// CHECK:STDOUT: %x.patt: %pattern_type.bec = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type.bec = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.d63 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.d63 = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc5_38.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc5_38.2: type = converted %.loc5_38.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %.loc5_46.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc5_46.2: type = converted %.loc5_46.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %struct_type.c.d: type = struct_type {.c: %empty_tuple.type, .d: %empty_struct_type} [concrete = constants.%struct_type.c.d.15a] +// CHECK:STDOUT: %x.param: %struct_type.a.b.391 = value_param call_param0 +// CHECK:STDOUT: %.loc5_26: type = splice_block %struct_type.a.b [concrete = constants.%struct_type.a.b.391] { +// CHECK:STDOUT: %.loc5_17.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc5_17.2: type = converted %.loc5_17.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %.loc5_25.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc5_25.2: type = converted %.loc5_25.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %struct_type.a.b: type = struct_type {.a: %empty_tuple.type, .b: %empty_struct_type} [concrete = constants.%struct_type.a.b.391] +// CHECK:STDOUT: } +// CHECK:STDOUT: %x: %struct_type.a.b.391 = bind_name x, %x.param +// CHECK:STDOUT: %return.param: ref %struct_type.c.d.15a = out_param call_param1 +// CHECK:STDOUT: %return: ref %struct_type.c.d.15a = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %.loc8_7.2 as %I.ref { +// CHECK:STDOUT: %F.decl.loc9_48.1: %F.type.39e918.1 = fn_decl @F.2 [concrete = constants.%F.c04b92.1] { +// CHECK:STDOUT: %y.patt: %pattern_type.231 = binding_pattern y [concrete] +// CHECK:STDOUT: %y.param_patt: %pattern_type.231 = value_param_pattern %y.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.844 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.844 = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc9_38.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc9_38.2: type = converted %.loc9_38.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %.loc9_46.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc9_46.2: type = converted %.loc9_46.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %struct_type.d.c: type = struct_type {.d: %empty_struct_type, .c: %empty_tuple.type} [concrete = constants.%struct_type.d.c.b36] +// CHECK:STDOUT: %y.param: %struct_type.b.a.40c = value_param call_param0 +// CHECK:STDOUT: %.loc9_26: type = splice_block %struct_type.b.a [concrete = constants.%struct_type.b.a.40c] { +// CHECK:STDOUT: %.loc9_17.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc9_17.2: type = converted %.loc9_17.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %.loc9_25.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc9_25.2: type = converted %.loc9_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %struct_type.b.a: type = struct_type {.b: %empty_struct_type, .a: %empty_tuple.type} [concrete = constants.%struct_type.b.a.40c] +// CHECK:STDOUT: } +// CHECK:STDOUT: %y: %struct_type.b.a.40c = bind_name y, %y.param +// CHECK:STDOUT: %return.param: ref %struct_type.d.c.b36 = out_param call_param1 +// CHECK:STDOUT: %return: ref %struct_type.d.c.b36 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc9_48.2: %F.type.39e918.2 = fn_decl @F.3 [concrete = constants.%F.c04b92.2] { +// CHECK:STDOUT: %x.patt: %pattern_type.bec = binding_pattern x [concrete] +// CHECK:STDOUT: %x.param_patt: %pattern_type.bec = value_param_pattern %x.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.d63 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.d63 = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %x.param: %struct_type.a.b.391 = value_param call_param0 +// CHECK:STDOUT: %x: %struct_type.a.b.391 = bind_name x, %x.param +// CHECK:STDOUT: %return.param: ref %struct_type.c.d.15a = out_param call_param1 +// CHECK:STDOUT: %return: ref %struct_type.c.d.15a = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl.loc9_48.1 +// CHECK:STDOUT: witness = file.%I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { +// CHECK:STDOUT: fn(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%y.param: %struct_type.b.a.40c) -> %return.param: %struct_type.d.c.b36; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %x.ref: %struct_type.a.b.391 = name_ref x, %x.param +// CHECK:STDOUT: %.loc9_48.1: ref %struct_type.d.c.b36 = temporary_storage +// CHECK:STDOUT: %.loc5_9.1: %empty_struct_type = struct_access %x.ref, element1 +// CHECK:STDOUT: %.loc5_9.2: %empty_tuple.type = struct_access %x.ref, element0 +// CHECK:STDOUT: %struct: %struct_type.b.a.40c = struct_value (%.loc5_9.1, %.loc5_9.2) +// CHECK:STDOUT: %.loc5_9.3: %struct_type.b.a.40c = converted %x.ref, %struct +// CHECK:STDOUT: %F.call: init %struct_type.d.c.b36 = call @impl.%F.decl.loc9_48.1(%.loc5_9.3) to %.loc9_48.1 +// CHECK:STDOUT: %.loc9_48.2: ref %struct_type.d.c.b36 = temporary %.loc9_48.1, %F.call +// CHECK:STDOUT: %.loc9_48.3: ref %empty_tuple.type = struct_access %.loc9_48.2, element1 +// CHECK:STDOUT: %.loc9_48.4: ref %empty_tuple.type = struct_access %return, element1 +// CHECK:STDOUT: %.loc9_48.5: init %empty_tuple.type = tuple_init () to %.loc9_48.4 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc9_48.6: init %empty_tuple.type = converted %.loc9_48.3, %.loc9_48.5 [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc9_48.7: ref %empty_struct_type = struct_access %.loc9_48.2, element0 +// CHECK:STDOUT: %.loc9_48.8: ref %empty_struct_type = struct_access %return, element0 +// CHECK:STDOUT: %.loc9_48.9: init %empty_struct_type = struct_init () to %.loc9_48.8 [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc9_48.10: init %empty_struct_type = converted %.loc9_48.7, %.loc9_48.9 [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc9_48.11: init %struct_type.c.d.15a = struct_init (%.loc9_48.6, %.loc9_48.10) to %return [concrete = constants.%struct] +// CHECK:STDOUT: %.loc9_48.12: init %struct_type.c.d.15a = converted %F.call, %.loc9_48.11 [concrete = constants.%struct] +// CHECK:STDOUT: return %.loc9_48.12 to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%I.facet) {} +// CHECK:STDOUT: +// CHECK:STDOUT: --- inheritance_conversion.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %B.elem: type = unbound_element_type %B, %A [concrete] +// CHECK:STDOUT: %struct_type.base.953: type = struct_type {.base: %A} [concrete] +// CHECK:STDOUT: %complete_type.020: = complete_type_witness %struct_type.base.953 [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %C.elem: type = unbound_element_type %C, %B [concrete] +// CHECK:STDOUT: %struct_type.base.0ff: type = struct_type {.base: %B} [concrete] +// CHECK:STDOUT: %complete_type.98e: = complete_type_witness %struct_type.base.0ff [concrete] +// CHECK:STDOUT: %X.type: type = facet_type <@X> [concrete] +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %ptr.d06: type = ptr_type %Self.as_type [symbolic] +// CHECK:STDOUT: %pattern_type.4c5: type = pattern_type %ptr.d06 [symbolic] +// CHECK:STDOUT: %pattern_type.f6d: type = pattern_type auto [concrete] +// CHECK:STDOUT: %F.type.594: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.b69: %F.type.594 = struct_value () [concrete] +// CHECK:STDOUT: %X.assoc_type: type = assoc_entity_type @X [concrete] +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, @X.%F.decl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness file.%X.impl_witness_table [concrete] +// CHECK:STDOUT: %ptr.6db: type = ptr_type %A [concrete] +// CHECK:STDOUT: %pattern_type.5f8: type = pattern_type %ptr.6db [concrete] +// CHECK:STDOUT: %ptr.019: type = ptr_type %C [concrete] +// CHECK:STDOUT: %pattern_type.44a: type = pattern_type %ptr.019 [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.5161e9.1: %F.type.f1b0b1.1 = struct_value () [concrete] +// CHECK:STDOUT: %X.facet: %X.type = facet_value %B, (%X.impl_witness) [concrete] +// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete] +// CHECK:STDOUT: %pattern_type.960: type = pattern_type %ptr.e79 [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.5161e9.2: %F.type.f1b0b1.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: %X.decl: type = interface_decl @X [concrete = constants.%X.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.impl_witness_table = impl_witness_table (@impl.%F.decl.loc13_39.2), @impl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @X { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.594 = fn_decl @F.1 [concrete = constants.%F.b69] { +// CHECK:STDOUT: %self.patt: @F.1.%pattern_type (%pattern_type.4c5) = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc9_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: @F.1.%pattern_type (%pattern_type.4c5) = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: @F.1.%pattern_type (%pattern_type.4c5) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref.loc9_43: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_47: type = facet_access_type %Self.ref.loc9_43 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_47: type = converted %Self.ref.loc9_43, %Self.as_type.loc9_47 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_47: type = ptr_type %.loc9_47 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: %self.param: @F.1.%ptr.loc9_23.1 (%ptr.d06) = value_param call_param0 +// CHECK:STDOUT: %.loc9_23.1: type = splice_block %ptr.loc9_23.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] { +// CHECK:STDOUT: %Self.ref.loc9_19: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_23.2: type = facet_access_type %Self.ref.loc9_19 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_23.2: type = converted %Self.ref.loc9_19, %Self.as_type.loc9_23.2 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_23.2: type = ptr_type %.loc9_23.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %self: @F.1.%ptr.loc9_23.1 (%ptr.d06) = bind_name self, %self.param +// CHECK:STDOUT: %other.param: @F.1.%ptr.loc9_23.1 (%ptr.d06) = value_param call_param1 +// CHECK:STDOUT: %.loc9_37.1: type = splice_block %ptr.loc9_37 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] { +// CHECK:STDOUT: %Self.ref.loc9_33: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_37: type = facet_access_type %Self.ref.loc9_33 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_37.2: type = converted %Self.ref.loc9_33, %Self.as_type.loc9_37 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_37: type = ptr_type %.loc9_37.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %other: @F.1.%ptr.loc9_23.1 (%ptr.d06) = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref @F.1.%ptr.loc9_23.1 (%ptr.d06) = out_param call_param2 +// CHECK:STDOUT: %return: ref @F.1.%ptr.loc9_23.1 (%ptr.d06) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %B.ref as %X.ref { +// CHECK:STDOUT: %F.decl.loc13_39.1: %F.type.f1b0b1.1 = fn_decl @F.2 [concrete = constants.%F.5161e9.1] { +// CHECK:STDOUT: %self.patt: %pattern_type.5f8 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.5f8 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc13_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.5f8 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.5f8 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.44a = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.44a = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %ptr.loc13_38: type = ptr_type %C.ref [concrete = constants.%ptr.019] +// CHECK:STDOUT: %self.param: %ptr.6db = value_param call_param0 +// CHECK:STDOUT: %.loc13_20: type = splice_block %ptr.loc13_20 [concrete = constants.%ptr.6db] { +// CHECK:STDOUT: %A.ref.loc13_19: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %ptr.loc13_20: type = ptr_type %A.ref.loc13_19 [concrete = constants.%ptr.6db] +// CHECK:STDOUT: } +// CHECK:STDOUT: %self: %ptr.6db = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %ptr.6db = value_param call_param1 +// CHECK:STDOUT: %.loc13_31: type = splice_block %ptr.loc13_31 [concrete = constants.%ptr.6db] { +// CHECK:STDOUT: %A.ref.loc13_30: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %ptr.loc13_31: type = ptr_type %A.ref.loc13_30 [concrete = constants.%ptr.6db] +// CHECK:STDOUT: } +// CHECK:STDOUT: %other: %ptr.6db = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref %ptr.019 = out_param call_param2 +// CHECK:STDOUT: %return: ref %ptr.019 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc13_39.2: %F.type.f1b0b1.2 = fn_decl @F.3 [concrete = constants.%F.5161e9.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.960 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.960 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc9_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.960 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.960 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.960 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.960 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %ptr.e79 = value_param call_param0 +// CHECK:STDOUT: %self: %ptr.e79 = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %ptr.e79 = value_param call_param1 +// CHECK:STDOUT: %other: %ptr.e79 = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref %ptr.e79 = out_param call_param2 +// CHECK:STDOUT: %return: ref %ptr.e79 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .C = +// CHECK:STDOUT: .F = %F.decl.loc13_39.1 +// CHECK:STDOUT: witness = file.%X.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %.loc5: %B.elem = base_decl %A.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %A} [concrete = constants.%struct_type.base.953] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.020] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .base = %.loc5 +// CHECK:STDOUT: extend %A.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %.loc6: %C.elem = base_decl %B.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %B} [concrete = constants.%struct_type.base.0ff] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.98e] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .B = +// CHECK:STDOUT: .base = %.loc6 +// CHECK:STDOUT: extend %B.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@X.%Self: %X.type) { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_23.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_23.1: type = ptr_type %Self.as_type.loc9_23.1 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.loc9_23.1 [symbolic = %pattern_type (constants.%pattern_type.4c5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%self.param: @F.1.%ptr.loc9_23.1 (%ptr.d06), %other.param: @F.1.%ptr.loc9_23.1 (%ptr.d06)) -> @F.1.%ptr.loc9_23.1 (%ptr.d06); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%self.param: %ptr.6db, %other.param: %ptr.6db) -> %ptr.019; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %ptr.e79 = name_ref self, %self.param +// CHECK:STDOUT: %.loc9_17.1: ref %B = deref %self.ref +// CHECK:STDOUT: %F.bound: = bound_method %.loc9_17.1, @impl.%F.decl.loc13_39.1 +// CHECK:STDOUT: %other.ref: %ptr.e79 = name_ref other, %other.param +// CHECK:STDOUT: %addr.loc9_17.1: %ptr.e79 = addr_of %.loc9_17.1 +// CHECK:STDOUT: %.loc9_17.2: ref %B = deref %addr.loc9_17.1 +// CHECK:STDOUT: %.loc9_17.3: ref %A = class_element_access %.loc9_17.2, element0 +// CHECK:STDOUT: %addr.loc9_17.2: %ptr.6db = addr_of %.loc9_17.3 +// CHECK:STDOUT: %.loc9_17.4: %ptr.6db = converted %addr.loc9_17.1, %addr.loc9_17.2 +// CHECK:STDOUT: %.loc9_31.1: ref %B = deref %other.ref +// CHECK:STDOUT: %.loc9_31.2: ref %A = class_element_access %.loc9_31.1, element0 +// CHECK:STDOUT: %addr.loc9_31: %ptr.6db = addr_of %.loc9_31.2 +// CHECK:STDOUT: %.loc9_31.3: %ptr.6db = converted %other.ref, %addr.loc9_31 +// CHECK:STDOUT: %F.call: init %ptr.019 = call %F.bound(%.loc9_17.4, %.loc9_31.3) +// CHECK:STDOUT: %.loc13_39.1: %ptr.019 = value_of_initializer %F.call +// CHECK:STDOUT: %.loc13_39.2: %ptr.019 = converted %F.call, %.loc13_39.1 +// CHECK:STDOUT: %.loc13_39.3: ref %C = deref %.loc13_39.2 +// CHECK:STDOUT: %.loc13_39.4: ref %B = class_element_access %.loc13_39.3, element0 +// CHECK:STDOUT: %addr.loc13: %ptr.e79 = addr_of %.loc13_39.4 +// CHECK:STDOUT: %.loc13_39.5: %ptr.e79 = converted %F.call, %addr.loc13 +// CHECK:STDOUT: return %.loc13_39.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc9_23.1 => constants.%Self.as_type +// CHECK:STDOUT: %ptr.loc9_23.1 => constants.%ptr.d06 +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.4c5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%X.facet) { +// CHECK:STDOUT: %Self => constants.%X.facet +// CHECK:STDOUT: %Self.as_type.loc9_23.1 => constants.%B +// CHECK:STDOUT: %ptr.loc9_23.1 => constants.%ptr.e79 +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.960 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- inheritance_value_conversion.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %B.elem: type = unbound_element_type %B, %A [concrete] +// CHECK:STDOUT: %struct_type.base.953: type = struct_type {.base: %A} [concrete] +// CHECK:STDOUT: %complete_type.020: = complete_type_witness %struct_type.base.953 [concrete] +// CHECK:STDOUT: %X.type: type = facet_type <@X> [concrete] +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.331: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %F.type.594: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.b69: %F.type.594 = struct_value () [concrete] +// CHECK:STDOUT: %X.assoc_type: type = assoc_entity_type @X [concrete] +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, @X.%F.decl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness file.%X.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.5161e9.1: %F.type.f1b0b1.1 = struct_value () [concrete] +// CHECK:STDOUT: %X.facet: %X.type = facet_value %B, (%X.impl_witness) [concrete] +// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.5161e9.2: %F.type.f1b0b1.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: %X.decl: type = interface_decl @X [concrete = constants.%X.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.impl_witness_table = impl_witness_table (@impl.%F.decl.loc12_26.2), @impl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @X { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.594 = fn_decl @F.1 [concrete = constants.%F.b69] { +// CHECK:STDOUT: %self.patt: @F.1.%pattern_type (%pattern_type.331) = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: @F.1.%pattern_type (%pattern_type.331) = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %other.patt: @F.1.%pattern_type (%pattern_type.331) = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: @F.1.%pattern_type (%pattern_type.331) = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = value_param call_param0 +// CHECK:STDOUT: %.loc8_14.1: type = splice_block %.loc8_14.2 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] { +// CHECK:STDOUT: %Self.ref.loc8_14: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_14.2: type = facet_access_type %Self.ref.loc8_14 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc8_14.2: type = converted %Self.ref.loc8_14, %Self.as_type.loc8_14.2 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %self: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = bind_name self, %self.param +// CHECK:STDOUT: %other.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = value_param call_param1 +// CHECK:STDOUT: %.loc8_27.1: type = splice_block %.loc8_27.2 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] { +// CHECK:STDOUT: %Self.ref.loc8_27: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_27: type = facet_access_type %Self.ref.loc8_27 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc8_27.2: type = converted %Self.ref.loc8_27, %Self.as_type.loc8_27 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %other: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = bind_name other, %other.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %B.ref as %X.ref { +// CHECK:STDOUT: %F.decl.loc12_26.1: %F.type.f1b0b1.1 = fn_decl @F.2 [concrete = constants.%F.5161e9.1] { +// CHECK:STDOUT: %self.patt: %pattern_type.c10 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.c10 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.c10 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.c10 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %A = value_param call_param0 +// CHECK:STDOUT: %A.ref.loc12_14: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %self: %A = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %A = value_param call_param1 +// CHECK:STDOUT: %A.ref.loc12_24: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %other: %A = bind_name other, %other.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc12_26.2: %F.type.f1b0b1.2 = fn_decl @F.3 [concrete = constants.%F.5161e9.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.049 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.049 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.049 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.049 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %B = value_param call_param0 +// CHECK:STDOUT: %self: %B = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %B = value_param call_param1 +// CHECK:STDOUT: %other: %B = bind_name other, %other.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .F = %F.decl.loc12_26.1 +// CHECK:STDOUT: witness = file.%X.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %.loc5: %B.elem = base_decl %A.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %A} [concrete = constants.%struct_type.base.953] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.020] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .base = %.loc5 +// CHECK:STDOUT: extend %A.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@X.%Self: %X.type) { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_14.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc8_14.1 [symbolic = %pattern_type (constants.%pattern_type.331)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type), %other.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type)); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%self.param: %A, %other.param: %A); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%self.param: %B, %other.param: %B) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %B = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.%F.decl.loc12_26.1 +// CHECK:STDOUT: %other.ref: %B = name_ref other, %other.param +// CHECK:STDOUT: %.loc8_12.1: ref %A = class_element_access %self.ref, element0 +// CHECK:STDOUT: %.loc8_12.2: ref %A = converted %self.ref, %.loc8_12.1 +// CHECK:STDOUT: %.loc8_12.3: %A = bind_value %.loc8_12.2 +// CHECK:STDOUT: %.loc8_25.1: ref %A = class_element_access %other.ref, element0 +// CHECK:STDOUT: %.loc8_25.2: ref %A = converted %other.ref, %.loc8_25.1 +// CHECK:STDOUT: %.loc8_25.3: %A = bind_value %.loc8_25.2 +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.bound(%.loc8_12.3, %.loc8_25.3) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc8_14.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.331 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%X.facet) { +// CHECK:STDOUT: %Self => constants.%X.facet +// CHECK:STDOUT: %Self.as_type.loc8_14.1 => constants.%B +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.049 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- inheritance_value_conversion_pointer.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %B.elem: type = unbound_element_type %B, %A [concrete] +// CHECK:STDOUT: %struct_type.base.953: type = struct_type {.base: %A} [concrete] +// CHECK:STDOUT: %complete_type.020: = complete_type_witness %struct_type.base.953 [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %C.elem: type = unbound_element_type %C, %B [concrete] +// CHECK:STDOUT: %struct_type.base.0ff: type = struct_type {.base: %B} [concrete] +// CHECK:STDOUT: %complete_type.98e: = complete_type_witness %struct_type.base.0ff [concrete] +// CHECK:STDOUT: %X.type: type = facet_type <@X> [concrete] +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %ptr.d06: type = ptr_type %Self.as_type [symbolic] +// CHECK:STDOUT: %pattern_type.4c5: type = pattern_type %ptr.d06 [symbolic] +// CHECK:STDOUT: %pattern_type.f6d: type = pattern_type auto [concrete] +// CHECK:STDOUT: %F.type.594: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.b69: %F.type.594 = struct_value () [concrete] +// CHECK:STDOUT: %X.assoc_type: type = assoc_entity_type @X [concrete] +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, @X.%F.decl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness file.%X.impl_witness_table [concrete] +// CHECK:STDOUT: %ptr.6db: type = ptr_type %A [concrete] +// CHECK:STDOUT: %pattern_type.5f8: type = pattern_type %ptr.6db [concrete] +// CHECK:STDOUT: %ptr.019: type = ptr_type %C [concrete] +// CHECK:STDOUT: %pattern_type.44a: type = pattern_type %ptr.019 [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.5161e9.1: %F.type.f1b0b1.1 = struct_value () [concrete] +// CHECK:STDOUT: %X.facet: %X.type = facet_value %B, (%X.impl_witness) [concrete] +// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete] +// CHECK:STDOUT: %pattern_type.960: type = pattern_type %ptr.e79 [concrete] +// CHECK:STDOUT: %F.type.f1b0b1.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.5161e9.2: %F.type.f1b0b1.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: %X.decl: type = interface_decl @X [concrete = constants.%X.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.impl_witness_table = impl_witness_table (@impl.%F.decl.loc13_39.2), @impl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @X { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.594 = fn_decl @F.1 [concrete = constants.%F.b69] { +// CHECK:STDOUT: %self.patt: @F.1.%pattern_type (%pattern_type.4c5) = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc9_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: @F.1.%pattern_type (%pattern_type.4c5) = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: @F.1.%pattern_type (%pattern_type.4c5) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @F.1.%pattern_type (%pattern_type.4c5) = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref.loc9_43: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_47: type = facet_access_type %Self.ref.loc9_43 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_47: type = converted %Self.ref.loc9_43, %Self.as_type.loc9_47 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_47: type = ptr_type %.loc9_47 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: %self.param: @F.1.%ptr.loc9_23.1 (%ptr.d06) = value_param call_param0 +// CHECK:STDOUT: %.loc9_23.1: type = splice_block %ptr.loc9_23.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] { +// CHECK:STDOUT: %Self.ref.loc9_19: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_23.2: type = facet_access_type %Self.ref.loc9_19 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_23.2: type = converted %Self.ref.loc9_19, %Self.as_type.loc9_23.2 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_23.2: type = ptr_type %.loc9_23.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %self: @F.1.%ptr.loc9_23.1 (%ptr.d06) = bind_name self, %self.param +// CHECK:STDOUT: %other.param: @F.1.%ptr.loc9_23.1 (%ptr.d06) = value_param call_param1 +// CHECK:STDOUT: %.loc9_37.1: type = splice_block %ptr.loc9_37 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] { +// CHECK:STDOUT: %Self.ref.loc9_33: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_37: type = facet_access_type %Self.ref.loc9_33 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc9_37.2: type = converted %Self.ref.loc9_33, %Self.as_type.loc9_37 [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_37: type = ptr_type %.loc9_37.2 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %other: @F.1.%ptr.loc9_23.1 (%ptr.d06) = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref @F.1.%ptr.loc9_23.1 (%ptr.d06) = out_param call_param2 +// CHECK:STDOUT: %return: ref @F.1.%ptr.loc9_23.1 (%ptr.d06) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %B.ref as %X.ref { +// CHECK:STDOUT: %F.decl.loc13_39.1: %F.type.f1b0b1.1 = fn_decl @F.2 [concrete = constants.%F.5161e9.1] { +// CHECK:STDOUT: %self.patt: %pattern_type.5f8 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.5f8 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc13_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.5f8 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.5f8 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.44a = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.44a = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %ptr.loc13_38: type = ptr_type %C.ref [concrete = constants.%ptr.019] +// CHECK:STDOUT: %self.param: %ptr.6db = value_param call_param0 +// CHECK:STDOUT: %.loc13_20: type = splice_block %ptr.loc13_20 [concrete = constants.%ptr.6db] { +// CHECK:STDOUT: %A.ref.loc13_19: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %ptr.loc13_20: type = ptr_type %A.ref.loc13_19 [concrete = constants.%ptr.6db] +// CHECK:STDOUT: } +// CHECK:STDOUT: %self: %ptr.6db = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %ptr.6db = value_param call_param1 +// CHECK:STDOUT: %.loc13_31: type = splice_block %ptr.loc13_31 [concrete = constants.%ptr.6db] { +// CHECK:STDOUT: %A.ref.loc13_30: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %ptr.loc13_31: type = ptr_type %A.ref.loc13_30 [concrete = constants.%ptr.6db] +// CHECK:STDOUT: } +// CHECK:STDOUT: %other: %ptr.6db = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref %ptr.019 = out_param call_param2 +// CHECK:STDOUT: %return: ref %ptr.019 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc13_39.2: %F.type.f1b0b1.2 = fn_decl @F.3 [concrete = constants.%F.5161e9.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.960 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.960 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.loc9_8: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %other.patt: %pattern_type.960 = binding_pattern other [concrete] +// CHECK:STDOUT: %other.param_patt: %pattern_type.960 = value_param_pattern %other.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.960 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.960 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %ptr.e79 = value_param call_param0 +// CHECK:STDOUT: %self: %ptr.e79 = bind_name self, %self.param +// CHECK:STDOUT: %other.param: %ptr.e79 = value_param call_param1 +// CHECK:STDOUT: %other: %ptr.e79 = bind_name other, %other.param +// CHECK:STDOUT: %return.param: ref %ptr.e79 = out_param call_param2 +// CHECK:STDOUT: %return: ref %ptr.e79 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .C = +// CHECK:STDOUT: .F = %F.decl.loc13_39.1 +// CHECK:STDOUT: witness = file.%X.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %.loc5: %B.elem = base_decl %A.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %A} [concrete = constants.%struct_type.base.953] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.020] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .base = %.loc5 +// CHECK:STDOUT: extend %A.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %.loc6: %C.elem = base_decl %B.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %B} [concrete = constants.%struct_type.base.0ff] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.98e] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .B = +// CHECK:STDOUT: .base = %.loc6 +// CHECK:STDOUT: extend %B.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@X.%Self: %X.type) { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc9_23.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc9_23.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %ptr.loc9_23.1: type = ptr_type %Self.as_type.loc9_23.1 [symbolic = %ptr.loc9_23.1 (constants.%ptr.d06)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr.loc9_23.1 [symbolic = %pattern_type (constants.%pattern_type.4c5)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%self.param: @F.1.%ptr.loc9_23.1 (%ptr.d06), %other.param: @F.1.%ptr.loc9_23.1 (%ptr.d06)) -> @F.1.%ptr.loc9_23.1 (%ptr.d06); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%self.param: %ptr.6db, %other.param: %ptr.6db) -> %ptr.019; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %ptr.e79 = name_ref self, %self.param +// CHECK:STDOUT: %.loc9_17.1: ref %B = deref %self.ref +// CHECK:STDOUT: %F.bound: = bound_method %.loc9_17.1, @impl.%F.decl.loc13_39.1 +// CHECK:STDOUT: %other.ref: %ptr.e79 = name_ref other, %other.param +// CHECK:STDOUT: %addr.loc9_17.1: %ptr.e79 = addr_of %.loc9_17.1 +// CHECK:STDOUT: %.loc9_17.2: ref %B = deref %addr.loc9_17.1 +// CHECK:STDOUT: %.loc9_17.3: ref %A = class_element_access %.loc9_17.2, element0 +// CHECK:STDOUT: %addr.loc9_17.2: %ptr.6db = addr_of %.loc9_17.3 +// CHECK:STDOUT: %.loc9_17.4: %ptr.6db = converted %addr.loc9_17.1, %addr.loc9_17.2 +// CHECK:STDOUT: %.loc9_31.1: ref %B = deref %other.ref +// CHECK:STDOUT: %.loc9_31.2: ref %A = class_element_access %.loc9_31.1, element0 +// CHECK:STDOUT: %addr.loc9_31: %ptr.6db = addr_of %.loc9_31.2 +// CHECK:STDOUT: %.loc9_31.3: %ptr.6db = converted %other.ref, %addr.loc9_31 +// CHECK:STDOUT: %F.call: init %ptr.019 = call %F.bound(%.loc9_17.4, %.loc9_31.3) +// CHECK:STDOUT: %.loc13_39.1: %ptr.019 = value_of_initializer %F.call +// CHECK:STDOUT: %.loc13_39.2: %ptr.019 = converted %F.call, %.loc13_39.1 +// CHECK:STDOUT: %.loc13_39.3: ref %C = deref %.loc13_39.2 +// CHECK:STDOUT: %.loc13_39.4: ref %B = class_element_access %.loc13_39.3, element0 +// CHECK:STDOUT: %addr.loc13: %ptr.e79 = addr_of %.loc13_39.4 +// CHECK:STDOUT: %.loc13_39.5: %ptr.e79 = converted %F.call, %addr.loc13 +// CHECK:STDOUT: return %.loc13_39.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc9_23.1 => constants.%Self.as_type +// CHECK:STDOUT: %ptr.loc9_23.1 => constants.%ptr.d06 +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.4c5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%X.facet) { +// CHECK:STDOUT: %Self => constants.%X.facet +// CHECK:STDOUT: %Self.as_type.loc9_23.1 => constants.%B +// CHECK:STDOUT: %ptr.loc9_23.1 => constants.%ptr.e79 +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.960 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_inheritance_value_conversion_copy_return.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %B.elem: type = unbound_element_type %B, %A [concrete] +// CHECK:STDOUT: %struct_type.base.953: type = struct_type {.base: %A} [concrete] +// CHECK:STDOUT: %complete_type.020: = complete_type_witness %struct_type.base.953 [concrete] +// CHECK:STDOUT: %X.type: type = facet_type <@X> [concrete] +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.331: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %F.type.594: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.b69: %F.type.594 = struct_value () [concrete] +// CHECK:STDOUT: %X.assoc_type: type = assoc_entity_type @X [concrete] +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, @X.%F.decl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness file.%X.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete] +// CHECK:STDOUT: %F.type.b24d6f.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.77e9d5.1: %F.type.b24d6f.1 = struct_value () [concrete] +// CHECK:STDOUT: %X.facet: %X.type = facet_value %A, (%X.impl_witness) [concrete] +// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete] +// CHECK:STDOUT: %F.type.b24d6f.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.77e9d5.2: %F.type.b24d6f.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: %X.decl: type = interface_decl @X [concrete = constants.%X.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.impl_witness_table = impl_witness_table (@impl.%F.decl.loc19_14.2), @impl [concrete] +// CHECK:STDOUT: %X.impl_witness: = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @X { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.594 = fn_decl @F.1 [concrete = constants.%F.b69] { +// CHECK:STDOUT: %return.patt: @F.1.%pattern_type (%pattern_type.331) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @F.1.%pattern_type (%pattern_type.331) = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref: %X.type = name_ref Self, @X.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_13.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc8_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc8: type = converted %Self.ref, %Self.as_type.loc8_13.2 [symbolic = %Self.as_type.loc8_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %return.param: ref @F.1.%Self.as_type.loc8_13.1 (%Self.as_type) = out_param call_param0 +// CHECK:STDOUT: %return: ref @F.1.%Self.as_type.loc8_13.1 (%Self.as_type) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %X.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %A.ref as %X.ref { +// CHECK:STDOUT: %F.decl.loc19_14.1: %F.type.b24d6f.1 = fn_decl @F.2 [concrete = constants.%F.77e9d5.1] { +// CHECK:STDOUT: %return.patt: %pattern_type.049 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.049 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %return.param: ref %B = out_param call_param0 +// CHECK:STDOUT: %return: ref %B = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc19_14.2: %F.type.b24d6f.2 = fn_decl @F.3 [concrete = constants.%F.77e9d5.2] { +// CHECK:STDOUT: %return.patt: %pattern_type.c10 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.c10 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %return.param: ref %A = out_param call_param0 +// CHECK:STDOUT: %return: ref %A = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .B = +// CHECK:STDOUT: .F = %F.decl.loc19_14.1 +// CHECK:STDOUT: witness = file.%X.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %.loc5: %B.elem = base_decl %A.ref, element0 [concrete] +// CHECK:STDOUT: %struct_type.base: type = struct_type {.base: %A} [concrete = constants.%struct_type.base.953] +// CHECK:STDOUT: %complete_type: = complete_type_witness %struct_type.base [concrete = constants.%complete_type.020] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: .A = +// CHECK:STDOUT: .base = %.loc5 +// CHECK:STDOUT: extend %A.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@X.%Self: %X.type) { +// CHECK:STDOUT: %Self: %X.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_13.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc8_13.1 [symbolic = %pattern_type (constants.%pattern_type.331)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @F.1.%Self.as_type.loc8_13.1 (%Self.as_type); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2() -> %return.param: %B; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3() -> %return.param: %A { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc19_14.1: ref %B = temporary_storage +// CHECK:STDOUT: %F.call: init %B = call @impl.%F.decl.loc19_14.1() to %.loc19_14.1 +// CHECK:STDOUT: %.loc19_14.2: ref %B = temporary %.loc19_14.1, %F.call +// CHECK:STDOUT: %.loc19_14.3: ref %A = class_element_access %.loc19_14.2, element0 +// CHECK:STDOUT: %.loc19_14.4: ref %A = converted %F.call, %.loc19_14.3 +// CHECK:STDOUT: %.loc19_14.5: %A = bind_value %.loc19_14.4 +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc8_13.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.331 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%X.facet) { +// CHECK:STDOUT: %Self => constants.%X.facet +// CHECK:STDOUT: %Self.as_type.loc8_13.1 => constants.%A +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.c10 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_param_type_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.6de: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness file.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete] +// CHECK:STDOUT: %F.type.2ae1ef.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.2a7aab.1: %F.type.2ae1ef.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %A, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete] +// CHECK:STDOUT: %F.type.2ae1ef.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.2a7aab.2: %F.type.2ae1ef.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc22_13.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.cf0 = fn_decl @F.1 [concrete = constants.%F.bc6] { +// CHECK:STDOUT: %a.patt: @F.1.%pattern_type (%pattern_type.6de) = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: @F.1.%pattern_type (%pattern_type.6de) = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: @F.1.%Self.as_type.loc8_11.1 (%Self.as_type) = value_param call_param0 +// CHECK:STDOUT: %.loc8_11.1: type = splice_block %.loc8_11.2 [symbolic = %Self.as_type.loc8_11.1 (constants.%Self.as_type)] { +// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_11.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc8_11.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc8_11.2: type = converted %Self.ref, %Self.as_type.loc8_11.2 [symbolic = %Self.as_type.loc8_11.1 (constants.%Self.as_type)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: @F.1.%Self.as_type.loc8_11.1 (%Self.as_type) = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %A.ref as %I.ref { +// CHECK:STDOUT: %F.decl.loc22_13.1: %F.type.2ae1ef.1 = fn_decl @F.2 [concrete = constants.%F.2a7aab.1] { +// CHECK:STDOUT: %a.patt: %pattern_type.049 = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.049 = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: %B = value_param call_param0 +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %a: %B = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc22_13.2: %F.type.2ae1ef.2 = fn_decl @F.3 [concrete = constants.%F.2a7aab.2] { +// CHECK:STDOUT: %a.patt: %pattern_type.c10 = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.c10 = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: %A = value_param call_param0 +// CHECK:STDOUT: %a: %A = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .B = +// CHECK:STDOUT: .F = %F.decl.loc22_13.1 +// CHECK:STDOUT: witness = file.%I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc8_11.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_11.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc8_11.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%a.param: @F.1.%Self.as_type.loc8_11.1 (%Self.as_type)); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2(%a.param: %B); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%a.param: %A) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %A = name_ref a, %a.param +// CHECK:STDOUT: %.loc8: %B = converted %a.ref, [concrete = ] +// CHECK:STDOUT: %F.call: init %empty_tuple.type = call @impl.%F.decl.loc22_13.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc8_11.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6de +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%I.facet) { +// CHECK:STDOUT: %Self => constants.%I.facet +// CHECK:STDOUT: %Self.as_type.loc8_11.1 => constants.%A +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.c10 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_return_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.6de: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %F.type.cf0: type = fn_type @F.1 [concrete] +// CHECK:STDOUT: %F.bc6: %F.type.cf0 = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%F.decl [concrete] +// CHECK:STDOUT: %A: type = class_type @A [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %B: type = class_type @B [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness file.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete] +// CHECK:STDOUT: %F.type.2ae1ef.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.2a7aab.1: %F.type.2ae1ef.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %A, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete] +// CHECK:STDOUT: %F.type.2ae1ef.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.2a7aab.2: %F.type.2ae1ef.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .B = %B.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: %A.decl: type = class_decl @A [concrete = constants.%A] {} {} +// CHECK:STDOUT: %B.decl: type = class_decl @B [concrete = constants.%B] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc19_14.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.cf0 = fn_decl @F.1 [concrete = constants.%F.bc6] { +// CHECK:STDOUT: %return.patt: @F.1.%pattern_type (%pattern_type.6de) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @F.1.%pattern_type (%pattern_type.6de) = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc5_13.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc5_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc5: type = converted %Self.ref, %Self.as_type.loc5_13.2 [symbolic = %Self.as_type.loc5_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %return.param: ref @F.1.%Self.as_type.loc5_13.1 (%Self.as_type) = out_param call_param0 +// CHECK:STDOUT: %return: ref @F.1.%Self.as_type.loc5_13.1 (%Self.as_type) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %assoc0 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %A.ref as %I.ref { +// CHECK:STDOUT: %F.decl.loc19_14.1: %F.type.2ae1ef.1 = fn_decl @F.2 [concrete = constants.%F.2a7aab.1] { +// CHECK:STDOUT: %return.patt: %pattern_type.049 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.049 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B] +// CHECK:STDOUT: %return.param: ref %B = out_param call_param0 +// CHECK:STDOUT: %return: ref %B = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc19_14.2: %F.type.2ae1ef.2 = fn_decl @F.3 [concrete = constants.%F.2a7aab.2] { +// CHECK:STDOUT: %return.patt: %pattern_type.c10 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.c10 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %return.param: ref %A = out_param call_param0 +// CHECK:STDOUT: %return: ref %A = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .B = +// CHECK:STDOUT: .F = %F.decl.loc19_14.1 +// CHECK:STDOUT: witness = file.%I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @B { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%B +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc5_13.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc5_13.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc5_13.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @F.1.%Self.as_type.loc5_13.1 (%Self.as_type); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2() -> %return.param: %B; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3() -> %return.param: %A { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc19_14.1: ref %B = temporary_storage +// CHECK:STDOUT: %F.call: init %B = call @impl.%F.decl.loc19_14.1() to %.loc19_14.1 +// CHECK:STDOUT: %.loc19_14.2: %A = converted %F.call, [concrete = ] +// CHECK:STDOUT: return to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc5_13.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6de +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%I.facet) { +// CHECK:STDOUT: %Self => constants.%I.facet +// CHECK:STDOUT: %Self.as_type.loc5_13.1 => constants.%A +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.c10 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- return_empty_tuple_mismatch_allowed.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self [symbolic] +// CHECK:STDOUT: %pattern_type.6de: type = pattern_type %Self.as_type [symbolic] +// CHECK:STDOUT: %HasReturn.type.bf9: type = fn_type @HasReturn.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %HasReturn.dcf: %HasReturn.type.bf9 = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%HasReturn.decl [concrete] +// CHECK:STDOUT: %NoReturn.type.7ff: type = fn_type @NoReturn.1 [concrete] +// CHECK:STDOUT: %NoReturn.7fd: %NoReturn.type.7ff = struct_value () [concrete] +// CHECK:STDOUT: %assoc1: %I.assoc_type = assoc_entity element1, @I.%NoReturn.decl [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.type.1cb: type = fn_type @EmptyTupleReturn.1 [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.c56: %EmptyTupleReturn.type.1cb = struct_value () [concrete] +// CHECK:STDOUT: %assoc2: %I.assoc_type = assoc_entity element2, @I.%EmptyTupleReturn.decl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness file.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %HasReturn.type.c73908.1: type = fn_type @HasReturn.2 [concrete] +// CHECK:STDOUT: %HasReturn.424378.1: %HasReturn.type.c73908.1 = struct_value () [concrete] +// CHECK:STDOUT: %NoReturn.type.948: type = fn_type @NoReturn.2 [concrete] +// CHECK:STDOUT: %NoReturn.9fa: %NoReturn.type.948 = struct_value () [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.type.9ea74f.1: type = fn_type @EmptyTupleReturn.2 [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.282179.1: %EmptyTupleReturn.type.9ea74f.1 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet: %I.type = facet_value %empty_tuple.type, (%I.impl_witness) [concrete] +// CHECK:STDOUT: %HasReturn.type.c73908.2: type = fn_type @HasReturn.3 [concrete] +// CHECK:STDOUT: %HasReturn.424378.2: %HasReturn.type.c73908.2 = struct_value () [concrete] +// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.type.9ea74f.2: type = fn_type @EmptyTupleReturn.3 [concrete] +// CHECK:STDOUT: %EmptyTupleReturn.282179.2: %EmptyTupleReturn.type.9ea74f.2 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: impl_decl @impl [concrete] {} { +// CHECK:STDOUT: %.loc10_7.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc10_7.2: type = converted %.loc10_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (@impl.%HasReturn.decl.loc12_17.2, @impl.%NoReturn.decl, @impl.%EmptyTupleReturn.decl.loc18_24.2), @impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %HasReturn.decl: %HasReturn.type.bf9 = fn_decl @HasReturn.1 [concrete = constants.%HasReturn.dcf] { +// CHECK:STDOUT: %return.patt: @HasReturn.1.%pattern_type (%pattern_type.6de) = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: @HasReturn.1.%pattern_type (%pattern_type.6de) = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc5_21.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc5_21.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %.loc5: type = converted %Self.ref, %Self.as_type.loc5_21.2 [symbolic = %Self.as_type.loc5_21.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %return.param: ref @HasReturn.1.%Self.as_type.loc5_21.1 (%Self.as_type) = out_param call_param0 +// CHECK:STDOUT: %return: ref @HasReturn.1.%Self.as_type.loc5_21.1 (%Self.as_type) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %HasReturn.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: %NoReturn.decl: %NoReturn.type.7ff = fn_decl @NoReturn.1 [concrete = constants.%NoReturn.7fd] {} {} +// CHECK:STDOUT: %assoc1: %I.assoc_type = assoc_entity element1, %NoReturn.decl [concrete = constants.%assoc1] +// CHECK:STDOUT: %EmptyTupleReturn.decl: %EmptyTupleReturn.type.1cb = fn_decl @EmptyTupleReturn.1 [concrete = constants.%EmptyTupleReturn.c56] { +// CHECK:STDOUT: %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc7_29.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc7_29.2: type = converted %.loc7_29.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param call_param0 +// CHECK:STDOUT: %return: ref %empty_tuple.type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %assoc2: %I.assoc_type = assoc_entity element2, %EmptyTupleReturn.decl [concrete = constants.%assoc2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .HasReturn = %assoc0 +// CHECK:STDOUT: .NoReturn = %assoc1 +// CHECK:STDOUT: .EmptyTupleReturn = %assoc2 +// CHECK:STDOUT: witness = (%HasReturn.decl, %NoReturn.decl, %EmptyTupleReturn.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %.loc10_7.2 as %I.ref { +// CHECK:STDOUT: %HasReturn.decl.loc12_17.1: %HasReturn.type.c73908.1 = fn_decl @HasReturn.2 [concrete = constants.%HasReturn.424378.1] {} {} +// CHECK:STDOUT: %NoReturn.decl: %NoReturn.type.948 = fn_decl @NoReturn.2 [concrete = constants.%NoReturn.9fa] {} {} +// CHECK:STDOUT: %EmptyTupleReturn.decl.loc18_24.1: %EmptyTupleReturn.type.9ea74f.1 = fn_decl @EmptyTupleReturn.2 [concrete = constants.%EmptyTupleReturn.282179.1] {} {} +// CHECK:STDOUT: %HasReturn.decl.loc12_17.2: %HasReturn.type.c73908.2 = fn_decl @HasReturn.3 [concrete = constants.%HasReturn.424378.2] { +// CHECK:STDOUT: %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param call_param0 +// CHECK:STDOUT: %return: ref %empty_tuple.type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %EmptyTupleReturn.decl.loc18_24.2: %EmptyTupleReturn.type.9ea74f.2 = fn_decl @EmptyTupleReturn.3 [concrete = constants.%EmptyTupleReturn.282179.2] { +// CHECK:STDOUT: %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param call_param0 +// CHECK:STDOUT: %return: ref %empty_tuple.type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .HasReturn = %HasReturn.decl.loc12_17.1 +// CHECK:STDOUT: .NoReturn = %NoReturn.decl +// CHECK:STDOUT: .EmptyTupleReturn = %EmptyTupleReturn.decl.loc18_24.1 +// CHECK:STDOUT: witness = file.%I.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @HasReturn.1(@I.%Self: %I.type) { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.as_type.loc5_21.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc5_21.1 (constants.%Self.as_type)] +// CHECK:STDOUT: %pattern_type: type = pattern_type %Self.as_type.loc5_21.1 [symbolic = %pattern_type (constants.%pattern_type.6de)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @HasReturn.1.%Self.as_type.loc5_21.1 (%Self.as_type); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @NoReturn.1(@I.%Self: %I.type) { +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @EmptyTupleReturn.1(@I.%Self: %I.type) { +// CHECK:STDOUT: fn() -> %empty_tuple.type; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @HasReturn.2(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NoReturn.2(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @EmptyTupleReturn.2(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @HasReturn.3() -> %empty_tuple.type { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %HasReturn.call: init %empty_tuple.type = call @impl.%HasReturn.decl.loc12_17.1() +// CHECK:STDOUT: %.loc12_17.1: ref %empty_tuple.type = temporary_storage +// CHECK:STDOUT: %.loc12_17.2: ref %empty_tuple.type = temporary %.loc12_17.1, %HasReturn.call +// CHECK:STDOUT: %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc12_17.3: %empty_tuple.type = converted %HasReturn.call, %tuple [concrete = constants.%empty_tuple] +// CHECK:STDOUT: return %.loc12_17.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @EmptyTupleReturn.3() -> %empty_tuple.type { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %EmptyTupleReturn.call: init %empty_tuple.type = call @impl.%EmptyTupleReturn.decl.loc18_24.1() +// CHECK:STDOUT: %.loc18_24.1: ref %empty_tuple.type = temporary_storage +// CHECK:STDOUT: %.loc18_24.2: ref %empty_tuple.type = temporary %.loc18_24.1, %EmptyTupleReturn.call +// CHECK:STDOUT: %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc18_24.3: %empty_tuple.type = converted %EmptyTupleReturn.call, %tuple [concrete = constants.%empty_tuple] +// CHECK:STDOUT: return %.loc18_24.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasReturn.1(constants.%Self) { +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: %Self.as_type.loc5_21.1 => constants.%Self.as_type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.6de +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @NoReturn.1(constants.%Self) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @EmptyTupleReturn.1(constants.%Self) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasReturn.1(constants.%I.facet) { +// CHECK:STDOUT: %Self => constants.%I.facet +// CHECK:STDOUT: %Self.as_type.loc5_21.1 => constants.%empty_tuple.type +// CHECK:STDOUT: %pattern_type => constants.%pattern_type.cb1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @NoReturn.1(constants.%I.facet) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @EmptyTupleReturn.1(constants.%I.facet) {} +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_return_empty_tuple_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %NoReturn.type.7ff: type = fn_type @NoReturn.1 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %NoReturn.7fd: %NoReturn.type.7ff = struct_value () [concrete] +// CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, @I.%NoReturn.decl [concrete] +// CHECK:STDOUT: %I.impl_witness.c4e: = impl_witness file.%I.impl_witness_table.loc8 [concrete] +// CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] +// CHECK:STDOUT: %NoReturn.type.948: type = fn_type @NoReturn.2 [concrete] +// CHECK:STDOUT: %NoReturn.9fa: %NoReturn.type.948 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet.372: %I.type = facet_value %empty_tuple.type, (%I.impl_witness.c4e) [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %I.impl_witness.464: = impl_witness file.%I.impl_witness_table.loc22 [concrete] +// CHECK:STDOUT: %pattern_type.c48: type = pattern_type %C [concrete] +// CHECK:STDOUT: %NoReturn.type.930: type = fn_type @NoReturn.3 [concrete] +// CHECK:STDOUT: %NoReturn.ac0: %NoReturn.type.930 = struct_value () [concrete] +// CHECK:STDOUT: %I.facet.be9: %I.type = facet_value %C, (%I.impl_witness.464) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: impl_decl @impl.4ab [concrete] {} { +// CHECK:STDOUT: %.loc8_7.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc8_7.2: type = converted %.loc8_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table.loc8 = impl_witness_table (), @impl.4ab [concrete] +// CHECK:STDOUT: %I.impl_witness.loc8: = impl_witness %I.impl_witness_table.loc8 [concrete = constants.%I.impl_witness.c4e] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: impl_decl @impl.770 [concrete] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.impl_witness_table.loc22 = impl_witness_table (), @impl.770 [concrete] +// CHECK:STDOUT: %I.impl_witness.loc22: = impl_witness %I.impl_witness_table.loc22 [concrete = constants.%I.impl_witness.464] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %NoReturn.decl: %NoReturn.type.7ff = fn_decl @NoReturn.1 [concrete = constants.%NoReturn.7fd] {} {} +// CHECK:STDOUT: %assoc0: %I.assoc_type = assoc_entity element0, %NoReturn.decl [concrete = constants.%assoc0] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .NoReturn = %assoc0 +// CHECK:STDOUT: witness = (%NoReturn.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.4ab: %.loc8_7.2 as %I.ref { +// CHECK:STDOUT: %NoReturn.decl: %NoReturn.type.948 = fn_decl @NoReturn.2 [concrete = constants.%NoReturn.9fa] { +// CHECK:STDOUT: %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc17_21.1: %empty_tuple.type = tuple_literal () +// CHECK:STDOUT: %.loc17_21.2: type = converted %.loc17_21.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %return.param: ref %empty_tuple.type = out_param call_param0 +// CHECK:STDOUT: %return: ref %empty_tuple.type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .NoReturn = %NoReturn.decl +// CHECK:STDOUT: witness = file.%I.impl_witness.loc8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.770: %C.ref as %I.ref { +// CHECK:STDOUT: %NoReturn.decl: %NoReturn.type.930 = fn_decl @NoReturn.3 [concrete = constants.%NoReturn.ac0] { +// CHECK:STDOUT: %return.patt: %pattern_type.c48 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.c48 = out_param_pattern %return.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %return.param: ref %C = out_param call_param0 +// CHECK:STDOUT: %return: ref %C = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .C = +// CHECK:STDOUT: .NoReturn = %NoReturn.decl +// CHECK:STDOUT: witness = file.%I.impl_witness.loc22 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @NoReturn.1(@I.%Self: %I.type) { +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NoReturn.2() -> %empty_tuple.type; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NoReturn.3() -> %C; +// CHECK:STDOUT: +// CHECK:STDOUT: specific @NoReturn.1(constants.%Self) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @NoReturn.1(constants.%I.facet.372) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @NoReturn.1(constants.%I.facet.be9) {} +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/use_assoc_const.carbon b/toolchain/check/testdata/impl/use_assoc_const.carbon index 4812e98b9d62..d73d57628e55 100644 --- a/toolchain/check/testdata/impl/use_assoc_const.carbon +++ b/toolchain/check/testdata/impl/use_assoc_const.carbon @@ -189,6 +189,13 @@ interface J2 { } impl () as J2 where .U2 = {} { + // CHECK:STDERR: fail_todo_self_period_associated_type.carbon:[[@LINE+7]]:3: error: expression cannot be used as a value [UseOfNonExprAsValue] + // CHECK:STDERR: fn F[self: Self](z: {}) -> {} { return z; } + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_self_period_associated_type.carbon:[[@LINE-7]]:3: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fn F[self: Self](z: Self.U2) -> Self.U2; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fn F[self: Self](z: {}) -> {} { return z; } } @@ -210,12 +217,12 @@ interface K { } impl () as K where .V = {.a: ()} { - // CHECK:STDERR: fail_associated_type_in_signature_mismatch.carbon:[[@LINE+7]]:20: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: fail_associated_type_in_signature_mismatch.carbon:[[@LINE+7]]:3: error: expression cannot be used as a value [UseOfNonExprAsValue] // CHECK:STDERR: fn F[self: Self](v: {.x: ()}) -> {.x: ()} { return v; } - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_associated_type_in_signature_mismatch.carbon:[[@LINE-7]]:20: note: previous declaration's corresponding parameter here [RedeclParamPrevious] + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_associated_type_in_signature_mismatch.carbon:[[@LINE-7]]:3: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: fn F[self: Self](v: V) -> V; - // CHECK:STDERR: ^~~~ + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fn F[self: Self](v: {.x: ()}) -> {.x: ()} { return v; } } @@ -2256,10 +2263,12 @@ fn F() { // CHECK:STDOUT: %J.impl_witness: = impl_witness @E.%J.impl_witness_table [concrete] // CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete] // CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete] -// CHECK:STDOUT: %F.type.b84: type = fn_type @F.2 [concrete] -// CHECK:STDOUT: %F.b07: %F.type.b84 = struct_value () [concrete] -// CHECK:STDOUT: %J.facet.bd9: %J.type = facet_value %E, (%J.impl_witness) [concrete] +// CHECK:STDOUT: %F.type.b842fd.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.b07d12.1: %F.type.b842fd.1 = struct_value () [concrete] +// CHECK:STDOUT: %J.facet.f43: %J.type = facet_value %E, (%J.impl_witness) [concrete] // CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %F.type.b842fd.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.b07d12.2: %F.type.b842fd.2 = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] @@ -2326,7 +2335,7 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %Self.ref as %.loc9_20 { -// CHECK:STDOUT: %F.decl: %F.type.b84 = fn_decl @F.2 [concrete = constants.%F.b07] { +// CHECK:STDOUT: %F.decl.loc24_21.1: %F.type.b842fd.1 = fn_decl @F.2 [concrete = constants.%F.b07d12.1] { // CHECK:STDOUT: %u.patt: = binding_pattern u [concrete] // CHECK:STDOUT: %u.param_patt: = value_param_pattern %u.patt, call_param0 [concrete] // CHECK:STDOUT: %return.patt: = return_slot_pattern [concrete] @@ -2343,10 +2352,21 @@ fn F() { // CHECK:STDOUT: %return.param: ref = out_param call_param1 // CHECK:STDOUT: %return: ref = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc24_21.2: %F.type.b842fd.2 = fn_decl @F.3 [concrete = constants.%F.b07d12.2] { +// CHECK:STDOUT: %u.patt: %pattern_type.7ce = binding_pattern u [concrete] +// CHECK:STDOUT: %u.param_patt: %pattern_type.7ce = value_param_pattern %u.patt, call_param0 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %u.param: %i32 = value_param call_param0 +// CHECK:STDOUT: %u: %i32 = bind_name u, %u.param +// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param1 +// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .U = -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc24_21.1 // CHECK:STDOUT: witness = @E.%J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: @@ -2366,7 +2386,7 @@ fn F() { // CHECK:STDOUT: requirement_rewrite %impl.elem0, %i32 // CHECK:STDOUT: } // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, ), @impl [concrete] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, @impl.%F.decl.loc24_21.2), @impl [concrete] // CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness] // CHECK:STDOUT: %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] @@ -2397,6 +2417,13 @@ fn F() { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%u.param: %i32) -> %i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %u.ref: %i32 = name_ref u, %u.param +// CHECK:STDOUT: %F.call: init = call @impl.%F.decl.loc24_21.1() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @U(constants.%Self.ccd) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @U(constants.%J.facet.521) {} @@ -2410,8 +2437,8 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: specific @U(constants.%J.facet.330) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%J.facet.bd9) { -// CHECK:STDOUT: %Self => constants.%J.facet.bd9 +// CHECK:STDOUT: specific @F.1(constants.%J.facet.f43) { +// CHECK:STDOUT: %Self => constants.%J.facet.f43 // CHECK:STDOUT: %J.lookup_impl_witness => constants.%J.impl_witness // CHECK:STDOUT: %impl.elem0.loc5_11.1 => constants.%i32 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.7ce @@ -2437,20 +2464,24 @@ fn F() { // CHECK:STDOUT: %impl.elem0: type = impl_witness_access %J2.lookup_impl_witness, element0 [symbolic_self] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %J2_where.type.9e1: type = facet_type <@J2 where %impl.elem0 = %empty_struct_type> [concrete] -// CHECK:STDOUT: %J2.impl_witness.1aa: = impl_witness file.%J2.impl_witness_table.loc22 [concrete] +// CHECK:STDOUT: %J2.impl_witness.6a9: = impl_witness file.%J2.impl_witness_table.loc22 [concrete] // CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] // CHECK:STDOUT: %pattern_type.a96: type = pattern_type %empty_struct_type [concrete] -// CHECK:STDOUT: %F.type.f40: type = fn_type @F.2 [concrete] -// CHECK:STDOUT: %F.214: %F.type.f40 = struct_value () [concrete] -// CHECK:STDOUT: %J2.facet.af8: %J2.type = facet_value %empty_tuple.type, (%J2.impl_witness.1aa) [concrete] +// CHECK:STDOUT: %F.type.f405c5.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.214a71.1: %F.type.f405c5.1 = struct_value () [concrete] +// CHECK:STDOUT: %J2.facet.86f: %J2.type = facet_value %empty_tuple.type, (%J2.impl_witness.6a9) [concrete] +// CHECK:STDOUT: %F.type.f405c5.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.214a71.2: %F.type.f405c5.2 = struct_value () [concrete] // CHECK:STDOUT: %C2: type = class_type @C2 [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %J2_where.type.df9: type = facet_type <@J2 where %impl.elem0 = %C2> [concrete] -// CHECK:STDOUT: %J2.impl_witness.774: = impl_witness file.%J2.impl_witness_table.loc31 [concrete] +// CHECK:STDOUT: %J2.impl_witness.267: = impl_witness file.%J2.impl_witness_table.loc38 [concrete] // CHECK:STDOUT: %pattern_type.838: type = pattern_type %C2 [concrete] -// CHECK:STDOUT: %F.type.05d: type = fn_type @F.3 [concrete] -// CHECK:STDOUT: %F.bfa: %F.type.05d = struct_value () [concrete] -// CHECK:STDOUT: %J2.facet.eed: %J2.type = facet_value %C2, (%J2.impl_witness.774) [concrete] +// CHECK:STDOUT: %F.type.05d6a0.1: type = fn_type @F.4 [concrete] +// CHECK:STDOUT: %F.bfa759.1: %F.type.05d6a0.1 = struct_value () [concrete] +// CHECK:STDOUT: %J2.facet.c3f: %J2.type = facet_value %C2, (%J2.impl_witness.267) [concrete] +// CHECK:STDOUT: %F.type.05d6a0.2: type = fn_type @F.5 [concrete] +// CHECK:STDOUT: %F.bfa759.2: %F.type.05d6a0.2 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -2484,27 +2515,27 @@ fn F() { // CHECK:STDOUT: requirement_rewrite %impl.elem0, %.loc22_28.2 // CHECK:STDOUT: } // CHECK:STDOUT: } -// CHECK:STDOUT: %J2.impl_witness_table.loc22 = impl_witness_table (%impl_witness_assoc_constant.loc22, ), @impl.4e9 [concrete] -// CHECK:STDOUT: %J2.impl_witness.loc22: = impl_witness %J2.impl_witness_table.loc22 [concrete = constants.%J2.impl_witness.1aa] +// CHECK:STDOUT: %J2.impl_witness_table.loc22 = impl_witness_table (%impl_witness_assoc_constant.loc22, @impl.4e9.%F.decl.loc30_33.2), @impl.4e9 [concrete] +// CHECK:STDOUT: %J2.impl_witness.loc22: = impl_witness %J2.impl_witness_table.loc22 [concrete = constants.%J2.impl_witness.6a9] // CHECK:STDOUT: %impl_witness_assoc_constant.loc22: type = impl_witness_assoc_constant constants.%empty_struct_type [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %C2.decl: type = class_decl @C2 [concrete = constants.%C2] {} {} // CHECK:STDOUT: impl_decl @impl.8b3 [concrete] {} { -// CHECK:STDOUT: %C2.ref.loc31_6: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] +// CHECK:STDOUT: %C2.ref.loc38_6: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] // CHECK:STDOUT: %J2.ref: type = name_ref J2, file.%J2.decl [concrete = constants.%J2.type] // CHECK:STDOUT: %.Self: %J2.type = bind_symbolic_name .Self [symbolic_self = constants.%.Self] // CHECK:STDOUT: %.Self.ref: %J2.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self] // CHECK:STDOUT: %U2.ref: %J2.assoc_type = name_ref U2, @U2.%assoc0 [concrete = constants.%assoc0] // CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %.loc31_21: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %.loc38_21: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.as_type] // CHECK:STDOUT: %impl.elem0: type = impl_witness_access constants.%J2.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0] -// CHECK:STDOUT: %C2.ref.loc31_27: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] -// CHECK:STDOUT: %.loc31_15: type = where_expr %.Self [concrete = constants.%J2_where.type.df9] { -// CHECK:STDOUT: requirement_rewrite %impl.elem0, %C2.ref.loc31_27 +// CHECK:STDOUT: %C2.ref.loc38_27: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] +// CHECK:STDOUT: %.loc38_15: type = where_expr %.Self [concrete = constants.%J2_where.type.df9] { +// CHECK:STDOUT: requirement_rewrite %impl.elem0, %C2.ref.loc38_27 // CHECK:STDOUT: } // CHECK:STDOUT: } -// CHECK:STDOUT: %J2.impl_witness_table.loc31 = impl_witness_table (%impl_witness_assoc_constant.loc31, ), @impl.8b3 [concrete] -// CHECK:STDOUT: %J2.impl_witness.loc31: = impl_witness %J2.impl_witness_table.loc31 [concrete = constants.%J2.impl_witness.774] -// CHECK:STDOUT: %impl_witness_assoc_constant.loc31: type = impl_witness_assoc_constant constants.%C2 [concrete = constants.%C2] +// CHECK:STDOUT: %J2.impl_witness_table.loc38 = impl_witness_table (%impl_witness_assoc_constant.loc38, @impl.8b3.%F.decl.loc39_33.2), @impl.8b3 [concrete] +// CHECK:STDOUT: %J2.impl_witness.loc38: = impl_witness %J2.impl_witness_table.loc38 [concrete = constants.%J2.impl_witness.267] +// CHECK:STDOUT: %impl_witness_assoc_constant.loc38: type = impl_witness_assoc_constant constants.%C2 [concrete = constants.%C2] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @J2 { @@ -2548,7 +2579,7 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl.4e9: %.loc22_7.2 as %.loc22_15 { -// CHECK:STDOUT: %F.decl: %F.type.f40 = fn_decl @F.2 [concrete = constants.%F.214] { +// CHECK:STDOUT: %F.decl.loc30_33.1: %F.type.f405c5.1 = fn_decl @F.2 [concrete = constants.%F.214a71.1] { // CHECK:STDOUT: %self.patt: %pattern_type.cb1 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %z.patt: %pattern_type.a96 = binding_pattern z [concrete] @@ -2556,28 +2587,41 @@ fn F() { // CHECK:STDOUT: %return.patt: %pattern_type.a96 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.a96 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc23_31.1: %empty_struct_type = struct_literal () -// CHECK:STDOUT: %.loc23_31.2: type = converted %.loc23_31.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %.loc30_31.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc30_31.2: type = converted %.loc30_31.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type] // CHECK:STDOUT: %self.param: %empty_tuple.type = value_param call_param0 // CHECK:STDOUT: %Self.ref: type = name_ref Self, @impl.4e9.%.loc22_7.2 [concrete = constants.%empty_tuple.type] // CHECK:STDOUT: %self: %empty_tuple.type = bind_name self, %self.param // CHECK:STDOUT: %z.param: %empty_struct_type = value_param call_param1 -// CHECK:STDOUT: %.loc23_24.1: type = splice_block %.loc23_24.3 [concrete = constants.%empty_struct_type] { -// CHECK:STDOUT: %.loc23_24.2: %empty_struct_type = struct_literal () -// CHECK:STDOUT: %.loc23_24.3: type = converted %.loc23_24.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %.loc30_24.1: type = splice_block %.loc30_24.3 [concrete = constants.%empty_struct_type] { +// CHECK:STDOUT: %.loc30_24.2: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc30_24.3: type = converted %.loc30_24.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type] // CHECK:STDOUT: } // CHECK:STDOUT: %z: %empty_struct_type = bind_name z, %z.param // CHECK:STDOUT: %return.param: ref %empty_struct_type = out_param call_param2 // CHECK:STDOUT: %return: ref %empty_struct_type = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc30_33.2: %F.type.f405c5.2 = fn_decl @F.3 [concrete = constants.%F.214a71.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.cb1 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.param_patt: = value_param_pattern , call_param1 [concrete] +// CHECK:STDOUT: %return.patt: = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %empty_tuple.type = value_param call_param0 +// CHECK:STDOUT: %self: %empty_tuple.type = bind_name self, %self.param +// CHECK:STDOUT: %.param: = value_param call_param1 +// CHECK:STDOUT: %return.param: ref = out_param call_param2 +// CHECK:STDOUT: %return: ref = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc30_33.1 // CHECK:STDOUT: witness = file.%J2.impl_witness.loc22 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl.8b3: %C2.ref.loc31_6 as %.loc31_15 { -// CHECK:STDOUT: %F.decl: %F.type.05d = fn_decl @F.3 [concrete = constants.%F.bfa] { +// CHECK:STDOUT: impl @impl.8b3: %C2.ref.loc38_6 as %.loc38_15 { +// CHECK:STDOUT: %F.decl.loc39_33.1: %F.type.05d6a0.1 = fn_decl @F.4 [concrete = constants.%F.bfa759.1] { // CHECK:STDOUT: %self.patt: %pattern_type.838 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.838 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %z.patt: %pattern_type.838 = binding_pattern z [concrete] @@ -2585,27 +2629,40 @@ fn F() { // CHECK:STDOUT: %return.patt: %pattern_type.838 = return_slot_pattern [concrete] // CHECK:STDOUT: %return.param_patt: %pattern_type.838 = out_param_pattern %return.patt, call_param2 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %C2.ref.loc32_30: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] +// CHECK:STDOUT: %C2.ref.loc39_30: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] // CHECK:STDOUT: %self.param: %C2 = value_param call_param0 -// CHECK:STDOUT: %Self.ref: type = name_ref Self, @impl.8b3.%C2.ref.loc31_6 [concrete = constants.%C2] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, @impl.8b3.%C2.ref.loc38_6 [concrete = constants.%C2] // CHECK:STDOUT: %self: %C2 = bind_name self, %self.param // CHECK:STDOUT: %z.param: %C2 = value_param call_param1 -// CHECK:STDOUT: %C2.ref.loc32_23: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] +// CHECK:STDOUT: %C2.ref.loc39_23: type = name_ref C2, file.%C2.decl [concrete = constants.%C2] // CHECK:STDOUT: %z: %C2 = bind_name z, %z.param // CHECK:STDOUT: %return.param: ref %C2 = out_param call_param2 // CHECK:STDOUT: %return: ref %C2 = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc39_33.2: %F.type.05d6a0.2 = fn_decl @F.5 [concrete = constants.%F.bfa759.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.838 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.838 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %.param_patt: = value_param_pattern , call_param1 [concrete] +// CHECK:STDOUT: %return.patt: = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %C2 = value_param call_param0 +// CHECK:STDOUT: %self: %C2 = bind_name self, %self.param +// CHECK:STDOUT: %.param: = value_param call_param1 +// CHECK:STDOUT: %return.param: ref = out_param call_param2 +// CHECK:STDOUT: %return: ref = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .C2 = -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = file.%J2.impl_witness.loc31 +// CHECK:STDOUT: .F = %F.decl.loc39_33.1 +// CHECK:STDOUT: witness = file.%J2.impl_witness.loc38 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C2 { -// CHECK:STDOUT: %.loc28_10: %empty_struct_type = struct_literal () -// CHECK:STDOUT: %.loc28_11: type = converted %.loc28_10, constants.%empty_struct_type [concrete = constants.%empty_struct_type] -// CHECK:STDOUT: adapt_decl %.loc28_11 [concrete] +// CHECK:STDOUT: %.loc35_10: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc35_11: type = converted %.loc35_10, constants.%empty_struct_type [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: adapt_decl %.loc35_11 [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type] // CHECK:STDOUT: complete_type_witness = %complete_type // CHECK:STDOUT: @@ -2627,12 +2684,28 @@ fn F() { // CHECK:STDOUT: return %z.ref // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.3(%self.param: %C2, %z.param: %C2) -> %C2 { +// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %.param: ) -> { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %empty_tuple.type = name_ref self, %self.param +// CHECK:STDOUT: %.ref: = name_ref , %.param [concrete = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.4(%self.param: %C2, %z.param: %C2) -> %C2 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %self.ref: %C2 = name_ref self, %self // CHECK:STDOUT: return %self.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @F.5(%self.param: %C2, %.param: ) -> { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %C2 = name_ref self, %self.param +// CHECK:STDOUT: %F.bound: = bound_method %self.ref, @impl.8b3.%F.decl.loc39_33.1 +// CHECK:STDOUT: %.ref: = name_ref , %.param [concrete = ] +// CHECK:STDOUT: %F.call: init %C2 = call %F.bound(%self.ref, ) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @U2(constants.%Self) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%Self) { @@ -2643,14 +2716,14 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: specific @U2(constants.%J2.facet.e30) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%J2.facet.af8) { -// CHECK:STDOUT: %Self => constants.%J2.facet.af8 +// CHECK:STDOUT: specific @F.1(constants.%J2.facet.86f) { +// CHECK:STDOUT: %Self => constants.%J2.facet.86f // CHECK:STDOUT: %Self.as_type.loc19_14.1 => constants.%empty_tuple.type // CHECK:STDOUT: %pattern_type => constants.%pattern_type.cb1 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%J2.facet.eed) { -// CHECK:STDOUT: %Self => constants.%J2.facet.eed +// CHECK:STDOUT: specific @F.1(constants.%J2.facet.c3f) { +// CHECK:STDOUT: %Self => constants.%J2.facet.c3f // CHECK:STDOUT: %Self.as_type.loc19_14.1 => constants.%C2 // CHECK:STDOUT: %pattern_type => constants.%pattern_type.838 // CHECK:STDOUT: } @@ -2683,10 +2756,12 @@ fn F() { // CHECK:STDOUT: %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete] // CHECK:STDOUT: %struct_type.x: type = struct_type {.x: %empty_tuple.type} [concrete] // CHECK:STDOUT: %pattern_type.414: type = pattern_type %struct_type.x [concrete] -// CHECK:STDOUT: %F.type.c52: type = fn_type @F.2 [concrete] -// CHECK:STDOUT: %F.5eb: %F.type.c52 = struct_value () [concrete] -// CHECK:STDOUT: %K.facet.77f: %K.type = facet_value %empty_tuple.type, (%K.impl_witness) [concrete] +// CHECK:STDOUT: %F.type.c5249c.1: type = fn_type @F.2 [concrete] +// CHECK:STDOUT: %F.5eb4dd.1: %F.type.c5249c.1 = struct_value () [concrete] +// CHECK:STDOUT: %K.facet.e32: %K.type = facet_value %empty_tuple.type, (%K.impl_witness) [concrete] // CHECK:STDOUT: %pattern_type.e85: type = pattern_type %struct_type.a [concrete] +// CHECK:STDOUT: %F.type.c5249c.2: type = fn_type @F.3 [concrete] +// CHECK:STDOUT: %F.5eb4dd.2: %F.type.c5249c.2 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -2720,7 +2795,7 @@ fn F() { // CHECK:STDOUT: requirement_rewrite %impl.elem0, %struct_type.a // CHECK:STDOUT: } // CHECK:STDOUT: } -// CHECK:STDOUT: %K.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, ), @impl [concrete] +// CHECK:STDOUT: %K.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, @impl.%F.decl.loc16_45.2), @impl [concrete] // CHECK:STDOUT: %K.impl_witness: = impl_witness %K.impl_witness_table [concrete = constants.%K.impl_witness] // CHECK:STDOUT: %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%struct_type.a [concrete = constants.%struct_type.a] // CHECK:STDOUT: } @@ -2770,7 +2845,7 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %.loc8_7.2 as %.loc8_14 { -// CHECK:STDOUT: %F.decl: %F.type.c52 = fn_decl @F.2 [concrete = constants.%F.5eb] { +// CHECK:STDOUT: %F.decl.loc16_45.1: %F.type.c5249c.1 = fn_decl @F.2 [concrete = constants.%F.5eb4dd.1] { // CHECK:STDOUT: %self.patt: %pattern_type.cb1 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: %v.patt: %pattern_type.414 = binding_pattern v [concrete] @@ -2794,9 +2869,24 @@ fn F() { // CHECK:STDOUT: %return.param: ref %struct_type.x = out_param call_param2 // CHECK:STDOUT: %return: ref %struct_type.x = return_slot %return.param // CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc16_45.2: %F.type.c5249c.2 = fn_decl @F.3 [concrete = constants.%F.5eb4dd.2] { +// CHECK:STDOUT: %self.patt: %pattern_type.cb1 = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %v.patt: %pattern_type.e85 = binding_pattern v [concrete] +// CHECK:STDOUT: %v.param_patt: %pattern_type.e85 = value_param_pattern %v.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.e85 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.e85 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: %empty_tuple.type = value_param call_param0 +// CHECK:STDOUT: %self: %empty_tuple.type = bind_name self, %self.param +// CHECK:STDOUT: %v.param: %struct_type.a = value_param call_param1 +// CHECK:STDOUT: %v: %struct_type.a = bind_name v, %v.param +// CHECK:STDOUT: %return.param: ref %struct_type.a = out_param call_param2 +// CHECK:STDOUT: %return: ref %struct_type.a = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .F = %F.decl.loc16_45.1 // CHECK:STDOUT: witness = file.%K.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: @@ -2817,6 +2907,13 @@ fn F() { // CHECK:STDOUT: return %v.ref // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %v.param: %struct_type.a) -> %struct_type.a { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: %empty_tuple.type = name_ref self, %self.param +// CHECK:STDOUT: %v.ref: %struct_type.a = name_ref v, %v.param +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @V(constants.%Self) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @V(constants.%K.facet.589) {} @@ -2832,8 +2929,8 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: specific @V(constants.%K.facet.b09) {} // CHECK:STDOUT: -// CHECK:STDOUT: specific @F.1(constants.%K.facet.77f) { -// CHECK:STDOUT: %Self => constants.%K.facet.77f +// CHECK:STDOUT: specific @F.1(constants.%K.facet.e32) { +// CHECK:STDOUT: %Self => constants.%K.facet.e32 // CHECK:STDOUT: %Self.as_type.loc5_14.1 => constants.%empty_tuple.type // CHECK:STDOUT: %pattern_type.loc5_8 => constants.%pattern_type.cb1 // CHECK:STDOUT: %K.lookup_impl_witness => constants.%K.impl_witness diff --git a/toolchain/check/thunk.cpp b/toolchain/check/thunk.cpp new file mode 100644 index 000000000000..16cde3576f0a --- /dev/null +++ b/toolchain/check/thunk.cpp @@ -0,0 +1,410 @@ +// 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 + +#include "toolchain/check/thunk.h" + +#include "toolchain/base/kind_switch.h" +#include "toolchain/check/call.h" +#include "toolchain/check/diagnostic_helpers.h" +#include "toolchain/check/function.h" +#include "toolchain/check/generic.h" +#include "toolchain/check/inst.h" +#include "toolchain/check/member_access.h" +#include "toolchain/check/pattern.h" +#include "toolchain/check/pattern_match.h" +#include "toolchain/check/pointer_dereference.h" +#include "toolchain/check/return.h" +#include "toolchain/check/type.h" +#include "toolchain/diagnostics/diagnostic.h" +#include "toolchain/sem_ir/function.h" +#include "toolchain/sem_ir/generic.h" +#include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/pattern.h" +#include "toolchain/sem_ir/typed_insts.h" + +namespace Carbon::Check { + +// Adds a pattern instruction for a thunk, copying the location from an existing +// instruction. +static auto RebuildPatternInst(Context& context, SemIR::InstId orig_inst_id, + SemIR::Inst new_inst) -> SemIR::InstId { + // Ensure we built the same kind of instruction. In particular, this ensures + // that the location of the old instruction can be reused for the new one. + CARBON_CHECK(context.insts().Get(orig_inst_id).kind() == new_inst.kind(), + "Rebuilt pattern with the wrong kind: {0} -> {1}", + context.insts().Get(orig_inst_id), new_inst); + return AddPatternInst(context, SemIR::LocIdAndInst::UncheckedLoc( + SemIR::LocId(orig_inst_id), new_inst)); +} + +// Wrapper to allow the type to be specified as a template argument for API +// consistency with `AddInst`. +template +static auto RebuildPatternInst(Context& context, SemIR::InstId orig_inst_id, + InstT new_inst) -> SemIR::InstId { + return RebuildPatternInst(context, orig_inst_id, SemIR::Inst(new_inst)); +} + +// Makes a copy of the given binding pattern, with its type adjusted to be +// `new_pattern_type_id`. +static auto CloneBindingPattern(Context& context, SemIR::InstId pattern_id, + SemIR::AnyBindingPattern pattern, + SemIR::TypeId new_pattern_type_id) + -> SemIR::InstId { + bool is_generic = pattern.kind == SemIR::SymbolicBindingPattern::Kind; + auto entity_name = context.entity_names().Get(pattern.entity_name_id); + CARBON_CHECK(is_generic == entity_name.bind_index().has_value()); + + // Get the transformed type of the binding. + if (new_pattern_type_id == SemIR::ErrorInst::TypeId) { + return SemIR::ErrorInst::InstId; + } + auto type_inst_id = context.types() + .GetAs(new_pattern_type_id) + .scrutinee_type_inst_id; + auto type_id = context.types().GetTypeIdForTypeInstId(type_inst_id); + auto type_expr_region_id = context.sem_ir().expr_regions().Add( + {.block_ids = {SemIR::InstBlockId::Empty}, .result_id = type_inst_id}); + + // Rebuild the binding pattern. + return AddBindingPattern(context, SemIR::LocId(pattern_id), + entity_name.name_id, type_id, type_expr_region_id, + is_generic, entity_name.is_template) + .pattern_id; +} + +// Makes a copy of the given pattern instruction, substituting values from a +// specific as needed. The resulting pattern behaves like a newly-created +// pattern, so is suitable for running `CalleePatternMatch` against. +static auto ClonePattern(Context& context, SemIR::SpecificId specific_id, + SemIR::InstId pattern_id) -> SemIR::InstId { + if (!pattern_id.has_value()) { + return SemIR::InstId::None; + } + + auto get_type = [&](SemIR::InstId inst_id) -> SemIR::TypeId { + return SemIR::GetTypeOfInstInSpecific(context.sem_ir(), specific_id, + inst_id); + }; + + auto pattern = context.insts().Get(pattern_id); + + // Decompose the pattern. The forms we allow for patterns in a function + // parameter list are currently fairly restrictive. + + // Optional `addr`, only for `self`. + auto [addr, addr_id] = context.insts().TryUnwrap( + pattern, pattern_id, &SemIR::AddrPattern::inner_id); + + // Optional parameter pattern. + auto [param, param_id] = context.insts().TryUnwrap( + pattern, pattern_id, &SemIR::AnyParamPattern::subpattern_id); + + // Finally, either a binding pattern or a return slot pattern. + auto new_pattern_id = SemIR::InstId::None; + if (auto binding = pattern.TryAs()) { + new_pattern_id = CloneBindingPattern(context, pattern_id, *binding, + get_type(pattern_id)); + } else if (auto return_slot = pattern.TryAs()) { + new_pattern_id = RebuildPatternInst( + context, pattern_id, + {.type_id = get_type(pattern_id), + .type_inst_id = SemIR::TypeInstId::None}); + } else { + CARBON_CHECK(pattern.Is(), + "Unexpected pattern {0} in function signature", pattern); + return SemIR::ErrorInst::InstId; + } + + // Rebuild parameter. + if (param) { + new_pattern_id = RebuildPatternInst( + context, param_id, + {.kind = param->kind, + .type_id = get_type(param_id), + .subpattern_id = new_pattern_id, + .index = SemIR::CallParamIndex::None}); + } + + // Rebuild `addr`. + if (addr) { + new_pattern_id = RebuildPatternInst( + context, addr_id, + {.type_id = get_type(addr_id), .inner_id = new_pattern_id}); + } + + return new_pattern_id; +} + +static auto ClonePatternBlock(Context& context, SemIR::SpecificId specific_id, + SemIR::InstBlockId inst_block_id) + -> SemIR::InstBlockId { + if (!inst_block_id.has_value()) { + return SemIR::InstBlockId::None; + } + return context.inst_blocks().Transform( + inst_block_id, [&](SemIR::InstId inst_id) { + return ClonePattern(context, specific_id, inst_id); + }); +} + +static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id, + SemIR::FunctionId signature_id, + SemIR::SpecificId signature_specific_id, + SemIR::FunctionId callee_id) + -> std::pair { + StartGenericDecl(context); + + // Clone the signature. Note that we re-get the function after each of these, + // because they might trigger imports that invalidate the function. + context.pattern_block_stack().Push(); + auto implicit_param_patterns_id = ClonePatternBlock( + context, signature_specific_id, + context.functions().Get(signature_id).implicit_param_patterns_id); + auto param_patterns_id = ClonePatternBlock( + context, signature_specific_id, + context.functions().Get(signature_id).param_patterns_id); + auto return_slot_pattern_id = ClonePattern( + context, signature_specific_id, + context.functions().Get(signature_id).return_slot_pattern_id); + auto self_param_id = FindSelfPattern(context, implicit_param_patterns_id); + auto pattern_block_id = context.pattern_block_stack().Pop(); + + // Perform callee-side pattern matching to rebuild the parameter list. + context.inst_block_stack().Push(); + auto call_params_id = + CalleePatternMatch(context, implicit_param_patterns_id, param_patterns_id, + return_slot_pattern_id); + auto decl_block_id = context.inst_block_stack().Pop(); + + // Create the `FunctionDecl` instruction. + SemIR::FunctionDecl function_decl = {SemIR::TypeId::None, + SemIR::FunctionId::None, decl_block_id}; + auto decl_id = AddPlaceholderInst( + context, SemIR::LocIdAndInst::UncheckedLoc(loc_id, function_decl)); + auto generic_id = BuildGenericDecl(context, decl_id); + + // Create the `Function` object. + auto& signature = context.functions().Get(signature_id); + auto& callee = context.functions().Get(callee_id); + function_decl.function_id = context.functions().Add( + SemIR::Function{{.name_id = signature.name_id, + .parent_scope_id = callee.parent_scope_id, + .generic_id = generic_id, + .first_param_node_id = signature.first_param_node_id, + .last_param_node_id = signature.last_param_node_id, + .pattern_block_id = pattern_block_id, + .implicit_param_patterns_id = implicit_param_patterns_id, + .param_patterns_id = param_patterns_id, + .is_extern = false, + .extern_library_id = SemIR::LibraryNameId::None, + .non_owning_decl_id = SemIR::InstId::None, + .first_owning_decl_id = decl_id, + .definition_id = decl_id}, + {.call_params_id = call_params_id, + .return_slot_pattern_id = return_slot_pattern_id, + .virtual_modifier = callee.virtual_modifier, + .virtual_index = callee.virtual_index, + .self_param_id = self_param_id}}); + function_decl.type_id = + GetFunctionType(context, function_decl.function_id, + context.scope_stack().PeekSpecificId()); + ReplaceInstBeforeConstantUse(context, decl_id, function_decl); + return {function_decl.function_id, decl_id}; +} + +// Build an expression that names the value matched by a pattern. +static auto BuildPatternRef(Context& context, SemIR::FunctionId function_id, + SemIR::InstId pattern_id) -> SemIR::InstId { + auto pattern = context.insts().Get(pattern_id); + + auto addr = context.insts() + .TryUnwrap(pattern, pattern_id, &SemIR::AddrPattern::inner_id) + .first; + + auto pattern_ref_id = SemIR::InstId::None; + if (auto value_param = pattern.TryAs()) { + // Build a reference to this parameter. + auto call_param_id = context.inst_blocks().Get( + context.functions() + .Get(function_id) + .call_params_id)[value_param->index.index]; + // Use a pretty name for the `name_ref`. While it's suspicious to use a + // pretty name in the IR like this, the only reason we include a name at + // all here is to make the formatted SemIR more readable. + pattern_ref_id = AddInst( + context, SemIR::LocId(pattern_id), + {.type_id = context.insts().Get(call_param_id).type_id(), + .name_id = SemIR::GetPrettyNameFromPatternId( + context.sem_ir(), value_param->subpattern_id), + .value_id = call_param_id}); + } else { + if (pattern_id != SemIR::ErrorInst::InstId) { + context.TODO( + pattern_id, + "don't know how to build reference to this pattern in thunk"); + } + return SemIR::ErrorInst::InstId; + } + + if (addr) { + pattern_ref_id = PerformPointerDereference( + context, SemIR::LocId(pattern_id), pattern_ref_id, [](SemIR::TypeId) { + CARBON_FATAL("addr subpattern is not a pointer"); + }); + } + + return pattern_ref_id; +} + +// Build a call to a function that forwards the arguments of the enclosing +// function, for use when constructing a thunk. +static auto BuildThunkCall(Context& context, SemIR::FunctionId function_id, + SemIR::InstId callee_id) -> SemIR::InstId { + auto loc_id = SemIR::LocId(callee_id); + auto& function = context.functions().Get(function_id); + + // If we have a self parameter, form `self.`. + if (function.self_param_id.has_value()) { + callee_id = PerformCompoundMemberAccess( + context, loc_id, + BuildPatternRef(context, function_id, function.self_param_id), + callee_id); + } + + // Form an argument list. + llvm::SmallVector args; + for (auto pattern_id : + context.inst_blocks().Get(function.param_patterns_id)) { + args.push_back(BuildPatternRef(context, function_id, pattern_id)); + } + + return PerformCall(context, loc_id, callee_id, args); +} + +static auto HasDeclaredReturnType(Context& context, + SemIR::FunctionId function_id) -> bool { + return context.functions() + .Get(function_id) + .return_slot_pattern_id.has_value(); +} + +// Given a declaration of a thunk and the function that it should call, build +// the thunk body. +static auto BuildThunkDefinition(Context& context, + SemIR::FunctionId signature_id, + SemIR::FunctionId function_id, + SemIR::InstId thunk_id, + SemIR::InstId callee_id) { + // TODO: Improve the diagnostics produced here. Specifically, it would likely + // be better for the primary error message to be that we tried to produce a + // thunk because of a type mismatch, but couldn't, with notes explaining + // why, rather than the primary error message being whatever went wrong + // building the thunk. + + { + // The check below produces diagnostics referring to the signature, so also + // note the callee. + Diagnostics::AnnotationScope annot_scope( + &context.emitter(), [&](DiagnosticBuilder& builder) { + CARBON_DIAGNOSTIC(ThunkCallee, Note, + "while building thunk calling this function"); + builder.Note(callee_id, ThunkCallee); + }); + + CheckFunctionDefinitionSignature(context, function_id); + } + + // TODO: This duplicates much of the handling for FunctionDefinitionStart and + // FunctionDefinition parse nodes. Consider refactoring. + context.scope_stack().PushForFunctionBody(thunk_id); + context.inst_block_stack().Push(); + context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd()); + StartGenericDefinition(context, + context.functions().Get(function_id).generic_id); + + // The checks below produce diagnostics pointing at the callee, so also note + // the signature. + Diagnostics::AnnotationScope annot_scope( + &context.emitter(), [&](DiagnosticBuilder& builder) { + CARBON_DIAGNOSTIC( + ThunkSignature, Note, + "while building thunk to match the signature of this function"); + builder.Note(context.functions().Get(signature_id).first_owning_decl_id, + ThunkSignature); + }); + + auto call_id = BuildThunkCall(context, function_id, callee_id); + if (HasDeclaredReturnType(context, function_id)) { + BuildReturnWithExpr(context, SemIR::LocId(callee_id), call_id); + } else { + BuildReturnWithNoExpr(context, SemIR::LocId(callee_id)); + } + + context.inst_block_stack().Pop(); + context.scope_stack().Pop(); + + auto& function = context.functions().Get(function_id); + function.body_block_ids = context.region_stack().PopRegion(); + FinishGenericDefinition(context, function.generic_id); +} + +auto BuildThunk(Context& context, SemIR::FunctionId signature_id, + SemIR::SpecificId signature_specific_id, + SemIR::InstId callee_id) -> SemIR::InstId { + auto callee = SemIR::GetCalleeFunction(context.sem_ir(), callee_id); + + // Check whether we can use the given function without a thunk. + // TODO: For virtual functions, we want different rules for checking `self`. + // TODO: This is too strict; for example, we should not compare parameter + // names here. + if (CheckFunctionTypeMatches( + context, context.functions().Get(callee.function_id), + context.functions().Get(signature_id), signature_specific_id, + /*check_syntax=*/false, /*check_self=*/true, /*diagnose=*/false)) { + return callee_id; + } + + // From P3763: + // If the function in the interface does not have a return type, the + // program is invalid if the function in the impl specifies a return type. + // + // Call into the redeclaration checking logic to produce a suitable error. + // + // TODO: Consider a different rule: always use an explicit return type for the + // thunk, and always convert the result of the wrapped call to the return type + // of the thunk. + if (!HasDeclaredReturnType(context, signature_id) && + HasDeclaredReturnType(context, callee.function_id)) { + bool success = CheckFunctionReturnTypeMatches( + context, context.functions().Get(callee.function_id), + context.functions().Get(signature_id), signature_specific_id); + CARBON_CHECK(!success, "Return type unexpectedly matches"); + return SemIR::ErrorInst::InstId; + } + + // Create a scope for the function's parameters and generic parameters. + context.scope_stack().PushForDeclName(); + + // We can't use the function directly. Build a thunk. + // TODO: Check for and diagnose obvious reasons why this will fail, such as + // arity mismatch, before trying to build the thunk. + auto [function_id, thunk_id] = + CloneFunctionDecl(context, SemIR::LocId(callee_id), signature_id, + signature_specific_id, callee.function_id); + + // Define the thunk. + // TODO: We should delay doing this until we get to the end of the enclosing + // deferred definition scope, if there is one. For example, an `impl` inside a + // `class` definition should have its thunks defined at the end of the class, + // like they would be if they were defined inline. + BuildThunkDefinition(context, signature_id, function_id, thunk_id, callee_id); + + context.scope_stack().Pop(); + + return thunk_id; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/thunk.h b/toolchain/check/thunk.h new file mode 100644 index 000000000000..61960b8116d3 --- /dev/null +++ b/toolchain/check/thunk.h @@ -0,0 +1,22 @@ +// 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 + +#ifndef CARBON_TOOLCHAIN_CHECK_THUNK_H_ +#define CARBON_TOOLCHAIN_CHECK_THUNK_H_ + +#include "toolchain/check/context.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +// Given a function signature and a callee function, build a thunk that matches +// the given signature and calls the specified callee. Returns the callee +// unchanged if it can be used directly. +auto BuildThunk(Context& context, SemIR::FunctionId signature_id, + SemIR::SpecificId signature_specific_id, + SemIR::InstId callee_id) -> SemIR::InstId; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_THUNK_H_ diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 65912dc3a3bf..7fff8b467ff0 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -240,6 +240,8 @@ CARBON_DIAGNOSTIC_KIND(InvalidMainRunSignature) CARBON_DIAGNOSTIC_KIND(MissingReturnStatement) CARBON_DIAGNOSTIC_KIND(UnknownBuiltinFunctionName) CARBON_DIAGNOSTIC_KIND(InvalidBuiltinSignature) +CARBON_DIAGNOSTIC_KIND(ThunkSignature) +CARBON_DIAGNOSTIC_KIND(ThunkCallee) CARBON_DIAGNOSTIC_KIND(DestroyFunctionOutsideClass) CARBON_DIAGNOSTIC_KIND(DestroyFunctionMissingSelf) diff --git a/toolchain/sem_ir/block_value_store.h b/toolchain/sem_ir/block_value_store.h index a8dc2d35495b..b66bf5f372aa 100644 --- a/toolchain/sem_ir/block_value_store.h +++ b/toolchain/sem_ir/block_value_store.h @@ -57,6 +57,14 @@ class BlockValueStore : public Yaml::Printable> { return values_.Get(id); } + // Returns a new block formed by applying `transform(elem_id)` to each element + // in the specified block. + template + auto Transform(IdT id, TransformFnT transform) -> IdT { + llvm::SmallVector block(llvm::map_range(Get(id), transform)); + return Add(block); + } + // Adds a block or finds an existing canonical block with the given content, // and returns an ID to reference it. auto AddCanonical(llvm::ArrayRef content) -> IdT { diff --git a/toolchain/sem_ir/function.cpp b/toolchain/sem_ir/function.cpp index b164a450d958..cd05d731c78c 100644 --- a/toolchain/sem_ir/function.cpp +++ b/toolchain/sem_ir/function.cpp @@ -70,23 +70,16 @@ auto Function::GetParamPatternInfoFromPatternId(const File& sem_ir, auto inst_id = pattern_id; auto inst = sem_ir.insts().Get(inst_id); - if (auto addr_pattern = inst.TryAs()) { - inst_id = addr_pattern->inner_id; - inst = sem_ir.insts().Get(inst_id); - } - - auto param_pattern_inst = inst.TryAs(); - if (!param_pattern_inst) { + sem_ir.insts().TryUnwrap(inst, inst_id, &AddrPattern::inner_id); + auto [param_pattern, param_pattern_id] = + sem_ir.insts().TryUnwrap(inst, inst_id, &AnyParamPattern::subpattern_id); + if (!param_pattern) { return std::nullopt; } - auto param_pattern_id = inst_id; - - inst_id = param_pattern_inst->subpattern_id; - inst = sem_ir.insts().Get(inst_id); auto binding_pattern = inst.As(); return {{.inst_id = param_pattern_id, - .inst = *param_pattern_inst, + .inst = *param_pattern, .entity_name_id = binding_pattern.entity_name_id}}; } diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index 2f6c23b95b9f..a072a49b3c54 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -451,6 +451,23 @@ class InstStore { return TryGetAs(inst_id); } + // Attempts to convert the given instruction to the type that contains + // `member`. If it can be converted, the instruction ID and instruction are + // replaced by the unwrapped value of that member, and the converted wrapper + // instruction and its ID are returned. Otherwise returns {nullopt, None}. + template + requires std::derived_from + auto TryUnwrap(Inst& inst, InstId& inst_id, InstIdT InstT::*member) const + -> std::pair, InstId> { + if (auto wrapped_inst = inst.TryAs()) { + auto wrapped_inst_id = inst_id; + inst_id = (*wrapped_inst).*member; + inst = Get(inst_id); + return {wrapped_inst, wrapped_inst_id}; + } + return {std::nullopt, InstId::None}; + } + // Returns a resolved LocId, which will point to a parse node, an import, or // be None. // diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index dc124320870a..62ca9a8afab2 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -1393,23 +1393,20 @@ struct RequireCompleteType { }; struct Return { - static constexpr auto Kind = - InstKind::Return.Define>( - {.ir_name = "return", - .constant_kind = InstConstantKind::Never, - .terminator_kind = TerminatorKind::Terminator}); + static constexpr auto Kind = InstKind::Return.Define( + {.ir_name = "return", + .constant_kind = InstConstantKind::Never, + .terminator_kind = TerminatorKind::Terminator}); // This is a statement, so has no type. }; // A `return expr;` statement. struct ReturnExpr { - static constexpr auto Kind = - InstKind::ReturnExpr.Define( - {.ir_name = "return", - .constant_kind = InstConstantKind::Never, - .terminator_kind = TerminatorKind::Terminator}); + static constexpr auto Kind = InstKind::ReturnExpr.Define( + {.ir_name = "return", + .constant_kind = InstConstantKind::Never, + .terminator_kind = TerminatorKind::Terminator}); // This is a statement, so has no type. InstId expr_id;