diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 91d69d107b909..42f186997a0e8 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -321,10 +321,11 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id, // Walk the non-lexical scopes and perform lookups into each of them. for (auto [index, lookup_scope_id, specific_id] : llvm::reverse(non_lexical_scopes)) { - if (auto non_lexical_result = LookupQualifiedName( - node_id, name_id, - {.name_scope_id = lookup_scope_id, .specific_id = specific_id}, - /*required=*/false); + if (auto non_lexical_result = + LookupQualifiedName(node_id, name_id, + LookupScope{.name_scope_id = lookup_scope_id, + .specific_id = specific_id}, + /*required=*/false); non_lexical_result.inst_id.is_valid()) { return non_lexical_result; } @@ -440,11 +441,59 @@ struct ProhibitedAccessInfo { bool is_parent_access; }; +auto Context::AppendLookupScopesForConstant( + SemIRLoc loc, SemIR::ConstantId base_const_id, + llvm::SmallVector* scopes) -> bool { + auto base_id = constant_values().GetInstId(base_const_id); + auto base = insts().Get(base_id); + if (auto base_as_namespace = base.TryAs()) { + scopes->push_back( + LookupScope{.name_scope_id = base_as_namespace->name_scope_id, + .specific_id = SemIR::SpecificId::Invalid}); + return true; + } + if (auto base_as_class = base.TryAs()) { + TryToDefineType(GetTypeIdForTypeConstant(base_const_id), [&] { + CARBON_DIAGNOSTIC(QualifiedExprInIncompleteClassScope, Error, + "member access into incomplete class {0}", + InstIdAsType); + return emitter().Build(loc, QualifiedExprInIncompleteClassScope, base_id); + }); + auto& class_info = classes().Get(base_as_class->class_id); + scopes->push_back(LookupScope{.name_scope_id = class_info.scope_id, + .specific_id = base_as_class->specific_id}); + return true; + } + if (auto base_as_facet_type = base.TryAs()) { + TryToDefineType(GetTypeIdForTypeConstant(base_const_id), [&] { + CARBON_DIAGNOSTIC(QualifiedExprInUndefinedInterfaceScope, Error, + "member access into undefined interface {0}", + InstIdAsType); + return emitter().Build(loc, QualifiedExprInUndefinedInterfaceScope, + base_id); + }); + const auto& facet_type_info = + facet_types().Get(base_as_facet_type->facet_type_id); + for (auto interface : facet_type_info.impls_constraints) { + auto& interface_info = interfaces().Get(interface.interface_id); + scopes->push_back(LookupScope{.name_scope_id = interface_info.scope_id, + .specific_id = interface.specific_id}); + } + return true; + } + // TODO: Per the design, if `base_id` is any kind of type, then lookup should + // treat it as a name scope, even if it doesn't have members. For example, + // `(i32*).X` should fail because there's no name `X` in `i32*`, not because + // there's no name `X` in `type`. + return false; +} + auto Context::LookupQualifiedName(SemIRLoc loc, SemIR::NameId name_id, - LookupScope scope, bool required, + llvm::ArrayRef lookup_scopes, + bool required, std::optional access_info) -> LookupResult { - llvm::SmallVector scopes = {scope}; + llvm::SmallVector scopes(lookup_scopes); // TODO: Support reporting of multiple prohibited access. llvm::SmallVector prohibited_accesses; @@ -457,6 +506,10 @@ auto Context::LookupQualifiedName(SemIRLoc loc, SemIR::NameId name_id, // Walk this scope and, if nothing is found here, the scopes it extends. while (!scopes.empty()) { auto [scope_id, specific_id] = scopes.pop_back_val(); + if (!scope_id.is_valid()) { + has_error = true; + continue; + } const auto& name_scope = name_scopes().Get(scope_id); has_error |= name_scope.has_error; @@ -479,13 +532,25 @@ auto Context::LookupQualifiedName(SemIRLoc loc, SemIR::NameId name_id, if (!scope_result_id.is_valid() || is_access_prohibited) { // If nothing is found in this scope or if we encountered an invalid // access, look in its extended scopes. - auto extended = name_scope.extended_scopes; + const auto& extended = name_scope.extended_scopes; scopes.reserve(scopes.size() + extended.size()); for (auto extended_id : llvm::reverse(extended)) { - // TODO: Track a constant describing the extended scope, and substitute - // into it to determine its corresponding specific. - scopes.push_back({.name_scope_id = extended_id, - .specific_id = SemIR::SpecificId::Invalid}); + // Substitute into the constant describing the extended scope to + // determine its corresponding specific. + CARBON_CHECK(extended_id.is_valid()); + SemIR::ConstantId const_id = + GetConstantValueInSpecific(sem_ir(), specific_id, extended_id); + + DiagnosticAnnotationScope annotate_diagnostics( + &emitter(), [&](auto& builder) { + CARBON_DIAGNOSTIC(FromExtendHere, Note, + "declared as an extended scope here"); + builder.Note(extended_id, FromExtendHere); + }); + if (!AppendLookupScopesForConstant(loc, const_id, &scopes)) { + // TODO: Handle case where we have a symbolic type and instead should + // look in its type. + } } is_parent_access |= !extended.empty(); continue; diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 78fc99e35ee52..4b23fb0b08451 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -225,10 +225,19 @@ class Context { const SemIR::NameScope& scope) -> std::pair; - // Performs a qualified name lookup in a specified scope and in scopes that - // it extends, returning the referenced instruction. + // Appends the lookup scopes corresponding to `base_const_id` to `*scopes`. + // Returns `false` if not a scope. On invalid scopes, prints a diagnostic, but + // still updates `*scopes` and returns `true`. + auto AppendLookupScopesForConstant(SemIRLoc loc, + SemIR::ConstantId base_const_id, + llvm::SmallVector* scopes) + -> bool; + + // Performs a qualified name lookup in a specified scopes and in scopes that + // they extend, returning the referenced instruction. auto LookupQualifiedName(SemIRLoc loc, SemIR::NameId name_id, - LookupScope scope, bool required = true, + llvm::ArrayRef lookup_scopes, + bool required = true, std::optional access_info = std::nullopt) -> LookupResult; diff --git a/toolchain/check/deduce.cpp b/toolchain/check/deduce.cpp index 92b675f24afb8..edd57ef5783ba 100644 --- a/toolchain/check/deduce.cpp +++ b/toolchain/check/deduce.cpp @@ -50,6 +50,9 @@ class DeductionWorklist { // Adds a single (param, arg) deduction of a specific. auto Add(SemIR::SpecificId param, SemIR::SpecificId arg, bool needs_substitution) -> void { + if (!param.is_valid() || !arg.is_valid()) { + return; + } auto& param_specific = context_.specifics().Get(param); auto& arg_specific = context_.specifics().Get(arg); if (param_specific.generic_id != arg_specific.generic_id) { diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index f0ef56f0f9a5e..56db92aba11d2 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -380,8 +380,8 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { return true; } - auto adapted_type_id = - ExprAsType(context, node_id, adapted_type_expr_id).type_id; + auto [adapted_inst_id, adapted_type_id] = + ExprAsType(context, node_id, adapted_type_expr_id); adapted_type_id = context.AsCompleteType( adapted_type_id, [&] { @@ -405,13 +405,13 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { // Extend the class scope with the adapted type's scope if requested. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { - auto extended_scope_id = SemIR::NameScopeId::Invalid; + auto extended_scope_inst_id = SemIR::InstId::Invalid; if (adapted_type_id == SemIR::TypeId::Error) { // Recover by not extending any scope. We instead set has_error to true // below. } else if (auto* adapted_class_info = TryGetAsClass(context, adapted_type_id)) { - extended_scope_id = adapted_class_info->scope_id; + extended_scope_inst_id = adapted_inst_id; CARBON_CHECK(adapted_class_info->scope_id.is_valid(), "Complete class should have a scope"); } else { @@ -420,8 +420,8 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { } auto& class_scope = context.name_scopes().Get(class_info.scope_id); - if (extended_scope_id.is_valid()) { - class_scope.extended_scopes.push_back(extended_scope_id); + if (extended_scope_inst_id.is_valid()) { + class_scope.extended_scopes.push_back(extended_scope_inst_id); } else { class_scope.has_error = true; } @@ -448,9 +448,11 @@ struct BaseInfo { SemIR::TypeId type_id; SemIR::NameScopeId scope_id; + SemIR::InstId inst_id; }; constexpr BaseInfo BaseInfo::Error = {.type_id = SemIR::TypeId::Error, - .scope_id = SemIR::NameScopeId::Invalid}; + .scope_id = SemIR::NameScopeId::Invalid, + .inst_id = SemIR::InstId::Invalid}; } // namespace // Diagnoses an attempt to derive from a final type. @@ -496,7 +498,9 @@ static auto CheckBaseType(Context& context, Parse::NodeId node_id, CARBON_CHECK(base_class_info->scope_id.is_valid(), "Complete class should have a scope"); - return {.type_id = base_type_id, .scope_id = base_class_info->scope_id}; + return {.type_id = base_type_id, + .scope_id = base_class_info->scope_id, + .inst_id = base_type_inst_id}; } auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { @@ -560,7 +564,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { auto& class_scope = context.name_scopes().Get(class_info.scope_id); if (base_info.scope_id.is_valid()) { - class_scope.extended_scopes.push_back(base_info.scope_id); + class_scope.extended_scopes.push_back(base_info.inst_id); } else { class_scope.has_error = true; } diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 8616e7e51d885..c546f7393192f 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -12,6 +12,7 @@ #include "toolchain/check/modifiers.h" #include "toolchain/check/pattern_match.h" #include "toolchain/parse/typed_nodes.h" +#include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/typed_insts.h" @@ -173,30 +174,20 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node, diag.Emit(); } - auto facet_type = context.types().TryGetAs(constraint_id); - if (!facet_type) { + if (!context.types().Is(constraint_id)) { context.TODO(node_id, "extending non-facet-type constraint"); parent_scope.has_error = true; return; } - const SemIR::FacetTypeInfo& info = - context.facet_types().Get(facet_type->facet_type_id); - for (auto interface_type : info.impls_constraints) { - auto& interface = context.interfaces().Get(interface_type.interface_id); - if (!interface.is_defined()) { - CARBON_DIAGNOSTIC(ExtendUndefinedInterface, Error, - "`extend impl` requires a definition for interface {0}", - InstIdAsType); - auto diag = context.emitter().Build(node_id, ExtendUndefinedInterface, - constraint_inst_id); - context.NoteUndefinedInterface(interface_type.interface_id, diag); - diag.Emit(); - parent_scope.has_error = true; - return; - } - - parent_scope.extended_scopes.push_back(interface.scope_id); - } + parent_scope.has_error |= !context.TryToDefineType(constraint_id, [&] { + CARBON_DIAGNOSTIC(ExtendUndefinedInterface, Error, + "`extend impl` requires a definition for facet type {0}", + InstIdAsType); + return context.emitter().Build(node_id, ExtendUndefinedInterface, + constraint_inst_id); + }); + + parent_scope.extended_scopes.push_back(constraint_inst_id); } // Pops the parameters of an `impl`, forming a `NameComponent` with no @@ -333,6 +324,15 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, // 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); + if (impl_info.generic_id.is_valid()) { + SemIR::TypeId type_id = context.insts().Get(constraint_inst_id).type_id(); + constraint_inst_id = context.AddInst( + context.insts().GetLocId(constraint_inst_id), + {.type_id = type_id, + .inst_id = constraint_inst_id, + .specific_id = + context.generics().GetSelfSpecific(impl_info.generic_id)}); + } ExtendImpl(context, extend_node, node_id, self_type_node, self_type_id, name.implicit_params_loc_id, constraint_inst_id, constraint_type_id); diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index b7100a4bdfb9b..e64b542641c38 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -1460,12 +1460,11 @@ class ImportRefResolver { context_.insts() .GetAs(new_class.base_id) .base_type_id); - const auto& base_class = context_.classes().Get( - context_.insts().GetAs(base_inst_id).class_id); - new_scope.extended_scopes.push_back(base_class.scope_id); + new_scope.extended_scopes.push_back(base_inst_id); } - CARBON_CHECK(new_scope.extended_scopes.size() == - import_scope.extended_scopes.size()); + // TODO: `extended_scopes` from `extend impl` are currently not imported. + // CARBON_CHECK(new_scope.extended_scopes.size() == + // import_scope.extended_scopes.size()); } auto TryResolveTypedInst(SemIR::ClassDecl inst, diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 4cc17c1ae292f..580a86d0a18d0 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -20,58 +20,6 @@ namespace Carbon::Check { -// Returns the lookup scope corresponding to base_id, or nullopt if not a scope. -// On invalid scopes, prints a diagnostic and still returns the scope. -static auto GetAsLookupScope(Context& context, SemIR::LocId loc_id, - SemIR::ConstantId base_const_id) - -> std::optional { - auto base_id = context.constant_values().GetInstId(base_const_id); - auto base = context.insts().Get(base_id); - if (auto base_as_namespace = base.TryAs()) { - return LookupScope{.name_scope_id = base_as_namespace->name_scope_id, - .specific_id = SemIR::SpecificId::Invalid}; - } - // TODO: Consider refactoring the near-identical class and interface support - // below. - if (auto base_as_class = base.TryAs()) { - context.TryToDefineType( - context.GetTypeIdForTypeConstant(base_const_id), [&] { - CARBON_DIAGNOSTIC(QualifiedExprInIncompleteClassScope, Error, - "member access into incomplete class {0}", - InstIdAsType); - return context.emitter().Build( - loc_id, QualifiedExprInIncompleteClassScope, base_id); - }); - auto& class_info = context.classes().Get(base_as_class->class_id); - return LookupScope{.name_scope_id = class_info.scope_id, - .specific_id = base_as_class->specific_id}; - } - if (auto base_as_facet_type = base.TryAs()) { - context.TryToDefineType( - context.GetTypeIdForTypeConstant(base_const_id), [&] { - CARBON_DIAGNOSTIC(QualifiedExprInUndefinedInterfaceScope, Error, - "member access into undefined interface {0}", - InstIdAsType); - return context.emitter().Build( - loc_id, QualifiedExprInUndefinedInterfaceScope, base_id); - }); - const auto& facet_type_info = - context.facet_types().Get(base_as_facet_type->facet_type_id); - auto base_as_interface = facet_type_info.TryAsSingleInterface(); - if (base_as_interface) { - auto& interface_info = - context.interfaces().Get(base_as_interface->interface_id); - return LookupScope{.name_scope_id = interface_info.scope_id, - .specific_id = base_as_interface->specific_id}; - } - } - // TODO: Per the design, if `base_id` is any kind of type, then lookup should - // treat it as a name scope, even if it doesn't have members. For example, - // `(i32*).X` should fail because there's no name `X` in `i32*`, not because - // there's no name `X` in `type`. - return std::nullopt; -} - // Returns the index of the specified class element within the class's // representation. static auto GetClassElementIndex(Context& context, SemIR::InstId element_id) @@ -152,18 +100,20 @@ static auto GetHighestAllowedAccess(Context& context, SemIR::LocId loc_id, // Returns whether `scope` is a scope for which impl lookup should be performed // if we find an associated entity. -static auto ScopeNeedsImplLookup(Context& context, LookupScope scope) -> bool { - auto [_, inst] = context.name_scopes().GetInstIfValid(scope.name_scope_id); - if (!inst) { - return false; - } - - if (inst->Is()) { +static auto ScopeNeedsImplLookup(Context& context, + SemIR::ConstantId name_scope_const_id) + -> bool { + SemIR::InstId inst_id = + context.constant_values().GetInstId(name_scope_const_id); + CARBON_CHECK(inst_id.is_valid()); + SemIR::Inst inst = context.insts().Get(inst_id); + + if (inst.Is()) { // Don't perform impl lookup if an associated entity is named as a member of // a facet type. return false; } - if (inst->Is()) { + if (inst.Is()) { // Don't perform impl lookup if an associated entity is named as a namespace // member. // TODO: This case is not yet listed in the design. @@ -255,22 +205,19 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, SemIR::InstId /*base_id*/, SemIR::NameId name_id, SemIR::ConstantId name_scope_const_id, - LookupScope lookup_scope) -> SemIR::InstId { - LookupResult result = {.specific_id = SemIR::SpecificId::Invalid, - .inst_id = SemIR::InstId::BuiltinError}; - if (lookup_scope.name_scope_id.is_valid()) { - AccessInfo access_info = { - .constant_id = name_scope_const_id, - .highest_allowed_access = - GetHighestAllowedAccess(context, loc_id, name_scope_const_id), - }; - - result = context.LookupQualifiedName(loc_id, name_id, lookup_scope, - /*required=*/true, access_info); - - if (!result.inst_id.is_valid()) { - return SemIR::InstId::BuiltinError; - } + llvm::ArrayRef lookup_scopes) + -> SemIR::InstId { + AccessInfo access_info = { + .constant_id = name_scope_const_id, + .highest_allowed_access = + GetHighestAllowedAccess(context, loc_id, name_scope_const_id), + }; + LookupResult result = + context.LookupQualifiedName(loc_id, name_id, lookup_scopes, + /*required=*/true, access_info); + + if (!result.inst_id.is_valid()) { + return SemIR::InstId::BuiltinError; } // TODO: This duplicates the work that HandleNameAsExpr does. Factor this out. @@ -303,7 +250,7 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, // impl member is not supposed to be treated as ambiguous. if (auto assoc_type = context.types().TryGetAs(type_id)) { - if (ScopeNeedsImplLookup(context, lookup_scope)) { + if (ScopeNeedsImplLookup(context, name_scope_const_id)) { member_id = PerformImplLookup(context, loc_id, name_scope_const_id, *assoc_type, member_id); } @@ -391,9 +338,11 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, // into that scope. if (auto base_const_id = context.constant_values().Get(base_id); base_const_id.is_constant()) { - if (auto lookup_scope = GetAsLookupScope(context, loc_id, base_const_id)) { + llvm::SmallVector lookup_scopes; + if (context.AppendLookupScopesForConstant(loc_id, base_const_id, + &lookup_scopes)) { return LookupMemberNameInScope(context, loc_id, base_id, name_id, - base_const_id, *lookup_scope); + base_const_id, lookup_scopes); } } @@ -415,8 +364,9 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, auto base_type_const_id = context.types().GetConstantId(base_type_id); // Find the scope corresponding to the base type. - auto lookup_scope = GetAsLookupScope(context, loc_id, base_type_const_id); - if (!lookup_scope) { + llvm::SmallVector lookup_scopes; + if (!context.AppendLookupScopesForConstant(loc_id, base_type_const_id, + &lookup_scopes)) { // The base type is not a name scope. Try some fallback options. if (auto struct_type = context.insts().TryGetAs( context.constant_values().GetInstId(base_type_const_id))) { @@ -451,7 +401,7 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, // Perform lookup into the base type. auto member_id = LookupMemberNameInScope(context, loc_id, base_id, name_id, - base_type_const_id, *lookup_scope); + base_type_const_id, lookup_scopes); // Perform instance binding if we found an instance member. member_id = PerformInstanceBinding(context, loc_id, base_id, member_id); diff --git a/toolchain/check/testdata/class/base.carbon b/toolchain/check/testdata/class/base.carbon index 13456e5a98dbd..13fde27329b21 100644 --- a/toolchain/check/testdata/class/base.carbon +++ b/toolchain/check/testdata/class/base.carbon @@ -134,7 +134,7 @@ fn Access(d: Derived) -> (i32, i32) { // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .base = %.loc16 // CHECK:STDOUT: .d = %.loc18_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/base_field.carbon b/toolchain/check/testdata/class/base_field.carbon index d5029b0110483..12226f70a4832 100644 --- a/toolchain/check/testdata/class/base_field.carbon +++ b/toolchain/check/testdata/class/base_field.carbon @@ -128,7 +128,7 @@ fn Access(p: Derived*) -> i32* { // CHECK:STDOUT: .base = %.loc18 // CHECK:STDOUT: .d = %.loc20_8 // CHECK:STDOUT: .e = %.loc21_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/base_function_unqualified.carbon b/toolchain/check/testdata/class/base_function_unqualified.carbon index 1024815d1855b..f5b3247ae99f7 100644 --- a/toolchain/check/testdata/class/base_function_unqualified.carbon +++ b/toolchain/check/testdata/class/base_function_unqualified.carbon @@ -83,7 +83,7 @@ fn Derived.H() { // CHECK:STDOUT: .base = %.loc16 // CHECK:STDOUT: .G = %G.decl // CHECK:STDOUT: .H = %H.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F(); diff --git a/toolchain/check/testdata/class/base_method.carbon b/toolchain/check/testdata/class/base_method.carbon index 54a62d528836c..63e99662f2401 100644 --- a/toolchain/check/testdata/class/base_method.carbon +++ b/toolchain/check/testdata/class/base_method.carbon @@ -123,7 +123,7 @@ fn Call(p: Derived*) { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .base = %.loc22 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/base_method_qualified.carbon b/toolchain/check/testdata/class/base_method_qualified.carbon index 99c240832c442..812eb19deb5b8 100644 --- a/toolchain/check/testdata/class/base_method_qualified.carbon +++ b/toolchain/check/testdata/class/base_method_qualified.carbon @@ -186,7 +186,7 @@ fn PassDerivedToBaseIndirect(p: Derived*) -> i32 { // CHECK:STDOUT: .base = %.loc19 // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Base { diff --git a/toolchain/check/testdata/class/base_method_shadow.carbon b/toolchain/check/testdata/class/base_method_shadow.carbon index e8f1af759078b..d3d01e4c1d456 100644 --- a/toolchain/check/testdata/class/base_method_shadow.carbon +++ b/toolchain/check/testdata/class/base_method_shadow.carbon @@ -156,7 +156,7 @@ fn Call(a: A*, b: B*, c: C*, d: D*) { // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc16 // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -178,7 +178,7 @@ fn Call(a: A*, b: B*, c: C*, d: D*) { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc21 // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @D { @@ -189,7 +189,7 @@ fn Call(a: A*, b: B*, c: C*, d: D*) { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D // CHECK:STDOUT: .base = %.loc26 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1[addr %self.param_patt: %.1](); diff --git a/toolchain/check/testdata/class/compound_field.carbon b/toolchain/check/testdata/class/compound_field.carbon index ce8cb7ab0d5bd..454a99a1f8769 100644 --- a/toolchain/check/testdata/class/compound_field.carbon +++ b/toolchain/check/testdata/class/compound_field.carbon @@ -196,7 +196,7 @@ fn AccessBaseIndirect(p: Derived*) -> i32* { // CHECK:STDOUT: .base = %.loc18 // CHECK:STDOUT: .d = %.loc20_8 // CHECK:STDOUT: .e = %.loc21_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/derived_to_base.carbon b/toolchain/check/testdata/class/derived_to_base.carbon index 0efbf70c34018..0f0160d2b25dc 100644 --- a/toolchain/check/testdata/class/derived_to_base.carbon +++ b/toolchain/check/testdata/class/derived_to_base.carbon @@ -212,7 +212,7 @@ fn ConvertInit() { // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc16 // CHECK:STDOUT: .b = %.loc17_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -228,7 +228,7 @@ fn ConvertInit() { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc21 // CHECK:STDOUT: .c = %.loc22_8 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/extend_adapt.carbon b/toolchain/check/testdata/class/extend_adapt.carbon index 987423d3c0558..69a776d666ca3 100644 --- a/toolchain/check/testdata/class/extend_adapt.carbon +++ b/toolchain/check/testdata/class/extend_adapt.carbon @@ -165,7 +165,7 @@ class StructAdapter { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%SomeClassAdapter -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %SomeClass.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @SomeClass { @@ -329,7 +329,7 @@ class StructAdapter { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%SomeClassAdapter -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %SomeClass.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1[%self.param_patt: %SomeClass](); @@ -507,7 +507,7 @@ class StructAdapter { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%SomeClassAdapter -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %SomeClass.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index d8b282e6b0ca7..7062f06c1e357 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -516,7 +516,7 @@ fn CallReturnAbstract() { // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .base = %.loc8 // CHECK:STDOUT: .d = %.loc10_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Abstract.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -603,7 +603,7 @@ fn CallReturnAbstract() { // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .base = %.loc8 // CHECK:STDOUT: .d = %.loc10_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Abstract.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -698,7 +698,7 @@ fn CallReturnAbstract() { // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .d = %.loc11_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Abstract.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/fail_adapt_modifiers.carbon b/toolchain/check/testdata/class/fail_adapt_modifiers.carbon index 3f2056accc4b6..0123fac87b7a0 100644 --- a/toolchain/check/testdata/class/fail_adapt_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_adapt_modifiers.carbon @@ -138,7 +138,7 @@ class C5 { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C4 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C5 { @@ -148,6 +148,6 @@ class C5 { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C5 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_adapt_with_subobjects.carbon b/toolchain/check/testdata/class/fail_adapt_with_subobjects.carbon index 491d06c1bf3dc..47e619d013e35 100644 --- a/toolchain/check/testdata/class/fail_adapt_with_subobjects.carbon +++ b/toolchain/check/testdata/class/fail_adapt_with_subobjects.carbon @@ -126,7 +126,7 @@ class AdaptWithBaseAndFields { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%AdaptWithBase // CHECK:STDOUT: .base = %.loc15 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -262,7 +262,7 @@ class AdaptWithBaseAndFields { // CHECK:STDOUT: .Self = constants.%AdaptWithBaseAndFields // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .n = %.loc8_8 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/fail_base_bad_type.carbon b/toolchain/check/testdata/class/fail_base_bad_type.carbon index 906e50016ac6f..e1baf5f06f607 100644 --- a/toolchain/check/testdata/class/fail_base_bad_type.carbon +++ b/toolchain/check/testdata/class/fail_base_bad_type.carbon @@ -1281,7 +1281,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%DeriveFromFinal // CHECK:STDOUT: .base = %.loc11 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Final.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/fail_base_method_define.carbon b/toolchain/check/testdata/class/fail_base_method_define.carbon index 99c7fbaaf8f97..6061bce2efc61 100644 --- a/toolchain/check/testdata/class/fail_base_method_define.carbon +++ b/toolchain/check/testdata/class/fail_base_method_define.carbon @@ -103,7 +103,7 @@ fn D.C.F() {} // CHECK:STDOUT: .Self = constants.%D // CHECK:STDOUT: .base = %.loc20 // CHECK:STDOUT: .F = file.%F.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1(); diff --git a/toolchain/check/testdata/class/fail_base_modifiers.carbon b/toolchain/check/testdata/class/fail_base_modifiers.carbon index 4d966e1120b25..ff3d100680081 100644 --- a/toolchain/check/testdata/class/fail_base_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_base_modifiers.carbon @@ -110,7 +110,7 @@ class C4 { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C1 // CHECK:STDOUT: .base = %.loc18 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C2 { @@ -131,7 +131,7 @@ class C4 { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C3 // CHECK:STDOUT: .base = %.loc41 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C4 { @@ -142,6 +142,6 @@ class C4 { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C4 // CHECK:STDOUT: .base = %.loc51 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_base_repeated.carbon b/toolchain/check/testdata/class/fail_base_repeated.carbon index 6ef9eb0c305c5..72ac46616e5c8 100644 --- a/toolchain/check/testdata/class/fail_base_repeated.carbon +++ b/toolchain/check/testdata/class/fail_base_repeated.carbon @@ -97,7 +97,7 @@ class D { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc15 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B1.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @D { @@ -109,6 +109,6 @@ class D { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D // CHECK:STDOUT: .base = %.loc28 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B1.ref.loc28 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_base_unbound.carbon b/toolchain/check/testdata/class/fail_base_unbound.carbon index bc8d0f7cd293e..55c70e39d5e8f 100644 --- a/toolchain/check/testdata/class/fail_base_unbound.carbon +++ b/toolchain/check/testdata/class/fail_base_unbound.carbon @@ -70,7 +70,7 @@ let b: B = C.base; // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc14 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { diff --git a/toolchain/check/testdata/class/fail_derived_to_base.carbon b/toolchain/check/testdata/class/fail_derived_to_base.carbon index 238c260825599..7c29257e162cd 100644 --- a/toolchain/check/testdata/class/fail_derived_to_base.carbon +++ b/toolchain/check/testdata/class/fail_derived_to_base.carbon @@ -214,7 +214,7 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; } // CHECK:STDOUT: .Self = constants.%B2 // CHECK:STDOUT: .base = %.loc20 // CHECK:STDOUT: .b = %.loc21_8 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %A2.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Incomplete; diff --git a/toolchain/check/testdata/class/fail_extend_cycle.carbon b/toolchain/check/testdata/class/fail_extend_cycle.carbon index 6089a844b3112..558a64bc5b7bf 100644 --- a/toolchain/check/testdata/class/fail_extend_cycle.carbon +++ b/toolchain/check/testdata/class/fail_extend_cycle.carbon @@ -81,7 +81,7 @@ base class A { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc16 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @.1 { @@ -95,6 +95,6 @@ base class A { // CHECK:STDOUT: .Self = constants.%.7 // CHECK:STDOUT: .base = %.loc27 // CHECK:STDOUT: .c = %.loc31 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/generic/base_is_generic.carbon b/toolchain/check/testdata/class/generic/base_is_generic.carbon new file mode 100644 index 0000000000000..fcef68f6cb3ab --- /dev/null +++ b/toolchain/check/testdata/class/generic/base_is_generic.carbon @@ -0,0 +1,1056 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/base_is_generic.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/base_is_generic.carbon + +// --- extend_generic_base.carbon + +library "[[@TEST_NAME]]"; + +base class Base(T:! type) { + var x: T; +} + +class Param { + var y: i32; +} + +class Derived { + extend base: Base(Param); +} + +fn DoubleFieldAccess(d: Derived) -> i32 { + return d.x.y; +} + +// --- import.carbon + +library "[[@TEST_NAME]]"; + +import library "extend_generic_base"; + +fn ImportedDoubleFieldAccess(d: Derived) -> i32 { + return d.x.y; +} + +// --- fail_todo_extend_symbolic_base.carbon + +library "[[@TEST_NAME]]"; + +class C(T:! type) { + // CHECK:STDERR: fail_todo_extend_symbolic_base.carbon:[[@LINE+4]]:16: error: deriving from final type `T`; base type must be an `abstract` or `base` class [BaseIsFinal] + // CHECK:STDERR: extend base: T; + // CHECK:STDERR: ^ + // CHECK:STDERR: + extend base: T; +} + +base class X { + fn G() {} +} + +fn F() { + C(X).G(); +} + +// --- extend_generic_symbolic_base.carbon + +library "[[@TEST_NAME]]"; + +base class X(U:! type) { + fn G() -> U { return G(); } +} + +class C(T:! type) { + extend base: X(T); +} + +fn F() { + let i: i32 = C(i32).G(); +} + + +// --- fail_todo_import_extend_generic_symbolic_base.carbon + +library "[[@TEST_NAME]]"; + +import library "extend_generic_symbolic_base"; + +fn H() { + // CHECK:STDERR: fail_todo_import_extend_generic_symbolic_base.carbon:[[@LINE+6]]:3: error: cannot implicitly convert from `T` to `i32` [ImplicitAsConversionFailure] + // CHECK:STDERR: let j: i32 = C(i32).G(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_import_extend_generic_symbolic_base.carbon:[[@LINE+3]]:3: note: type `T` does not implement interface `ImplicitAs(i32)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: let j: i32 = C(i32).G(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + let j: i32 = C(i32).G(); +} + +// CHECK:STDOUT: --- extend_generic_base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Base.type: type = generic_class_type @Base [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %Base.1: %Base.type = struct_value () [template] +// CHECK:STDOUT: %Base.2: type = class_type @Base, @Base(%T) [symbolic] +// CHECK:STDOUT: %.1: type = unbound_element_type %Base.2, %T [symbolic] +// CHECK:STDOUT: %.2: type = struct_type {.x: %T} [symbolic] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [symbolic] +// CHECK:STDOUT: %Param: type = class_type @Param [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.4: type = unbound_element_type %Param, i32 [template] +// CHECK:STDOUT: %.5: type = struct_type {.y: i32} [template] +// CHECK:STDOUT: %.6: = complete_type_witness %.5 [template] +// CHECK:STDOUT: %Derived: type = class_type @Derived [template] +// CHECK:STDOUT: %Base.3: type = class_type @Base, @Base(%Param) [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %Base.3, %Param [template] +// CHECK:STDOUT: %.8: type = struct_type {.x: %Param} [template] +// CHECK:STDOUT: %.9: = complete_type_witness %.8 [template] +// CHECK:STDOUT: %.10: type = ptr_type %.5 [template] +// CHECK:STDOUT: %.11: type = struct_type {.x: %.10} [template] +// CHECK:STDOUT: %.12: type = ptr_type %.8 [template] +// CHECK:STDOUT: %.13: type = unbound_element_type %Derived, %Base.3 [template] +// CHECK:STDOUT: %.14: type = struct_type {.base: %Base.3} [template] +// CHECK:STDOUT: %.15: = complete_type_witness %.14 [template] +// CHECK:STDOUT: %DoubleFieldAccess.type: type = fn_type @DoubleFieldAccess [template] +// CHECK:STDOUT: %DoubleFieldAccess: %DoubleFieldAccess.type = struct_value () [template] +// CHECK:STDOUT: %.16: type = struct_type {.base: %.12} [template] +// CHECK:STDOUT: %.17: type = ptr_type %.14 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Base = %Base.decl +// CHECK:STDOUT: .Param = %Param.decl +// CHECK:STDOUT: .Derived = %Derived.decl +// CHECK:STDOUT: .DoubleFieldAccess = %DoubleFieldAccess.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Base.decl: %Base.type = class_decl @Base [template = constants.%Base.1] { +// CHECK:STDOUT: %T.patt.loc4_17.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_17.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_17.1, runtime_param [symbolic = %T.patt.loc4_17.2 (constants.%T.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_17.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_17.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Param.decl: type = class_decl @Param [template = constants.%Param] {} {} +// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [template = constants.%Derived] {} {} +// CHECK:STDOUT: %DoubleFieldAccess.decl: %DoubleFieldAccess.type = fn_decl @DoubleFieldAccess [template = constants.%DoubleFieldAccess] { +// CHECK:STDOUT: %d.patt: %Derived = binding_pattern d +// CHECK:STDOUT: %d.param_patt: %Derived = value_param_pattern %d.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: i32 = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc16_37.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc16_37.2: type = converted %int.make_type_32, %.loc16_37.1 [template = i32] +// CHECK:STDOUT: %d.param: %Derived = value_param runtime_param0 +// CHECK:STDOUT: %d: %Derived = bind_name d, %d.param +// CHECK:STDOUT: %return.param: ref i32 = out_param runtime_param1 +// CHECK:STDOUT: %return: ref i32 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Base(%T.loc4_17.1: type) { +// CHECK:STDOUT: %T.loc4_17.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_17.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_17.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_17.2 (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Base: type = class_type @Base, @Base(%T.loc4_17.2) [symbolic = %Base (constants.%Base.2)] +// CHECK:STDOUT: %.loc5_8.2: type = unbound_element_type @Base.%Base (%Base.2), @Base.%T.loc4_17.2 (%T) [symbolic = %.loc5_8.2 (constants.%.1)] +// CHECK:STDOUT: %.loc6_1.2: type = struct_type {.x: @Base.%T.loc4_17.2 (%T)} [symbolic = %.loc6_1.2 (constants.%.2)] +// CHECK:STDOUT: %.loc6_1.3: = complete_type_witness @Base.%.loc6_1.2 (%.2) [symbolic = %.loc6_1.3 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_17.1 [symbolic = %T.loc4_17.2 (constants.%T)] +// CHECK:STDOUT: %.loc5_8.1: @Base.%.loc5_8.2 (%.1) = field_decl x, element0 [template] +// CHECK:STDOUT: %.loc6_1.1: = complete_type_witness %.2 [symbolic = %.loc6_1.3 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Base.2 +// CHECK:STDOUT: .x = %.loc5_8.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Param { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc9_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc9_10.2: type = converted %int.make_type_32, %.loc9_10.1 [template = i32] +// CHECK:STDOUT: %.loc9_8: %.4 = field_decl y, element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness %.5 [template = constants.%.6] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Param +// CHECK:STDOUT: .y = %.loc9_8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: %Base.ref: %Base.type = name_ref Base, file.%Base.decl [template = constants.%Base.1] +// CHECK:STDOUT: %Param.ref: type = name_ref Param, file.%Param.decl [template = constants.%Param] +// CHECK:STDOUT: %Base: type = class_type @Base, @Base(constants.%Param) [template = constants.%Base.3] +// CHECK:STDOUT: %.loc13: %.13 = base_decl %Base.3, element0 [template] +// CHECK:STDOUT: %.loc14: = complete_type_witness %.14 [template = constants.%.15] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Derived +// CHECK:STDOUT: .base = %.loc13 +// CHECK:STDOUT: extend %Base +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @DoubleFieldAccess(%d.param_patt: %Derived) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d +// CHECK:STDOUT: %x.ref: %.7 = name_ref x, @Base.%.loc5_8.1 [template = @Base.%.loc5_8.1] +// CHECK:STDOUT: %.loc17_11.1: ref %Base.3 = class_element_access %d.ref, element0 +// CHECK:STDOUT: %.loc17_11.2: ref %Base.3 = converted %d.ref, %.loc17_11.1 +// CHECK:STDOUT: %.loc17_11.3: ref %Param = class_element_access %.loc17_11.2, element0 +// CHECK:STDOUT: %y.ref: %.4 = name_ref y, @Param.%.loc9_8 [template = @Param.%.loc9_8] +// CHECK:STDOUT: %.loc17_13.1: ref i32 = class_element_access %.loc17_11.3, element0 +// CHECK:STDOUT: %.loc17_13.2: i32 = bind_value %.loc17_13.1 +// CHECK:STDOUT: return %.loc17_13.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(constants.%T) { +// CHECK:STDOUT: %T.loc4_17.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_17.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(@Base.%T.loc4_17.2) { +// CHECK:STDOUT: %T.loc4_17.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_17.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(constants.%Param) { +// CHECK:STDOUT: %T.loc4_17.2 => constants.%Param +// CHECK:STDOUT: %T.patt.loc4_17.2 => constants.%Param +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Base => constants.%Base.3 +// CHECK:STDOUT: %.loc5_8.2 => constants.%.7 +// CHECK:STDOUT: %.loc6_1.2 => constants.%.8 +// CHECK:STDOUT: %.loc6_1.3 => constants.%.9 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Derived: type = class_type @Derived [template] +// CHECK:STDOUT: %Param: type = class_type @Param [template] +// CHECK:STDOUT: %.1: type = struct_type {.y: i32} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %Base.type: type = generic_class_type @Base [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %Base.1: %Base.type = struct_value () [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %.3: type = struct_type {.x: %T} [symbolic] +// CHECK:STDOUT: %.4: = complete_type_witness %.3 [symbolic] +// CHECK:STDOUT: %Base.2: type = class_type @Base, @Base(%T) [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %Base.3: type = class_type @Base, @Base(%Param) [template] +// CHECK:STDOUT: %.5: type = unbound_element_type %Derived, %Base.3 [template] +// CHECK:STDOUT: %.6: type = struct_type {.base: %Base.3} [template] +// CHECK:STDOUT: %.7: = complete_type_witness %.6 [template] +// CHECK:STDOUT: %.8: type = unbound_element_type %Base.2, %T [symbolic] +// CHECK:STDOUT: %.9: type = unbound_element_type %Base.3, %Param [template] +// CHECK:STDOUT: %.10: type = struct_type {.x: %Param} [template] +// CHECK:STDOUT: %.11: = complete_type_witness %.10 [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %ImportedDoubleFieldAccess.type: type = fn_type @ImportedDoubleFieldAccess [template] +// CHECK:STDOUT: %ImportedDoubleFieldAccess: %ImportedDoubleFieldAccess.type = struct_value () [template] +// CHECK:STDOUT: %.12: type = ptr_type %.3 [symbolic] +// CHECK:STDOUT: %.13: type = struct_type {.base: %.12} [symbolic] +// CHECK:STDOUT: %.14: type = ptr_type %.6 [template] +// CHECK:STDOUT: %.15: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.16: type = unbound_element_type %Param, i32 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extend_generic_base, inst+9, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//extend_generic_base, inst+26, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//extend_generic_base, inst+43, loaded [template = constants.%Derived] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//extend_generic_base, inst+72, unloaded +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.11 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.5 = import_ref Main//extend_generic_base, inst+27, unloaded +// CHECK:STDOUT: %import_ref.6: %.16 = import_ref Main//extend_generic_base, inst+39, loaded [template = %.1] +// CHECK:STDOUT: %import_ref.7 = import_ref Main//extend_generic_base, inst+15, unloaded +// CHECK:STDOUT: %import_ref.8: @Base.%.1 (%.8) = import_ref Main//extend_generic_base, inst+18, loaded [template = %.2] +// CHECK:STDOUT: %import_ref.9 = import_ref Main//extend_generic_base, inst+44, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//extend_generic_base, inst+56, unloaded +// CHECK:STDOUT: %import_ref.11: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Base = imports.%import_ref.1 +// CHECK:STDOUT: .Param = imports.%import_ref.2 +// CHECK:STDOUT: .Derived = imports.%import_ref.3 +// CHECK:STDOUT: .DoubleFieldAccess = imports.%import_ref.4 +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .ImportedDoubleFieldAccess = %ImportedDoubleFieldAccess.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %ImportedDoubleFieldAccess.decl: %ImportedDoubleFieldAccess.type = fn_decl @ImportedDoubleFieldAccess [template = constants.%ImportedDoubleFieldAccess] { +// CHECK:STDOUT: %d.patt: %Derived = binding_pattern d +// CHECK:STDOUT: %d.param_patt: %Derived = value_param_pattern %d.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: i32 = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, imports.%import_ref.3 [template = constants.%Derived] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_45.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc6_45.2: type = converted %int.make_type_32, %.loc6_45.1 [template = i32] +// CHECK:STDOUT: %d.param: %Derived = value_param runtime_param0 +// CHECK:STDOUT: %d: %Derived = bind_name d, %d.param +// CHECK:STDOUT: %return.param: ref i32 = out_param runtime_param1 +// CHECK:STDOUT: %return: ref i32 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Derived { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.9 +// CHECK:STDOUT: .base = imports.%import_ref.10 +// CHECK:STDOUT: extend constants.%Base.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Param { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .y = imports.%import_ref.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Base(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @Base.%Base (%Base.2), @Base.%T (%T) [symbolic = %.1 (constants.%.8)] +// CHECK:STDOUT: %.2: type = struct_type {.x: @Base.%T (%T)} [symbolic = %.2 (constants.%.3)] +// CHECK:STDOUT: %.3: = complete_type_witness @Base.%.2 (%.3) [symbolic = %.3 (constants.%.4)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .x = imports.%import_ref.8 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @ImportedDoubleFieldAccess(%d.param_patt: %Derived) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d +// CHECK:STDOUT: %x.ref: %.9 = name_ref x, imports.%import_ref.8 [template = imports.%.2] +// CHECK:STDOUT: %.loc7_11.1: ref %Base.3 = class_element_access %d.ref, element0 +// CHECK:STDOUT: %.loc7_11.2: ref %Base.3 = converted %d.ref, %.loc7_11.1 +// CHECK:STDOUT: %.loc7_11.3: ref %Param = class_element_access %.loc7_11.2, element0 +// CHECK:STDOUT: %y.ref: %.16 = name_ref y, imports.%import_ref.6 [template = imports.%.1] +// CHECK:STDOUT: %.loc7_13.1: ref i32 = class_element_access %.loc7_11.3, element0 +// CHECK:STDOUT: %.loc7_13.2: i32 = bind_value %.loc7_13.1 +// CHECK:STDOUT: return %.loc7_13.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %T.patt => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(constants.%Param) { +// CHECK:STDOUT: %T => constants.%Param +// CHECK:STDOUT: %T.patt => constants.%Param +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %Base => constants.%Base.3 +// CHECK:STDOUT: %.1 => constants.%.9 +// CHECK:STDOUT: %.2 => constants.%.10 +// CHECK:STDOUT: %.3 => constants.%.11 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Base(@Base.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %T.patt => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_extend_symbolic_base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %X: type = class_type @X [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(%X) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %T.patt.loc4_9.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_9.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_9.1, runtime_param [symbolic = %T.patt.loc4_9.2 (constants.%T.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_9.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_9.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.decl: type = class_decl @X [template = constants.%X] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(%T.loc4_9.1: type) { +// CHECK:STDOUT: %T.loc4_9.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_9.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_9.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_9.2 (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc4_9.1 [symbolic = %T.loc4_9.2 (constants.%T)] +// CHECK:STDOUT: %.loc9: = base_decl , element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness [template = ] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: .base = %.loc9 +// CHECK:STDOUT: has_error +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @X { +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] {} {} +// CHECK:STDOUT: %.loc14: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%X +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [template = constants.%C.1] +// CHECK:STDOUT: %X.ref: type = name_ref X, file.%X.decl [template = constants.%X] +// CHECK:STDOUT: %C: type = class_type @C, @C(constants.%X) [template = constants.%C.3] +// CHECK:STDOUT: %G.ref: = name_ref G, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T.loc4_9.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%X) { +// CHECK:STDOUT: %T.loc4_9.2 => constants.%X +// CHECK:STDOUT: %T.patt.loc4_9.2 => constants.%X +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- extend_generic_symbolic_base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic] +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 0 [symbolic] +// CHECK:STDOUT: %X.type: type = generic_class_type @X [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %X.1: %X.type = struct_value () [template] +// CHECK:STDOUT: %X.2: type = class_type @X, @X(%U) [symbolic] +// CHECK:STDOUT: %G.type.1: type = fn_type @G, @X(%U) [symbolic] +// CHECK:STDOUT: %G.1: %G.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %.3: = specific_function %G.1, @G(%U) [symbolic] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %X.3: type = class_type @X, @X(%T) [symbolic] +// CHECK:STDOUT: %G.type.2: type = fn_type @G, @X(%T) [symbolic] +// CHECK:STDOUT: %G.2: %G.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.4: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.5: type = unbound_element_type %C.2, %X.3 [symbolic] +// CHECK:STDOUT: %.6: type = struct_type {.base: %X.3} [symbolic] +// CHECK:STDOUT: %.7: = complete_type_witness %.6 [symbolic] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(i32) [template] +// CHECK:STDOUT: %X.4: type = class_type @X, @X(i32) [template] +// CHECK:STDOUT: %.8: type = unbound_element_type %C.3, %X.4 [template] +// CHECK:STDOUT: %.9: type = struct_type {.base: %X.4} [template] +// CHECK:STDOUT: %.10: = complete_type_witness %.9 [template] +// CHECK:STDOUT: %G.type.3: type = fn_type @G, @X(i32) [template] +// CHECK:STDOUT: %G.3: %G.type.3 = struct_value () [template] +// CHECK:STDOUT: %.11: type = struct_type {.base: %.4} [template] +// CHECK:STDOUT: %.12: type = ptr_type %.9 [template] +// CHECK:STDOUT: %.13: = specific_function %G.3, @G(i32) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %X.decl: %X.type = class_decl @X [template = constants.%X.1] { +// CHECK:STDOUT: %U.patt.loc4_14.1: type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc4_14.2 (constants.%U.patt)] +// CHECK:STDOUT: %U.param_patt: type = value_param_pattern %U.patt.loc4_14.1, runtime_param [symbolic = %U.patt.loc4_14.2 (constants.%U.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %U.param: type = value_param runtime_param +// CHECK:STDOUT: %U.loc4_14.1: type = bind_symbolic_name U, 0, %U.param [symbolic = %U.loc4_14.2 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: %C.type = class_decl @C [template = constants.%C.1] { +// CHECK:STDOUT: %T.patt.loc8_9.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_9.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc8_9.1, runtime_param [symbolic = %T.patt.loc8_9.2 (constants.%T.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc8_9.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc8_9.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @X(%U.loc4_14.1: type) { +// CHECK:STDOUT: %U.loc4_14.2: type = bind_symbolic_name U, 0 [symbolic = %U.loc4_14.2 (constants.%U)] +// CHECK:STDOUT: %U.patt.loc4_14.2: type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc4_14.2 (constants.%U.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type: type = fn_type @G, @X(%U.loc4_14.2) [symbolic = %G.type (constants.%G.type.1)] +// CHECK:STDOUT: %G: @X.%G.type (%G.type.1) = struct_value () [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %G.decl: @X.%G.type (%G.type.1) = fn_decl @G [symbolic = @X.%G (constants.%G.1)] { +// CHECK:STDOUT: %return.patt: @G.%U (%U) = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: @G.%U (%U) = out_param_pattern %return.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %U.ref: type = name_ref U, @X.%U.loc4_14.1 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %return.param: ref @G.%U (%U) = out_param runtime_param0 +// CHECK:STDOUT: %return: ref @G.%U (%U) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc6: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%X.2 +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(%T.loc8_9.1: type) { +// CHECK:STDOUT: %T.loc8_9.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_9.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc8_9.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc8_9.2 (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %X.loc9_17.2: type = class_type @X, @X(%T.loc8_9.2) [symbolic = %X.loc9_17.2 (constants.%X.3)] +// CHECK:STDOUT: %C: type = class_type @C, @C(%T.loc8_9.2) [symbolic = %C (constants.%C.2)] +// CHECK:STDOUT: %.loc9_20.2: type = unbound_element_type @C.%C (%C.2), @C.%X.loc9_17.2 (%X.3) [symbolic = %.loc9_20.2 (constants.%.5)] +// CHECK:STDOUT: %.loc10_1.2: type = struct_type {.base: @C.%X.loc9_17.2 (%X.3)} [symbolic = %.loc10_1.2 (constants.%.6)] +// CHECK:STDOUT: %.loc10_1.3: = complete_type_witness @C.%.loc10_1.2 (%.6) [symbolic = %.loc10_1.3 (constants.%.7)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: %X.ref: %X.type = name_ref X, file.%X.decl [template = constants.%X.1] +// CHECK:STDOUT: %T.ref: type = name_ref T, %T.loc8_9.1 [symbolic = %T.loc8_9.2 (constants.%T)] +// CHECK:STDOUT: %X.loc9_17.1: type = class_type @X, @X(constants.%T) [symbolic = %X.loc9_17.2 (constants.%X.3)] +// CHECK:STDOUT: %.loc9_20.1: @C.%.loc9_20.2 (%.5) = base_decl %X.3, element0 [template] +// CHECK:STDOUT: %.loc10_1.1: = complete_type_witness %.6 [symbolic = %.loc10_1.3 (constants.%.7)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: .base = %.loc9_20.1 +// CHECK:STDOUT: extend %X.loc9_17.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @G(@X.%U.loc4_14.1: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type: type = fn_type @G, @X(%U) [symbolic = %G.type (constants.%G.type.1)] +// CHECK:STDOUT: %G: @G.%G.type (%G.type.1) = struct_value () [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: %.loc5_24.3: = specific_function %G, @G(%U) [symbolic = %.loc5_24.3 (constants.%.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @G.%U (%U) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_24.1: @G.%G.type (%G.type.1) = specific_constant @X.%G.decl, @X(constants.%U) [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: %G.ref: @G.%G.type (%G.type.1) = name_ref G, %.loc5_24.1 [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: %.loc5_24.2: = specific_function %G.ref, @G(constants.%U) [symbolic = %.loc5_24.3 (constants.%.3)] +// CHECK:STDOUT: %G.call: init @G.%U (%U) = call %.loc5_24.2() +// CHECK:STDOUT: %.loc5_27.1: @G.%U (%U) = value_of_initializer %G.call +// CHECK:STDOUT: %.loc5_27.2: @G.%U (%U) = converted %G.call, %.loc5_27.1 +// CHECK:STDOUT: return %.loc5_27.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int.make_type_32.loc13_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_10.1: type = value_of_initializer %int.make_type_32.loc13_10 [template = i32] +// CHECK:STDOUT: %.loc13_10.2: type = converted %int.make_type_32.loc13_10, %.loc13_10.1 [template = i32] +// CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [template = constants.%C.1] +// CHECK:STDOUT: %int.make_type_32.loc13_18: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_17.1: type = value_of_initializer %int.make_type_32.loc13_18 [template = i32] +// CHECK:STDOUT: %.loc13_17.2: type = converted %int.make_type_32.loc13_18, %.loc13_17.1 [template = i32] +// CHECK:STDOUT: %C: type = class_type @C, @C(i32) [template = constants.%C.3] +// CHECK:STDOUT: %.loc13_22.1: %G.type.3 = specific_constant @X.%G.decl, @X(i32) [template = constants.%G.3] +// CHECK:STDOUT: %G.ref: %G.type.3 = name_ref G, %.loc13_22.1 [template = constants.%G.3] +// CHECK:STDOUT: %.loc13_22.2: = specific_function %G.ref, @G(i32) [template = constants.%.13] +// CHECK:STDOUT: %G.call: init i32 = call %.loc13_22.2() +// CHECK:STDOUT: %.loc13_26.1: i32 = value_of_initializer %G.call +// CHECK:STDOUT: %.loc13_26.2: i32 = converted %G.call, %.loc13_26.1 +// CHECK:STDOUT: %i: i32 = bind_name i, %.loc13_26.2 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(constants.%U) { +// CHECK:STDOUT: %U.loc4_14.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc4_14.2 => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.1 +// CHECK:STDOUT: %G => constants.%G.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.1 +// CHECK:STDOUT: %G => constants.%G.1 +// CHECK:STDOUT: %.loc5_24.3 => constants.%.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@X.%U.loc4_14.2) { +// CHECK:STDOUT: %U.loc4_14.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc4_14.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@G.%U) { +// CHECK:STDOUT: %U.loc4_14.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc4_14.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(@G.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T.loc8_9.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc8_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(constants.%T) { +// CHECK:STDOUT: %U.loc4_14.2 => constants.%T +// CHECK:STDOUT: %U.patt.loc4_14.2 => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.2 +// CHECK:STDOUT: %G => constants.%G.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@C.%T.loc8_9.2) { +// CHECK:STDOUT: %U.loc4_14.2 => constants.%T +// CHECK:STDOUT: %U.patt.loc4_14.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(@C.%T.loc8_9.2) { +// CHECK:STDOUT: %T.loc8_9.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc8_9.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(i32) { +// CHECK:STDOUT: %T.loc8_9.2 => i32 +// CHECK:STDOUT: %T.patt.loc8_9.2 => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %X.loc9_17.2 => constants.%X.4 +// CHECK:STDOUT: %C => constants.%C.3 +// CHECK:STDOUT: %.loc9_20.2 => constants.%.8 +// CHECK:STDOUT: %.loc10_1.2 => constants.%.9 +// CHECK:STDOUT: %.loc10_1.3 => constants.%.10 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(i32) { +// CHECK:STDOUT: %U.loc4_14.2 => i32 +// CHECK:STDOUT: %U.patt.loc4_14.2 => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.3 +// CHECK:STDOUT: %G => constants.%G.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(i32) { +// CHECK:STDOUT: %U => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.3 +// CHECK:STDOUT: %G => constants.%G.3 +// CHECK:STDOUT: %.loc5_24.3 => constants.%.13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_import_extend_generic_symbolic_base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %H.type: type = fn_type @H [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %H: %H.type = struct_value () [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %C.type: type = generic_class_type @C [template] +// CHECK:STDOUT: %C.1: %C.type = struct_value () [template] +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %X.type: type = generic_class_type @X [template] +// CHECK:STDOUT: %X.1: %X.type = struct_value () [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic] +// CHECK:STDOUT: %X.2: type = class_type @X, @X(%U) [symbolic] +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 0 [symbolic] +// CHECK:STDOUT: %X.3: type = class_type @X, @X(%T) [symbolic] +// CHECK:STDOUT: %C.2: type = class_type @C, @C(%T) [symbolic] +// CHECK:STDOUT: %.3: type = unbound_element_type %C.2, %X.3 [symbolic] +// CHECK:STDOUT: %.4: type = struct_type {.base: %X.3} [symbolic] +// CHECK:STDOUT: %.5: = complete_type_witness %.4 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %G.type.1: type = fn_type @G, @X(%U) [symbolic] +// CHECK:STDOUT: %G.1: %G.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.6: = specific_function %G.1, @G(%U) [symbolic] +// CHECK:STDOUT: %G.type.2: type = fn_type @G, @X(%T) [symbolic] +// CHECK:STDOUT: %G.2: %G.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %C.3: type = class_type @C, @C(i32) [template] +// CHECK:STDOUT: %X.4: type = class_type @X, @X(i32) [template] +// CHECK:STDOUT: %.7: type = unbound_element_type %C.3, %X.4 [template] +// CHECK:STDOUT: %.8: type = struct_type {.base: %X.4} [template] +// CHECK:STDOUT: %.9: = complete_type_witness %.8 [template] +// CHECK:STDOUT: %.10: type = ptr_type %.1 [template] +// CHECK:STDOUT: %.11: type = struct_type {.base: %.10} [template] +// CHECK:STDOUT: %.12: type = ptr_type %.4 [symbolic] +// CHECK:STDOUT: %.13: = specific_function %G.2, @G(%T) [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.1: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type.1 = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.2: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic] +// CHECK:STDOUT: %Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2) = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Dest.patt: type = symbolic_binding_pattern Dest, 0 [symbolic] +// CHECK:STDOUT: %Self.2: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.14: type = assoc_entity_type %ImplicitAs.type.2, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.15: %.14 = assoc_entity element0, imports.%import_ref.13 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type.3: type = facet_type <@ImplicitAs, @ImplicitAs(i32)> [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(i32) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.16: type = assoc_entity_type %ImplicitAs.type.3, %Convert.type.2 [template] +// CHECK:STDOUT: %.17: %.16 = assoc_entity element0, imports.%import_ref.13 [template] +// CHECK:STDOUT: %.18: %.14 = assoc_entity element0, imports.%import_ref.14 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extend_generic_symbolic_base, inst+9, unloaded +// CHECK:STDOUT: %import_ref.2: %C.type = import_ref Main//extend_generic_symbolic_base, inst+47, loaded [template = constants.%C.1] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//extend_generic_symbolic_base, inst+70, unloaded +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref.4 +// CHECK:STDOUT: .ImplicitAs = %import_ref.9 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: %import_ref.5 = import_ref Main//extend_generic_symbolic_base, inst+15, unloaded +// CHECK:STDOUT: %import_ref.6: @X.%G.type (%G.type.1) = import_ref Main//extend_generic_symbolic_base, inst+21, loaded [symbolic = @X.%G (constants.%G.1)] +// CHECK:STDOUT: %import_ref.7 = import_ref Main//extend_generic_symbolic_base, inst+52, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref Main//extend_generic_symbolic_base, inst+61, unloaded +// CHECK:STDOUT: %import_ref.9: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+48, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.10 = import_ref Core//prelude/operators/as, inst+54, unloaded +// CHECK:STDOUT: %import_ref.11: @ImplicitAs.%.1 (%.14) = import_ref Core//prelude/operators/as, inst+76, loaded [symbolic = @ImplicitAs.%.2 (constants.%.18)] +// CHECK:STDOUT: %import_ref.12 = import_ref Core//prelude/operators/as, inst+69, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Core//prelude/operators/as, inst+69, unloaded +// CHECK:STDOUT: %import_ref.14 = import_ref Core//prelude/operators/as, inst+69, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .X = imports.%import_ref.1 +// CHECK:STDOUT: .C = imports.%import_ref.2 +// CHECK:STDOUT: .F = imports.%import_ref.3 +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .H = %H.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %H.decl: %H.type = fn_decl @H [template = constants.%H] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %Dest.patt: type = symbolic_binding_pattern Dest, 0 [symbolic = %Dest.patt (constants.%Dest.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.1: type = assoc_entity_type @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.1 (constants.%.14)] +// CHECK:STDOUT: %.2: @ImplicitAs.%.1 (%.14) = assoc_entity element0, imports.%import_ref.13 [symbolic = %.2 (constants.%.15)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.10 +// CHECK:STDOUT: .Convert = imports.%import_ref.11 +// CHECK:STDOUT: witness = (imports.%import_ref.12) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @C(constants.%T: type) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %X: type = class_type @X, @X(%T) [symbolic = %X (constants.%X.3)] +// CHECK:STDOUT: %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.2)] +// CHECK:STDOUT: %.1: type = unbound_element_type @C.%C (%C.2), @C.%X (%X.3) [symbolic = %.1 (constants.%.3)] +// CHECK:STDOUT: %.2: type = struct_type {.base: @C.%X (%X.3)} [symbolic = %.2 (constants.%.4)] +// CHECK:STDOUT: %.3: = complete_type_witness @C.%.2 (%.4) [symbolic = %.3 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .base = imports.%import_ref.8 +// CHECK:STDOUT: extend constants.%X.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @X(constants.%U: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 0 [symbolic = %U.patt (constants.%U.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type: type = fn_type @G, @X(%U) [symbolic = %G.type (constants.%G.type.1)] +// CHECK:STDOUT: %G: @X.%G.type (%G.type.1) = struct_value () [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.5 +// CHECK:STDOUT: .G = imports.%import_ref.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @H() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int.make_type_32.loc13_10: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_10.1: type = value_of_initializer %int.make_type_32.loc13_10 [template = i32] +// CHECK:STDOUT: %.loc13_10.2: type = converted %int.make_type_32.loc13_10, %.loc13_10.1 [template = i32] +// CHECK:STDOUT: %C.ref: %C.type = name_ref C, imports.%import_ref.2 [template = constants.%C.1] +// CHECK:STDOUT: %int.make_type_32.loc13_18: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc13_17.1: type = value_of_initializer %int.make_type_32.loc13_18 [template = i32] +// CHECK:STDOUT: %.loc13_17.2: type = converted %int.make_type_32.loc13_18, %.loc13_17.1 [template = i32] +// CHECK:STDOUT: %C: type = class_type @C, @C(i32) [template = constants.%C.3] +// CHECK:STDOUT: %.loc13_22.1: %G.type.2 = specific_constant imports.%import_ref.6, @X(constants.%T) [symbolic = constants.%G.2] +// CHECK:STDOUT: %G.ref: %G.type.2 = name_ref G, %.loc13_22.1 [symbolic = constants.%G.2] +// CHECK:STDOUT: %.loc13_22.2: = specific_function %G.ref, @G(constants.%T) [symbolic = constants.%.13] +// CHECK:STDOUT: %G.call: init %T = call %.loc13_22.2() +// CHECK:STDOUT: %.loc13_26: i32 = converted %G.call, [template = ] +// CHECK:STDOUT: %j: i32 = bind_name j, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @G(constants.%U: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type: type = fn_type @G, @X(%U) [symbolic = %G.type (constants.%G.type.1)] +// CHECK:STDOUT: %G: @G.%G.type (%G.type.1) = struct_value () [symbolic = %G (constants.%G.1)] +// CHECK:STDOUT: %.1: = specific_function %G, @G(%U) [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @G.%U (%U); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.2)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest, 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.2)] +// CHECK:STDOUT: %Self: %ImplicitAs.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self.param_patt: @Convert.%Self (%Self.2)]() -> @Convert.%Dest (%Dest); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %U.patt => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.1 +// CHECK:STDOUT: %G => constants.%G.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(constants.%T) { +// CHECK:STDOUT: %U => constants.%T +// CHECK:STDOUT: %U.patt => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.2 +// CHECK:STDOUT: %G => constants.%G.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(constants.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %T.patt => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@X.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %U.patt => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@C.%T) { +// CHECK:STDOUT: %U => constants.%T +// CHECK:STDOUT: %U.patt => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(@C.%T) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %T.patt => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.1 +// CHECK:STDOUT: %G => constants.%G.1 +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@G.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %U.patt => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(@G.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @C(i32) { +// CHECK:STDOUT: %T => i32 +// CHECK:STDOUT: %T.patt => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %X => constants.%X.4 +// CHECK:STDOUT: %C => constants.%C.3 +// CHECK:STDOUT: %.1 => constants.%.7 +// CHECK:STDOUT: %.2 => constants.%.8 +// CHECK:STDOUT: %.3 => constants.%.9 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(i32) { +// CHECK:STDOUT: %U => i32 +// CHECK:STDOUT: %U.patt => i32 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @G(constants.%T) { +// CHECK:STDOUT: %U => constants.%T +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %G.type => constants.%G.type.2 +// CHECK:STDOUT: %G => constants.%G.2 +// CHECK:STDOUT: %.1 => constants.%.13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %Dest.patt => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %Dest.patt => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %Dest.patt => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.1) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.2 +// CHECK:STDOUT: %Self => constants.%Self.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(i32) { +// CHECK:STDOUT: %Dest => i32 +// CHECK:STDOUT: %Dest.patt => i32 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %ImplicitAs.type => constants.%ImplicitAs.type.3 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.1 => constants.%.16 +// CHECK:STDOUT: %.2 => constants.%.17 +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/import_base.carbon b/toolchain/check/testdata/class/import_base.carbon index e5affd0b4c668..0e2315b3b0c51 100644 --- a/toolchain/check/testdata/class/import_base.carbon +++ b/toolchain/check/testdata/class/import_base.carbon @@ -120,7 +120,7 @@ fn Run() { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Child // CHECK:STDOUT: .base = %.loc13 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F[%self.param_patt: %Base](); @@ -188,7 +188,7 @@ fn Run() { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = imports.%import_ref.8 // CHECK:STDOUT: .base = imports.%import_ref.9 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend constants.%Base // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Base { diff --git a/toolchain/check/testdata/class/inheritance_access.carbon b/toolchain/check/testdata/class/inheritance_access.carbon index 043f43470a331..01845845250d3 100644 --- a/toolchain/check/testdata/class/inheritance_access.carbon +++ b/toolchain/check/testdata/class/inheritance_access.carbon @@ -316,7 +316,7 @@ class B { // CHECK:STDOUT: .Self = constants.%Circle // CHECK:STDOUT: .base = %.loc10 // CHECK:STDOUT: .GetPosition = %GetPosition.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Shape.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -426,7 +426,7 @@ class B { // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .F [private] = %F.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -452,7 +452,7 @@ class B { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc14 // CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F.1(); @@ -570,7 +570,7 @@ class B { // CHECK:STDOUT: .base = %.loc12 // CHECK:STDOUT: .G = %G.decl // CHECK:STDOUT: .H = %H.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -675,7 +675,7 @@ class B { // CHECK:STDOUT: .Self = constants.%Square // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .GetPosition = %GetPosition.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Shape.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -852,7 +852,7 @@ class B { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -924,7 +924,7 @@ class B { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -1146,7 +1146,7 @@ class B { // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; @@ -1229,7 +1229,7 @@ class B { // CHECK:STDOUT: .Self = constants.%B // CHECK:STDOUT: .base = %.loc9 // CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %A.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/self_conversion.carbon b/toolchain/check/testdata/class/self_conversion.carbon index b8e79024e6ff3..853eced964b3d 100644 --- a/toolchain/check/testdata/class/self_conversion.carbon +++ b/toolchain/check/testdata/class/self_conversion.carbon @@ -169,7 +169,7 @@ fn Call(p: Derived*) -> i32 { // CHECK:STDOUT: .base = %.loc16 // CHECK:STDOUT: .SelfBase = %SelfBase.decl // CHECK:STDOUT: .AddrSelfBase = %AddrSelfBase.decl -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/class/virtual_modifiers.carbon b/toolchain/check/testdata/class/virtual_modifiers.carbon index d3af60eff68c4..efe147694bd23 100644 --- a/toolchain/check/testdata/class/virtual_modifiers.carbon +++ b/toolchain/check/testdata/class/virtual_modifiers.carbon @@ -174,7 +174,7 @@ fn F() { // CHECK:STDOUT: .Self = constants.%Derived // CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: .base = %.loc8 -// CHECK:STDOUT: extend name_scope4 +// CHECK:STDOUT: extend %Base.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Base { diff --git a/toolchain/check/testdata/impl/extend_impl.carbon b/toolchain/check/testdata/impl/extend_impl.carbon index b7ca2b3106266..76a1687e80fef 100644 --- a/toolchain/check/testdata/impl/extend_impl.carbon +++ b/toolchain/check/testdata/impl/extend_impl.carbon @@ -100,7 +100,7 @@ fn G(c: C) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend @impl.%HasF.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@HasF.%Self: %HasF.type) { diff --git a/toolchain/check/testdata/impl/extend_impl_generic.carbon b/toolchain/check/testdata/impl/extend_impl_generic.carbon new file mode 100644 index 0000000000000..1fdf3156b9a04 --- /dev/null +++ b/toolchain/check/testdata/impl/extend_impl_generic.carbon @@ -0,0 +1,550 @@ +// 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/extend_impl_generic.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/extend_impl_generic.carbon + +// --- extend_impl_generic_interface.carbon + +library "[[@TEST_NAME]]"; + +interface HasF(T:! type) { + fn F() -> T; +} + +class Param { + var x: i32; +} + +class C { + extend impl as HasF(Param) { + fn F() -> Param { + return {.x = 2}; + } + } +} + +fn G(c: C) { + let a: i32 = C.F().x; + var b: i32 = c.F().x; +} + +// --- extend_impl_generic_class.carbon + +library "[[@TEST_NAME]]"; + +interface I(T:! type) { + fn F[self: Self](t: T); +} + +class X(U:! type) { + extend impl as I(U) { + fn F[self: Self](t: U) { } + } +} + +// CHECK:STDOUT: --- extend_impl_generic_interface.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %HasF.type.1: type = generic_interface_type @HasF [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %HasF: %HasF.type.1 = struct_value () [template] +// CHECK:STDOUT: %HasF.type.2: type = facet_type <@HasF, @HasF(%T)> [symbolic] +// CHECK:STDOUT: %Self: %HasF.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @HasF(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.1: type = assoc_entity_type %HasF.type.2, %F.type.1 [symbolic] +// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @HasF.%F.decl [symbolic] +// CHECK:STDOUT: %Param: type = class_type @Param [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = unbound_element_type %Param, i32 [template] +// CHECK:STDOUT: %.4: type = struct_type {.x: i32} [template] +// CHECK:STDOUT: %.5: = complete_type_witness %.4 [template] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %HasF.type.3: type = facet_type <@HasF, @HasF(%Param)> [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @HasF(%Param) [template] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %HasF.type.3, %F.type.2 [template] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element0, @HasF.%F.decl [template] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [template] +// CHECK:STDOUT: %.8: = interface_witness (%F.3) [template] +// CHECK:STDOUT: %.9: type = struct_type {} [template] +// CHECK:STDOUT: %.10: = complete_type_witness %.9 [template] +// CHECK:STDOUT: %.11: type = ptr_type %.4 [template] +// CHECK:STDOUT: %.12: i32 = int_value 2 [template] +// CHECK:STDOUT: %struct: %Param = struct_value (%.12) [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.13: type = ptr_type %.9 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .HasF = %HasF.decl +// CHECK:STDOUT: .Param = %Param.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %HasF.decl: %HasF.type.1 = interface_decl @HasF [template = constants.%HasF] { +// CHECK:STDOUT: %T.patt.loc4_16.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_16.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_16.1, runtime_param [symbolic = %T.patt.loc4_16.2 (constants.%T.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_16.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_16.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Param.decl: type = class_decl @Param [template = constants.%Param] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %c.patt: %C = binding_pattern c +// CHECK:STDOUT: %c.param_patt: %C = value_param_pattern %c.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc20: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %c.param: %C = value_param runtime_param0 +// CHECK:STDOUT: %c: %C = bind_name c, %c.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @HasF(%T.loc4_16.1: type) { +// CHECK:STDOUT: %T.loc4_16.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_16.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_16.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_16.2 (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %HasF.type: type = facet_type <@HasF, @HasF(%T.loc4_16.2)> [symbolic = %HasF.type (constants.%HasF.type.2)] +// CHECK:STDOUT: %Self.2: %HasF.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @HasF(%T.loc4_16.2) [symbolic = %F.type (constants.%F.type.1)] +// CHECK:STDOUT: %F: @HasF.%F.type (%F.type.1) = struct_value () [symbolic = %F (constants.%F.1)] +// CHECK:STDOUT: %.loc5_14.2: type = assoc_entity_type @HasF.%HasF.type (%HasF.type.2), @HasF.%F.type (%F.type.1) [symbolic = %.loc5_14.2 (constants.%.1)] +// CHECK:STDOUT: %.loc5_14.3: @HasF.%.loc5_14.2 (%.1) = assoc_entity element0, %F.decl [symbolic = %.loc5_14.3 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @HasF.%HasF.type (%HasF.type.2) = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.decl: @HasF.%F.type (%F.type.1) = fn_decl @F.1 [symbolic = @HasF.%F (constants.%F.1)] { +// CHECK:STDOUT: %return.patt: @F.1.%T (%T) = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: @F.1.%T (%T) = out_param_pattern %return.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.ref: type = name_ref T, @HasF.%T.loc4_16.1 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %return.param: ref @F.1.%T (%T) = out_param runtime_param0 +// CHECK:STDOUT: %return: ref @F.1.%T (%T) = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_14.1: @HasF.%.loc5_14.2 (%.1) = assoc_entity element0, %F.decl [symbolic = %.loc5_14.3 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: .F = %.loc5_14.1 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %Self.ref as %HasF.type { +// CHECK:STDOUT: %F.decl: %F.type.3 = fn_decl @F.2 [template = constants.%F.3] { +// CHECK:STDOUT: %return.patt: %Param = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: %Param = out_param_pattern %return.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Param.ref: type = name_ref Param, file.%Param.decl [template = constants.%Param] +// CHECK:STDOUT: %return.param: ref %Param = out_param runtime_param0 +// CHECK:STDOUT: %return: ref %Param = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc13: = interface_witness (%F.decl) [template = constants.%.8] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Param { +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc9_10.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc9_10.2: type = converted %int.make_type_32, %.loc9_10.1 [template = i32] +// CHECK:STDOUT: %.loc9_8: %.3 = field_decl x, element0 [template] +// CHECK:STDOUT: %.loc10: = complete_type_witness %.4 [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Param +// CHECK:STDOUT: .x = %.loc9_8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: impl_decl @impl [template] {} { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] +// CHECK:STDOUT: %HasF.ref: %HasF.type.1 = name_ref HasF, file.%HasF.decl [template = constants.%HasF] +// CHECK:STDOUT: %Param.ref: type = name_ref Param, file.%Param.decl [template = constants.%Param] +// CHECK:STDOUT: %HasF.type: type = facet_type <@HasF, @HasF(constants.%Param)> [template = constants.%HasF.type.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc18: = complete_type_witness %.9 [template = constants.%.10] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: extend @impl.%HasF.type +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@HasF.%T.loc4_16.1: type, @HasF.%Self.1: @HasF.%HasF.type (%HasF.type.2)) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn() -> @F.1.%T (%T); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2() -> %return: %Param { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc15_20: i32 = int_value 2 [template = constants.%.12] +// CHECK:STDOUT: %.loc15_21.1: %.4 = struct_literal (%.loc15_20) +// CHECK:STDOUT: %.loc15_21.2: ref i32 = class_element_access %return, element0 +// CHECK:STDOUT: %.loc15_21.3: init i32 = initialize_from %.loc15_20 to %.loc15_21.2 [template = constants.%.12] +// CHECK:STDOUT: %.loc15_21.4: init %Param = class_init (%.loc15_21.3), %return [template = constants.%struct] +// CHECK:STDOUT: %.loc15_22: init %Param = converted %.loc15_21.1, %.loc15_21.4 [template = constants.%struct] +// CHECK:STDOUT: return %.loc15_22 to %return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%c.param_patt: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %int.make_type_32.loc21: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc21_10.1: type = value_of_initializer %int.make_type_32.loc21 [template = i32] +// CHECK:STDOUT: %.loc21_10.2: type = converted %int.make_type_32.loc21, %.loc21_10.1 [template = i32] +// CHECK:STDOUT: %C.ref.loc21: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc21_17.1: %.6 = specific_constant @HasF.%.loc5_14.1, @HasF(constants.%Param) [template = constants.%.7] +// CHECK:STDOUT: %F.ref.loc21: %.6 = name_ref F, %.loc21_17.1 [template = constants.%.7] +// CHECK:STDOUT: %.loc21_17.2: %F.type.2 = interface_witness_access constants.%.8, element0 [template = constants.%F.3] +// CHECK:STDOUT: %.loc21_19.1: ref %Param = temporary_storage +// CHECK:STDOUT: %F.call.loc21: init %Param = call %.loc21_17.2() to %.loc21_19.1 +// CHECK:STDOUT: %.loc21_19.2: ref %Param = temporary %.loc21_19.1, %F.call.loc21 +// CHECK:STDOUT: %x.ref.loc21: %.3 = name_ref x, @Param.%.loc9_8 [template = @Param.%.loc9_8] +// CHECK:STDOUT: %.loc21_21.1: ref i32 = class_element_access %.loc21_19.2, element0 +// CHECK:STDOUT: %.loc21_21.2: i32 = bind_value %.loc21_21.1 +// CHECK:STDOUT: %a: i32 = bind_name a, %.loc21_21.2 +// CHECK:STDOUT: %int.make_type_32.loc22: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc22_10.1: type = value_of_initializer %int.make_type_32.loc22 [template = i32] +// CHECK:STDOUT: %.loc22_10.2: type = converted %int.make_type_32.loc22, %.loc22_10.1 [template = i32] +// CHECK:STDOUT: %b.var: ref i32 = var b +// CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var +// CHECK:STDOUT: %c.ref: %C = name_ref c, %c +// CHECK:STDOUT: %.loc22_17.1: %.6 = specific_constant @HasF.%.loc5_14.1, @HasF(constants.%Param) [template = constants.%.7] +// CHECK:STDOUT: %F.ref.loc22: %.6 = name_ref F, %.loc22_17.1 [template = constants.%.7] +// CHECK:STDOUT: %.loc22_17.2: %F.type.2 = interface_witness_access constants.%.8, element0 [template = constants.%F.3] +// CHECK:STDOUT: %.loc22_19.1: ref %Param = temporary_storage +// CHECK:STDOUT: %F.call.loc22: init %Param = call %.loc22_17.2() to %.loc22_19.1 +// CHECK:STDOUT: %.loc22_19.2: ref %Param = temporary %.loc22_19.1, %F.call.loc22 +// CHECK:STDOUT: %x.ref.loc22: %.3 = name_ref x, @Param.%.loc9_8 [template = @Param.%.loc9_8] +// CHECK:STDOUT: %.loc22_21.1: ref i32 = class_element_access %.loc22_19.2, element0 +// CHECK:STDOUT: %.loc22_21.2: i32 = bind_value %.loc22_21.1 +// CHECK:STDOUT: assign %b.var, %.loc22_21.2 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF(constants.%T) { +// CHECK:STDOUT: %T.loc4_16.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_16.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%T, constants.%Self) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF(@HasF.%T.loc4_16.2) { +// CHECK:STDOUT: %T.loc4_16.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_16.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @HasF(constants.%Param) { +// CHECK:STDOUT: %T.loc4_16.2 => constants.%Param +// CHECK:STDOUT: %T.patt.loc4_16.2 => constants.%Param +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %HasF.type => constants.%HasF.type.3 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type.2 +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: %.loc5_14.2 => constants.%.6 +// CHECK:STDOUT: %.loc5_14.3 => constants.%.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Param, constants.%C) { +// CHECK:STDOUT: %T => constants.%Param +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- extend_impl_generic_class.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic] +// CHECK:STDOUT: %T.patt: type = symbolic_binding_pattern T, 0 [symbolic] +// CHECK:STDOUT: %I.type.1: type = generic_interface_type @I [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %I: %I.type.1 = struct_value () [template] +// CHECK:STDOUT: %I.type.2: type = facet_type <@I, @I(%T)> [symbolic] +// CHECK:STDOUT: %Self: %I.type.2 = bind_symbolic_name Self, 1 [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1, @I(%T) [symbolic] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.1: type = assoc_entity_type %I.type.2, %F.type.1 [symbolic] +// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic] +// CHECK:STDOUT: %U.patt: type = symbolic_binding_pattern U, 0 [symbolic] +// CHECK:STDOUT: %X.type: type = generic_class_type @X [template] +// CHECK:STDOUT: %X.1: %X.type = struct_value () [template] +// CHECK:STDOUT: %X.2: type = class_type @X, @X(%U) [symbolic] +// CHECK:STDOUT: %I.type.3: type = facet_type <@I, @I(%U)> [symbolic] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.1, @I(%U) [symbolic] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type %I.type.3, %F.type.2 [symbolic] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%F.decl [symbolic] +// CHECK:STDOUT: %F.type.3: type = fn_type @F.2, @impl(%U) [symbolic] +// CHECK:STDOUT: %F.3: %F.type.3 = struct_value () [symbolic] +// CHECK:STDOUT: %.5: = interface_witness (%F.3) [symbolic] +// CHECK:STDOUT: %.6: type = struct_type {} [template] +// CHECK:STDOUT: %.7: = complete_type_witness %.6 [template] +// CHECK:STDOUT: %.8: type = ptr_type %.6 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %I.decl: %I.type.1 = interface_decl @I [template = constants.%I] { +// CHECK:STDOUT: %T.patt.loc4_13.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)] +// CHECK:STDOUT: %T.param_patt: type = value_param_pattern %T.patt.loc4_13.1, runtime_param [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %T.param: type = value_param runtime_param +// CHECK:STDOUT: %T.loc4_13.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc4_13.2 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.decl: %X.type = class_decl @X [template = constants.%X.1] { +// CHECK:STDOUT: %U.patt.loc8_9.1: type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc8_9.2 (constants.%U.patt)] +// CHECK:STDOUT: %U.param_patt: type = value_param_pattern %U.patt.loc8_9.1, runtime_param [symbolic = %U.patt.loc8_9.2 (constants.%U.patt)] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %U.param: type = value_param runtime_param +// CHECK:STDOUT: %U.loc8_9.1: type = bind_symbolic_name U, 0, %U.param [symbolic = %U.loc8_9.2 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @I(%T.loc4_13.1: type) { +// CHECK:STDOUT: %T.loc4_13.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_13.2 (constants.%T)] +// CHECK:STDOUT: %T.patt.loc4_13.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4_13.2 (constants.%T.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %I.type: type = facet_type <@I, @I(%T.loc4_13.2)> [symbolic = %I.type (constants.%I.type.2)] +// CHECK:STDOUT: %Self.2: %I.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self.2 (constants.%Self)] +// CHECK:STDOUT: %F.type: type = fn_type @F.1, @I(%T.loc4_13.2) [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: %.loc5_25.2: type = assoc_entity_type @I.%I.type (%I.type.2), @I.%F.type (%F.type.1) [symbolic = %.loc5_25.2 (constants.%.1)] +// CHECK:STDOUT: %.loc5_25.3: @I.%.loc5_25.2 (%.1) = assoc_entity element0, %F.decl [symbolic = %.loc5_25.3 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: %Self.1: @I.%I.type (%I.type.2) = 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: %self.param_patt: @F.1.%Self (%Self) = value_param_pattern %self.patt, runtime_param0 +// CHECK:STDOUT: %t.patt: @F.1.%T (%T) = binding_pattern t +// CHECK:STDOUT: %t.param_patt: @F.1.%T (%T) = value_param_pattern %t.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc5_14.1: @F.1.%I.type (%I.type.2) = specific_constant @I.%Self.1, @I(constants.%T) [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %Self.ref: @F.1.%I.type (%I.type.2) = name_ref Self, %.loc5_14.1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.loc5_14.2: type = facet_type_access %Self.ref [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %.loc5_14.3: type = converted %Self.ref, %.loc5_14.2 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: %T.ref: type = name_ref T, @I.%T.loc4_13.1 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %self.param: @F.1.%Self (%Self) = value_param runtime_param0 +// CHECK:STDOUT: %self: @F.1.%Self (%Self) = bind_name self, %self.param +// CHECK:STDOUT: %t.param: @F.1.%T (%T) = value_param runtime_param1 +// CHECK:STDOUT: %t: @F.1.%T (%T) = bind_name t, %t.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc5_25.1: @I.%.loc5_25.2 (%.1) = assoc_entity element0, %F.decl [symbolic = %.loc5_25.3 (constants.%.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self.1 +// CHECK:STDOUT: .F = %.loc5_25.1 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic impl @impl(@X.%U.loc8_9.1: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %X: type = class_type @X, @X(%U) [symbolic = %X (constants.%X.2)] +// CHECK:STDOUT: %I.type.loc9_19.2: type = facet_type <@I, @I(%U)> [symbolic = %I.type.loc9_19.2 (constants.%I.type.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type: type = fn_type @F.2, @impl(%U) [symbolic = %F.type (constants.%F.type.3)] +// CHECK:STDOUT: %F: @impl.%F.type (%F.type.3) = struct_value () [symbolic = %F (constants.%F.3)] +// CHECK:STDOUT: %.loc9_23.2: = interface_witness (%F) [symbolic = %.loc9_23.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: impl: %Self.ref as %I.type.loc9_19.1 { +// CHECK:STDOUT: %F.decl: @impl.%F.type (%F.type.3) = fn_decl @F.2 [symbolic = @impl.%F (constants.%F.3)] { +// CHECK:STDOUT: %self.patt: @F.2.%X (%X.2) = binding_pattern self +// CHECK:STDOUT: %self.param_patt: @F.2.%X (%X.2) = value_param_pattern %self.patt, runtime_param0 +// CHECK:STDOUT: %t.patt: @F.2.%U (%U) = binding_pattern t +// CHECK:STDOUT: %t.param_patt: @F.2.%U (%U) = value_param_pattern %t.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %.loc10: type = specific_constant constants.%X.2, @X(constants.%U) [symbolic = %X (constants.%X.2)] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc10 [symbolic = %X (constants.%X.2)] +// CHECK:STDOUT: %U.ref: type = name_ref U, @X.%U.loc8_9.1 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %self.param: @F.2.%X (%X.2) = value_param runtime_param0 +// CHECK:STDOUT: %self: @F.2.%X (%X.2) = bind_name self, %self.param +// CHECK:STDOUT: %t.param: @F.2.%U (%U) = value_param runtime_param1 +// CHECK:STDOUT: %t: @F.2.%U (%U) = bind_name t, %t.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc9_23.1: = interface_witness (%F.decl) [symbolic = %.loc9_23.2 (constants.%.5)] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc9_23.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @X(%U.loc8_9.1: type) { +// CHECK:STDOUT: %U.loc8_9.2: type = bind_symbolic_name U, 0 [symbolic = %U.loc8_9.2 (constants.%U)] +// CHECK:STDOUT: %U.patt.loc8_9.2: type = symbolic_binding_pattern U, 0 [symbolic = %U.patt.loc8_9.2 (constants.%U.patt)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %I.type: type = facet_type <@I, @I(%U.loc8_9.2)> [symbolic = %I.type (constants.%I.type.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: class { +// CHECK:STDOUT: impl_decl @impl [template] {} { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%X.2 [symbolic = %X (constants.%X.2)] +// CHECK:STDOUT: %I.ref: %I.type.1 = name_ref I, file.%I.decl [template = constants.%I] +// CHECK:STDOUT: %U.ref: type = name_ref U, @X.%U.loc8_9.1 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %I.type.loc9_19.1: type = facet_type <@I, @I(constants.%U)> [symbolic = %I.type.loc9_19.2 (constants.%I.type.3)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc9: type = specific_constant @impl.%I.type.loc9_19.1, @impl(constants.%U) [symbolic = %I.type (constants.%I.type.3)] +// CHECK:STDOUT: %.loc12: = complete_type_witness %.6 [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%X.2 +// CHECK:STDOUT: extend %.loc9 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%T.loc4_13.1: type, @I.%Self.1: @I.%I.type (%I.type.2)) { +// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] +// CHECK:STDOUT: %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.2)] +// CHECK:STDOUT: %Self: %I.type.2 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self.param_patt: @F.1.%Self (%Self)](%t.param_patt: @F.1.%T (%T)); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.2(@X.%U.loc8_9.1: type) { +// CHECK:STDOUT: %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)] +// CHECK:STDOUT: %X: type = class_type @X, @X(%U) [symbolic = %X (constants.%X.2)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self.param_patt: @F.2.%X (%X.2)](%t.param_patt: @F.2.%U (%U)) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%T) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@F.1.%T) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%T, constants.%Self) { +// CHECK:STDOUT: %T => constants.%T +// CHECK:STDOUT: %I.type => constants.%I.type.2 +// CHECK:STDOUT: %Self => constants.%Self +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@I.%T.loc4_13.2) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%T +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(constants.%U) { +// CHECK:STDOUT: %U.loc8_9.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc8_9.2 => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %I.type => constants.%I.type.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(constants.%U) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%U +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%U +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %I.type => constants.%I.type.3 +// CHECK:STDOUT: %Self.2 => constants.%Self +// CHECK:STDOUT: %F.type => constants.%F.type.2 +// CHECK:STDOUT: %F => constants.%F.2 +// CHECK:STDOUT: %.loc5_25.2 => constants.%.3 +// CHECK:STDOUT: %.loc5_25.3 => constants.%.4 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@impl.%U) { +// CHECK:STDOUT: %U.loc8_9.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc8_9.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@impl.%U) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%U +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %X => constants.%X.2 +// CHECK:STDOUT: %I.type.loc9_19.2 => constants.%I.type.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %F.type => constants.%F.type.3 +// CHECK:STDOUT: %F => constants.%F.3 +// CHECK:STDOUT: %.loc9_23.2 => constants.%.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @X(@F.2.%U) { +// CHECK:STDOUT: %U.loc8_9.2 => constants.%U +// CHECK:STDOUT: %U.patt.loc8_9.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.2(constants.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %X => constants.%X.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%U, constants.%X.2) { +// CHECK:STDOUT: %T => constants.%U +// CHECK:STDOUT: %I.type => constants.%I.type.3 +// CHECK:STDOUT: %Self => constants.%X.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @impl(@impl.%U) { +// CHECK:STDOUT: %U => constants.%U +// CHECK:STDOUT: %X => constants.%X.2 +// CHECK:STDOUT: %I.type.loc9_19.2 => constants.%I.type.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I(@X.%U.loc8_9.2) { +// CHECK:STDOUT: %T.loc4_13.2 => constants.%U +// CHECK:STDOUT: %T.patt.loc4_13.2 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon index fe040a8d6aaf7..60fbdc46308c4 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_forall.carbon @@ -137,6 +137,7 @@ class C { // CHECK:STDOUT: %T.param: type = value_param runtime_param // CHECK:STDOUT: %T.loc19_23.1: type = bind_symbolic_name T, 0, %T.param [symbolic = %T.loc19_23.2 (constants.%T)] // CHECK:STDOUT: } +// CHECK:STDOUT: %.loc19: type = specific_constant @impl.%GenericInterface.type.loc19_52.1, @impl(constants.%T) [symbolic = constants.%GenericInterface.type.2] // CHECK:STDOUT: %.loc22: = complete_type_witness %.4 [template = constants.%.5] // CHECK:STDOUT: // CHECK:STDOUT: !members: diff --git a/toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon b/toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon index 7281d829cbe50..c8ca7ce8240f7 100644 --- a/toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon +++ b/toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon @@ -126,7 +126,7 @@ class E { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend @impl.2.%I.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @E { @@ -138,7 +138,7 @@ class E { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%E -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend @impl.3.%I.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; 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 c655b88cf99b9..475d3dc8fcf13 100644 --- a/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon +++ b/toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon @@ -10,7 +10,7 @@ interface I { class C { - // CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE+6]]:5: error: `extend impl` requires a definition for interface `I` [ExtendUndefinedInterface] + // CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE+6]]:5: error: `extend impl` requires a definition for facet type `I` [ExtendUndefinedInterface] // CHECK:STDERR: extend impl as I; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE-5]]:1: note: interface is currently being defined [InterfaceUndefinedWithinDefinition] @@ -27,6 +27,7 @@ interface I { // CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] // CHECK:STDOUT: %C.1: type = class_type @C [template] // CHECK:STDOUT: %C.2: type = class_type @C, @C(%Self) [symbolic] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] // CHECK:STDOUT: } @@ -72,10 +73,12 @@ interface I { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C.2 [symbolic = %C (constants.%C.2)] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%I.type] // CHECK:STDOUT: } +// CHECK:STDOUT: %.loc19: type = specific_constant @impl.%I.ref, @impl(constants.%Self) [template = constants.%I.type] // CHECK:STDOUT: %.loc20: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C.2 +// CHECK:STDOUT: extend %.loc19 // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon b/toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon index 646b13fe503ac..9b93710a50c40 100644 --- a/toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon +++ b/toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon @@ -11,22 +11,51 @@ interface I; class C { - // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE+6]]:3: error: `extend impl` requires a definition for interface `I` [ExtendUndefinedInterface] + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE+7]]:3: error: `extend impl` requires a definition for facet type `I` [ExtendUndefinedInterface] // CHECK:STDERR: extend impl as I; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere] // CHECK:STDERR: interface I; // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: extend impl as I; } +fn F(c: C) { + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE+10]]:3: error: member access into undefined interface `I` [QualifiedExprInUndefinedInterfaceScope] + // CHECK:STDERR: C.F(); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-17]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere] + // CHECK:STDERR: interface I; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-10]]:18: note: declared as an extended scope here [FromExtendHere] + // CHECK:STDERR: extend impl as I; + // CHECK:STDERR: ^ + // CHECK:STDERR: + C.F(); + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE+9]]:3: error: member access into undefined interface `I` [QualifiedExprInUndefinedInterfaceScope] + // CHECK:STDERR: c.F(); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-28]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere] + // CHECK:STDERR: interface I; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-21]]:18: note: declared as an extended scope here [FromExtendHere] + // CHECK:STDERR: extend impl as I; + // CHECK:STDERR: ^ + c.F(); +} + // CHECK:STDOUT: --- fail_extend_undefined_interface.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %I.type: type = facet_type <@I> [template] // CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -41,10 +70,19 @@ class C { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .I = %I.decl // CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%I.type] {} {} // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %c.patt: %C = binding_pattern c +// CHECK:STDOUT: %c.param_patt: %C = value_param_pattern %c.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc24: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %c.param: %C = value_param runtime_param0 +// CHECK:STDOUT: %c: %C = bind_name c, %c.param +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @I; @@ -56,10 +94,20 @@ class C { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%I.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc21: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: %.loc22: = complete_type_witness %.1 [template = constants.%.2] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: extend @impl.%I.ref // CHECK:STDOUT: has_error // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%c.param_patt: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc35: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %F.ref.loc35: = name_ref F, [template = ] +// CHECK:STDOUT: %c.ref: %C = name_ref c, %c +// CHECK:STDOUT: %F.ref.loc45: = name_ref F, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: 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 165df6797a33f..36195b38371c9 100644 --- a/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon +++ b/toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon @@ -117,7 +117,7 @@ impl C as I { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend @impl.1.%I.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { diff --git a/toolchain/check/testdata/impl/lookup/instance_method.carbon b/toolchain/check/testdata/impl/lookup/instance_method.carbon index b9f15a47bb1ff..4fc726b05904c 100644 --- a/toolchain/check/testdata/impl/lookup/instance_method.carbon +++ b/toolchain/check/testdata/impl/lookup/instance_method.carbon @@ -143,7 +143,7 @@ fn F(c: C) -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend @impl.%I.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; diff --git a/toolchain/check/testdata/impl/multiple_extend.carbon b/toolchain/check/testdata/impl/multiple_extend.carbon index 3aa6ec1cee374..f1c0a3e8ed8a4 100644 --- a/toolchain/check/testdata/impl/multiple_extend.carbon +++ b/toolchain/check/testdata/impl/multiple_extend.carbon @@ -271,8 +271,8 @@ fn P(o: O) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: extend name_scope2 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend @impl.1.%HasF.ref +// CHECK:STDOUT: extend @impl.2.%HasG.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @F.1(@HasF.%Self: %HasF.type) { @@ -436,8 +436,8 @@ fn P(o: O) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D -// CHECK:STDOUT: extend name_scope2 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend @impl.1.%HasA1.ref +// CHECK:STDOUT: extend @impl.2.%HasA2.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @A.1(@HasA1.%Self: %HasA1.type) { @@ -576,8 +576,8 @@ fn P(o: O) { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%E // CHECK:STDOUT: .base = %.loc13 -// CHECK:STDOUT: extend name_scope3 -// CHECK:STDOUT: extend name_scope2 +// CHECK:STDOUT: extend %B.ref +// CHECK:STDOUT: extend @impl.%HasI.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @I.1(@HasI.%Self: %HasI.type) { @@ -717,8 +717,8 @@ fn P(o: O) { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%L // CHECK:STDOUT: .base = %.loc13 -// CHECK:STDOUT: extend name_scope2 -// CHECK:STDOUT: extend name_scope3 +// CHECK:STDOUT: extend %Base.ref +// CHECK:STDOUT: extend @impl.%HasK.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @K.1() { @@ -887,9 +887,9 @@ fn P(o: O) { // CHECK:STDOUT: .Self = constants.%O // CHECK:STDOUT: .base = %.loc17 // CHECK:STDOUT: .N = %N.decl -// CHECK:STDOUT: extend name_scope2 -// CHECK:STDOUT: extend name_scope3 -// CHECK:STDOUT: extend name_scope4 +// CHECK:STDOUT: extend %NBase.ref +// CHECK:STDOUT: extend @impl.1.%HasN1.ref +// CHECK:STDOUT: extend @impl.2.%HasN2.ref // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @N.1() { diff --git a/toolchain/check/testdata/impl/no_prelude/import_extend_impl.carbon b/toolchain/check/testdata/impl/no_prelude/import_extend_impl.carbon new file mode 100644 index 0000000000000..5ac9ea66e3d25 --- /dev/null +++ b/toolchain/check/testdata/impl/no_prelude/import_extend_impl.carbon @@ -0,0 +1,164 @@ +// 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_extend_impl.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/import_extend_impl.carbon + +// --- extend_impl_library.carbon + +library "[[@TEST_NAME]]"; + +interface I { + fn F(); +} + +class C { + extend impl as I { + fn F() {} + } +} + +// --- fail_todo_use_imported_class_extend_impl.carbon + +library "[[@TEST_NAME]]"; + +import library "extend_impl_library"; + +fn G(c: C) { + // CHECK:STDERR: fail_todo_use_imported_class_extend_impl.carbon:[[@LINE+4]]:3: error: name `F` not found [NameNotFound] + // CHECK:STDERR: C.F(); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + C.F(); + // CHECK:STDERR: fail_todo_use_imported_class_extend_impl.carbon:[[@LINE+3]]:3: error: name `F` not found [NameNotFound] + // CHECK:STDERR: c.F(); + // CHECK:STDERR: ^~~ + c.F(); +} + +// CHECK:STDOUT: --- extend_impl_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %I.type: type = facet_type <@I> [template] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %F.type.1: type = fn_type @F.1 [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %F.1: %F.type.1 = struct_value () [template] +// CHECK:STDOUT: %.1: type = assoc_entity_type %I.type, %F.type.1 [template] +// CHECK:STDOUT: %.2: %.1 = assoc_entity element0, @I.%F.decl [template] +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %F.type.2: type = fn_type @F.2 [template] +// CHECK:STDOUT: %F.2: %F.type.2 = struct_value () [template] +// CHECK:STDOUT: %.3: = interface_witness (%F.2) [template] +// CHECK:STDOUT: %.4: type = struct_type {} [template] +// CHECK:STDOUT: %.5: = complete_type_witness %.4 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%I.type] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %F.decl: %F.type.1 = fn_decl @F.1 [template = constants.%F.1] {} {} +// CHECK:STDOUT: %.loc5: %.1 = assoc_entity element0, %F.decl [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .F = %.loc5 +// CHECK:STDOUT: witness = (%F.decl) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %Self.ref as %I.ref { +// CHECK:STDOUT: %F.decl: %F.type.2 = fn_decl @F.2 [template = constants.%F.2] {} {} +// CHECK:STDOUT: %.loc9: = interface_witness (%F.decl) [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: witness = %.loc9 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: impl_decl @impl [template] {} { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc12: = complete_type_witness %.4 [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: extend @impl.%I.ref +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @F.1(@I.%Self: %I.type) { +// CHECK:STDOUT: +// CHECK:STDOUT: fn(); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F.2() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%Self) {} +// CHECK:STDOUT: +// CHECK:STDOUT: specific @F.1(constants.%C) {} +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_use_imported_class_extend_impl.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: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.3: type = ptr_type %.1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extend_impl_library, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//extend_impl_library, inst+12, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//extend_impl_library, inst+13, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .I = imports.%import_ref.1 +// CHECK:STDOUT: .C = imports.%import_ref.2 +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %c.patt: %C = binding_pattern c +// CHECK:STDOUT: %c.param_patt: %C = value_param_pattern %c.patt, runtime_param0 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, imports.%import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %c.param: %C = value_param runtime_param0 +// CHECK:STDOUT: %c: %C = bind_name c, %c.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G(%c.param_patt: %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %C.ref.loc11: type = name_ref C, imports.%import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %F.ref.loc11: = name_ref F, [template = ] +// CHECK:STDOUT: %c.ref: %C = name_ref c, %c +// CHECK:STDOUT: %F.ref.loc15: = name_ref F, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_lookup_in_type_type.carbon b/toolchain/check/testdata/interface/no_prelude/fail_lookup_in_type_type.carbon index b16a04dca864d..c1927467a69ad 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_lookup_in_type_type.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_lookup_in_type_type.carbon @@ -22,7 +22,7 @@ let T: type.not_found = {}; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+3]]:8: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] +// CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+3]]:8: error: name `missing` not found [NameNotFound] // CHECK:STDERR: let U: (type where .Self impls type).missing = {}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ let U: (type where .Self impls type).missing = {}; @@ -64,6 +64,7 @@ let U: (type where .Self impls type).missing = {}; // CHECK:STDOUT: %.loc7: type = where_expr %.Self [template = constants.%type_where] { // CHECK:STDOUT: requirement_impls %.Self.ref, type // CHECK:STDOUT: } +// CHECK:STDOUT: %missing.ref: = name_ref missing, [template = ] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 46b7a4153c9c1..51d72e6a74fd8 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -272,6 +272,7 @@ CARBON_DIAGNOSTIC_KIND(QualifiedDeclInIncompleteClassScope) CARBON_DIAGNOSTIC_KIND(QualifiedDeclInUndefinedInterfaceScope) // Name lookup. +CARBON_DIAGNOSTIC_KIND(FromExtendHere) CARBON_DIAGNOSTIC_KIND(InNameLookup) CARBON_DIAGNOSTIC_KIND(NameAmbiguousDueToExtend) CARBON_DIAGNOSTIC_KIND(NameNotFound) diff --git a/toolchain/sem_ir/facet_type_info.h b/toolchain/sem_ir/facet_type_info.h index 98bc1ff52fd00..823deac25c67c 100644 --- a/toolchain/sem_ir/facet_type_info.h +++ b/toolchain/sem_ir/facet_type_info.h @@ -32,11 +32,12 @@ struct FacetTypeInfo : Printable { // TODO: extend this so it can represent named constraint requirements // and requirements on members, not just `.Self`. + // TODO: Add whether this is a lookup context. Those that are should sort + // first for easy access. Right now, all are assumed to be lookup contexts. InterfaceId interface_id; SpecificId specific_id; }; llvm::SmallVector impls_constraints; - // TODO: Add lookup contexts. // TODO: Add rewrite constraints. // TODO: Add same-type constraints. // TODO: Remove `requirement_block_id`. diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index ab4fd82562b5d..8abf565b3a3e1 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -501,9 +501,10 @@ class FormatterImpl { } for (auto extended_scope_id : scope.extended_scopes) { - // TODO: Print this scope in a better way. Indent(); - out_ << "extend " << extended_scope_id << "\n"; + out_ << "extend "; + FormatName(extended_scope_id); + out_ << "\n"; } // This is used to cluster all "Core//prelude/..." imports, but not diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index d3d1a740e1a88..fe985ab7c996a 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -75,22 +75,13 @@ struct NameScope : Printable { llvm::SmallVector names; Map name_map; - // Scopes extended by this scope. - // - // TODO: A `NameScopeId` is currently insufficient to describe an extended - // scope in general. For example: - // - // class A(T:! type) { - // extend base: B(T*); - // } - // - // needs to describe the `T*` argument. + // Instructions returning values that are extended by this scope. // // Small vector size is set to 1: we expect that there will rarely be more // than a single extended scope. // TODO: Revisit this once we have more kinds of extended scope and data. // TODO: Consider using something like `TinyPtrVector` for this. - llvm::SmallVector extended_scopes; + llvm::SmallVector extended_scopes; // The instruction which owns the scope. InstId inst_id;