From 4f474fafb5a5716ab0835ae96e97a8ababf71614 Mon Sep 17 00:00:00 2001 From: josh11b <15258583+josh11b@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:43:45 -0800 Subject: [PATCH] Remove some single-interface restrictions from some uses of facet types (#4508) Co-authored-by: Josh L --- toolchain/check/context.cpp | 30 +++++++--------- toolchain/check/handle_impl.cpp | 34 ++++++++----------- toolchain/check/impl.cpp | 7 ++-- .../fail_lookup_in_type_type.carbon | 9 ++--- toolchain/diagnostics/diagnostic_kind.def | 1 - 5 files changed, 33 insertions(+), 48 deletions(-) diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index c5a5ae4916f1..f26997e2cac4 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -1188,26 +1188,20 @@ auto Context::TryToDefineType(SemIR::TypeId type_id, if (auto facet_type = types().TryGetAs(type_id)) { const auto& facet_type_info = sem_ir().facet_types().Get(facet_type->facet_type_id); - auto interface = facet_type_info.TryAsSingleInterface(); - if (!interface) { - auto builder = diagnoser(); - CARBON_DIAGNOSTIC(SingleInterfaceFacetTypeOnly, Note, - "only single interface facet types supported so far"); - builder.Note(SemIR::LocId::Invalid, SingleInterfaceFacetTypeOnly); - builder.Emit(); - return false; - } - auto interface_id = interface->interface_id; - if (!interfaces().Get(interface_id).is_defined()) { - auto builder = diagnoser(); - NoteUndefinedInterface(interface_id, builder); - builder.Emit(); - return false; - } + for (auto interface : facet_type_info.impls_constraints) { + auto interface_id = interface.interface_id; + if (!interfaces().Get(interface_id).is_defined()) { + auto builder = diagnoser(); + NoteUndefinedInterface(interface_id, builder); + builder.Emit(); + return false; + } - if (interface->specific_id.is_valid()) { - ResolveSpecificDefinition(*this, interface->specific_id); + if (interface.specific_id.is_valid()) { + ResolveSpecificDefinition(*this, interface.specific_id); + } } + // TODO: Process other requirements. } return true; diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 6543e615a295..5b62b81e8e9b 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -181,28 +181,22 @@ static auto ExtendImpl(Context& context, Parse::NodeId extend_node, } const SemIR::FacetTypeInfo& info = context.sem_ir().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; + } - auto interface_type = info.TryAsSingleInterface(); - if (!interface_type) { - context.TODO(node_id, "extending non-single-interface facet type"); - parent_scope.has_error = true; - return; + parent_scope.extended_scopes.push_back(interface.scope_id); } - - 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); } // Pops the parameters of an `impl`, forming a `NameComponent` with no diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 69c0c3fef7fe..f067148bd818 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -124,11 +124,14 @@ static auto CheckAssociatedFunctionImplementation( // Builds a witness that the specified impl implements the given interface. static auto BuildInterfaceWitness( - Context& context, const SemIR::Impl& impl, SemIR::TypeId interface_type_id, + Context& context, const SemIR::Impl& impl, SemIR::TypeId facet_type_id, SemIR::FacetTypeInfo::ImplsConstraint interface_type, llvm::SmallVectorImpl& used_decl_ids) -> SemIR::InstId { const auto& interface = context.interfaces().Get(interface_type.interface_id); - if (!context.TryToDefineType(interface_type_id, [&] { + // TODO: This is going to try and define all the interfaces for this facet + // type, and so once we support impl of a facet type with more than one + // interface, it might give the wrong name in the diagnostic. + if (!context.TryToDefineType(facet_type_id, [&] { CARBON_DIAGNOSTIC(ImplOfUndefinedInterface, Error, "implementation of undefined interface {0}", SemIR::NameId); 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 1a94b583631e..b16a04dca864 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,11 +22,6 @@ let T: type.not_found = {}; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+8]]:8: error: member access into undefined interface `type where...` [QualifiedExprInUndefinedInterfaceScope] -// CHECK:STDERR: let U: (type where .Self impls type).missing = {}; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_lookup_type_where.carbon: note: only single interface facet types supported so far [SingleInterfaceFacetTypeOnly] -// CHECK:STDERR: // CHECK:STDERR: fail_lookup_type_where.carbon:[[@LINE+3]]:8: error: type `type` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: let U: (type where .Self impls type).missing = {}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -66,14 +61,14 @@ let U: (type where .Self impls type).missing = {}; // CHECK:STDOUT: } // CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self] // CHECK:STDOUT: %.Self.ref: type = name_ref .Self, %.Self [symbolic = constants.%.Self] -// CHECK:STDOUT: %.loc12: type = where_expr %.Self [template = constants.%type_where] { +// CHECK:STDOUT: %.loc7: type = where_expr %.Self [template = constants.%type_where] { // CHECK:STDOUT: requirement_impls %.Self.ref, type // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc12: %.1 = struct_literal () +// CHECK:STDOUT: %.loc7: %.1 = struct_literal () // CHECK:STDOUT: %U: = bind_name U, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 312d4c8b7118..46b7a4153c9c 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -240,7 +240,6 @@ CARBON_DIAGNOSTIC_KIND(ExportPrevious) // Interface checking. CARBON_DIAGNOSTIC_KIND(InterfaceForwardDeclaredHere) CARBON_DIAGNOSTIC_KIND(InterfaceUndefinedWithinDefinition) -CARBON_DIAGNOSTIC_KIND(SingleInterfaceFacetTypeOnly) // Impl checking. CARBON_DIAGNOSTIC_KIND(ExtendImplForall)