Procházet zdrojové kódy

Use the IdentifiedFacetType when mangling an ImplDecl (#6665)

The code was going through the raw `constraint_id` facet type, which
could be a named constraint. To get the interface being impl'd, use the
IdentifiedFacetType.

Import was adding an IdenfiedFacetTypeId for the facet type when
importing an ImplDecl, however it was using an attached self constant.
Then later lookups using `constant_values().GetConstantId(...)` from the
`self_id` would give an unattached constant and not find the
IdentifiedFacetTypeId. So have import do what we do when making an
ImplDecl locally, and use the unattached constant for the
RequireIdentifiedFacetType call.

We add a test of mangling an `impl as` for a named constraint, which
crashes before this change.
Dana Jansens před 3 měsíci
rodič
revize
f64d084f27

+ 5 - 1
toolchain/check/import_ref.cpp

@@ -2628,8 +2628,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   // declarations always identify the facet type.
   if (auto facet_type = resolver.local_insts().TryGetAs<SemIR::FacetType>(
           resolver.local_constant_values().GetInstId(constraint_const_id))) {
+    // Lookups later will be with the unattached constant, whereas
+    // GetLocalConstantId gave us an attached constant.
+    auto unattached_self_const_id =
+        resolver.local_constant_values().GetUnattachedConstant(self_const_id);
     RequireIdentifiedFacetType(resolver.local_context(), SemIR::LocId::None,
-                               self_const_id, *facet_type, nullptr);
+                               unattached_self_const_id, *facet_type, nullptr);
   }
   if (import_impl.is_complete()) {
     AddImplDefinition(resolver, import_impl, new_impl);

+ 15 - 8
toolchain/lower/mangler.cpp

@@ -13,6 +13,8 @@
 #include "toolchain/sem_ir/entry_point.h"
 #include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/pattern.h"
+#include "toolchain/sem_ir/specific_interface.h"
+#include "toolchain/sem_ir/specific_named_constraint.h"
 #include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::Lower {
@@ -66,16 +68,21 @@ auto Mangler::MangleInverseQualifiedNameScope(llvm::raw_ostream& os,
 
         auto facet_type = insts().GetAs<SemIR::FacetType>(
             constant_values().GetConstantInstId(impl.constraint_id));
-        const auto& facet_type_info =
-            sem_ir().facet_types().Get(facet_type.facet_type_id);
-        CARBON_CHECK(facet_type_info.extend_constraints.size() == 1,
-                     "Mangling of an impl of something other than a single "
-                     "interface is not yet supported.");
-        auto interface_type = facet_type_info.extend_constraints.front();
+
+        auto identified_facet_type_id =
+            sem_ir().identified_facet_types().Lookup(
+                {.facet_type_id = facet_type.facet_type_id,
+                 .self_const_id =
+                     sem_ir().constant_values().Get(impl.self_id)});
+        CARBON_CHECK(identified_facet_type_id.has_value(),
+                     "ImplDecl with unidentified facet type constraint");
+        const auto& identified =
+            sem_ir().identified_facet_types().Get(identified_facet_type_id);
+        auto impl_target = identified.impl_as_target_interface();
         const auto& interface =
-            sem_ir().interfaces().Get(interface_type.interface_id);
+            sem_ir().interfaces().Get(impl_target.interface_id);
         names_to_render.push_back({.name_scope_id = interface.scope_id,
-                                   .specific_id = interface_type.specific_id,
+                                   .specific_id = impl_target.specific_id,
                                    .prefix = ':'});
 
         auto self_const_inst_id =

+ 16 - 0
toolchain/lower/testdata/interface/mangle_declared_class.carbon

@@ -18,6 +18,14 @@ impl C as I {
   fn F() {}
 }
 
+constraint N {
+  extend require impls I;
+}
+class D;
+impl D as N {
+  fn F() {}
+}
+
 // CHECK:STDOUT: ; ModuleID = 'mangle_declared_class.carbon'
 // CHECK:STDOUT: source_filename = "mangle_declared_class.carbon"
 // CHECK:STDOUT:
@@ -27,6 +35,12 @@ impl C as I {
 // CHECK:STDOUT:   ret void, !dbg !7
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: ; Function Attrs: nounwind
+// CHECK:STDOUT: define void @"_CF.D.Main:I.Main"() #0 !dbg !8 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   ret void, !dbg !9
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nounwind }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
@@ -40,3 +54,5 @@ impl C as I {
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{null}
 // CHECK:STDOUT: !7 = !DILocation(line: 18, column: 3, scope: !4)
+// CHECK:STDOUT: !8 = distinct !DISubprogram(name: "F", linkageName: "_CF.D.Main:I.Main", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !9 = !DILocation(line: 26, column: 3, scope: !8)