diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index adfbfd4f1230..8161bbd6c4fa 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -5,8 +5,10 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/decl_name_stack.h" +#include "toolchain/check/generic.h" #include "toolchain/check/handle.h" #include "toolchain/check/impl.h" +#include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/parse/typed_nodes.h" #include "toolchain/sem_ir/ids.h" @@ -31,11 +33,13 @@ auto HandleParseNode(Context& context, Parse::ImplIntroducerId node_id) // parameters. context.decl_name_stack().PushScopeAndStartName(); + // This might be a generic impl. + StartGenericDecl(context); + // Push a pattern block for the signature of the `forall` (if any). // TODO: Instead use a separate parse node kinds for `impl` and `impl forall`, // and only push a pattern block in `forall` case. context.pattern_block_stack().Push(); - return true; } @@ -44,6 +48,7 @@ auto HandleParseNode(Context& context, Parse::ImplForallId node_id) -> bool { context.node_stack().Pop(); context.node_stack() .PopAndDiscardSoloNodeId(); + RequireGenericParams(context, params_id); context.node_stack().Push(node_id, params_id); return true; } @@ -180,6 +185,56 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node, parent_scope.extended_scopes.push_back(interface.scope_id); } +// Pops the parameters of an `impl`, forming a `NameComponent` with no +// associated name that describes them. +static auto PopImplIntroducerAndParamsAsNameComponent( + Context& context, Parse::AnyImplDeclId end_of_decl_node_id) + -> NameComponent { + auto [implicit_params_loc_id, implicit_params_id] = + context.node_stack().PopWithNodeIdIf(); + + Parse::NodeId first_param_node_id = + context.node_stack().PopForSoloNodeId(); + Parse::NodeId last_param_node_id = end_of_decl_node_id; + + return { + .name_loc_id = Parse::NodeId::Invalid, + .name_id = SemIR::NameId::Invalid, + .first_param_node_id = first_param_node_id, + .last_param_node_id = last_param_node_id, + .implicit_params_loc_id = implicit_params_loc_id, + .implicit_params_id = + implicit_params_id.value_or(SemIR::InstBlockId::Invalid), + .params_loc_id = Parse::NodeId::Invalid, + .params_id = SemIR::InstBlockId::Invalid, + .pattern_block_id = context.pattern_block_stack().Pop(), + }; +} + +static auto MergeImplRedecl(Context& context, SemIR::Impl& new_impl, + SemIR::ImplId prev_impl_id) -> bool { + auto& prev_impl = context.impls().Get(prev_impl_id); + + // TODO: Following #3763, disallow redeclarations in different scopes. + + // If the parameters aren't the same, then this is not a redeclaration of this + // `impl`. Keep looking for a prior declaration without issuing a diagnostic. + if (!CheckRedeclParamsMatch(context, DeclParams(new_impl), + DeclParams(prev_impl), SemIR::SpecificId::Invalid, + /*check_syntax=*/true, /*diagnose=*/false)) { + // NOLINTNEXTLINE(readability-simplify-boolean-expr) + return false; + } + + // TODO: CheckIsAllowedRedecl. We don't have a suitable NameId; decide if we + // need to treat the `T as I` as a kind of name. + + // TODO: Merge information from the new declaration into the old one as + // needed. + + return true; +} + // Build an ImplDecl describing the signature of an impl. This handles the // common logic shared by impl forward declarations and impl definitions. static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, @@ -189,10 +244,9 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, context.node_stack().PopExprWithNodeId(); auto [self_type_node, self_type_id] = context.node_stack().PopWithNodeId(); - auto [params_node, params_id] = - context.node_stack().PopWithNodeIdIf(); + // Pop the `impl` introducer and any `forall` parameters as a "name". + auto name = PopImplIntroducerAndParamsAsNameComponent(context, node_id); auto decl_block_id = context.inst_block_stack().Pop(); - context.node_stack().PopForSoloNodeId(); // Convert the constraint expression to a type. // TODO: Check that its constant value is a constraint. @@ -212,24 +266,46 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, // TODO: Check for an orphan `impl`. - // TODO: Check parameters. Store them on the `Impl` in some form. - static_cast(params_id); + // Add the impl declaration. + SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::Invalid, + .decl_block_id = decl_block_id}; + auto impl_decl_id = + context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, impl_decl)); + + SemIR::Impl impl_info = { + name_context.MakeEntityWithParamsBase(name, impl_decl_id, + /*is_extern=*/false, + SemIR::LibraryNameId::Invalid), + {.self_id = self_type_id, .constraint_id = constraint_type_id}}; // Add the impl declaration. - // TODO: Does lookup in an impl file need to look for a prior impl declaration - // in the api file? - auto impl_id = context.impls().LookupOrAdd(self_type_id, constraint_type_id); - context.impls().Get(impl_id).pattern_block_id = - context.pattern_block_stack().Pop(); - SemIR::ImplDecl impl_decl = {.impl_id = impl_id, - .decl_block_id = decl_block_id}; - auto impl_decl_id = context.AddInst(node_id, impl_decl); + auto& lookup_bucket = context.impls().GetOrAddLookupBucket( + impl_info.self_id, impl_info.constraint_id); + for (auto prev_impl_id : lookup_bucket) { + if (MergeImplRedecl(context, impl_info, prev_impl_id)) { + impl_decl.impl_id = prev_impl_id; + break; + } + } + + // Create a new impl if this isn't a valid redeclaration. + if (!impl_decl.impl_id.is_valid()) { + impl_info.generic_id = FinishGenericDecl(context, impl_decl_id); + impl_decl.impl_id = context.impls().Add(impl_info); + lookup_bucket.push_back(impl_decl.impl_id); + } else { + FinishGenericRedecl(context, impl_decl_id, + context.impls().Get(impl_decl.impl_id).generic_id); + } + + // Write the impl ID into the ImplDecl. + context.ReplaceInstBeforeConstantUse(impl_decl_id, impl_decl); // For an `extend impl` declaration, mark the impl as extending this `impl`. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { auto extend_node = introducer.modifier_node_id(ModifierOrder::Decl); ExtendImpl(context, extend_node, node_id, self_type_node, self_type_id, - params_node, constraint_type_id); + name.implicit_params_loc_id, constraint_type_id); } if (!is_definition && context.IsImplFile()) { diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 14c10f65d20e..16c9fb60e051 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -560,10 +560,16 @@ class ImportRefResolver { if (!generic_id.is_valid()) { return SemIR::ConstantId::Invalid; } - return GetLocalConstantId( - import_ir_.insts() - .Get(import_ir_.generics().Get(generic_id).decl_id) - .type_id()); + auto import_decl_inst_id = import_ir_.generics().Get(generic_id).decl_id; + auto import_decl_inst = import_ir_.insts().Get(import_decl_inst_id); + if (import_decl_inst.Is()) { + // For an impl declaration, the imported entity can be found via the + // declaration. + return GetLocalConstantId(import_decl_inst_id); + } + // For all other kinds of declaration, the imported entity can be found via + // the type of the declaration. + return GetLocalConstantId(import_decl_inst.type_id()); } // Gets a local generic ID given the corresponding local constant ID returned @@ -572,9 +578,9 @@ class ImportRefResolver { if (!local_const_id.is_valid()) { return SemIR::GenericId::Invalid; } - auto type = context_.insts().Get( + auto inst = context_.insts().Get( context_.constant_values().GetInstId(local_const_id)); - CARBON_KIND_SWITCH(type) { + CARBON_KIND_SWITCH(inst) { case CARBON_KIND(SemIR::FunctionType fn_type): { return context_.functions().Get(fn_type.function_id).generic_id; } @@ -586,8 +592,11 @@ class ImportRefResolver { .Get(interface_type.interface_id) .generic_id; } + case CARBON_KIND(SemIR::ImplDecl impl_decl): { + return context_.impls().Get(impl_decl.impl_id).generic_id; + } default: { - CARBON_FATAL("Unexpected type for generic declaration: {0}", type); + CARBON_FATAL("Unexpected inst for generic declaration: {0}", inst); } } } @@ -781,10 +790,6 @@ class ImportRefResolver { // Get the constant value for the scope. auto const_id = SemIR::ConstantId::Invalid; CARBON_KIND_SWITCH(*inst) { - case SemIR::ImplDecl::Kind: - // TODO: Import the scope for an `impl` definition. - return SemIR::NameScopeId::Invalid; - case SemIR::Namespace::Kind: // If the namespace has already been imported, we can use its constant. // However, if it hasn't, we use Invalid instead of adding it to the @@ -808,6 +813,9 @@ class ImportRefResolver { case CARBON_KIND(SemIR::ClassType inst): { return context_.classes().Get(inst.class_id).scope_id; } + case CARBON_KIND(SemIR::ImplDecl inst): { + return context_.impls().Get(inst.impl_id).scope_id; + } case CARBON_KIND(SemIR::InterfaceType inst): { return context_.interfaces().Get(inst.interface_id).scope_id; } @@ -1037,6 +1045,9 @@ class ImportRefResolver { case CARBON_KIND(SemIR::GenericInterfaceType inst): { return TryResolveTypedInst(inst); } + case CARBON_KIND(SemIR::ImplDecl inst): { + return TryResolveTypedInst(inst, const_id); + } case CARBON_KIND(SemIR::ImportRefLoaded inst): { return TryResolveTypedInst(inst, inst_id); } @@ -1569,6 +1580,138 @@ class ImportRefResolver { context_.types().GetConstantId(interface_val.type_id())); } + // Forms a constant ID that represents the given instruction ID that denotes + // an impl declaration. Impl declarations don't have a constant value, but for + // the purposes of importing we pretend that they do. + // + // TODO: Consider alternative options here. We could make impl declarations + // actually evaluate to themselves to avoid this hack. + static auto ImplDeclIdAsConstantId(SemIR::InstId impl_decl_id) + -> SemIR::ConstantId { + return SemIR::ConstantId::ForTemplateConstant(impl_decl_id); + } + + // Gets the instruction ID for an impl declaration represented by the + // specified constant ID. + auto ConstantIdAsImplDeclId(SemIR::ConstantId impl_const_id) + -> SemIR::InstId { + return context_.constant_values().GetInstId(impl_const_id); + } + + // Make a declaration of an impl. This is done as a separate step from + // importing the impl definition in order to resolve cycles. + auto MakeImplDeclaration(const SemIR::Impl& import_impl) + -> std::pair { + SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::Invalid, + .decl_block_id = SemIR::InstBlockId::Empty}; + auto impl_decl_id = + context_.AddPlaceholderInstInNoBlock(context_.MakeImportedLocAndInst( + AddImportIRInst(import_impl.latest_decl_id()), impl_decl)); + impl_decl.impl_id = context_.impls().Add( + {GetIncompleteLocalEntityBase(impl_decl_id, import_impl), + {.self_id = SemIR::TypeId::Invalid, + .constraint_id = SemIR::TypeId::Invalid, + .witness_id = SemIR::InstId::Invalid}}); + + // Write the impl ID into the ImplDecl. + context_.ReplaceInstBeforeConstantUse(impl_decl_id, impl_decl); + return {impl_decl.impl_id, ImplDeclIdAsConstantId(impl_decl_id)}; + } + + // Imports the definition of an impl. + auto AddImplDefinition(const SemIR::Impl& import_impl, SemIR::Impl& new_impl, + SemIR::InstId witness_id) -> void { + new_impl.definition_id = new_impl.first_owning_decl_id; + + new_impl.witness_id = witness_id; + + // Import the definition scope, if we might need it. Name lookup is never + // performed into this scope by a user of the impl, so this is only + // necessary in the same library that defined the impl, in order to support + // defining members of the impl out of line in the impl file when the impl + // is defined in the API file. + if (import_ir_id_ == SemIR::ImportIRId::ApiForImpl) { + new_impl.scope_id = context_.name_scopes().Add( + new_impl.first_owning_decl_id, SemIR::NameId::Invalid, + new_impl.parent_scope_id); + auto& new_scope = context_.name_scopes().Get(new_impl.scope_id); + const auto& import_scope = + import_ir_.name_scopes().Get(import_impl.scope_id); + + // Push a block so that we can add scoped instructions to it. + context_.inst_block_stack().Push(); + AddNameScopeImportRefs(import_scope, new_scope); + new_impl.body_block_id = context_.inst_block_stack().Pop(); + } + } + + auto TryResolveTypedInst(SemIR::ImplDecl inst, + SemIR::ConstantId impl_const_id) -> ResolveResult { + // TODO: This duplicates a lot of the handling of interfaces, classes, and + // functions. Factor out the commonality. + const auto& import_impl = import_ir_.impls().Get(inst.impl_id); + + SemIR::ImplId impl_id = SemIR::ImplId::Invalid; + if (!impl_const_id.is_valid()) { + if (HasNewWork()) { + // This is the end of the first phase. Don't make a new impl yet if we + // already have new work. + return Retry(); + } + + // On the second phase, create a forward declaration of the impl for any + // recursive references. + std::tie(impl_id, impl_const_id) = MakeImplDeclaration(import_impl); + } else { + // On the third phase, compute the impl ID from the "constant value" of + // the declaration, which is a reference to the created ImplDecl. + auto impl_const_inst = context_.insts().GetAs( + context_.constant_values().GetInstId(impl_const_id)); + impl_id = impl_const_inst.impl_id; + } + + // Load constants for the definition. + auto parent_scope_id = GetLocalNameScopeId(import_impl.parent_scope_id); + auto implicit_param_const_ids = + GetLocalParamConstantIds(import_impl.implicit_param_refs_id); + auto generic_data = GetLocalGenericData(import_impl.generic_id); + auto self_const_id = GetLocalConstantId(import_impl.self_id); + auto constraint_const_id = GetLocalConstantId(import_impl.constraint_id); + + if (HasNewWork()) { + return Retry(impl_const_id); + } + + auto& new_impl = context_.impls().Get(impl_id); + new_impl.parent_scope_id = parent_scope_id; + new_impl.implicit_param_refs_id = GetLocalParamRefsId( + import_impl.implicit_param_refs_id, implicit_param_const_ids); + CARBON_CHECK(!import_impl.param_refs_id.is_valid() && + !new_impl.param_refs_id.is_valid()); + SetGenericData(import_impl.generic_id, new_impl.generic_id, generic_data); + new_impl.self_id = context_.GetTypeIdForTypeConstant(self_const_id); + new_impl.constraint_id = + context_.GetTypeIdForTypeConstant(constraint_const_id); + + if (import_impl.is_defined()) { + auto witness_id = AddImportRef( + context_, {.ir_id = import_ir_id_, .inst_id = import_impl.witness_id}, + SemIR::EntityNameId::Invalid); + AddImplDefinition(import_impl, new_impl, witness_id); + } + + // If the `impl` is declared in the API file corresponding to the current + // file, add this to impl lookup so that it can be found by redeclarations + // in the current file. + if (import_ir_id_ == SemIR::ImportIRId::ApiForImpl) { + context_.impls() + .GetOrAddLookupBucket(new_impl.self_id, new_impl.constraint_id) + .push_back(impl_id); + } + + return ResolveAsConstant(impl_const_id); + } + auto TryResolveTypedInst(SemIR::ImportRefLoaded /*inst*/, SemIR::InstId inst_id) -> ResolveResult { // Return the constant for the instruction of the imported constant. @@ -1883,9 +2026,18 @@ class ImportRefResolver { // Note that the individual Finish steps can add new pending work, so keep // going until we have no more work to do. while (!pending_generics_.empty() || !pending_specifics_.empty()) { - while (!pending_generics_.empty()) { - FinishPendingGeneric(pending_generics_.pop_back_val()); + // Process generics in the order that we added them because a later + // generic might refer to an earlier one, and the calls to + // RebuildGenericEvalBlock assume that the reachable SemIR is in a valid + // state. + // TODO: Import the generic eval block rather than calling + // RebuildGenericEvalBlock to rebuild it so that order doesn't matter. + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i != pending_generics_.size(); ++i) { + FinishPendingGeneric(pending_generics_[i]); } + pending_generics_.clear(); + while (!pending_specifics_.empty()) { FinishPendingSpecific(pending_specifics_.pop_back_val()); } @@ -2076,30 +2228,6 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void { } } -// Imports the impl `import_impl_id` from the imported IR `import_ir`. -static auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id, - const SemIR::File& import_ir, - SemIR::ImplId import_impl_id) -> void { - // Resolve the imported impl to a local impl ID. - ImportRefResolver resolver(context, import_ir_id); - const auto& import_impl = import_ir.impls().Get(import_impl_id); - auto self_id = resolver.ResolveType(import_impl.self_id); - auto constraint_id = resolver.ResolveType(import_impl.constraint_id); - - // Import the definition if the impl is defined. - // TODO: Do we need to check for multiple definitions? - auto impl_id = context.impls().LookupOrAdd(self_id, constraint_id); - if (import_impl.is_defined()) { - // TODO: Create a scope for the `impl` if necessary. - // TODO: Consider importing the definition_id. - - auto& impl = context.impls().Get(impl_id); - impl.witness_id = AddImportRef( - context, {.ir_id = import_ir_id, .inst_id = import_impl.witness_id}, - SemIR::EntityNameId::Invalid); - } -} - // TODO: This doesn't belong in this file. Consider moving the import resolver // and this file elsewhere. auto ImportImpls(Context& context) -> void { @@ -2112,7 +2240,10 @@ auto ImportImpls(Context& context) -> void { SemIR::ImportIRId import_ir_id(import_index); for (auto impl_index : llvm::seq(import_ir.sem_ir->impls().size())) { SemIR::ImplId impl_id(impl_index); - ImportImpl(context, import_ir_id, *import_ir.sem_ir, impl_id); + + // Resolve the imported impl to a local impl ID. + ImportRefResolver resolver(context, import_ir_id); + resolver.Resolve(import_ir.sem_ir->impls().Get(impl_id).first_decl_id()); } } } diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index ab769ef2b323..aa1498bc1223 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -192,16 +192,17 @@ static auto EntityHasParamError(Context& context, const DeclParams& info) // Returns false if a param differs for a redeclaration. The caller is expected // to provide a diagnostic. -static auto CheckRedeclParam(Context& context, - llvm::StringLiteral param_diag_label, - int32_t param_index, - SemIR::InstId new_param_ref_id, - SemIR::InstId prev_param_ref_id, - SemIR::SpecificId prev_specific_id) -> bool { +static auto CheckRedeclParam( + Context& context, llvm::StringLiteral param_diag_label, int32_t param_index, + SemIR::InstId new_param_ref_id, SemIR::InstId prev_param_ref_id, + SemIR::SpecificId prev_specific_id, bool diagnose) -> bool { // TODO: Consider differentiating between type and name mistakes. For now, // taking the simpler approach because I also think we may want to refactor // params. - auto diagnose = [&]() { + auto emit_diagnostic = [&]() { + if (!diagnose) { + return; + } CARBON_DIAGNOSTIC(RedeclParamDiffers, Error, "redeclaration differs at {0}parameter {1}", llvm::StringLiteral, int32_t); @@ -222,7 +223,7 @@ static auto CheckRedeclParam(Context& context, new_param_ref.type_id(), SemIR::GetTypeInSpecific(context.sem_ir(), prev_specific_id, prev_param_ref.type_id()))) { - diagnose(); + emit_diagnostic(); return false; } @@ -232,7 +233,7 @@ static auto CheckRedeclParam(Context& context, prev_param_ref = context.insts().Get(prev_param_ref.As().inner_id); if (new_param_ref.kind() != prev_param_ref.kind()) { - diagnose(); + emit_diagnostic(); return false; } } @@ -247,7 +248,7 @@ static auto CheckRedeclParam(Context& context, auto new_param = new_param_ref.As(); auto prev_param = prev_param_ref.As(); if (new_param.name_id != prev_param.name_id) { - diagnose(); + emit_diagnostic(); return false; } @@ -260,7 +261,8 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc, SemIRLoc prev_decl_loc, SemIR::InstBlockId prev_param_refs_id, llvm::StringLiteral param_diag_label, - SemIR::SpecificId prev_specific_id) -> bool { + SemIR::SpecificId prev_specific_id, bool diagnose) + -> bool { // This will often occur for empty params. if (new_param_refs_id == prev_param_refs_id) { return true; @@ -268,6 +270,9 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc, // If exactly one of the parameter lists was present, they differ. if (new_param_refs_id.is_valid() != prev_param_refs_id.is_valid()) { + if (!diagnose) { + return false; + } CARBON_DIAGNOSTIC(RedeclParamListDiffers, Error, "redeclaration differs because of {1}{0}parameter list", llvm::StringLiteral, llvm::StringLiteral); @@ -288,6 +293,9 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc, const auto new_param_ref_ids = context.inst_blocks().Get(new_param_refs_id); const auto prev_param_ref_ids = context.inst_blocks().Get(prev_param_refs_id); if (new_param_ref_ids.size() != prev_param_ref_ids.size()) { + if (!diagnose) { + return false; + } CARBON_DIAGNOSTIC( RedeclParamCountDiffers, Error, "redeclaration differs because of {0}parameter count of {1}", @@ -306,7 +314,7 @@ static auto CheckRedeclParams(Context& context, SemIRLoc new_decl_loc, for (auto [index, new_param_ref_id, prev_param_ref_id] : llvm::enumerate(new_param_ref_ids, prev_param_ref_ids)) { if (!CheckRedeclParam(context, param_diag_label, index, new_param_ref_id, - prev_param_ref_id, prev_specific_id)) { + prev_param_ref_id, prev_specific_id, diagnose)) { return false; } } @@ -338,8 +346,8 @@ static auto CheckRedeclParamSyntax(Context& context, Parse::NodeId new_first_param_node_id, Parse::NodeId new_last_param_node_id, Parse::NodeId prev_first_param_node_id, - Parse::NodeId prev_last_param_node_id) - -> bool { + Parse::NodeId prev_last_param_node_id, + bool diagnose) -> bool { // Parse nodes may not always be available to compare. // TODO: Support cross-file syntax checks. Right now imports provide invalid // nodes, and we'll need to follow the declaration to its original file to @@ -366,6 +374,9 @@ static auto CheckRedeclParamSyntax(Context& context, // sizes here. for (auto [new_node_id, prev_node_id] : llvm::zip(new_range, prev_range)) { if (!IsNodeSyntaxEqual(context, new_node_id, prev_node_id)) { + if (!diagnose) { + return false; + } CARBON_DIAGNOSTIC(RedeclParamSyntaxDiffers, Error, "redeclaration syntax differs here"); CARBON_DIAGNOSTIC(RedeclParamSyntaxPrevious, Note, @@ -374,7 +385,6 @@ static auto CheckRedeclParamSyntax(Context& context, .Build(new_node_id, RedeclParamSyntaxDiffers) .Note(prev_node_id, RedeclParamSyntaxPrevious) .Emit(); - return false; } } @@ -385,7 +395,7 @@ static auto CheckRedeclParamSyntax(Context& context, auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, const DeclParams& prev_entity, SemIR::SpecificId prev_specific_id, - bool check_syntax) -> bool { + bool check_syntax, bool diagnose) -> bool { if (EntityHasParamError(context, new_entity) || EntityHasParamError(context, prev_entity)) { return false; @@ -393,19 +403,19 @@ auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, if (!CheckRedeclParams(context, new_entity.loc, new_entity.implicit_param_refs_id, prev_entity.loc, prev_entity.implicit_param_refs_id, "implicit ", - prev_specific_id)) { + prev_specific_id, diagnose)) { return false; } if (!CheckRedeclParams(context, new_entity.loc, new_entity.param_refs_id, prev_entity.loc, prev_entity.param_refs_id, "", - prev_specific_id)) { + prev_specific_id, diagnose)) { return false; } if (check_syntax && !CheckRedeclParamSyntax(context, new_entity.first_param_node_id, new_entity.last_param_node_id, prev_entity.first_param_node_id, - prev_entity.last_param_node_id)) { + prev_entity.last_param_node_id, diagnose)) { return false; } return true; diff --git a/toolchain/check/merge.h b/toolchain/check/merge.h index 3c1cf69ed9f0..011cca0aa523 100644 --- a/toolchain/check/merge.h +++ b/toolchain/check/merge.h @@ -93,13 +93,13 @@ struct DeclParams { }; // Checks that the parameters in a redeclaration of an entity match the -// parameters in the prior declaration. If not, produces a diagnostic and -// returns false. +// parameters in the prior declaration. If not, produces a diagnostic if +// `diagnose` is true, and returns false. auto CheckRedeclParamsMatch( Context& context, const DeclParams& new_entity, const DeclParams& prev_entity, SemIR::SpecificId prev_specific_id = SemIR::SpecificId::Invalid, - bool check_syntax = true) -> bool; + bool check_syntax = true, bool diagnose = true) -> bool; } // namespace Carbon::Check diff --git a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon index d5af31306ea9..01f247a54ba2 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -100,19 +100,24 @@ class C { // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.2 { -// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] { -// CHECK:STDOUT: %x.patt: @F.2.%T (%T) = binding_pattern x -// CHECK:STDOUT: } { -// CHECK:STDOUT: %T.ref: type = name_ref T, @impl.%T [symbolic = %T (constants.%T)] -// CHECK:STDOUT: %x.param: @F.2.%T (%T) = param x, runtime_param0 -// CHECK:STDOUT: %x: @F.2.%T (%T) = bind_name x, %x.param -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc19_56: = interface_witness (%F.decl) [template = constants.%.5] +// CHECK:STDOUT: generic impl @impl(%T.loc19: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @GenericInterface, @GenericInterface(%T.1) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = %.loc19_56 +// CHECK:STDOUT: impl: %C as %.2 { +// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] { +// CHECK:STDOUT: %x.patt: @F.2.%T (%T) = binding_pattern x +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, @impl.%T.loc19 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %x.param: @F.2.%T (%T) = param x, runtime_param0 +// CHECK:STDOUT: %x: @F.2.%T (%T) = bind_name x, %x.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc19_56: = interface_witness (%F.decl) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc19_56 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -120,10 +125,10 @@ class C { // CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 // CHECK:STDOUT: } { // CHECK:STDOUT: %T.param: type = param T, runtime_param -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, %T.param [symbolic = constants.%T] +// CHECK:STDOUT: %T.loc19: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] // CHECK:STDOUT: %GenericInterface.ref: %GenericInterface.type = name_ref GenericInterface, file.%GenericInterface.decl [template = constants.%GenericInterface] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = constants.%T] -// CHECK:STDOUT: %.loc19_52: type = interface_type @GenericInterface, @GenericInterface(constants.%T) [symbolic = constants.%.2] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc19 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc19_52: type = interface_type @GenericInterface, @GenericInterface(constants.%T) [symbolic = %.1 (constants.%.2)] // CHECK:STDOUT: } // CHECK:STDOUT: %.loc22: = complete_type_witness %.6 [template = constants.%.7] // CHECK:STDOUT: @@ -138,7 +143,7 @@ class C { // CHECK:STDOUT: fn(%x: @F.1.%T (%T)); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.2(@impl.%T: type) { +// CHECK:STDOUT: generic fn @F.2(@impl.%T.loc19: type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: @@ -169,6 +174,15 @@ class C { // CHECK:STDOUT: %T.1 => constants.%T // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @GenericInterface(@impl.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @F.2(constants.%T) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon index 4e4df169c813..c0c55c8fb98a 100644 --- a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon +++ b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon @@ -63,7 +63,10 @@ interface I { // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C.2 as %.1; +// CHECK:STDOUT: generic impl @impl(@I.%Self: %.1) { +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C.2 as %.1; +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic class @C(@I.%Self: %.1) { // CHECK:STDOUT: !definition: @@ -82,3 +85,5 @@ interface I { // CHECK:STDOUT: // CHECK:STDOUT: specific @C(constants.%Self) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%Self) {} +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/impl_forall.carbon b/toolchain/check/testdata/impl/impl_forall.carbon index 35480f0aa6aa..062c1a7a7a2f 100644 --- a/toolchain/check/testdata/impl/impl_forall.carbon +++ b/toolchain/check/testdata/impl/impl_forall.carbon @@ -56,8 +56,8 @@ impl forall [T:! type] T as Simple { // CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 // CHECK:STDOUT: } { // CHECK:STDOUT: %T.param: type = param T, runtime_param -// CHECK:STDOUT: %T: type = bind_symbolic_name T 0, %T.param [symbolic = constants.%T] -// CHECK:STDOUT: %T.ref: type = name_ref T, %T [symbolic = constants.%T] +// CHECK:STDOUT: %T.loc15: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc15 [symbolic = %T.1 (constants.%T)] // CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -73,13 +73,17 @@ impl forall [T:! type] T as Simple { // CHECK:STDOUT: witness = (%F.decl) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %T as %.1 { -// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {} {} -// CHECK:STDOUT: %.loc15: = interface_witness (%F.decl) [template = constants.%.5] +// CHECK:STDOUT: generic impl @impl(%T.loc15: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] // CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: witness = %.loc15 +// CHECK:STDOUT: impl: %T as %.1 { +// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {} {} +// CHECK:STDOUT: %.loc15: = interface_witness (%F.decl) [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc15 +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@Simple.%Self: %.1) { @@ -87,7 +91,7 @@ impl forall [T:! type] T as Simple { // CHECK:STDOUT: fn(); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.2(@impl.%T: type) { +// CHECK:STDOUT: generic fn @F.2(@impl.%T.loc15: type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: // CHECK:STDOUT: fn() { @@ -98,6 +102,10 @@ impl forall [T:! type] T as Simple { // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%Self) {} // CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @F.2(constants.%T) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @F.1(constants.%T) {} diff --git a/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon b/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon index faadb91a7b3d..ff63dd804b36 100644 --- a/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon +++ b/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon @@ -82,9 +82,9 @@ impl C as I { // CHECK:STDOUT: %.loc19_11.2: type = converted %int.make_type_32, %.loc19_11.1 [template = i32] // CHECK:STDOUT: %return: ref i32 = var // CHECK:STDOUT: } -// CHECK:STDOUT: impl_decl @impl {} { +// CHECK:STDOUT: impl_decl @impl.2 {} { // CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] -// CHECK:STDOUT: %I.ref.loc27: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -99,7 +99,9 @@ impl C as I { // CHECK:STDOUT: witness = (%F.decl) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.1 { +// CHECK:STDOUT: impl @impl.1: %C as %.1; +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: %C as %.1 { // CHECK:STDOUT: %F.decl: %F.type.3 = fn_decl @F.3 [template = constants.%F.3] {} {} // CHECK:STDOUT: %.loc27: = interface_witness (%F.decl) [template = constants.%.8] // CHECK:STDOUT: @@ -109,8 +111,8 @@ impl C as I { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { -// CHECK:STDOUT: impl_decl @impl {} { -// CHECK:STDOUT: %I.ref.loc16: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: impl_decl @impl.1 {} { +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: %.loc17: = complete_type_witness %.5 [template = constants.%.6] // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/import.carbon b/toolchain/check/testdata/impl/lookup/import.carbon index a25cc256410f..6dde0ae47269 100644 --- a/toolchain/check/testdata/impl/lookup/import.carbon +++ b/toolchain/check/testdata/impl/lookup/import.carbon @@ -120,18 +120,18 @@ fn G(c: Impl.C) { // CHECK:STDOUT: --- use.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @HasF [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %.3: type = interface_type @HasF [template] -// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %.6: type = assoc_entity_type %.3, %F.type.1 [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %.1, %F.type.1 [template] // CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.8 [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] @@ -154,13 +154,13 @@ fn G(c: Impl.C) { // CHECK:STDOUT: .HasF = %import_ref.7 // CHECK:STDOUT: import Impl//default // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1 = import_ref Impl//default, inst+15, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Impl//default, inst+5, unloaded -// CHECK:STDOUT: %import_ref.3: %.6 = import_ref Impl//default, inst+12, loaded [template = constants.%.7] -// CHECK:STDOUT: %import_ref.4 = import_ref Impl//default, inst+7, unloaded +// CHECK:STDOUT: %import_ref.1 = import_ref Impl//default, inst+5, unloaded +// CHECK:STDOUT: %import_ref.2: %.6 = import_ref Impl//default, inst+12, loaded [template = constants.%.7] +// CHECK:STDOUT: %import_ref.3 = import_ref Impl//default, inst+7, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Impl//default, inst+15, unloaded // CHECK:STDOUT: %import_ref.5: = import_ref Impl//default, inst+25, loaded [template = constants.%.8] // CHECK:STDOUT: %import_ref.6: type = import_ref Impl//default, inst+14, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.7: type = import_ref Impl//default, inst+3, loaded [template = constants.%.3] +// CHECK:STDOUT: %import_ref.7: type = import_ref Impl//default, inst+3, loaded [template = constants.%.1] // CHECK:STDOUT: %import_ref.8 = import_ref Impl//default, inst+7, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: @@ -184,33 +184,33 @@ fn G(c: Impl.C) { // CHECK:STDOUT: // CHECK:STDOUT: interface @HasF { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.2 -// CHECK:STDOUT: .F = imports.%import_ref.3 -// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: .Self = imports.%import_ref.1 +// CHECK:STDOUT: .F = imports.%import_ref.2 +// CHECK:STDOUT: witness = (imports.%import_ref.3) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.3 { +// CHECK:STDOUT: impl @impl: %C as %.1 { // CHECK:STDOUT: !members: // CHECK:STDOUT: witness = imports.%import_ref.5 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.1 +// CHECK:STDOUT: .Self = imports.%import_ref.4 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @G(%c: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: %C = name_ref c, %c // CHECK:STDOUT: %Impl.ref.loc5: = name_ref Impl, imports.%Impl [template = imports.%Impl] -// CHECK:STDOUT: %HasF.ref: type = name_ref HasF, imports.%import_ref.7 [template = constants.%.3] -// CHECK:STDOUT: %F.ref: %.6 = name_ref F, imports.%import_ref.3 [template = constants.%.7] +// CHECK:STDOUT: %HasF.ref: type = name_ref HasF, imports.%import_ref.7 [template = constants.%.1] +// CHECK:STDOUT: %F.ref: %.6 = name_ref F, imports.%import_ref.2 [template = constants.%.7] // CHECK:STDOUT: %.loc5: %F.type.1 = interface_witness_access imports.%import_ref.5, element0 [template = constants.%F.2] // CHECK:STDOUT: %F.call: init %.4 = call %.loc5() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.3) { +// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.1) { // CHECK:STDOUT: // CHECK:STDOUT: fn(); // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon b/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon new file mode 100644 index 000000000000..546f6a856892 --- /dev/null +++ b/toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon @@ -0,0 +1,434 @@ +// 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/lookup/no_prelude/impl_forall.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/no_prelude/impl_forall.carbon + +// --- fail_todo_impl_forall.carbon + +class A(T:! type) { + var n: T; +} + +interface I(U:! type) { + fn F[self: Self]() -> U; +} + +impl forall [V:! type] A(V) as I(V) { + fn F[self: Self]() -> V { + return self.n; + } +} + +fn TestGeneric[W:! type](a: A(W)) -> W { + // CHECK:STDERR: fail_todo_impl_forall.carbon:[[@LINE+4]]:10: error: cannot access member of interface `I` in type `A` that does not implement that interface + // CHECK:STDERR: return a.(I(W).F)(); + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + return a.(I(W).F)(); +} + +fn TestSpecific(a: A({})) -> {} { + // CHECK:STDERR: fail_todo_impl_forall.carbon:[[@LINE+3]]:10: error: cannot access member of interface `I` in type `A` that does not implement that interface + // CHECK:STDERR: return a.(I({}).F)(); + // CHECK:STDERR: ^~~~~~~~~~~ + return a.(I({}).F)(); +} + +// CHECK:STDOUT: --- fail_todo_impl_forall.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %A.type: type = generic_class_type @A [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %A.1: %A.type = struct_value () [template] +// CHECK:STDOUT: %A.2: type = class_type @A, @A(%T) [symbolic] +// CHECK:STDOUT: %.2: type = unbound_element_type %A.2, %T [symbolic] +// CHECK:STDOUT: %.3: type = struct_type {.n: %T} [symbolic] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic] +// CHECK:STDOUT: %I.type: type = generic_interface_type @I [template] +// CHECK:STDOUT: %I: %I.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = interface_type @I, @I(%U) [symbolic] +// CHECK:STDOUT: %Self: %.5 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @I(%U) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.6: type = assoc_entity_type %.5, %F.type.1 [symbolic] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %V: type = bind_symbolic_name V 0 [symbolic] +// CHECK:STDOUT: %A.3: type = class_type @A, @A(%V) [symbolic] +// CHECK:STDOUT: %.8: type = interface_type @I, @I(%V) [symbolic] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.1, @I(%V) [symbolic] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [symbolic] +// CHECK:STDOUT: %.9: type = assoc_entity_type %.8, %F.type.3 [symbolic] +// CHECK:STDOUT: %.10: %.9 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %.11: = interface_witness (%F.2) [template] +// CHECK:STDOUT: %.12: type = unbound_element_type %A.3, %V [symbolic] +// CHECK:STDOUT: %.13: type = struct_type {.n: %V} [symbolic] +// CHECK:STDOUT: %.14: = complete_type_witness %.13 [symbolic] +// CHECK:STDOUT: %.15: type = ptr_type %.13 [symbolic] +// CHECK:STDOUT: %W: type = bind_symbolic_name W 0 [symbolic] +// CHECK:STDOUT: %A.4: type = class_type @A, @A(%W) [symbolic] +// CHECK:STDOUT: %TestGeneric.type: type = fn_type @TestGeneric [template] +// CHECK:STDOUT: %TestGeneric: %TestGeneric.type = struct_value () [template] +// CHECK:STDOUT: %.16: type = unbound_element_type %A.4, %W [symbolic] +// CHECK:STDOUT: %.17: type = struct_type {.n: %W} [symbolic] +// CHECK:STDOUT: %.18: = complete_type_witness %.17 [symbolic] +// CHECK:STDOUT: %.19: type = ptr_type %.17 [symbolic] +// CHECK:STDOUT: %.20: type = interface_type @I, @I(%W) [symbolic] +// CHECK:STDOUT: %F.type.4: type = fn_type @F.1, @I(%W) [symbolic] +// CHECK:STDOUT: %F.4: %F.type.4 = struct_value () [symbolic] +// CHECK:STDOUT: %.21: type = assoc_entity_type %.20, %F.type.4 [symbolic] +// CHECK:STDOUT: %.22: %.21 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %.23: type = struct_type {} [template] +// CHECK:STDOUT: %A.5: type = class_type @A, @A(%.23) [template] +// CHECK:STDOUT: %TestSpecific.type: type = fn_type @TestSpecific [template] +// CHECK:STDOUT: %TestSpecific: %TestSpecific.type = struct_value () [template] +// CHECK:STDOUT: %.24: type = unbound_element_type %A.5, %.23 [template] +// CHECK:STDOUT: %.25: type = struct_type {.n: %.23} [template] +// CHECK:STDOUT: %.26: = complete_type_witness %.25 [template] +// CHECK:STDOUT: %.27: type = struct_type {.n: %.1} [template] +// CHECK:STDOUT: %.28: type = ptr_type %.25 [template] +// CHECK:STDOUT: %.29: type = interface_type @I, @I(%.23) [template] +// CHECK:STDOUT: %F.type.5: type = fn_type @F.1, @I(%.23) [template] +// CHECK:STDOUT: %F.5: %F.type.5 = struct_value () [template] +// CHECK:STDOUT: %.30: type = assoc_entity_type %.29, %F.type.5 [template] +// CHECK:STDOUT: %.31: %.30 = assoc_entity element0, @I.%F.decl [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .TestGeneric = %TestGeneric.decl +// CHECK:STDOUT: .TestSpecific = %TestSpecific.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %A.decl: %A.type = class_decl @A [template = constants.%A.1] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc2: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: %I.type = interface_decl @I [template = constants.%I] { +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %U.param: type = param U, runtime_param +// CHECK:STDOUT: %U.loc6: type = bind_symbolic_name U 0, %U.param [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %V.patt: type = symbolic_binding_pattern V 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %V.param: type = param V, runtime_param +// CHECK:STDOUT: %V.loc10: type = bind_symbolic_name V 0, %V.param [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A.1] +// CHECK:STDOUT: %V.ref.loc10_26: type = name_ref V, %V.loc10 [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: %A.loc10: type = class_type @A, @A(constants.%V) [symbolic = %A.1 (constants.%A.3)] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %V.ref.loc10_34: type = name_ref V, %V.loc10 [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: %.loc10_33: type = interface_type @I, @I(constants.%V) [symbolic = %.1 (constants.%.8)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestGeneric.decl: %TestGeneric.type = fn_decl @TestGeneric [template = constants.%TestGeneric] { +// CHECK:STDOUT: %W.patt: type = symbolic_binding_pattern W 0 +// CHECK:STDOUT: %a.patt: @TestGeneric.%A.1 (%A.4) = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %W.param: type = param W, runtime_param +// CHECK:STDOUT: %W.loc16: type = bind_symbolic_name W 0, %W.param [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A.1] +// CHECK:STDOUT: %W.ref.loc16_31: type = name_ref W, %W.loc16 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %A.loc16: type = class_type @A, @A(constants.%W) [symbolic = %A.1 (constants.%A.4)] +// CHECK:STDOUT: %a.param: @TestGeneric.%A.1 (%A.4) = param a, runtime_param0 +// CHECK:STDOUT: %a: @TestGeneric.%A.1 (%A.4) = bind_name a, %a.param +// CHECK:STDOUT: %W.ref.loc16_38: type = name_ref W, %W.loc16 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %return: ref @TestGeneric.%W.1 (%W) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %TestSpecific.decl: %TestSpecific.type = fn_decl @TestSpecific [template = constants.%TestSpecific] { +// CHECK:STDOUT: %a.patt: %A.5 = binding_pattern a +// CHECK:STDOUT: } { +// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A.1] +// CHECK:STDOUT: %.loc24_23: %.23 = struct_literal () +// CHECK:STDOUT: %.loc24_21: type = converted %.loc24_23, constants.%.23 [template = constants.%.23] +// CHECK:STDOUT: %A: type = class_type @A, @A(constants.%.23) [template = constants.%A.5] +// CHECK:STDOUT: %a.param: %A.5 = param a, runtime_param0 +// CHECK:STDOUT: %a: %A.5 = bind_name a, %a.param +// CHECK:STDOUT: %.loc24_31.1: %.23 = struct_literal () +// CHECK:STDOUT: %.loc24_31.2: type = converted %.loc24_31.1, constants.%.23 [template = constants.%.23] +// CHECK:STDOUT: %return: ref %.23 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @I(%U.loc6: type) { +// CHECK:STDOUT: %U.1: type = bind_symbolic_name U 0 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%U.1) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %Self.2: %.5 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @I(%U.1) [symbolic = %F.type (constants.%F.type.1)] +// CHECK:STDOUT: %F: @I.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @I.%.1 (%.5), @I.%F.type (%F.type.1) [symbolic = %.2 (constants.%.6)] +// CHECK:STDOUT: %.3: @I.%.2 (%.6) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @I.%.1 (%.5) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.decl: @I.%F.type (%F.type.1) = fn_decl @F.1 [symbolic = @I.%F (constants.%F.1)] { +// CHECK:STDOUT: %self.patt: @F.1.%Self (%Self) = binding_pattern self +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc7_14.1: @F.1.%.1 (%.5) = specific_constant @I.%Self.1, @I(constants.%U) [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.ref: @F.1.%.1 (%.5) = name_ref Self, %.loc7_14.1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.loc7_14.2: type = facet_type_access %Self.ref [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.loc7_14.3: type = converted %Self.ref, %.loc7_14.2 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %self.param: @F.1.%Self (%Self) = param self, runtime_param0 +// CHECK:STDOUT: %self: @F.1.%Self (%Self) = bind_name self, %self.param +// CHECK:STDOUT: %U.ref: type = name_ref U, @I.%U.loc6 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %return: ref @F.1.%U (%U) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc7: @I.%.2 (%.6) = assoc_entity element0, %F.decl [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: .F = %.loc7 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl(%V.loc10: type) { +// CHECK:STDOUT: %V.1: type = bind_symbolic_name V 0 [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: %A.1: type = class_type @A, @A(%V.1) [symbolic = %A.1 (constants.%A.3)] +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%V.1) [symbolic = %.1 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %A.3 as %.8 { +// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] { +// CHECK:STDOUT: %self.patt: @F.2.%A (%A.3) = binding_pattern self +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%A.3 [symbolic = %A (constants.%A.3)] +// CHECK:STDOUT: %self.param: @F.2.%A (%A.3) = param self, runtime_param0 +// CHECK:STDOUT: %self: @F.2.%A (%A.3) = bind_name self, %self.param +// CHECK:STDOUT: %V.ref: type = name_ref V, @impl.%V.loc10 [symbolic = %V (constants.%V)] +// CHECK:STDOUT: %return: ref @F.2.%V (%V) = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc10_37: = interface_witness (%F.decl) [template = constants.%.11] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc10_37 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @A(%T.loc2: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %A: type = class_type @A, @A(%T.1) [symbolic = %A (constants.%A.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @A.%A (%A.2), @A.%T.1 (%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %.2: type = struct_type {.n: @A.%T.1 (%T)} [symbolic = %.2 (constants.%.3)] +// CHECK:STDOUT: %.3: = complete_type_witness @A.%.2 (%.3) [symbolic = %.3 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc2 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc3: @A.%.1 (%.2) = field_decl n, element0 [template] +// CHECK:STDOUT: %.loc4: = complete_type_witness %.3 [symbolic = %.3 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%A.2 +// CHECK:STDOUT: .n = %.loc3 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%U.loc6: type, @I.%Self.1: @I.%.1 (%.5)) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%U) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %Self: %.5 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @F.1.%Self (%Self)]() -> @F.1.%U (%U); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.2(@impl.%V.loc10: type) { +// CHECK:STDOUT: %V: type = bind_symbolic_name V 0 [symbolic = %V (constants.%V)] +// CHECK:STDOUT: %A: type = class_type @A, @A(%V) [symbolic = %A (constants.%A.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = unbound_element_type @F.2.%A (%A.3), @F.2.%V (%V) [symbolic = %.1 (constants.%.12)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @F.2.%A (%A.3)]() -> @F.2.%V (%V) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %self.ref: @F.2.%A (%A.3) = name_ref self, %self +// CHECK:STDOUT: %n.ref: @F.2.%.1 (%.12) = name_ref n, @A.%.loc3 [template = @A.%.loc3] +// CHECK:STDOUT: %.loc12_16.1: ref @F.2.%V (%V) = class_element_access %self.ref, element0 +// CHECK:STDOUT: %.loc12_16.2: @F.2.%V (%V) = bind_value %.loc12_16.1 +// CHECK:STDOUT: return %.loc12_16.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @TestGeneric(%W.loc16: type) { +// CHECK:STDOUT: %W.1: type = bind_symbolic_name W 0 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %A.1: type = class_type @A, @A(%W.1) [symbolic = %A.1 (constants.%A.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%W.1) [symbolic = %.1 (constants.%.20)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @I(%W.1) [symbolic = %F.type (constants.%F.type.4)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @TestGeneric.%.1 (%.20), @TestGeneric.%F.type (%F.type.4) [symbolic = %.2 (constants.%.21)] +// CHECK:STDOUT: %.3: @TestGeneric.%.2 (%.21) = assoc_entity element0, @I.%F.decl [symbolic = %.3 (constants.%.22)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%W.loc16: type](%a: @TestGeneric.%A.1 (%A.4)) -> @TestGeneric.%W.1 (%W) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: @TestGeneric.%A.1 (%A.4) = name_ref a, %a +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %W.ref.loc21: type = name_ref W, %W.loc16 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: %.loc21_14: type = interface_type @I, @I(constants.%W) [symbolic = %.1 (constants.%.20)] +// CHECK:STDOUT: %.loc21_17: @TestGeneric.%.2 (%.21) = specific_constant @I.%.loc7, @I(constants.%W) [symbolic = %.3 (constants.%.22)] +// CHECK:STDOUT: %F.ref: @TestGeneric.%.2 (%.21) = name_ref F, %.loc21_17 [symbolic = %.3 (constants.%.22)] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @TestSpecific(%a: %A.5) -> %.23 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %A.5 = name_ref a, %a +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %.loc28_16: %.23 = struct_literal () +// CHECK:STDOUT: %.loc28_14.1: type = converted %.loc28_16, constants.%.23 [template = constants.%.23] +// CHECK:STDOUT: %.loc28_14.2: type = interface_type @I, @I(constants.%.23) [template = constants.%.29] +// CHECK:STDOUT: %.loc28_18: %.30 = specific_constant @I.%.loc7, @I(constants.%.23) [template = constants.%.31] +// CHECK:STDOUT: %F.ref: %.30 = name_ref F, %.loc28_18 [template = constants.%.31] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(@A.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%U) { +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@F.1.%U) { +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%U, constants.%Self) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@I.%U.1) { +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%V) { +// CHECK:STDOUT: %T.1 => constants.%V +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %A => constants.%A.3 +// CHECK:STDOUT: %.1 => constants.%.12 +// CHECK:STDOUT: %.2 => constants.%.13 +// CHECK:STDOUT: %.3 => constants.%.14 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%V) { +// CHECK:STDOUT: %U.1 => constants.%V +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: %.2 => constants.%.9 +// CHECK:STDOUT: %.3 => constants.%.10 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(@impl.%V.1) { +// CHECK:STDOUT: %T.1 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.%V.1) { +// CHECK:STDOUT: %U.1 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%V) { +// CHECK:STDOUT: %V.1 => constants.%V +// CHECK:STDOUT: %A.1 => constants.%A.3 +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(@F.2.%V) { +// CHECK:STDOUT: %T.1 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%V) { +// CHECK:STDOUT: %V => constants.%V +// CHECK:STDOUT: %A => constants.%A.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%V, constants.%A.3) { +// CHECK:STDOUT: %U => constants.%V +// CHECK:STDOUT: %.1 => constants.%.8 +// CHECK:STDOUT: %Self => constants.%A.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%W) { +// CHECK:STDOUT: %T.1 => constants.%W +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %A => constants.%A.4 +// CHECK:STDOUT: %.1 => constants.%.16 +// CHECK:STDOUT: %.2 => constants.%.17 +// CHECK:STDOUT: %.3 => constants.%.18 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(@TestGeneric.%W.1) { +// CHECK:STDOUT: %T.1 => constants.%W +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @TestGeneric(constants.%W) { +// CHECK:STDOUT: %W.1 => constants.%W +// CHECK:STDOUT: %A.1 => constants.%A.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%W) { +// CHECK:STDOUT: %U.1 => constants.%W +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.20 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type.4 +// CHECK:STDOUT: %F => constants.%F.4 +// CHECK:STDOUT: %.2 => constants.%.21 +// CHECK:STDOUT: %.3 => constants.%.22 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@TestGeneric.%W.1) { +// CHECK:STDOUT: %U.1 => constants.%W +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%.23) { +// CHECK:STDOUT: %T.1 => constants.%.23 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %A => constants.%A.5 +// CHECK:STDOUT: %.1 => constants.%.24 +// CHECK:STDOUT: %.2 => constants.%.25 +// CHECK:STDOUT: %.3 => constants.%.26 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%.23) { +// CHECK:STDOUT: %U.1 => constants.%.23 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.29 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type.5 +// CHECK:STDOUT: %F => constants.%F.5 +// CHECK:STDOUT: %.2 => constants.%.30 +// CHECK:STDOUT: %.3 => constants.%.31 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon index 5144bf0473fe..4324aa5b3ea7 100644 --- a/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon +++ b/toolchain/check/testdata/impl/lookup/no_prelude/import.carbon @@ -105,18 +105,18 @@ fn G(c: Impl.C) { // CHECK:STDOUT: --- use.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @HasF [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %.3: type = interface_type @HasF [template] -// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] -// CHECK:STDOUT: %.5: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: type = ptr_type %.2 [template] // CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] // CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] -// CHECK:STDOUT: %.6: type = assoc_entity_type %.3, %F.type.1 [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %.1, %F.type.1 [template] // CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.8 [template] // CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] // CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] @@ -129,13 +129,13 @@ fn G(c: Impl.C) { // CHECK:STDOUT: .HasF = %import_ref.7 // CHECK:STDOUT: import Impl//default // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1 = import_ref Impl//default, inst+13, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Impl//default, inst+3, unloaded -// CHECK:STDOUT: %import_ref.3: %.6 = import_ref Impl//default, inst+10, loaded [template = constants.%.7] -// CHECK:STDOUT: %import_ref.4 = import_ref Impl//default, inst+5, unloaded +// CHECK:STDOUT: %import_ref.1 = import_ref Impl//default, inst+3, unloaded +// CHECK:STDOUT: %import_ref.2: %.6 = import_ref Impl//default, inst+10, loaded [template = constants.%.7] +// CHECK:STDOUT: %import_ref.3 = import_ref Impl//default, inst+5, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Impl//default, inst+13, unloaded // CHECK:STDOUT: %import_ref.5: = import_ref Impl//default, inst+23, loaded [template = constants.%.8] // CHECK:STDOUT: %import_ref.6: type = import_ref Impl//default, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.7: type = import_ref Impl//default, inst+1, loaded [template = constants.%.3] +// CHECK:STDOUT: %import_ref.7: type = import_ref Impl//default, inst+1, loaded [template = constants.%.1] // CHECK:STDOUT: %import_ref.8 = import_ref Impl//default, inst+5, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: @@ -157,33 +157,33 @@ fn G(c: Impl.C) { // CHECK:STDOUT: // CHECK:STDOUT: interface @HasF { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.2 -// CHECK:STDOUT: .F = imports.%import_ref.3 -// CHECK:STDOUT: witness = (imports.%import_ref.4) +// CHECK:STDOUT: .Self = imports.%import_ref.1 +// CHECK:STDOUT: .F = imports.%import_ref.2 +// CHECK:STDOUT: witness = (imports.%import_ref.3) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %C as %.3 { +// CHECK:STDOUT: impl @impl: %C as %.1 { // CHECK:STDOUT: !members: // CHECK:STDOUT: witness = imports.%import_ref.5 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.1 +// CHECK:STDOUT: .Self = imports.%import_ref.4 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @G(%c: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %c.ref: %C = name_ref c, %c // CHECK:STDOUT: %Impl.ref.loc5: = name_ref Impl, imports.%Impl [template = imports.%Impl] -// CHECK:STDOUT: %HasF.ref: type = name_ref HasF, imports.%import_ref.7 [template = constants.%.3] -// CHECK:STDOUT: %F.ref: %.6 = name_ref F, imports.%import_ref.3 [template = constants.%.7] +// CHECK:STDOUT: %HasF.ref: type = name_ref HasF, imports.%import_ref.7 [template = constants.%.1] +// CHECK:STDOUT: %F.ref: %.6 = name_ref F, imports.%import_ref.2 [template = constants.%.7] // CHECK:STDOUT: %.loc5: %F.type.1 = interface_witness_access imports.%import_ref.5, element0 [template = constants.%F.2] // CHECK:STDOUT: %F.call: init %.4 = call %.loc5() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.3) { +// CHECK:STDOUT: generic fn @F.1(constants.%Self: %.1) { // CHECK:STDOUT: // CHECK:STDOUT: fn(); // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon b/toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon new file mode 100644 index 000000000000..4d2f2cb8c38f --- /dev/null +++ b/toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon @@ -0,0 +1,335 @@ +// 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/generic_redeclaration.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon + +// --- same_self_and_interface.carbon + +library "[[@TEST_NAME]]"; + +interface I {} +interface J {} +interface K {} + +impl forall [T:! I] T as K; +impl forall [T:! J] T as K; + +// These are two different impls, so this is not a redefinition, even though the +// self type and constraint type are the same. +impl forall [T:! I] T as K {} +impl forall [T:! J] T as K {} + +// --- fail_same_self_and_interface_redefined.carbon + +library "[[@TEST_NAME]]"; + +interface I {} +interface J {} + +impl forall [T:! I] T as J {} +// CHECK:STDERR: fail_same_self_and_interface_redefined.carbon:[[@LINE+6]]:1: error: redefinition of `impl T as J` +// CHECK:STDERR: impl forall [T:! I] T as J {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_same_self_and_interface_redefined.carbon:[[@LINE-4]]:1: note: previous definition was here +// CHECK:STDERR: impl forall [T:! I] T as J {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ +impl forall [T:! I] T as J {} + +// --- same_type_different_spelling.carbon + +library "[[@TEST_NAME]]"; + +class C; +interface I {} + +// We accept this because these two types are spelled differently, even though +// they evaluate to the same type constant. Any use of this impl will be +// ambiguous unless resolved by a `match_first` or similar. +// +// TODO: Produce a warning or maybe an error when this happens in a non-generic +// impl. +impl C as I {} +impl (C, C).0 as I {} + +// CHECK:STDOUT: --- same_self_and_interface.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @I [template] +// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @J [template] +// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.3: type = interface_type @K [template] +// CHECK:STDOUT: %Self.3: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %T.1: %.1 = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %T.2: %.2 = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: = interface_witness () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .J = %J.decl +// CHECK:STDOUT: .K = %K.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} {} +// CHECK:STDOUT: %J.decl: type = interface_decl @J [template = constants.%.2] {} {} +// CHECK:STDOUT: %K.decl: type = interface_decl @K [template = constants.%.3] {} {} +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %T.patt: %.1 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: %T.param: %.1 = param T, runtime_param +// CHECK:STDOUT: %T.loc8: %.1 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T.loc8 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %.loc8_21.1: type = facet_type_access %T.ref [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %.loc8_21.2: type = converted %T.ref, %.loc8_21.1 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %K.ref: type = name_ref K, file.%K.decl [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %T.patt: %.2 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [template = constants.%.2] +// CHECK:STDOUT: %T.param: %.2 = param T, runtime_param +// CHECK:STDOUT: %T.loc9: %.2 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %T.ref: %.2 = name_ref T, %T.loc9 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %.loc9_21.1: type = facet_type_access %T.ref [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %.loc9_21.2: type = converted %T.ref, %.loc9_21.1 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %K.ref: type = name_ref K, file.%K.decl [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.3 { +// CHECK:STDOUT: %T.patt: %.1 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: %T.param: %.1 = param T, runtime_param +// CHECK:STDOUT: %T.loc13: %.1 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %T.ref: %.1 = name_ref T, %T.loc13 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %.loc13_21.1: type = facet_type_access %T.ref [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %.loc13_21.2: type = converted %T.ref, %.loc13_21.1 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: %K.ref: type = name_ref K, file.%K.decl [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.4 { +// CHECK:STDOUT: %T.patt: %.2 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [template = constants.%.2] +// CHECK:STDOUT: %T.param: %.2 = param T, runtime_param +// CHECK:STDOUT: %T.loc14: %.2 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %T.ref: %.2 = name_ref T, %T.loc14 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %.loc14_21.1: type = facet_type_access %T.ref [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %.loc14_21.2: type = converted %T.ref, %.loc14_21.1 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: %K.ref: type = name_ref K, file.%K.decl [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @J { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @K { +// CHECK:STDOUT: %Self: %.3 = bind_symbolic_name Self 0 [symbolic = constants.%Self.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.1(%T.loc8: %.1) { +// CHECK:STDOUT: %T.1: %.1 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %T.1 as %.3; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.2(%T.loc9: %.2) { +// CHECK:STDOUT: %T.1: %.2 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %T.2 as %.3; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.3(%T.loc13: %.1) { +// CHECK:STDOUT: %T.1: %.1 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %T.1 as %.3 { +// CHECK:STDOUT: %.loc13_28: = interface_witness () [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc13_28 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.4(%T.loc14: %.2) { +// CHECK:STDOUT: %T.1: %.2 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %T.2 as %.3 { +// CHECK:STDOUT: %.loc14_28: = interface_witness () [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc14_28 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.1(constants.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.2(constants.%T.2) { +// CHECK:STDOUT: %T.1 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.3(constants.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.4(constants.%T.2) { +// CHECK:STDOUT: %T.1 => constants.%T.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_same_self_and_interface_redefined.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @I [template] +// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @J [template] +// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %T: %.1 = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %.4: = interface_witness () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .J = %J.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} {} +// CHECK:STDOUT: %J.decl: type = interface_decl @J [template = constants.%.2] {} {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %T.patt: %.1 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %I.ref.loc7: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: %T.param.loc7: %.1 = param T, runtime_param +// CHECK:STDOUT: %T.loc7: %.1 = bind_symbolic_name T 0, %T.param.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %T.ref.loc7: %.1 = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc7_21.1: type = facet_type_access %T.ref.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc7_21.2: type = converted %T.ref.loc7, %.loc7_21.1 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %J.ref.loc7: type = name_ref J, file.%J.decl [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %T.patt: %.1 = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %I.ref.loc14: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: %T.param.loc14: %.1 = param T, runtime_param +// CHECK:STDOUT: %T.loc14: %.1 = bind_symbolic_name T 0, %T.param.loc14 [symbolic = constants.%T] +// CHECK:STDOUT: %T.ref.loc14: %.1 = name_ref T, %T.loc14 [symbolic = constants.%T] +// CHECK:STDOUT: %.loc14_21.1: type = facet_type_access %T.ref.loc14 [symbolic = constants.%T] +// CHECK:STDOUT: %.loc14_21.2: type = converted %T.ref.loc14, %.loc14_21.1 [symbolic = constants.%T] +// CHECK:STDOUT: %J.ref.loc14: type = name_ref J, file.%J.decl [template = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @J { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl(%T.loc7: %.1) { +// CHECK:STDOUT: %T.1: %.1 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %T as %.2 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = .inst+21.loc7_28 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- same_type_different_spelling.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = interface_type @I [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: = interface_witness () [template] +// CHECK:STDOUT: %.4: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %.5: i32 = int_literal 0 [template] +// CHECK:STDOUT: %.6: type = ptr_type %.4 [template] +// CHECK:STDOUT: %tuple: %.4 = tuple_value (%C, %C) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} {} +// CHECK:STDOUT: impl_decl @impl.1 {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 {} { +// CHECK:STDOUT: %C.ref.loc14_7: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %C.ref.loc14_10: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc14_11.1: %.4 = tuple_literal (%C.ref.loc14_7, %C.ref.loc14_10) +// CHECK:STDOUT: %.loc14_13: i32 = int_literal 0 [template = constants.%.5] +// CHECK:STDOUT: %tuple: %.4 = tuple_value (%C.ref.loc14_7, %C.ref.loc14_10) [template = constants.%tuple] +// CHECK:STDOUT: %.loc14_11.2: %.4 = converted %.loc14_11.1, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %.loc14_12: type = tuple_access %.loc14_11.2, element0 [template = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.1: %C as %.1 { +// CHECK:STDOUT: %.loc13: = interface_witness () [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: %C as %.1 { +// CHECK:STDOUT: %.loc14_20: = interface_witness () [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc14_20 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/import_generic.carbon b/toolchain/check/testdata/impl/no_prelude/import_generic.carbon new file mode 100644 index 000000000000..123267215d62 --- /dev/null +++ b/toolchain/check/testdata/impl/no_prelude/import_generic.carbon @@ -0,0 +1,408 @@ +// 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/import_generic.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/import_generic.carbon + +// --- import_generic.carbon + +library "[[@TEST_NAME]]"; + +class C {} +interface I(T:! type) {} + +impl forall [T:! type] C as I(T); +impl forall [T:! type] C as I(T*) {} + +// --- import_generic.impl.carbon + +impl library "[[@TEST_NAME]]"; + +impl forall [T:! type] C as I(T) {} + +// --- fail_import_generic.impl.carbon + +impl library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+7]]:1: error: redefinition of `impl C as I` +// CHECK:STDERR: impl forall [T:! type] C as I(T*) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE-5]]:6: in import +// CHECK:STDERR: import_generic.carbon:8:1: note: previous definition was here +// CHECK:STDERR: impl forall [T:! type] C as I(T*) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +impl forall [T:! type] C as I(T*) {} + +// CHECK:STDOUT: --- import_generic.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %I.type: type = generic_interface_type @I [template] +// CHECK:STDOUT: %.3: type = tuple_type () [template] +// CHECK:STDOUT: %I: %I.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = interface_type @I, @I(%T) [symbolic] +// CHECK:STDOUT: %Self: %.4 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %.5: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %.6: type = interface_type @I, @I(%.5) [symbolic] +// CHECK:STDOUT: %.7: = interface_witness () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %I.decl: %I.type = interface_decl @I [template = constants.%I] { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc5: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.1 { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc7: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc7 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc7: type = interface_type @I, @I(constants.%T) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @impl.2 { +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T 0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc8: type = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc8 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.loc8_32: type = ptr_type %T [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %.loc8_30: type = interface_type @I, @I(constants.%.5) [symbolic = %.2 (constants.%.6)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @I(%T.loc5: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T.1) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @I.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.1(%T.loc7: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T.1) [symbolic = %.1 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.4; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.2(%T.loc8: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = ptr_type @impl.2.%T.1 (%T) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %.2: type = interface_type @I, @I(%.1) [symbolic = %.2 (constants.%.6)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.6 { +// CHECK:STDOUT: %.loc8_35: = interface_witness () [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc8_35 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc4: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@I.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.1.%T.1) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.1(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%.5) { +// CHECK:STDOUT: %T.1 => constants.%.5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.2.%.1) { +// CHECK:STDOUT: %T.1 => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.2(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %.2 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_generic.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %I.type: type = generic_interface_type @I [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %I: %I.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = interface_type @I, @I(%T) [symbolic] +// CHECK:STDOUT: %Self.1: @I.%.1 (%.2) = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.3: type = struct_type {} [template] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [template] +// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %.5: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %.6: type = interface_type @I, @I(%.5) [symbolic] +// CHECK:STDOUT: %.7: = interface_witness () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//import_generic, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: %I.type = import_ref Main//import_generic, inst+10, loaded [template = constants.%I] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//import_generic, inst+16, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//import_generic, inst+2, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//import_generic, inst+44, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .I = imports.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: impl_decl @impl.1 {} { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc4: type = bind_symbolic_name T 0, %T.param [symbolic = constants.%T] +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, imports.%import_ref.2 [template = constants.%I] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4 [symbolic = constants.%T] +// CHECK:STDOUT: %.loc4_30: type = interface_type @I, @I(constants.%T) [symbolic = constants.%.2] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @I(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.1(constants.%T: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T.1) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.2 { +// CHECK:STDOUT: %.loc4_34: = interface_witness () [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc4_34 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.2(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.1: type = ptr_type @impl.2.%T (%T) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %.2: type = interface_type @I, @I(%.1) [symbolic = %.2 (constants.%.6)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.6 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = imports.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@I.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.1.%T.1) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.1(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%.5) { +// CHECK:STDOUT: %T => constants.%.5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.2.%.1) { +// CHECK:STDOUT: %T => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.2(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %.2 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_generic.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %I.type: type = generic_interface_type @I [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %I: %I.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = interface_type @I, @I(%T) [symbolic] +// CHECK:STDOUT: %Self.1: @I.%.1 (%.2) = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.3: type = struct_type {} [template] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [template] +// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %.5: type = ptr_type %T [symbolic] +// CHECK:STDOUT: %.6: type = interface_type @I, @I(%.5) [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//import_generic, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: %I.type = import_ref Main//import_generic, inst+10, loaded [template = constants.%I] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//import_generic, inst+16, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//import_generic, inst+2, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//import_generic, inst+44, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = imports.%import_ref.1 +// CHECK:STDOUT: .I = imports.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: impl_decl @impl.2 {} { +// CHECK:STDOUT: %T.param: type = param T, runtime_param +// CHECK:STDOUT: %T.loc11: type = bind_symbolic_name T 0, %T.param [symbolic = constants.%T] +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %I.ref: %I.type = name_ref I, imports.%import_ref.2 [template = constants.%I] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc11 [symbolic = constants.%T] +// CHECK:STDOUT: %.loc11_32: type = ptr_type %T [symbolic = constants.%.5] +// CHECK:STDOUT: %.loc11_30: type = interface_type @I, @I(constants.%.5) [symbolic = constants.%.6] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @I(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.1(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %.1: type = interface_type @I, @I(%T) [symbolic = %.1 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.2; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl.2(constants.%T: type) { +// CHECK:STDOUT: %T.1: type = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: %.1: type = ptr_type @impl.2.%T.1 (%T) [symbolic = %.1 (constants.%.5)] +// CHECK:STDOUT: %.2: type = interface_type @I, @I(%.1) [symbolic = %.2 (constants.%.6)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %C as %.6 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = imports.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@I.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.1.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.1(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %.1 => constants.%.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%.5) { +// CHECK:STDOUT: %T => constants.%.5 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.2.%.1) { +// CHECK:STDOUT: %T => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl.2(constants.%T) { +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: %.1 => constants.%.5 +// CHECK:STDOUT: %.2 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/no_prelude/interface_args.carbon b/toolchain/check/testdata/impl/no_prelude/interface_args.carbon index 8a6fd56c6084..183cf0b8f5d9 100644 --- a/toolchain/check/testdata/impl/no_prelude/interface_args.carbon +++ b/toolchain/check/testdata/impl/no_prelude/interface_args.carbon @@ -244,10 +244,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: --- action.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %A: type = class_type @A [template] +// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %Action.type: type = generic_interface_type @Action [template] // CHECK:STDOUT: %.3: type = tuple_type () [template] // CHECK:STDOUT: %Action: %Action.type = struct_value () [template] @@ -255,19 +254,20 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %.4: type = interface_type @Action, @Action(%T) [symbolic] // CHECK:STDOUT: %Self.1: @Action.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.5: type = interface_type @Action, @Action(%B) [template] +// CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %Op.type.1: type = fn_type @Op.1, @Action(%T) [symbolic] // CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.6: type = assoc_entity_type %.4, %Op.type.1 [symbolic] -// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.11 [symbolic] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.13 [symbolic] // CHECK:STDOUT: %Op.type.2: type = fn_type @Op.1, @Action(%B) [template] // CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template] // CHECK:STDOUT: %.8: type = assoc_entity_type %.5, %Op.type.2 [template] -// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.12 [template] +// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.14 [template] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] // CHECK:STDOUT: %.10: type = ptr_type %.1 [template] -// CHECK:STDOUT: %.11: %.6 = assoc_entity element0, imports.%import_ref.14 [symbolic] +// CHECK:STDOUT: %.11: %.6 = assoc_entity element0, imports.%import_ref.15 [symbolic] // CHECK:STDOUT: %Op.type.3: type = fn_type @Op.2 [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] // CHECK:STDOUT: %.12: = interface_witness (%Op.3) [template] @@ -279,15 +279,16 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %import_ref.3: type = import_ref Main//action, inst+30, loaded [template = constants.%B] // CHECK:STDOUT: %import_ref.4 = import_ref Main//action, inst+33, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//action, inst+56, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//action, inst+26, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//action, inst+31, unloaded -// CHECK:STDOUT: %import_ref.8 = import_ref Main//action, inst+11, unloaded -// CHECK:STDOUT: %import_ref.9: @Action.%.2 (%.6) = import_ref Main//action, inst+17, loaded [symbolic = @Action.%.3 (constants.%.11)] -// CHECK:STDOUT: %import_ref.10 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.12 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.13: = import_ref Main//action, inst+49, loaded [template = constants.%.12] +// CHECK:STDOUT: %import_ref.6 = import_ref Main//action, inst+31, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//action, inst+11, unloaded +// CHECK:STDOUT: %import_ref.8: @Action.%.2 (%.6) = import_ref Main//action, inst+17, loaded [symbolic = @Action.%.3 (constants.%.11)] +// CHECK:STDOUT: %import_ref.9 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//action, inst+26, unloaded +// CHECK:STDOUT: %import_ref.11: = import_ref Main//action, inst+49, loaded [template = constants.%.12] +// CHECK:STDOUT: %import_ref.12 = import_ref Main//action, inst+42, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Main//action, inst+13, unloaded // CHECK:STDOUT: %import_ref.14 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.15 = import_ref Main//action, inst+13, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -319,29 +320,30 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Op.type: type = fn_type @Op.1, @Action(%T) [symbolic = %Op.type (constants.%Op.type.1)] // CHECK:STDOUT: %Op: @Action.%Op.type (%Op.type.1) = struct_value () [symbolic = %Op (constants.%Op.1)] // CHECK:STDOUT: %.2: type = assoc_entity_type @Action.%.1 (%.4), @Action.%Op.type (%Op.type.1) [symbolic = %.2 (constants.%.6)] -// CHECK:STDOUT: %.3: @Action.%.2 (%.6) = assoc_entity element0, imports.%import_ref.11 [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: %.3: @Action.%.2 (%.6) = assoc_entity element0, imports.%import_ref.13 [symbolic = %.3 (constants.%.7)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.8 -// CHECK:STDOUT: .Op = imports.%import_ref.9 -// CHECK:STDOUT: witness = (imports.%import_ref.10) +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .Op = imports.%import_ref.8 +// CHECK:STDOUT: witness = (imports.%import_ref.9) // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %A as %.5 { // CHECK:STDOUT: !members: -// CHECK:STDOUT: witness = imports.%import_ref.13 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @A { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: .Op = imports.%import_ref.12 +// CHECK:STDOUT: witness = imports.%import_ref.11 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.10 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @Op.1(constants.%T: type, constants.%Self.1: @Action.%.1 (%.4)) { @@ -355,9 +357,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Action.ref: %Action.type = name_ref Action, imports.%import_ref.1 [template = constants.%Action] // CHECK:STDOUT: %B.ref: type = name_ref B, imports.%import_ref.3 [template = constants.%B] // CHECK:STDOUT: %.loc4_23: type = interface_type @Action, @Action(constants.%B) [template = constants.%.5] -// CHECK:STDOUT: %.loc4_26: %.8 = specific_constant imports.%import_ref.9, @Action(constants.%B) [template = constants.%.9] +// CHECK:STDOUT: %.loc4_26: %.8 = specific_constant imports.%import_ref.8, @Action(constants.%B) [template = constants.%.9] // CHECK:STDOUT: %Op.ref: %.8 = name_ref Op, %.loc4_26 [template = constants.%.9] -// CHECK:STDOUT: %.loc4_15: %Op.type.2 = interface_witness_access imports.%import_ref.13, element0 [template = constants.%Op.3] +// CHECK:STDOUT: %.loc4_15: %Op.type.2 = interface_witness_access imports.%import_ref.11, element0 [template = constants.%Op.3] // CHECK:STDOUT: %Op.call: init %.3 = call %.loc4_15() // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -389,10 +391,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: --- fail_action.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %A: type = class_type @A [template] +// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %Action.type: type = generic_interface_type @Action [template] // CHECK:STDOUT: %.3: type = tuple_type () [template] // CHECK:STDOUT: %Action: %Action.type = struct_value () [template] @@ -400,15 +401,16 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %.4: type = interface_type @Action, @Action(%T) [symbolic] // CHECK:STDOUT: %Self.1: @Action.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.5: type = interface_type @Action, @Action(%B) [template] +// CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %Op.type.1: type = fn_type @Op, @Action(%T) [symbolic] // CHECK:STDOUT: %Op.1: %Op.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.6: type = assoc_entity_type %.4, %Op.type.1 [symbolic] -// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.11 [symbolic] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.13 [symbolic] // CHECK:STDOUT: %Op.type.2: type = fn_type @Op, @Action(%B) [template] // CHECK:STDOUT: %Op.2: %Op.type.2 = struct_value () [template] // CHECK:STDOUT: %.8: type = assoc_entity_type %.5, %Op.type.2 [template] -// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.12 [template] +// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.14 [template] // CHECK:STDOUT: %G.type: type = fn_type @G [template] // CHECK:STDOUT: %G: %G.type = struct_value () [template] // CHECK:STDOUT: %.10: type = ptr_type %.1 [template] @@ -417,8 +419,8 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Op.type.3: type = fn_type @Op, @Action(%C) [template] // CHECK:STDOUT: %Op.3: %Op.type.3 = struct_value () [template] // CHECK:STDOUT: %.12: type = assoc_entity_type %.11, %Op.type.3 [template] -// CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.11 [template] -// CHECK:STDOUT: %.14: %.6 = assoc_entity element0, imports.%import_ref.15 [symbolic] +// CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.13 [template] +// CHECK:STDOUT: %.14: %.6 = assoc_entity element0, imports.%import_ref.16 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -427,16 +429,17 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %import_ref.3 = import_ref Main//action, inst+30, unloaded // CHECK:STDOUT: %import_ref.4: type = import_ref Main//action, inst+33, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.5 = import_ref Main//action, inst+56, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//action, inst+26, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//action, inst+31, unloaded -// CHECK:STDOUT: %import_ref.8 = import_ref Main//action, inst+11, unloaded -// CHECK:STDOUT: %import_ref.9: @Action.%.2 (%.6) = import_ref Main//action, inst+17, loaded [symbolic = @Action.%.3 (constants.%.14)] -// CHECK:STDOUT: %import_ref.10 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.12 = import_ref Main//action, inst+13, unloaded -// CHECK:STDOUT: %import_ref.13 = import_ref Main//action, inst+49, unloaded -// CHECK:STDOUT: %import_ref.14 = import_ref Main//action, inst+34, unloaded -// CHECK:STDOUT: %import_ref.15 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//action, inst+31, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//action, inst+11, unloaded +// CHECK:STDOUT: %import_ref.8: @Action.%.2 (%.6) = import_ref Main//action, inst+17, loaded [symbolic = @Action.%.3 (constants.%.14)] +// CHECK:STDOUT: %import_ref.9 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//action, inst+26, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//action, inst+49, unloaded +// CHECK:STDOUT: %import_ref.12 = import_ref Main//action, inst+42, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.14 = import_ref Main//action, inst+13, unloaded +// CHECK:STDOUT: %import_ref.15 = import_ref Main//action, inst+34, unloaded +// CHECK:STDOUT: %import_ref.16 = import_ref Main//action, inst+13, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -468,34 +471,35 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Op.type: type = fn_type @Op, @Action(%T) [symbolic = %Op.type (constants.%Op.type.1)] // CHECK:STDOUT: %Op: @Action.%Op.type (%Op.type.1) = struct_value () [symbolic = %Op (constants.%Op.1)] // CHECK:STDOUT: %.2: type = assoc_entity_type @Action.%.1 (%.4), @Action.%Op.type (%Op.type.1) [symbolic = %.2 (constants.%.6)] -// CHECK:STDOUT: %.3: @Action.%.2 (%.6) = assoc_entity element0, imports.%import_ref.11 [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: %.3: @Action.%.2 (%.6) = assoc_entity element0, imports.%import_ref.13 [symbolic = %.3 (constants.%.7)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.8 -// CHECK:STDOUT: .Op = imports.%import_ref.9 -// CHECK:STDOUT: witness = (imports.%import_ref.10) +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .Op = imports.%import_ref.8 +// CHECK:STDOUT: witness = (imports.%import_ref.9) // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %A as %.5 { // CHECK:STDOUT: !members: -// CHECK:STDOUT: witness = imports.%import_ref.13 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @A { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: .Op = imports.%import_ref.12 +// CHECK:STDOUT: witness = imports.%import_ref.11 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .Self = imports.%import_ref.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.10 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.14 +// CHECK:STDOUT: .Self = imports.%import_ref.15 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @Op(constants.%T: type, constants.%Self.1: @Action.%.1 (%.4)) { @@ -509,7 +513,7 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Action.ref: %Action.type = name_ref Action, imports.%import_ref.1 [template = constants.%Action] // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.4 [template = constants.%C] // CHECK:STDOUT: %.loc8_23: type = interface_type @Action, @Action(constants.%C) [template = constants.%.11] -// CHECK:STDOUT: %.loc8_26: %.12 = specific_constant imports.%import_ref.9, @Action(constants.%C) [template = constants.%.13] +// CHECK:STDOUT: %.loc8_26: %.12 = specific_constant imports.%import_ref.8, @Action(constants.%C) [template = constants.%.13] // CHECK:STDOUT: %Op.ref: %.12 = name_ref Op, %.loc8_26 [template = constants.%.13] // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -688,10 +692,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: --- factory.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %A: type = class_type @A [template] +// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %Factory.type: type = generic_interface_type @Factory [template] // CHECK:STDOUT: %.3: type = tuple_type () [template] // CHECK:STDOUT: %Factory: %Factory.type = struct_value () [template] @@ -699,19 +702,20 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %.4: type = interface_type @Factory, @Factory(%T) [symbolic] // CHECK:STDOUT: %Self.1: @Factory.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.5: type = interface_type @Factory, @Factory(%B) [template] +// CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %Make.type.1: type = fn_type @Make.1, @Factory(%T) [symbolic] // CHECK:STDOUT: %Make.1: %Make.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.6: type = assoc_entity_type %.4, %Make.type.1 [symbolic] -// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.9 [symbolic] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.11 [symbolic] // CHECK:STDOUT: %Make.type.2: type = fn_type @Make.1, @Factory(%B) [template] // CHECK:STDOUT: %Make.2: %Make.type.2 = struct_value () [template] // CHECK:STDOUT: %.8: type = assoc_entity_type %.5, %Make.type.2 [template] -// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.10 [template] +// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.12 [template] // CHECK:STDOUT: %MakeB.type: type = fn_type @MakeB [template] // CHECK:STDOUT: %MakeB: %MakeB.type = struct_value () [template] // CHECK:STDOUT: %.10: type = ptr_type %.1 [template] -// CHECK:STDOUT: %.11: %.6 = assoc_entity element0, imports.%import_ref.12 [symbolic] +// CHECK:STDOUT: %.11: %.6 = assoc_entity element0, imports.%import_ref.13 [symbolic] // CHECK:STDOUT: %Make.type.3: type = fn_type @Make.2 [template] // CHECK:STDOUT: %Make.3: %Make.type.3 = struct_value () [template] // CHECK:STDOUT: %.12: = interface_witness (%Make.3) [template] @@ -721,15 +725,16 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %import_ref.1: %Factory.type = import_ref Main//factory, inst+5, loaded [template = constants.%Factory] // CHECK:STDOUT: %import_ref.2: type = import_ref Main//factory, inst+28, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.3: type = import_ref Main//factory, inst+33, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//factory, inst+29, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//factory, inst+34, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//factory, inst+11, unloaded -// CHECK:STDOUT: %import_ref.7: @Factory.%.2 (%.6) = import_ref Main//factory, inst+20, loaded [symbolic = @Factory.%.3 (constants.%.11)] -// CHECK:STDOUT: %import_ref.8 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.10 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.11: = import_ref Main//factory, inst+51, loaded [template = constants.%.12] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//factory, inst+34, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//factory, inst+11, unloaded +// CHECK:STDOUT: %import_ref.6: @Factory.%.2 (%.6) = import_ref Main//factory, inst+20, loaded [symbolic = @Factory.%.3 (constants.%.11)] +// CHECK:STDOUT: %import_ref.7 = import_ref Main//factory, inst+15, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref Main//factory, inst+29, unloaded +// CHECK:STDOUT: %import_ref.9: = import_ref Main//factory, inst+51, loaded [template = constants.%.12] +// CHECK:STDOUT: %import_ref.10 = import_ref Main//factory, inst+44, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//factory, inst+15, unloaded // CHECK:STDOUT: %import_ref.12 = import_ref Main//factory, inst+15, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Main//factory, inst+15, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -761,29 +766,30 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Make.type: type = fn_type @Make.1, @Factory(%T) [symbolic = %Make.type (constants.%Make.type.1)] // CHECK:STDOUT: %Make: @Factory.%Make.type (%Make.type.1) = struct_value () [symbolic = %Make (constants.%Make.1)] // CHECK:STDOUT: %.2: type = assoc_entity_type @Factory.%.1 (%.4), @Factory.%Make.type (%Make.type.1) [symbolic = %.2 (constants.%.6)] -// CHECK:STDOUT: %.3: @Factory.%.2 (%.6) = assoc_entity element0, imports.%import_ref.9 [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: %.3: @Factory.%.2 (%.6) = assoc_entity element0, imports.%import_ref.11 [symbolic = %.3 (constants.%.7)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 -// CHECK:STDOUT: .Make = imports.%import_ref.7 -// CHECK:STDOUT: witness = (imports.%import_ref.8) +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .Make = imports.%import_ref.6 +// CHECK:STDOUT: witness = (imports.%import_ref.7) // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %A as %.5 { // CHECK:STDOUT: !members: -// CHECK:STDOUT: witness = imports.%import_ref.11 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @A { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: .Make = imports.%import_ref.10 +// CHECK:STDOUT: witness = imports.%import_ref.9 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.8 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @Make.1(constants.%T: type, constants.%Self.1: @Factory.%.1 (%.4)) { @@ -798,9 +804,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Factory.ref: %Factory.type = name_ref Factory, imports.%import_ref.1 [template = constants.%Factory] // CHECK:STDOUT: %B.ref.loc5: type = name_ref B, imports.%import_ref.3 [template = constants.%B] // CHECK:STDOUT: %.loc5_20: type = interface_type @Factory, @Factory(constants.%B) [template = constants.%.5] -// CHECK:STDOUT: %.loc5_23: %.8 = specific_constant imports.%import_ref.7, @Factory(constants.%B) [template = constants.%.9] +// CHECK:STDOUT: %.loc5_23: %.8 = specific_constant imports.%import_ref.6, @Factory(constants.%B) [template = constants.%.9] // CHECK:STDOUT: %Make.ref: %.8 = name_ref Make, %.loc5_23 [template = constants.%.9] -// CHECK:STDOUT: %.loc5_11: %Make.type.2 = interface_witness_access imports.%import_ref.11, element0 [template = constants.%Make.3] +// CHECK:STDOUT: %.loc5_11: %Make.type.2 = interface_witness_access imports.%import_ref.9, element0 [template = constants.%Make.3] // CHECK:STDOUT: %.loc4: ref %B = splice_block %return {} // CHECK:STDOUT: %Make.call: init %B = call %.loc5_11() to %.loc4 // CHECK:STDOUT: return %Make.call to %return @@ -835,10 +841,9 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: --- fail_factory.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %A: type = class_type @A [template] +// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] -// CHECK:STDOUT: %B: type = class_type @B [template] // CHECK:STDOUT: %Factory.type: type = generic_interface_type @Factory [template] // CHECK:STDOUT: %.3: type = tuple_type () [template] // CHECK:STDOUT: %Factory: %Factory.type = struct_value () [template] @@ -846,15 +851,16 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %.4: type = interface_type @Factory, @Factory(%T) [symbolic] // CHECK:STDOUT: %Self.1: @Factory.%.1 (%.4) = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %.5: type = interface_type @Factory, @Factory(%B) [template] +// CHECK:STDOUT: %A: type = class_type @A [template] // CHECK:STDOUT: %Self.2: %.4 = bind_symbolic_name Self 1 [symbolic] // CHECK:STDOUT: %Make.type.1: type = fn_type @Make, @Factory(%T) [symbolic] // CHECK:STDOUT: %Make.1: %Make.type.1 = struct_value () [symbolic] // CHECK:STDOUT: %.6: type = assoc_entity_type %.4, %Make.type.1 [symbolic] -// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.9 [symbolic] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, imports.%import_ref.11 [symbolic] // CHECK:STDOUT: %Make.type.2: type = fn_type @Make, @Factory(%B) [template] // CHECK:STDOUT: %Make.2: %Make.type.2 = struct_value () [template] // CHECK:STDOUT: %.8: type = assoc_entity_type %.5, %Make.type.2 [template] -// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.10 [template] +// CHECK:STDOUT: %.9: %.8 = assoc_entity element0, imports.%import_ref.12 [template] // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %MakeC.type: type = fn_type @MakeC [template] // CHECK:STDOUT: %MakeC: %MakeC.type = struct_value () [template] @@ -863,23 +869,24 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Make.type.3: type = fn_type @Make, @Factory(%C) [template] // CHECK:STDOUT: %Make.3: %Make.type.3 = struct_value () [template] // CHECK:STDOUT: %.12: type = assoc_entity_type %.11, %Make.type.3 [template] -// CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.9 [template] -// CHECK:STDOUT: %.14: %.6 = assoc_entity element0, imports.%import_ref.12 [symbolic] +// CHECK:STDOUT: %.13: %.12 = assoc_entity element0, imports.%import_ref.11 [template] +// CHECK:STDOUT: %.14: %.6 = assoc_entity element0, imports.%import_ref.13 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Factory.type = import_ref Main//factory, inst+5, loaded [template = constants.%Factory] // CHECK:STDOUT: %import_ref.2: type = import_ref Main//factory, inst+28, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.3 = import_ref Main//factory, inst+33, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//factory, inst+29, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//factory, inst+34, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//factory, inst+11, unloaded -// CHECK:STDOUT: %import_ref.7: @Factory.%.2 (%.6) = import_ref Main//factory, inst+20, loaded [symbolic = @Factory.%.3 (constants.%.14)] -// CHECK:STDOUT: %import_ref.8 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.10 = import_ref Main//factory, inst+15, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//factory, inst+51, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//factory, inst+34, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//factory, inst+11, unloaded +// CHECK:STDOUT: %import_ref.6: @Factory.%.2 (%.6) = import_ref Main//factory, inst+20, loaded [symbolic = @Factory.%.3 (constants.%.14)] +// CHECK:STDOUT: %import_ref.7 = import_ref Main//factory, inst+15, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref Main//factory, inst+29, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref Main//factory, inst+51, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//factory, inst+44, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//factory, inst+15, unloaded // CHECK:STDOUT: %import_ref.12 = import_ref Main//factory, inst+15, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Main//factory, inst+15, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -913,29 +920,30 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Make.type: type = fn_type @Make, @Factory(%T) [symbolic = %Make.type (constants.%Make.type.1)] // CHECK:STDOUT: %Make: @Factory.%Make.type (%Make.type.1) = struct_value () [symbolic = %Make (constants.%Make.1)] // CHECK:STDOUT: %.2: type = assoc_entity_type @Factory.%.1 (%.4), @Factory.%Make.type (%Make.type.1) [symbolic = %.2 (constants.%.6)] -// CHECK:STDOUT: %.3: @Factory.%.2 (%.6) = assoc_entity element0, imports.%import_ref.9 [symbolic = %.3 (constants.%.7)] +// CHECK:STDOUT: %.3: @Factory.%.2 (%.6) = assoc_entity element0, imports.%import_ref.11 [symbolic = %.3 (constants.%.7)] // CHECK:STDOUT: // CHECK:STDOUT: interface { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.6 -// CHECK:STDOUT: .Make = imports.%import_ref.7 -// CHECK:STDOUT: witness = (imports.%import_ref.8) +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .Make = imports.%import_ref.6 +// CHECK:STDOUT: witness = (imports.%import_ref.7) // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @impl: %A as %.5 { // CHECK:STDOUT: !members: -// CHECK:STDOUT: witness = imports.%import_ref.11 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @A { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: .Make = imports.%import_ref.10 +// CHECK:STDOUT: witness = imports.%import_ref.9 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @B { // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .Self = imports.%import_ref.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @A { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.8 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -957,7 +965,7 @@ fn MakeC(a: A) -> C { // CHECK:STDOUT: %Factory.ref: %Factory.type = name_ref Factory, imports.%import_ref.1 [template = constants.%Factory] // CHECK:STDOUT: %C.ref.loc10: type = name_ref C, file.%C.decl [template = constants.%C] // CHECK:STDOUT: %.loc10_20: type = interface_type @Factory, @Factory(constants.%C) [template = constants.%.11] -// CHECK:STDOUT: %.loc10_23: %.12 = specific_constant imports.%import_ref.7, @Factory(constants.%C) [template = constants.%.13] +// CHECK:STDOUT: %.loc10_23: %.12 = specific_constant imports.%import_ref.6, @Factory(constants.%C) [template = constants.%.13] // CHECK:STDOUT: %Make.ref: %.12 = name_ref Make, %.loc10_23 [template = constants.%.13] // CHECK:STDOUT: return to %return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/no_prelude/no_definition_in_impl_file.carbon b/toolchain/check/testdata/impl/no_prelude/no_definition_in_impl_file.carbon index d150f8f6b29a..4aff59a7b874 100644 --- a/toolchain/check/testdata/impl/no_prelude/no_definition_in_impl_file.carbon +++ b/toolchain/check/testdata/impl/no_prelude/no_definition_in_impl_file.carbon @@ -112,14 +112,14 @@ impl () as D; // CHECK:STDOUT: --- decl_in_api_definition_in_impl.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %.2: type = interface_type @A [template] -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.1: type = interface_type @A [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %.3: = interface_witness () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//decl_in_api_definition_in_impl, inst+1, loaded [template = constants.%.2] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//decl_in_api_definition_in_impl, inst+1, loaded [template = constants.%.1] // CHECK:STDOUT: %import_ref.2 = import_ref Main//decl_in_api_definition_in_impl, inst+3, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: @@ -130,14 +130,14 @@ impl () as D; // CHECK:STDOUT: %default.import.loc2_6.1 = import // CHECK:STDOUT: %default.import.loc2_6.2 = import // CHECK:STDOUT: impl_decl @impl {} { -// CHECK:STDOUT: %.loc4_7.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc4_7.2: type = converted %.loc4_7.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %A.ref.loc4: type = name_ref A, imports.%import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc4_7.1: %.2 = tuple_literal () +// CHECK:STDOUT: %.loc4_7.2: type = converted %.loc4_7.1, constants.%.2 [template = constants.%.2] +// CHECK:STDOUT: %A.ref.loc4: type = name_ref A, imports.%import_ref.1 [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: impl_decl @impl {} { -// CHECK:STDOUT: %.loc6_7.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc6_7.2: type = converted %.loc6_7.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %A.ref.loc6: type = name_ref A, imports.%import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc6_7.1: %.2 = tuple_literal () +// CHECK:STDOUT: %.loc6_7.2: type = converted %.loc6_7.1, constants.%.2 [template = constants.%.2] +// CHECK:STDOUT: %A.ref.loc6: type = name_ref A, imports.%import_ref.1 [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -147,7 +147,7 @@ impl () as D; // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %.1 as %.2 { +// CHECK:STDOUT: impl @impl: %.2 as %.1 { // CHECK:STDOUT: %.loc6_14: = interface_witness () [template = constants.%.3] // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -163,9 +163,9 @@ impl () as D; // CHECK:STDOUT: --- use_decl_in_api.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %.2: type = interface_type @A [template] -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.1: type = interface_type @A [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -187,7 +187,7 @@ impl () as D; // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %.1 as %.2; +// CHECK:STDOUT: impl @impl: %.2 as %.1; // CHECK:STDOUT: // CHECK:STDOUT: --- decl_only_in_api.carbon // CHECK:STDOUT: @@ -222,9 +222,9 @@ impl () as D; // CHECK:STDOUT: --- decl_only_in_api.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %.2: type = interface_type @B [template] -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.1: type = interface_type @B [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -246,7 +246,7 @@ impl () as D; // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %.1 as %.2; +// CHECK:STDOUT: impl @impl: %.2 as %.1; // CHECK:STDOUT: // CHECK:STDOUT: --- decl_in_api_decl_in_impl.carbon // CHECK:STDOUT: @@ -281,13 +281,13 @@ impl () as D; // CHECK:STDOUT: --- fail_decl_in_api_decl_in_impl.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %.2: type = interface_type @C [template] -// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.1: type = interface_type @C [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//decl_in_api_decl_in_impl, inst+1, loaded [template = constants.%.2] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//decl_in_api_decl_in_impl, inst+1, loaded [template = constants.%.1] // CHECK:STDOUT: %import_ref.2 = import_ref Main//decl_in_api_decl_in_impl, inst+3, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: @@ -298,9 +298,9 @@ impl () as D; // CHECK:STDOUT: %default.import.loc2_6.1 = import // CHECK:STDOUT: %default.import.loc2_6.2 = import // CHECK:STDOUT: impl_decl @impl {} { -// CHECK:STDOUT: %.loc8_7.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc8_7.2: type = converted %.loc8_7.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc8_7.1: %.2 = tuple_literal () +// CHECK:STDOUT: %.loc8_7.2: type = converted %.loc8_7.1, constants.%.2 [template = constants.%.2] +// CHECK:STDOUT: %C.ref: type = name_ref C, imports.%import_ref.1 [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -310,7 +310,7 @@ impl () as D; // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %.1 as %.2; +// CHECK:STDOUT: impl @impl: %.2 as %.1; // CHECK:STDOUT: // CHECK:STDOUT: --- decl_only_in_impl.carbon // CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/redeclaration.carbon b/toolchain/check/testdata/impl/redeclaration.carbon index 0098cc8c86fc..33f3cd931a46 100644 --- a/toolchain/check/testdata/impl/redeclaration.carbon +++ b/toolchain/check/testdata/impl/redeclaration.carbon @@ -55,18 +55,18 @@ impl i32 as I {} // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} {} -// CHECK:STDOUT: impl_decl @impl {} { +// CHECK:STDOUT: impl_decl @impl.1 {} { // CHECK:STDOUT: %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc13_6.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32] // CHECK:STDOUT: %.loc13_6.2: type = converted %int.make_type_32.loc13, %.loc13_6.1 [template = i32] // CHECK:STDOUT: %I.ref.loc13: type = name_ref I, file.%I.decl [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: %X.decl: type = class_decl @X [template = constants.%X] {} {} -// CHECK:STDOUT: impl_decl @impl {} { -// CHECK:STDOUT: %int.make_type_32.loc19: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc19_6.1: type = value_of_initializer %int.make_type_32.loc19 [template = i32] -// CHECK:STDOUT: %.loc19_6.2: type = converted %int.make_type_32.loc19, %.loc19_6.1 [template = i32] -// CHECK:STDOUT: %I.ref.loc19: type = name_ref I, file.%I.decl [template = constants.%.1] +// CHECK:STDOUT: impl_decl @impl.2 {} { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc19_6.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc19_6.2: type = converted %int.make_type_32, %.loc19_6.1 [template = i32] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -78,7 +78,9 @@ impl i32 as I {} // CHECK:STDOUT: witness = () // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: i32 as %.1 { +// CHECK:STDOUT: impl @impl.1: i32 as %.1; +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl.2: i32 as %.1 { // CHECK:STDOUT: %.loc19_15: = interface_witness () [template = constants.%.5] // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -86,7 +88,7 @@ impl i32 as I {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @X { -// CHECK:STDOUT: impl_decl @impl {} { +// CHECK:STDOUT: impl_decl @impl.1 {} { // CHECK:STDOUT: %int.make_type_32.loc16: init type = call constants.%Int32() [template = i32] // CHECK:STDOUT: %.loc16_8.1: type = value_of_initializer %int.make_type_32.loc16 [template = i32] // CHECK:STDOUT: %.loc16_8.2: type = converted %int.make_type_32.loc16, %.loc16_8.1 [template = i32] diff --git a/toolchain/check/testdata/interface/no_prelude/import_interface_decl.carbon b/toolchain/check/testdata/interface/no_prelude/import_interface_decl.carbon index dc70802ace6c..2e39b16083cf 100644 --- a/toolchain/check/testdata/interface/no_prelude/import_interface_decl.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import_interface_decl.carbon @@ -43,8 +43,8 @@ impl library "[[@TEST_NAME]]"; // CHECK:STDOUT: --- a.impl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %.2: type = interface_type @A [template] +// CHECK:STDOUT: %.1: type = interface_type @A [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -61,5 +61,5 @@ impl library "[[@TEST_NAME]]"; // CHECK:STDOUT: // CHECK:STDOUT: interface @A; // CHECK:STDOUT: -// CHECK:STDOUT: impl @impl: %.1 as %.2; +// CHECK:STDOUT: impl @impl: %.2 as %.1; // CHECK:STDOUT: diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 62492bc95f9a..8fad41c56d9d 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -223,10 +223,9 @@ class FormatterImpl { // Formats a full impl. auto FormatImpl(ImplId id) -> void { const Impl& impl_info = sem_ir_.impls().Get(id); - FormatEntityStart("impl", SemIR::GenericId::Invalid, id); + FormatEntityStart("impl", impl_info.generic_id, id); out_ << ": "; - // TODO: Include the deduced parameter list if present. FormatType(impl_info.self_id); out_ << " as "; FormatType(impl_info.constraint_id); @@ -256,6 +255,8 @@ class FormatterImpl { } else { out_ << ";\n"; } + + FormatEntityEnd(impl_info.generic_id); } // Formats a full function. diff --git a/toolchain/sem_ir/impl.h b/toolchain/sem_ir/impl.h index adc1d20f4f6d..ac5ff40a8c51 100644 --- a/toolchain/sem_ir/impl.h +++ b/toolchain/sem_ir/impl.h @@ -6,32 +6,16 @@ #define CARBON_TOOLCHAIN_SEM_IR_IMPL_H_ #include "common/map.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "toolchain/sem_ir/entity_with_params_base.h" #include "toolchain/sem_ir/ids.h" namespace Carbon::SemIR { -// An implementation of a constraint. -struct Impl : public Printable { - auto Print(llvm::raw_ostream& out) const -> void { - out << "{self: " << self_id << ", constraint: " << constraint_id << "}"; - } - - // Determines whether this impl has been fully defined. This is false until we - // reach the `}` of the impl definition. - auto is_defined() const -> bool { return witness_id.is_valid(); } - - // Determines whether this impl's definition has begun but not yet ended. - auto is_being_defined() const -> bool { - return definition_id.is_valid() && !is_defined(); - } - +struct ImplFields { // The following members always have values, and do not change throughout the // lifetime of the interface. - // A block containing the pattern insts for the `impl forall` parameters, - // if any. - InstBlockId pattern_block_id = InstBlockId::Invalid; - // TODO: Track the generic parameters for `impl forall`. // The type for which the impl is implementing a constraint. TypeId self_id; // The constraint that the impl implements. @@ -39,8 +23,6 @@ struct Impl : public Printable { // The following members are set at the `{` of the impl definition. - // The definition of the impl. This is an ImplDecl. - InstId definition_id = InstId::Invalid; // The impl scope. NameScopeId scope_id = NameScopeId::Invalid; // The first block of the impl body. @@ -53,20 +35,49 @@ struct Impl : public Printable { InstId witness_id = InstId::Invalid; }; +// An implementation of a constraint. See EntityWithParamsBase regarding the +// inheritance here. +struct Impl : public EntityWithParamsBase, + public ImplFields, + public Printable { + auto Print(llvm::raw_ostream& out) const -> void { + out << "{self: " << self_id << ", constraint: " << constraint_id << "}"; + } + + // Determines whether this impl has been fully defined. This is false until we + // reach the `}` of the impl definition. + auto is_defined() const -> bool { return witness_id.is_valid(); } + + // Determines whether this impl's definition has begun but not yet ended. + auto is_being_defined() const -> bool { + return definition_id.is_valid() && !is_defined(); + } +}; + // A collection of `Impl`s, which can be accessed by the self type and // constraint implemented. class ImplStore { public: - // Looks up the impl with this self type and constraint, or creates a new - // `Impl` if none exists. - // TODO: Handle parameters. - auto LookupOrAdd(TypeId self_id, TypeId constraint_id) -> ImplId { - auto result = lookup_.Insert(std::pair{self_id, constraint_id}, [&]() { - return values_.Add({.self_id = self_id, .constraint_id = constraint_id}); - }); - return result.value(); + // TODO: Switch to something like TinyPtrVector. We expect it to be rare for + // there to be more than one ImplId per bucket. + using LookupBucket = llvm::SmallVector; + + // Returns the lookup bucket containing the list of impls with this self type + // and constraint, or adds a new bucket if this is the first time we've seen + // an impl of this kind. The lookup bucket should only include impls from the + // current file and its API file; impls from other files should not be added + // to it. + auto GetOrAddLookupBucket(TypeId self_id, TypeId constraint_id) + -> LookupBucket& { + return lookup_ + .Insert(std::pair{self_id, constraint_id}, + [] { return LookupBucket(); }) + .value(); } + // Adds the specified impl to the store. Does not add it to impl lookup. + auto Add(Impl impl) -> ImplId { return values_.Add(impl); } + // Returns a mutable value for an ID. auto Get(ImplId id) -> Impl& { return values_.Get(id); } @@ -89,7 +100,7 @@ class ImplStore { private: ValueStore values_; - Map, ImplId> lookup_; + Map, LookupBucket> lookup_; }; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 05672d631ba8..01419b942371 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -107,7 +107,7 @@ InstNamer::InstNamer(const Lex::TokenizedBuffer& tokenized_buffer, globals_.AllocateName(*this, impl_loc, "impl"); AddBlockLabel(impl_scope, impl_info.body_block_id, "impl", impl_loc); CollectNamesInBlock(impl_scope, impl_info.body_block_id); - // TODO: Collect names from the generic once we support generic impls. + CollectNamesInGeneric(impl_scope, impl_info.generic_id); } }