From 63757d281e6aff1f9f2a0405afdfabe520db52b7 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 21 Jul 2026 15:31:54 -0400 Subject: [PATCH] Require all impls constraints in `impl as` to be satisfied (#7531) We checked that requirements inside the impl-as target interface were satisfied. But we also need to check that requirements coming from the constraint facet type, or named constraints that it targets, are satisfied. --- toolchain/check/handle_impl.cpp | 3 +- toolchain/check/impl.cpp | 103 ++++-- .../testdata/impl/impl_assoc_const.carbon | 4 +- .../check/testdata/impl/import_generic.carbon | 18 +- .../check/testdata/impl/incomplete.carbon | 341 ++++++++++++++---- .../require_satisified_in_interface.carbon | 14 +- ...uire_satisified_in_named_constraint.carbon | 14 +- .../testdata/where_expr/dot_self_impls.carbon | 8 +- toolchain/diagnostics/kind.def | 3 +- 9 files changed, 375 insertions(+), 133 deletions(-) diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index c67fb28cac8a..865da1ba3c58 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -421,8 +421,6 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionStartId node_id) auto [impl_id, impl_decl_id] = BuildImplDecl(context, node_id, true); auto& impl = context.impls().Get(impl_id); - CheckRequireDeclsSatisfied(context, node_id, impl); - impl.scope_id = context.name_scopes().Add(impl_decl_id, SemIR::NameId::None, context.decl_name_stack().PeekParentScopeId()); @@ -434,6 +432,7 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionStartId node_id) context.generics().GetSelfSpecific(impl.generic_id)); StartGenericDefinition(context, impl.generic_id); ImplWitnessStartDefinition(context, impl); + CheckRequireDeclsSatisfied(context, node_id, impl); context.inst_block_stack().Push(); context.node_stack().Push(node_id, impl_id); diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 20f42de6eae6..68ef4d0d957f 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -762,15 +762,59 @@ auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id, return; } - const auto& interface = context.interfaces().Get(impl.interface.interface_id); - if (!interface.is_complete()) { - // This will be diagnosed later. We check for required decls before starting - // the definition to avoid inserting these lookups into the definition, as - // the lookups can end up looking for the impl being defined, which creates - // a cycle. - return; + // TODO: Check other kinds of constraints too: rewrites into targets other + // than `Self.(TargetInterface.__)` and same-type constraints. Consider maybe + // building a facet type that just excludes anything about the impl-as target + // interface, and then just perform lookup of Self as that facet type, so we + // don't have to re-implement all of the validation of impl lookup? + + // The IdentifiedFacetType canonicalizes the self facets, so we do the same + // for comparing with it. + auto self_const_id = GetCanonicalFacetOrTypeValue( + context, context.constant_values().Get(impl.self_id)); + auto canon_constraint_id = + context.constant_values().GetConstantTypeInstId(impl.constraint_id); + + // TODO: Consider a function that just forms the key and returns the ID for an + // already-identified facet type? Or plumb through the IdentifiedFacetType? + auto identified_id = TryToIdentifyFacetType( + context, loc_id, self_const_id, canon_constraint_id, + /*allow_partially_identified=*/false); + CARBON_CHECK(identified_id.has_value()); + const auto& identified = context.identified_facet_types().Get(identified_id); + for (auto req : identified.required_impls()) { + if (req.self_facet_value == self_const_id && + req.specific_interface == identified.impl_as_target_interface()) { + // This is what the impl is implementing, so it's not already satisfied. + continue; + } + auto result = LookupImplWitness( + context, loc_id, req.self_facet_value, + GetInterfaceType(context, req.specific_interface.interface_id, + req.specific_interface.specific_id) + .AsConstantId()); + if (!result.has_value()) { + CARBON_DIAGNOSTIC(IdentifiedRequireImplsNotImplemented, Error, + "constraint {0} being implemented requires that {1} " + "implements `{2}`", + SemIR::DeclaredFacetTypeId, InstIdAsConstant, + SemIR::SpecificInterface); + context.emitter().Emit( + loc_id, IdentifiedRequireImplsNotImplemented, + context.insts() + .GetAs(canon_constraint_id) + .declared_facet_type_id, + context.constant_values().GetInstId(req.self_facet_value), + req.specific_interface); + } + if (!result.has_value() || result.has_error_value()) { + FillImplWitnessWithErrors(context, impl); + return; + } } + const auto& interface = context.interfaces().Get(impl.interface.interface_id); + auto require_ids = context.require_impls_blocks().Get(interface.require_impls_block_id); if (require_ids.empty()) { @@ -792,41 +836,34 @@ auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id, auto require_specific_id = CopySpecificToGeneric( context, SemIR::LocId(require.decl_id), interface_with_self_specific_id, require.generic_id); - auto self_const_id = GetConstantValueInSpecific( + auto req_self_const_id = GetConstantValueInSpecific( context.sem_ir(), require_specific_id, require.self_id); - auto facet_type_const_id = GetConstantValueInSpecific( + auto req_facet_type_const_id = GetConstantValueInSpecific( context.sem_ir(), require_specific_id, require.facet_type_inst_id); - if (self_const_id == SemIR::ErrorInst::ConstantId || - facet_type_const_id == SemIR::ErrorInst::ConstantId) { + if (req_self_const_id == SemIR::ErrorInst::ConstantId || + req_facet_type_const_id == SemIR::ErrorInst::ConstantId) { FillImplWitnessWithErrors(context, impl); - break; + return; } - auto result = - LookupImplWitness(context, loc_id, self_const_id, facet_type_const_id); - // TODO: If the facet type contains 2 interfaces, and one is not `impl`ed, - // it would be nice to diagnose which one was not `impl`ed, but that - // requires LookupImplWitness to return a partial result, or take a - // diagnostic lambda or something. + auto result = LookupImplWitness(context, loc_id, req_self_const_id, + req_facet_type_const_id); if (!result.has_value()) { - if (!result.has_error_value() && - facet_type_const_id != SemIR::ErrorInst::ConstantId) { - CARBON_DIAGNOSTIC(RequireImplsNotImplemented, Error, - "interface `{0}` being implemented requires that {1} " - "implements {2}", - SemIR::SpecificInterface, SemIR::TypeId, - SemIR::DeclaredFacetTypeId); - context.emitter().Emit( - loc_id, RequireImplsNotImplemented, impl.interface, - context.types().GetTypeIdForTypeConstantId(self_const_id), - context.constant_values() - .GetInstAs(facet_type_const_id) - .declared_facet_type_id); - } + CARBON_DIAGNOSTIC(InterfaceRequireImplsNotImplemented, Error, + "interface `{0}` being implemented requires that {1} " + "implements {2}", + SemIR::SpecificInterface, SemIR::TypeId, + SemIR::DeclaredFacetTypeId); + context.emitter().Emit( + loc_id, InterfaceRequireImplsNotImplemented, impl.interface, + context.types().GetTypeIdForTypeConstantId(req_self_const_id), + context.constant_values() + .GetInstAs(req_facet_type_const_id) + .declared_facet_type_id); } if (!result.has_value() || result.has_error_value()) { FillImplWitnessWithErrors(context, impl); - break; + return; } } } diff --git a/toolchain/check/testdata/impl/impl_assoc_const.carbon b/toolchain/check/testdata/impl/impl_assoc_const.carbon index 7b36111ef5ad..b4b2e59f1cba 100644 --- a/toolchain/check/testdata/impl/impl_assoc_const.carbon +++ b/toolchain/check/testdata/impl/impl_assoc_const.carbon @@ -406,6 +406,8 @@ library "[[@TEST_NAME]]"; interface I { let X: type; } interface J {} +impl () as J {} + // Test that we avoid an infinite impl lookup cycle from an LookupImplWitness // instruction in the impl declaration. When matching this impl during impl // lookup, we deduce and replace `T` with a specific argument, and resolve that @@ -413,7 +415,7 @@ interface J {} // `.X`. If that lookup found this impl (since it's a final impl, eval can find // it), we would deduce and produce an infinite cycle. Instructions inside the // impl decl should not be able to find the impl. -final impl forall [T: type] T as I where .X impls J and .X = () {} +final impl forall [T: type] T as I where .X = () and .X impls J {} fn F(unused generic T: I where .X = ()) {} fn G() { diff --git a/toolchain/check/testdata/impl/import_generic.carbon b/toolchain/check/testdata/impl/import_generic.carbon index 9d21eecae824..db56286340fb 100644 --- a/toolchain/check/testdata/impl/import_generic.carbon +++ b/toolchain/check/testdata/impl/import_generic.carbon @@ -349,10 +349,10 @@ impl forall [T: type] D as N(T*) {} // CHECK:STDOUT: %Self.as_type: type = facet_access_type %Self.9f1 [symbolic] // CHECK:STDOUT: %J.type.80f: type = facet_type <@J, @J(%empty_struct_type)> [concrete] // CHECK:STDOUT: %J.impl_witness: = impl_witness @C.as.J.impl.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %Self.043: %J.type.80f = symbolic_binding Self, 1 [symbolic] +// CHECK:STDOUT: %complete_type.7da: = complete_type_witness %I.type.81d [concrete] // CHECK:STDOUT: %type: type = facet_type [concrete] // CHECK:STDOUT: %C.type.facet: %type = facet_value %C, () [concrete] -// CHECK:STDOUT: %complete_type.7da: = complete_type_witness %I.type.81d [concrete] -// CHECK:STDOUT: %Self.043: %J.type.80f = symbolic_binding Self, 1 [symbolic] // CHECK:STDOUT: %J.facet: %J.type.80f = facet_value %C, (%J.impl_witness) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -521,6 +521,13 @@ impl forall [T: type] D as N(T*) {} // CHECK:STDOUT: %Self => constants.%Self.043 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.9f1) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %T => constants.%empty_struct_type +// CHECK:STDOUT: %I.type => constants.%I.type.81d +// CHECK:STDOUT: %require_complete => constants.%complete_type.7da +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%C.type.facet) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %T => constants.%empty_struct_type @@ -536,13 +543,6 @@ impl forall [T: type] D as N(T*) {} // CHECK:STDOUT: %I.type => constants.%I.type.81d // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.9f1) { -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: %T => constants.%empty_struct_type -// CHECK:STDOUT: %I.type => constants.%I.type.81d -// CHECK:STDOUT: %require_complete => constants.%complete_type.7da -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%J.facet) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %T => constants.%empty_struct_type diff --git a/toolchain/check/testdata/impl/incomplete.carbon b/toolchain/check/testdata/impl/incomplete.carbon index 07fba630952c..823adecadcad 100644 --- a/toolchain/check/testdata/impl/incomplete.carbon +++ b/toolchain/check/testdata/impl/incomplete.carbon @@ -98,9 +98,14 @@ class C {} interface I {} interface Incomplete; +impl C as I where .Self impls Incomplete; + +interface Incomplete {} +impl C as Incomplete {} + impl C as I where .Self impls Incomplete {} -// --- declaration_incomplete_where_rewrite.carbon +// --- incomplete_where_rewrite.carbon library "[[@TEST_NAME]]"; class C {} @@ -110,8 +115,25 @@ interface Incomplete; impl C as J where .Self impls Incomplete and .T = (); +interface Incomplete {} +impl C as Incomplete {} + impl C as J where .Self impls Incomplete and .T = () {} +// --- fail_incomplete_where_definition.carbon +library "[[@TEST_NAME]]"; + +class C {} + +interface I {} +interface Incomplete; + +// CHECK:STDERR: fail_incomplete_where_definition.carbon:[[@LINE+4]]:1: error: constraint `I where .Self impls Incomplete` being implemented requires that `C` implements `Incomplete` [IdentifiedRequireImplsNotImplemented] +// CHECK:STDERR: impl C as I where .Self impls Incomplete {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +impl C as I where .Self impls Incomplete {} + // --- fail_declaration_lookup_into_incomplete.carbon library "[[@TEST_NAME]]"; @@ -120,11 +142,15 @@ class C {} interface I {} interface Incomplete; +// CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE+4]]:1: error: constraint `I where .Self impls Incomplete` being implemented requires that `C` implements `Incomplete` [IdentifiedRequireImplsNotImplemented] +// CHECK:STDERR: impl C as I where .Self impls Incomplete { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: impl C as I where .Self impls Incomplete { // CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE+7]]:19: error: member access into incomplete facet type `Incomplete` [QualifiedExprInIncompleteFacetTypeScope] // CHECK:STDERR: fn F() -> Self.(Incomplete.T); // CHECK:STDERR: ^~~~~~~~~~~~ - // CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere] + // CHECK:STDERR: fail_declaration_lookup_into_incomplete.carbon:[[@LINE-10]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere] // CHECK:STDERR: interface Incomplete; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -386,7 +412,7 @@ interface B { // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] -// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Self.37e: %I.type = symbolic_binding Self, 0 [symbolic] // CHECK:STDOUT: %Incomplete.type: type = facet_type <@Incomplete> [concrete] // CHECK:STDOUT: %.Self.frozen: %I.type = symbolic_binding .Self [symbolic_self] // CHECK:STDOUT: %.Self.frozen.as_type: type = facet_access_type %.Self.frozen [symbolic_self] @@ -394,6 +420,9 @@ interface B { // CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self [symbolic_self] // CHECK:STDOUT: %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete] // CHECK:STDOUT: %I.impl_witness: = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete] +// CHECK:STDOUT: %Self.d08: %Incomplete.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Incomplete.impl_witness: = impl_witness @C.as.Incomplete.impl.%Incomplete.impl_witness_table [concrete] +// CHECK:STDOUT: %Incomplete.facet: %Incomplete.type = facet_value %C, (%Incomplete.impl_witness) [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -401,35 +430,60 @@ interface B { // CHECK:STDOUT: package: = namespace [concrete] { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: .I = %I.decl -// CHECK:STDOUT: .Incomplete = %Incomplete.decl +// CHECK:STDOUT: .Incomplete = %Incomplete.decl.loc6 // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} -// CHECK:STDOUT: %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} +// CHECK:STDOUT: %Incomplete.decl.loc6: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} // CHECK:STDOUT: impl_decl @C.as.I.impl [concrete] {} { -// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] -// CHECK:STDOUT: %.Self.frozen: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] -// CHECK:STDOUT: %.Self.ref.loc8_19.1: %I.type = name_ref .Self, %.Self.frozen [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %I.ref.loc8: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: %.Self.frozen.loc8: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %base_facet_type.loc8 = requirement_base_facet_type %I.ref.loc8 [concrete] +// CHECK:STDOUT: %.Self.ref.loc8_19.1: %I.type = name_ref .Self, %.Self.frozen.loc8 [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %Incomplete.ref.loc8: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] // CHECK:STDOUT: %.Self.as_type.loc8_19.1: type = facet_access_type %.Self.ref.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] // CHECK:STDOUT: %.loc8_19.1: type = converted %.Self.ref.loc8_19.1, %.Self.as_type.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %impls.loc8_25.1 = requirement_impls %.loc8_19.1, %Incomplete.ref [concrete] -// CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %.Self.ref.loc8_19.2: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %impls.loc8_25.1 = requirement_impls %.loc8_19.1, %Incomplete.ref.loc8 [concrete] +// CHECK:STDOUT: %.Self.loc8: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.ref.loc8_19.2: %I.type = name_ref .Self, %.Self.loc8 [symbolic_self = constants.%.Self] // CHECK:STDOUT: %.Self.as_type.loc8_19.2: type = facet_access_type %.Self.ref.loc8_19.2 [symbolic_self = constants.%.Self.as_type] // CHECK:STDOUT: %.loc8_19.2: type = converted %.Self.ref.loc8_19.1, %.Self.as_type.loc8_19.2 [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref.loc8 [concrete] // CHECK:STDOUT: %.loc8_13: type = where_expr [concrete = constants.%I_where.type] { -// CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] -// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: %base_facet_type.loc8 = requirement_base_facet_type %I.ref.loc8 [concrete] +// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref.loc8 [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: %Incomplete.decl.loc10: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} +// CHECK:STDOUT: impl_decl @C.as.Incomplete.impl [concrete] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: impl_decl @C.as.I.impl [concrete] {} { +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %I.ref.loc13: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: %.Self.frozen.loc13: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %base_facet_type.loc13 = requirement_base_facet_type %I.ref.loc13 [concrete] +// CHECK:STDOUT: %.Self.ref.loc13_19.1: %I.type = name_ref .Self, %.Self.frozen.loc13 [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %Incomplete.ref.loc13: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: %.Self.as_type.loc13_19.1: type = facet_access_type %.Self.ref.loc13_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %.loc13_19.1: type = converted %.Self.ref.loc13_19.1, %.Self.as_type.loc13_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %impls.loc13_25.1 = requirement_impls %.loc13_19.1, %Incomplete.ref.loc13 [concrete] +// CHECK:STDOUT: %.Self.loc13: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.ref.loc13_19.2: %I.type = name_ref .Self, %.Self.loc13 [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.as_type.loc13_19.2: type = facet_access_type %.Self.ref.loc13_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %.loc13_19.2: type = converted %.Self.ref.loc13_19.1, %.Self.as_type.loc13_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %impls.loc13_25.2 = requirement_impls %.loc13_19.2, %Incomplete.ref.loc13 [concrete] +// CHECK:STDOUT: %.loc13_13: type = where_expr [concrete = constants.%I_where.type] { +// CHECK:STDOUT: %base_facet_type.loc13 = requirement_base_facet_type %I.ref.loc13 [concrete] +// CHECK:STDOUT: %impls.loc13_25.2 = requirement_impls %.loc13_19.2, %Incomplete.ref.loc13 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @I { -// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.37e] // CHECK:STDOUT: %I.WithSelf.decl = interface_with_self_decl @I [concrete] // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -439,9 +493,18 @@ interface B { // CHECK:STDOUT: !requires: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: interface @Incomplete; +// CHECK:STDOUT: interface @Incomplete { +// CHECK:STDOUT: %Self: %Incomplete.type = symbolic_binding Self, 0 [symbolic = constants.%Self.d08] +// CHECK:STDOUT: %Incomplete.WithSelf.decl = interface_with_self_decl @Incomplete [concrete] // CHECK:STDOUT: -// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc8_13 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: +// CHECK:STDOUT: !requires: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @C.as.I.impl: %C.ref.loc8 as %.loc8_13 { // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete] // CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] // CHECK:STDOUT: @@ -450,6 +513,15 @@ interface B { // CHECK:STDOUT: witness = %I.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: impl @C.as.Incomplete.impl: %C.ref as %Incomplete.ref { +// CHECK:STDOUT: %Incomplete.impl_witness_table = impl_witness_table (), @C.as.Incomplete.impl [concrete] +// CHECK:STDOUT: %Incomplete.impl_witness: = impl_witness %Incomplete.impl_witness_table [concrete = constants.%Incomplete.impl_witness] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: extend %Incomplete.ref +// CHECK:STDOUT: witness = %Incomplete.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -458,7 +530,15 @@ interface B { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) { +// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.37e) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Incomplete.WithSelf(constants.%Self.d08) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Incomplete.WithSelf(constants.%Incomplete.facet) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -466,14 +546,14 @@ interface B { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- declaration_incomplete_where_rewrite.carbon +// CHECK:STDOUT: --- incomplete_where_rewrite.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %J.type: type = facet_type <@J> [concrete] -// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Self.653: %J.type = symbolic_binding Self, 0 [symbolic] // CHECK:STDOUT: %J.assoc_type: type = assoc_entity_type @J [concrete] // CHECK:STDOUT: %assoc0: %J.assoc_type = assoc_entity element0, @J.WithSelf.%T [concrete] // CHECK:STDOUT: %Incomplete.type: type = facet_type <@Incomplete> [concrete] @@ -489,6 +569,9 @@ interface B { // CHECK:STDOUT: %impl.elem0.bbd: type = impl_witness_access %J.lookup_impl_witness.df8, element0 [symbolic_self] // CHECK:STDOUT: %J_where.type: type = facet_type <@J where .Self impls @Incomplete and %impl.elem0.bbd = %empty_tuple.type> [concrete] // CHECK:STDOUT: %J.impl_witness: = impl_witness @C.as.J.impl.%J.impl_witness_table [concrete] +// CHECK:STDOUT: %Self.d08: %Incomplete.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Incomplete.impl_witness: = impl_witness @C.as.Incomplete.impl.%Incomplete.impl_witness_table [concrete] +// CHECK:STDOUT: %Incomplete.facet: %Incomplete.type = facet_value %C, (%Incomplete.impl_witness) [concrete] // CHECK:STDOUT: %J.facet: %J.type = facet_value %C, (%J.impl_witness) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -496,18 +579,18 @@ interface B { // CHECK:STDOUT: package: = namespace [concrete] { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: .J = %J.decl -// CHECK:STDOUT: .Incomplete = %Incomplete.decl +// CHECK:STDOUT: .Incomplete = %Incomplete.decl.loc6 // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {} -// CHECK:STDOUT: %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} +// CHECK:STDOUT: %Incomplete.decl.loc6: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} // CHECK:STDOUT: impl_decl @C.as.J.impl [concrete] {} { // CHECK:STDOUT: %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: %J.ref.loc8: type = name_ref J, file.%J.decl [concrete = constants.%J.type] // CHECK:STDOUT: %.Self.frozen.loc8: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] // CHECK:STDOUT: %base_facet_type.loc8 = requirement_base_facet_type %J.ref.loc8 [concrete] // CHECK:STDOUT: %.Self.ref.loc8_19.1: %J.type = name_ref .Self, %.Self.frozen.loc8 [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %Incomplete.ref.loc8: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: %Incomplete.ref.loc8: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] // CHECK:STDOUT: %.Self.as_type.loc8_19.1: type = facet_access_type %.Self.ref.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] // CHECK:STDOUT: %.loc8_19.1: type = converted %.Self.ref.loc8_19.1, %.Self.as_type.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] // CHECK:STDOUT: %impls.loc8_25.1 = requirement_impls %.loc8_19.1, %Incomplete.ref.loc8 [concrete] @@ -532,41 +615,46 @@ interface B { // CHECK:STDOUT: %rewrite.loc8_49.2 = requirement_rewrite %impl.elem0.loc8_46.2, %.loc8_52.2 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: } +// CHECK:STDOUT: %Incomplete.decl.loc10: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} +// CHECK:STDOUT: impl_decl @C.as.Incomplete.impl [concrete] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: } // CHECK:STDOUT: impl_decl @C.as.J.impl [concrete] {} { -// CHECK:STDOUT: %C.ref.loc10: type = name_ref C, file.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %J.ref.loc10: type = name_ref J, file.%J.decl [concrete = constants.%J.type] -// CHECK:STDOUT: %.Self.frozen.loc10: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %base_facet_type.loc10 = requirement_base_facet_type %J.ref.loc10 [concrete] -// CHECK:STDOUT: %.Self.ref.loc10_19.1: %J.type = name_ref .Self, %.Self.frozen.loc10 [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %Incomplete.ref.loc10: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type] -// CHECK:STDOUT: %.Self.as_type.loc10_19.1: type = facet_access_type %.Self.ref.loc10_19.1 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %.loc10_19.1: type = converted %.Self.ref.loc10_19.1, %.Self.as_type.loc10_19.1 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %impls.loc10_25.1 = requirement_impls %.loc10_19.1, %Incomplete.ref.loc10 [concrete] -// CHECK:STDOUT: %.Self.ref.loc10_46: %J.type = name_ref .Self, %.Self.frozen.loc10 [symbolic_self = constants.%.Self.frozen] -// CHECK:STDOUT: %.Self.as_type.loc10_46: type = facet_access_type %.Self.ref.loc10_46 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %.loc10_46: type = converted %.Self.ref.loc10_46, %.Self.as_type.loc10_46 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %T.ref.loc10: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0] -// CHECK:STDOUT: %impl.elem0.loc10_46.1: type = impl_witness_access constants.%J.lookup_impl_witness.cb1, element0 [symbolic_self = constants.%impl.elem0.221] -// CHECK:STDOUT: %.loc10_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] -// CHECK:STDOUT: %.loc10_52.2: type = converted %.loc10_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] -// CHECK:STDOUT: %rewrite.loc10_49.1 = requirement_rewrite %impl.elem0.loc10_46.1, %.loc10_52.2 [concrete] -// CHECK:STDOUT: %.Self.loc10: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %.Self.ref.loc10_19.2: %J.type = name_ref .Self, %.Self.loc10 [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %.Self.as_type.loc10_19.2: type = facet_access_type %.Self.ref.loc10_19.2 [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %.loc10_19.2: type = converted %.Self.ref.loc10_19.1, %.Self.as_type.loc10_19.2 [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %impls.loc10_25.2 = requirement_impls %.loc10_19.2, %Incomplete.ref.loc10 [concrete] -// CHECK:STDOUT: %impl.elem0.loc10_46.2: type = impl_witness_access constants.%J.lookup_impl_witness.df8, element0 [symbolic_self = constants.%impl.elem0.bbd] -// CHECK:STDOUT: %rewrite.loc10_49.2 = requirement_rewrite %impl.elem0.loc10_46.2, %.loc10_52.2 [concrete] -// CHECK:STDOUT: %.loc10_13: type = where_expr [concrete = constants.%J_where.type] { -// CHECK:STDOUT: %base_facet_type.loc10 = requirement_base_facet_type %J.ref.loc10 [concrete] -// CHECK:STDOUT: %impls.loc10_25.2 = requirement_impls %.loc10_19.2, %Incomplete.ref.loc10 [concrete] -// CHECK:STDOUT: %rewrite.loc10_49.2 = requirement_rewrite %impl.elem0.loc10_46.2, %.loc10_52.2 [concrete] +// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %J.ref.loc13: type = name_ref J, file.%J.decl [concrete = constants.%J.type] +// CHECK:STDOUT: %.Self.frozen.loc13: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %base_facet_type.loc13 = requirement_base_facet_type %J.ref.loc13 [concrete] +// CHECK:STDOUT: %.Self.ref.loc13_19.1: %J.type = name_ref .Self, %.Self.frozen.loc13 [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %Incomplete.ref.loc13: type = name_ref Incomplete, file.%Incomplete.decl.loc6 [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: %.Self.as_type.loc13_19.1: type = facet_access_type %.Self.ref.loc13_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %.loc13_19.1: type = converted %.Self.ref.loc13_19.1, %.Self.as_type.loc13_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %impls.loc13_25.1 = requirement_impls %.loc13_19.1, %Incomplete.ref.loc13 [concrete] +// CHECK:STDOUT: %.Self.ref.loc13_46: %J.type = name_ref .Self, %.Self.frozen.loc13 [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %.Self.as_type.loc13_46: type = facet_access_type %.Self.ref.loc13_46 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %.loc13_46: type = converted %.Self.ref.loc13_46, %.Self.as_type.loc13_46 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %T.ref.loc13: %J.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0] +// CHECK:STDOUT: %impl.elem0.loc13_46.1: type = impl_witness_access constants.%J.lookup_impl_witness.cb1, element0 [symbolic_self = constants.%impl.elem0.221] +// CHECK:STDOUT: %.loc13_52.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] +// CHECK:STDOUT: %.loc13_52.2: type = converted %.loc13_52.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type] +// CHECK:STDOUT: %rewrite.loc13_49.1 = requirement_rewrite %impl.elem0.loc13_46.1, %.loc13_52.2 [concrete] +// CHECK:STDOUT: %.Self.loc13: %J.type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.ref.loc13_19.2: %J.type = name_ref .Self, %.Self.loc13 [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.as_type.loc13_19.2: type = facet_access_type %.Self.ref.loc13_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %.loc13_19.2: type = converted %.Self.ref.loc13_19.1, %.Self.as_type.loc13_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %impls.loc13_25.2 = requirement_impls %.loc13_19.2, %Incomplete.ref.loc13 [concrete] +// CHECK:STDOUT: %impl.elem0.loc13_46.2: type = impl_witness_access constants.%J.lookup_impl_witness.df8, element0 [symbolic_self = constants.%impl.elem0.bbd] +// CHECK:STDOUT: %rewrite.loc13_49.2 = requirement_rewrite %impl.elem0.loc13_46.2, %.loc13_52.2 [concrete] +// CHECK:STDOUT: %.loc13_13: type = where_expr [concrete = constants.%J_where.type] { +// CHECK:STDOUT: %base_facet_type.loc13 = requirement_base_facet_type %J.ref.loc13 [concrete] +// CHECK:STDOUT: %impls.loc13_25.2 = requirement_impls %.loc13_19.2, %Incomplete.ref.loc13 [concrete] +// CHECK:STDOUT: %rewrite.loc13_49.2 = requirement_rewrite %impl.elem0.loc13_46.2, %.loc13_52.2 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @J { -// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.653] // CHECK:STDOUT: %J.WithSelf.decl = interface_with_self_decl @J [concrete] // CHECK:STDOUT: // CHECK:STDOUT: !with Self: @@ -582,7 +670,16 @@ interface B { // CHECK:STDOUT: !requires: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: interface @Incomplete; +// CHECK:STDOUT: interface @Incomplete { +// CHECK:STDOUT: %Self: %Incomplete.type = symbolic_binding Self, 0 [symbolic = constants.%Self.d08] +// CHECK:STDOUT: %Incomplete.WithSelf.decl = interface_with_self_decl @Incomplete [concrete] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: +// CHECK:STDOUT: !requires: +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @C.as.J.impl: %C.ref.loc8 as %.loc8_13 { // CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @C.as.J.impl [concrete] @@ -594,6 +691,15 @@ interface B { // CHECK:STDOUT: witness = %J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: impl @C.as.Incomplete.impl: %C.ref as %Incomplete.ref { +// CHECK:STDOUT: %Incomplete.impl_witness_table = impl_witness_table (), @C.as.Incomplete.impl [concrete] +// CHECK:STDOUT: %Incomplete.impl_witness: = impl_witness %Incomplete.impl_witness_table [concrete = constants.%Incomplete.impl_witness] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: extend %Incomplete.ref +// CHECK:STDOUT: witness = %Incomplete.impl_witness +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: class @C { // CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type] // CHECK:STDOUT: complete_type_witness = %complete_type @@ -602,7 +708,7 @@ interface B { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @J.WithSelf(constants.%Self) { +// CHECK:STDOUT: specific @J.WithSelf(constants.%Self.653) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -610,10 +716,100 @@ interface B { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Incomplete.WithSelf(constants.%Self.d08) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Incomplete.WithSelf(constants.%Incomplete.facet) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_incomplete_where_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %I.type: type = facet_type <@I> [concrete] +// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic] +// CHECK:STDOUT: %Incomplete.type: type = facet_type <@Incomplete> [concrete] +// CHECK:STDOUT: %.Self.frozen: %I.type = symbolic_binding .Self [symbolic_self] +// CHECK:STDOUT: %.Self.frozen.as_type: type = facet_access_type %.Self.frozen [symbolic_self] +// CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self] +// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self [symbolic_self] +// CHECK:STDOUT: %I_where.type: type = facet_type <@I where .Self impls @Incomplete> [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .Incomplete = %Incomplete.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {} +// CHECK:STDOUT: %Incomplete.decl: type = interface_decl @Incomplete [concrete = constants.%Incomplete.type] {} {} +// CHECK:STDOUT: impl_decl @C.as.I.impl [concrete] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] +// CHECK:STDOUT: %.Self.frozen: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] +// CHECK:STDOUT: %.Self.ref.loc12_19.1: %I.type = name_ref .Self, %.Self.frozen [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type] +// CHECK:STDOUT: %.Self.as_type.loc12_19.1: type = facet_access_type %.Self.ref.loc12_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %.loc12_19.1: type = converted %.Self.ref.loc12_19.1, %.Self.as_type.loc12_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %impls.loc12_25.1 = requirement_impls %.loc12_19.1, %Incomplete.ref [concrete] +// CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.ref.loc12_19.2: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.as_type.loc12_19.2: type = facet_access_type %.Self.ref.loc12_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %.loc12_19.2: type = converted %.Self.ref.loc12_19.1, %.Self.as_type.loc12_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %impls.loc12_25.2 = requirement_impls %.loc12_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: %.loc12_13: type = where_expr [concrete = constants.%I_where.type] { +// CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] +// CHECK:STDOUT: %impls.loc12_25.2 = requirement_impls %.loc12_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %I.WithSelf.decl = interface_with_self_decl @I [concrete] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: +// CHECK:STDOUT: !requires: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Incomplete; +// CHECK:STDOUT: +// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc12_13 { +// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete] +// CHECK:STDOUT: %I.impl_witness: = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: extend %.loc12_13 +// CHECK:STDOUT: witness = +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_declaration_lookup_into_incomplete.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -631,7 +827,6 @@ interface B { // CHECK:STDOUT: %I.impl_witness: = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete] // CHECK:STDOUT: %C.as.I.impl.F.type: type = fn_type @C.as.I.impl.F [concrete] // CHECK:STDOUT: %C.as.I.impl.F: %C.as.I.impl.F.type = struct_value () [concrete] -// CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -648,19 +843,19 @@ interface B { // CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type] // CHECK:STDOUT: %.Self.frozen: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.frozen] // CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] -// CHECK:STDOUT: %.Self.ref.loc8_19.1: %I.type = name_ref .Self, %.Self.frozen [symbolic_self = constants.%.Self.frozen] +// CHECK:STDOUT: %.Self.ref.loc12_19.1: %I.type = name_ref .Self, %.Self.frozen [symbolic_self = constants.%.Self.frozen] // CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type] -// CHECK:STDOUT: %.Self.as_type.loc8_19.1: type = facet_access_type %.Self.ref.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %.loc8_19.1: type = converted %.Self.ref.loc8_19.1, %.Self.as_type.loc8_19.1 [symbolic_self = constants.%.Self.frozen.as_type] -// CHECK:STDOUT: %impls.loc8_25.1 = requirement_impls %.loc8_19.1, %Incomplete.ref [concrete] +// CHECK:STDOUT: %.Self.as_type.loc12_19.1: type = facet_access_type %.Self.ref.loc12_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %.loc12_19.1: type = converted %.Self.ref.loc12_19.1, %.Self.as_type.loc12_19.1 [symbolic_self = constants.%.Self.frozen.as_type] +// CHECK:STDOUT: %impls.loc12_25.1 = requirement_impls %.loc12_19.1, %Incomplete.ref [concrete] // CHECK:STDOUT: %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %.Self.ref.loc8_19.2: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %.Self.as_type.loc8_19.2: type = facet_access_type %.Self.ref.loc8_19.2 [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %.loc8_19.2: type = converted %.Self.ref.loc8_19.1, %.Self.as_type.loc8_19.2 [symbolic_self = constants.%.Self.as_type] -// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref [concrete] -// CHECK:STDOUT: %.loc8_13: type = where_expr [concrete = constants.%I_where.type] { +// CHECK:STDOUT: %.Self.ref.loc12_19.2: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %.Self.as_type.loc12_19.2: type = facet_access_type %.Self.ref.loc12_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %.loc12_19.2: type = converted %.Self.ref.loc12_19.1, %.Self.as_type.loc12_19.2 [symbolic_self = constants.%.Self.as_type] +// CHECK:STDOUT: %impls.loc12_25.2 = requirement_impls %.loc12_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: %.loc12_13: type = where_expr [concrete = constants.%I_where.type] { // CHECK:STDOUT: %base_facet_type = requirement_base_facet_type %I.ref [concrete] -// CHECK:STDOUT: %impls.loc8_25.2 = requirement_impls %.loc8_19.2, %Incomplete.ref [concrete] +// CHECK:STDOUT: %impls.loc12_25.2 = requirement_impls %.loc12_19.2, %Incomplete.ref [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -679,7 +874,7 @@ interface B { // CHECK:STDOUT: // CHECK:STDOUT: interface @Incomplete; // CHECK:STDOUT: -// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc8_13 { +// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc12_13 { // CHECK:STDOUT: %C.as.I.impl.F.decl: %C.as.I.impl.F.type = fn_decl @C.as.I.impl.F [concrete = constants.%C.as.I.impl.F] { // CHECK:STDOUT: %return.patt: = return_slot_pattern , [concrete = ] // CHECK:STDOUT: } { @@ -694,8 +889,8 @@ interface B { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Incomplete = // CHECK:STDOUT: .F = %C.as.I.impl.F.decl -// CHECK:STDOUT: extend %.loc8_13 -// CHECK:STDOUT: witness = %I.impl_witness +// CHECK:STDOUT: extend %.loc12_13 +// CHECK:STDOUT: witness = // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -712,10 +907,6 @@ interface B { // CHECK:STDOUT: !definition: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) { -// CHECK:STDOUT: !definition: -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_unidentified_constraint.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/impl/require_satisified_in_interface.carbon b/toolchain/check/testdata/impl/require_satisified_in_interface.carbon index 3368aa14433e..43ef7ca8b84e 100644 --- a/toolchain/check/testdata/impl/require_satisified_in_interface.carbon +++ b/toolchain/check/testdata/impl/require_satisified_in_interface.carbon @@ -23,7 +23,7 @@ interface Y { impl () as Y; // () needs to impl Z at the start of the definition. -// CHECK:STDERR: fail_missing_extend_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `()` implements `Z` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_extend_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `()` implements `Z` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl () as Y {} // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: @@ -42,7 +42,7 @@ interface Y { impl () as Y; // () needs to impl Z at the start of the definition. -// CHECK:STDERR: fail_missing_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `()` implements `Z` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `()` implements `Z` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl () as Y {} // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: @@ -61,7 +61,7 @@ interface Y { impl forall [T: type] T as Y; // T needs to impl Z at the start of the definition. -// CHECK:STDERR: fail_missing_extend_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `T` implements `Z` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_extend_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `T` implements `Z` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl forall [T: type] T as Y {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -80,7 +80,7 @@ interface Y { impl forall [T: type] T as Y; // T needs to impl Z at the start of the definition. -// CHECK:STDERR: fail_missing_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `T` implements `Z` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `T` implements `Z` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl forall [T: type] T as Y {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -99,7 +99,7 @@ interface Y(U: type) { extend require impls Z1(U) & Z2(B); } -// CHECK:STDERR: fail_missing_extend_require_double.carbon:[[@LINE+4]]:1: error: interface `Y(A)` being implemented requires that `()` implements `Z1(A) & Z2(B)` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_extend_require_double.carbon:[[@LINE+4]]:1: error: interface `Y(A)` being implemented requires that `()` implements `Z1(A) & Z2(B)` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl () as Y(A) {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -118,7 +118,7 @@ interface Y(U: type) { require impls Z1(U) & Z2(B); } -// CHECK:STDERR: fail_missing_require_double.carbon:[[@LINE+4]]:1: error: interface `Y(A)` being implemented requires that `()` implements `Z1(A) & Z2(B)` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_missing_require_double.carbon:[[@LINE+4]]:1: error: interface `Y(A)` being implemented requires that `()` implements `Z1(A) & Z2(B)` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl () as Y(A) {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -227,7 +227,7 @@ interface Y(U: type) { } // Y requires that C impls Z(Self), but it does not do so. -// CHECK:STDERR: fail_require_non_self_missing.carbon:[[@LINE+4]]:1: error: interface `Y(())` being implemented requires that `C` implements `Z(())` [RequireImplsNotImplemented] +// CHECK:STDERR: fail_require_non_self_missing.carbon:[[@LINE+4]]:1: error: interface `Y(())` being implemented requires that `C` implements `Z(())` [InterfaceRequireImplsNotImplemented] // CHECK:STDERR: impl () as Y(()) {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/impl/require_satisified_in_named_constraint.carbon b/toolchain/check/testdata/impl/require_satisified_in_named_constraint.carbon index a87063464f5d..ef864c0c24d5 100644 --- a/toolchain/check/testdata/impl/require_satisified_in_named_constraint.carbon +++ b/toolchain/check/testdata/impl/require_satisified_in_named_constraint.carbon @@ -10,7 +10,7 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/require_satisified_in_named_constraint.carbon -// --- todo_fail_missing_require_for_concrete_type.carbon +// --- fail_missing_require_for_concrete_type.carbon library "[[@TEST_NAME]]"; interface Y {} @@ -25,10 +25,13 @@ constraint N { impl () as N; // () needs to impl Z at the start of the definition. -// TODO: RequireImplsNotImplemented error that () does not implement Z. +// CHECK:STDERR: fail_missing_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: constraint `N` being implemented requires that `()` implements `Z` [IdentifiedRequireImplsNotImplemented] +// CHECK:STDERR: impl () as N {} +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: impl () as N {} -// --- todo_fail_missing_require_for_symbolic_type.carbon +// --- fail_missing_require_for_symbolic_type.carbon library "[[@TEST_NAME]]"; interface Y {} @@ -43,7 +46,10 @@ constraint N { impl forall [T: type] T as N; // T needs to impl Z at the start of the definition. -// TODO: RequireImplsNotImplemented error that () does not implement Z. +// CHECK:STDERR: fail_missing_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: constraint `N` being implemented requires that `T` implements `Z` [IdentifiedRequireImplsNotImplemented] +// CHECK:STDERR: impl forall [T: type] T as N {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: impl forall [T: type] T as N {} // --- require_for_concrete_type.carbon diff --git a/toolchain/check/testdata/where_expr/dot_self_impls.carbon b/toolchain/check/testdata/where_expr/dot_self_impls.carbon index 9be76d0545a4..c4fd8c4d4c51 100644 --- a/toolchain/check/testdata/where_expr/dot_self_impls.carbon +++ b/toolchain/check/testdata/where_expr/dot_self_impls.carbon @@ -271,8 +271,14 @@ interface J { let T: type; } // Interfaces to the right of the `where` don't interfere with the // "can only impl a facet type with a single interface" rule. Only // the interface being implemented needs to have all of its -// associated constants set +// associated constants set. +impl {.a: C} as I where .Self impls J; +impl {.b: C} as J where .Self impls I and .T = (); + +// The requirements after `where` must be met before we define the above impls. +impl {.a: C} as J where .T = () {} impl {.a: C} as I where .Self impls J {} +impl {.b: C} as I {} impl {.b: C} as J where .Self impls I and .T = () {} // --- impl_with_rewrite_of_interface_not_being_implemented.carbon diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index 345bc06a6ad6..a3e57e918707 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -411,7 +411,8 @@ CARBON_DIAGNOSTIC_KIND(RequireImplsMissingSelfEmptyFacetType) CARBON_DIAGNOSTIC_KIND(RequireImplsIncompleteFacetType) CARBON_DIAGNOSTIC_KIND(RequireImplsReferenceCycle) CARBON_DIAGNOSTIC_KIND(RequireImplsUnidentifiedFacetType) -CARBON_DIAGNOSTIC_KIND(RequireImplsNotImplemented) +CARBON_DIAGNOSTIC_KIND(IdentifiedRequireImplsNotImplemented) +CARBON_DIAGNOSTIC_KIND(InterfaceRequireImplsNotImplemented) CARBON_DIAGNOSTIC_KIND(RequireInWrongScope) // Observe checking.