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

Avoid mismatched InterfaceId comparison between two files (#6241)

Co-authored-by: Dana Jansens <danakj@orodu.net>
David Blaikie 6 месяцев назад
Родитель
Сommit
0ed5d41a1b

+ 13 - 3
toolchain/check/impl_validation.cpp

@@ -366,12 +366,22 @@ static auto ImportFinalImplsWithImplInFile(Context& context) -> void {
 
     auto interface_id = impl.interface.interface_id;
     const auto& interface = context.interfaces().Get(interface_id);
-    auto import_ir_id = GetIRId(context, interface.first_owning_decl_id);
-    if (!import_ir_id.has_value()) {
+    if (!interface.first_owning_decl_id.has_value()) {
+      continue;
+    }
+    const auto& import_ir_inst =
+        GetCanonicalImportIRInst(context, interface.first_owning_decl_id);
+    if (!import_ir_inst.ir_id().has_value()) {
       continue;
     }
     interfaces_to_import.push_back(
-        {.ir_id = import_ir_id, .interface_id = interface_id});
+        {.ir_id = import_ir_inst.ir_id(),
+         .interface_id =
+             context.import_irs()
+                 .Get(import_ir_inst.ir_id())
+                 .sem_ir->insts()
+                 .GetAs<SemIR::InterfaceDecl>(import_ir_inst.inst_id())
+                 .interface_id});
   }
 
   llvm::sort(interfaces_to_import);

+ 7 - 3
toolchain/check/testdata/impl/lookup/impl_overlap.carbon

@@ -22,6 +22,10 @@ interface Z(T:! type) {}
 // --- interface_z_with_impl.carbon
 library "[[@TEST_NAME]]";
 
+// Add an extra unused interface to bump `Z`'s id up so that it doesn't
+// accidentally match the id assigned to the imported copy of `Z`.
+interface Other(T:! type) {}
+
 interface Z(T:! type) {}
 
 final impl forall [T:! type] T as Z(T) {}
@@ -176,7 +180,7 @@ class C;
 // CHECK:STDERR: final impl C as Z(()) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_final_impl_with_both_interface_and_self_but_different_files.carbon:[[@LINE-10]]:1: in import [InImport]
-// CHECK:STDERR: interface_z_with_impl.carbon:5:1: note: imported `final impl` here [FinalImplOverlapsDifferentFileNote]
+// CHECK:STDERR: interface_z_with_impl.carbon:9:1: note: imported `final impl` here [FinalImplOverlapsDifferentFileNote]
 // CHECK:STDERR: final impl forall [T:! type] T as Z(T) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -196,7 +200,7 @@ class C;
 // CHECK:STDERR: final impl C as Z(C) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_final_overlaps_final_from_other_file.carbon:[[@LINE-10]]:1: in import [InImport]
-// CHECK:STDERR: interface_z_with_impl.carbon:5:1: note: imported `final impl` here [FinalImplOverlapsDifferentFileNote]
+// CHECK:STDERR: interface_z_with_impl.carbon:9:1: note: imported `final impl` here [FinalImplOverlapsDifferentFileNote]
 // CHECK:STDERR: final impl forall [T:! type] T as Z(T) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -215,7 +219,7 @@ class C;
 // CHECK:STDERR: impl C as Z(C) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_final_overlaps_non_final_from_other_file.carbon:[[@LINE-9]]:1: in import [InImport]
-// CHECK:STDERR: interface_z_with_impl.carbon:5:1: note: `final impl` declared here would always be used instead [ImplFinalOverlapsNonFinalNote]
+// CHECK:STDERR: interface_z_with_impl.carbon:9:1: note: `final impl` declared here would always be used instead [ImplFinalOverlapsNonFinalNote]
 // CHECK:STDERR: final impl forall [T:! type] T as Z(T) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR: