Просмотр исходного кода

Remove some single-interface restrictions from some uses of facet types (#4508)

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
josh11b 1 год назад
Родитель
Сommit
4f474fafb5

+ 12 - 18
toolchain/check/context.cpp

@@ -1188,26 +1188,20 @@ auto Context::TryToDefineType(SemIR::TypeId type_id,
   if (auto facet_type = types().TryGetAs<SemIR::FacetType>(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;

+ 14 - 20
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;
-  }
-
-  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.extended_scopes.push_back(interface.scope_id);
 }
 
 // Pops the parameters of an `impl`, forming a `NameComponent` with no

+ 5 - 2
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<SemIR::InstId>& 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);

+ 2 - 7
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: <error> = bind_name U, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 0 - 1
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)