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

Switch import logic to rely on constants. (#3917)

Breaks extern handling, makes other things work. TODOs in import_ref for
extern, the tests need rewritten too under the new model.
Jon Ross-Perkins 2 лет назад
Родитель
Сommit
6483044597

+ 1 - 1
toolchain/check/context.cpp

@@ -326,7 +326,7 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
     auto import_inst_id =
         AddImportRef(context, {.ir_id = import_ir_id, .inst_id = it->second});
     if (result_id.is_valid()) {
-      MergeImportRef(context, import_inst_id, result_id);
+      context.DiagnoseDuplicateName(import_inst_id, result_id);
     } else {
       LoadImportRef(context, import_inst_id,
                     mark_imports_used ? loc : SemIR::LocId::Invalid);

+ 1 - 1
toolchain/check/import.cpp

@@ -253,7 +253,7 @@ auto ImportLibraryFromCurrentPackage(Context& context,
                                .Get(enclosing_scope_id)
                                .names.insert({name_id, target_id});
       if (!success) {
-        MergeImportRef(context, target_id, it->second);
+        context.DiagnoseDuplicateName(target_id, it->second);
       }
     }
   }

+ 103 - 16
toolchain/check/import_ref.cpp

@@ -9,6 +9,7 @@
 #include "toolchain/check/context.h"
 #include "toolchain/check/eval.h"
 #include "toolchain/parse/node_ids.h"
+#include "toolchain/sem_ir/constant.h"
 #include "toolchain/sem_ir/file.h"
 #include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/inst.h"
@@ -40,11 +41,10 @@ auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void {
 auto AddImportIR(Context& context, SemIR::ImportIR import_ir)
     -> SemIR::ImportIRId {
   auto& ir_id = context.check_ir_map()[import_ir.sem_ir->check_ir_id().index];
-  if (ir_id.is_valid()) {
-    return ir_id;
+  if (!ir_id.is_valid()) {
+    // Note this updates check_ir_map.
+    ir_id = InternalAddImportIR(context, import_ir);
   }
-  // Note this updates check_ir_map.
-  ir_id = InternalAddImportIR(context, import_ir);
   return ir_id;
 }
 
@@ -102,14 +102,19 @@ auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst)
 // chance of a second call, it's important to reserve all expensive logic until
 // it's been established that input constants are available; this in particular
 // includes GetTypeIdForTypeConstant calls which do a hash table lookup.
+//
+// TODO: Fix class `extern` handling and merging, rewrite tests.
+// - check/testdata/class/cross_package_import.carbon
+// - check/testdata/class/extern.carbon
+// TODO: Fix function `extern` handling and merging, rewrite tests.
+// - check/testdata/function/declaration/import.carbon
+// - check/testdata/packages/cross_package_import.carbon
 class ImportRefResolver {
  public:
   explicit ImportRefResolver(Context& context, SemIR::ImportIRId import_ir_id)
       : context_(context),
         import_ir_id_(import_ir_id),
-        import_ir_(*context_.import_irs().Get(import_ir_id).sem_ir),
-        import_ir_constant_values_(
-            context_.import_ir_constant_values()[import_ir_id.index]) {}
+        import_ir_(*context_.import_irs().Get(import_ir_id).sem_ir) {}
 
   // Iteratively resolves an imported instruction's inner references until a
   // constant ID referencing the current IR is produced. See the class comment
@@ -121,8 +126,8 @@ class ImportRefResolver {
       CARBON_CHECK(work.inst_id.is_valid());
 
       // Step 1: check for a constant value.
-      auto existing_const_id = import_ir_constant_values_.Get(work.inst_id);
-      if (existing_const_id.is_valid() && !work.retry) {
+      auto existing = FindResolvedConstId(work.inst_id);
+      if (existing.const_id.is_valid() && !work.retry) {
         work_stack_.pop_back();
         continue;
       }
@@ -130,13 +135,15 @@ class ImportRefResolver {
       // Step 2: resolve the instruction.
       auto initial_work = work_stack_.size();
       auto [new_const_id, finished] =
-          TryResolveInst(work.inst_id, existing_const_id);
+          TryResolveInst(work.inst_id, existing.const_id);
       CARBON_CHECK(finished == !HasNewWork(initial_work));
 
-      CARBON_CHECK(!existing_const_id.is_valid() ||
-                   existing_const_id == new_const_id)
+      CARBON_CHECK(!existing.const_id.is_valid() ||
+                   existing.const_id == new_const_id)
           << "Constant value changed in second pass.";
-      import_ir_constant_values_.Set(work.inst_id, new_const_id);
+      if (!existing.const_id.is_valid()) {
+        SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id);
+      }
 
       // Step 3: pop or retry.
       if (finished) {
@@ -145,7 +152,7 @@ class ImportRefResolver {
         work_stack_[initial_work - 1].retry = true;
       }
     }
-    auto constant_id = import_ir_constant_values_.Get(inst_id);
+    auto constant_id = import_ir_constant_values().Get(inst_id);
     CARBON_CHECK(constant_id.is_valid());
     return constant_id;
   }
@@ -196,6 +203,83 @@ class ImportRefResolver {
     bool finished = true;
   };
 
+  // The constant found by FindResolvedConstId.
+  struct ResolvedConstId {
+    // The constant for the instruction. Invalid if not yet resolved.
+    SemIR::ConstantId const_id = SemIR::ConstantId::Invalid;
+
+    // Instructions which are indirect but equivalent to the current instruction
+    // being resolved, and should have their constant set to the same. Empty
+    // when const_id is valid.
+    llvm::SmallVector<SemIR::ImportIRInst> indirect_insts = {};
+  };
+
+  // Looks to see if an instruction has been resolved. If a constant is only
+  // found indirectly, sets the constant for any indirect steps that don't
+  // already have the constant. If a constant isn't found, returns the indirect
+  // instructions so that they can have the resolved constant assigned later.
+  auto FindResolvedConstId(SemIR::InstId inst_id) -> ResolvedConstId {
+    ResolvedConstId result;
+
+    if (auto existing_const_id = import_ir_constant_values().Get(inst_id);
+        existing_const_id.is_valid()) {
+      result.const_id = existing_const_id;
+      return result;
+    }
+
+    const auto* cursor_ir = &import_ir_;
+    auto cursor_ir_id = SemIR::ImportIRId::Invalid;
+    auto cursor_inst_id = inst_id;
+
+    while (true) {
+      auto loc_id = cursor_ir->insts().GetLocId(cursor_inst_id);
+      if (!loc_id.is_import_ir_inst_id()) {
+        return result;
+      }
+      auto ir_inst =
+          cursor_ir->import_ir_insts().Get(loc_id.import_ir_inst_id());
+
+      const auto* prev_ir = cursor_ir;
+      auto prev_inst_id = cursor_inst_id;
+
+      cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id).sem_ir;
+      cursor_ir_id = context_.check_ir_map()[cursor_ir->check_ir_id().index];
+      if (!cursor_ir_id.is_valid()) {
+        // TODO: Should we figure out a location to assign here?
+        cursor_ir_id = AddImportIR(
+            context_, {.node_id = Parse::NodeId::Invalid, .sem_ir = cursor_ir});
+      }
+      cursor_inst_id = ir_inst.inst_id;
+
+      CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id)
+          << cursor_ir->insts().Get(cursor_inst_id);
+
+      if (auto const_id =
+              context_.import_ir_constant_values()[cursor_ir_id.index].Get(
+                  cursor_inst_id);
+          const_id.is_valid()) {
+        SetResolvedConstId(inst_id, result.indirect_insts, const_id);
+        result.const_id = const_id;
+        result.indirect_insts.clear();
+        return result;
+      } else {
+        result.indirect_insts.push_back(
+            {.ir_id = cursor_ir_id, .inst_id = cursor_inst_id});
+      }
+    }
+  }
+
+  // Sets a resolved constant into the current and indirect instructions.
+  auto SetResolvedConstId(SemIR::InstId inst_id,
+                          llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,
+                          SemIR::ConstantId const_id) -> void {
+    import_ir_constant_values().Set(inst_id, const_id);
+    for (auto indirect_inst : indirect_insts) {
+      context_.import_ir_constant_values()[indirect_inst.ir_id.index].Set(
+          indirect_inst.inst_id, const_id);
+    }
+  }
+
   // Returns true if new unresolved constants were found.
   //
   // At the start of a function, do:
@@ -216,7 +300,7 @@ class ImportRefResolver {
   // Returns the ConstantId for an InstId. Adds unresolved constants to
   // work_stack_.
   auto GetLocalConstantId(SemIR::InstId inst_id) -> SemIR::ConstantId {
-    auto const_id = import_ir_constant_values_.Get(inst_id);
+    auto const_id = import_ir_constant_values().Get(inst_id);
     if (!const_id.is_valid()) {
       work_stack_.push_back({inst_id});
     }
@@ -1029,10 +1113,13 @@ class ImportRefResolver {
         context_.GetTypeIdForTypeConstant(elem_const_id)))};
   }
 
+  auto import_ir_constant_values() -> SemIR::ConstantValueStore& {
+    return context_.import_ir_constant_values()[import_ir_id_.index];
+  }
+
   Context& context_;
   SemIR::ImportIRId import_ir_id_;
   const SemIR::File& import_ir_;
-  SemIR::ConstantValueStore& import_ir_constant_values_;
   llvm::SmallVector<Work> work_stack_;
 };
 

+ 0 - 92
toolchain/check/merge.cpp

@@ -157,44 +157,6 @@ auto ResolvePrevInstForMerge(Context& context, Parse::NodeId node_id,
   return result;
 }
 
-// Returns the instruction to consider when merging the given inst_id. Returns
-// nullopt if merging is infeasible and no diagnostic should be printed.
-static auto ResolveMergeableInst(Context& context, SemIR::InstId inst_id)
-    -> std::optional<InstForMerge> {
-  auto inst = context.insts().Get(inst_id);
-  switch (inst.kind()) {
-    case SemIR::ImportRefUnloaded::Kind:
-      // Load before merging.
-      LoadImportRef(context, inst_id, SemIR::LocId::Invalid);
-      break;
-
-    case SemIR::ImportRefLoaded::Kind:
-    case SemIR::ImportRefUsed::Kind:
-      // Already loaded.
-      break;
-
-    case SemIR::Namespace::Kind:
-      // Return back the namespace directly.
-      return {
-          {.inst = inst, .import_ir_inst_id = SemIR::ImportIRInstId::Invalid}};
-
-    default:
-      CARBON_FATAL() << "Unexpected inst kind passed to ResolveMergeableInst: "
-                     << inst;
-  }
-
-  auto const_id = context.constant_values().Get(inst_id);
-  // TODO: Function and type declarations are constant, but `var` declarations
-  // are non-constant and should still merge.
-  if (!const_id.is_constant()) {
-    return std::nullopt;
-  }
-
-  return {
-      {.inst = context.insts().Get(const_id.inst_id()),
-       .import_ir_inst_id = inst.As<SemIR::AnyImportRef>().import_ir_inst_id}};
-}
-
 auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,
                              SemIR::NameId name_id, SemIR::InstId new_inst_id)
     -> void {
@@ -205,58 +167,4 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,
   }
 }
 
-// TODO: On successful merges, this may need to "spoil" new_inst_id in order to
-// prevent it from being emitted in lowering.
-auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
-                    SemIR::InstId prev_inst_id) -> void {
-  auto new_inst = ResolveMergeableInst(context, new_inst_id);
-  auto prev_inst = ResolveMergeableInst(context, prev_inst_id);
-  if (!new_inst || !prev_inst) {
-    // TODO: Once `var` declarations get an associated instruction for handling,
-    // it might be more appropriate to return without diagnosing here, to handle
-    // invalid declarations.
-    context.DiagnoseDuplicateName(new_inst_id, prev_inst_id);
-    return;
-  }
-
-  if (new_inst->inst.kind() != prev_inst->inst.kind()) {
-    context.DiagnoseDuplicateName(new_inst_id, prev_inst_id);
-    return;
-  }
-
-  CARBON_KIND_SWITCH(new_inst->inst) {
-    case CARBON_KIND(SemIR::FunctionDecl new_decl): {
-      auto prev_decl = prev_inst->inst.TryAs<SemIR::FunctionDecl>();
-      if (!prev_decl) {
-        break;
-      }
-
-      auto new_fn = context.functions().Get(new_decl.function_id);
-      MergeFunctionRedecl(context, new_inst_id, new_fn,
-                          /*new_is_import=*/true,
-                          /*new_is_definition=*/false, prev_decl->function_id,
-                          prev_inst->import_ir_inst_id);
-      return;
-    }
-    case CARBON_KIND(SemIR::ClassType new_type): {
-      auto prev_type = prev_inst->inst.TryAs<SemIR::ClassType>();
-      if (!prev_type) {
-        break;
-      }
-
-      auto new_class = context.classes().Get(new_type.class_id);
-      // TODO: Fix is_extern logic.
-      MergeClassRedecl(context, new_inst_id, new_class,
-                       /*new_is_import=*/true, new_class.is_defined(),
-                       /*new_is_extern=*/false, prev_type->class_id,
-                       /*prev_is_extern=*/false, prev_inst->import_ir_inst_id);
-      return;
-    }
-    default:
-      context.TODO(new_inst_id, llvm::formatv("Merging {0} not yet supported.",
-                                              new_inst->inst.kind()));
-      return;
-  }
-}
-
 }  // namespace Carbon::Check

+ 0 - 5
toolchain/check/merge.h

@@ -56,11 +56,6 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,
                              SemIR::NameId name_id, SemIR::InstId new_inst_id)
     -> void;
 
-// Merges an import ref at new_inst_id another at prev_inst_id. May print a
-// diagnostic if merging is invalid.
-auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
-                    SemIR::InstId prev_inst_id) -> void;
-
 }  // namespace Carbon::Check
 
 #endif  // CARBON_TOOLCHAIN_CHECK_MERGE_H_

+ 12 - 18
toolchain/check/testdata/class/cross_package_import.carbon

@@ -64,13 +64,13 @@ import Other library "define";
 // CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+12]]:1: In import.
 // CHECK:STDERR: import Other library "extern";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: other_extern.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: other_extern.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import Other library "define";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: other_define.carbon:4:1: Previously declared here.
+// CHECK:STDERR: other_define.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: class C {}
 // CHECK:STDERR: ^~~~~~~~~
 import Other library "extern";
@@ -235,9 +235,8 @@ var c: Other.C = {};
 // CHECK:STDOUT: --- fail_todo_merge_define_extern.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
+// CHECK:STDOUT:   %C: type = class_type @C [template]
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
 // CHECK:STDOUT:   %.2: type = tuple_type () [template]
 // CHECK:STDOUT:   %.3: type = ptr_type {} [template]
 // CHECK:STDOUT:   %struct: C = struct_value () [template]
@@ -252,23 +251,20 @@ var c: Other.C = {};
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Other: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Other.ref: <namespace> = name_ref Other, %Other [template = %Other]
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir2, inst+2, loc_19 [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir2, inst+2, loc_19 [template = constants.%C]
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+3, unloaded
-// CHECK:STDOUT:   %import_ref.3: type = import_ref ir3, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
-// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C.1]
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir3, inst+2, unloaded
+// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
 // CHECK:STDOUT:   %c.var: ref C = var c
 // CHECK:STDOUT:   %c: ref C = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1 {
+// CHECK:STDOUT: class @C {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = file.%import_ref.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2;
-// CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc23_19.1: {} = struct_literal ()
@@ -281,7 +277,7 @@ var c: Other.C = {};
 // CHECK:STDOUT: --- fail_conflict.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C: type = class_type @C.2 [template]
+// CHECK:STDOUT:   %C: type = class_type @C [template]
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
 // CHECK:STDOUT:   %.2: type = tuple_type () [template]
 // CHECK:STDOUT:   %.3: type = ptr_type {} [template]
@@ -298,21 +294,19 @@ var c: Other.C = {};
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Other.ref: <namespace> = name_ref Other, %Other [template = %Other]
 // CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_19 [template = constants.%C]
-// CHECK:STDOUT:   %C.decl: type = class_decl @C.2 [template = constants.%C] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+3, unloaded
-// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir2, inst+2, loaded [template = imports.%C]
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
 // CHECK:STDOUT:   %c.var: ref C = var c
 // CHECK:STDOUT:   %c: ref C = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2 {
+// CHECK:STDOUT: class @C {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = file.%import_ref.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @C.1();
-// CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc22_19.1: {} = struct_literal ()

+ 23 - 98
toolchain/check/testdata/class/extern.carbon

@@ -129,13 +129,13 @@ import library "extern_decl";
 // CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE+13]]:1: In import.
 // CHECK:STDERR: import library "decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: class C;
 // CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -149,13 +149,13 @@ import library "decl";
 // CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE+13]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: extern_decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import library "decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: class C;
 // CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR:
@@ -169,13 +169,13 @@ import library "extern_decl";
 // CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE+13]]:1: In import.
 // CHECK:STDERR: import library "def";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: def.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: class C {}
 // CHECK:STDERR: ^~~~~~~~~
 // CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -189,13 +189,13 @@ import library "extern_decl";
 // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import.
 // CHECK:STDERR: import library "decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: class C;
 // CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -203,13 +203,13 @@ import library "decl";
 // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import.
 // CHECK:STDERR: import library "def";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: def.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: class C {}
 // CHECK:STDERR: ^~~~~~~~~
 // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-21]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -223,13 +223,13 @@ import library "extern_decl";
 // CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+12]]:1: In import.
 // CHECK:STDERR: import library "extern_decl_copy";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl_copy.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`.
+// CHECK:STDERR: extern_decl_copy.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: extern class C;
 // CHECK:STDERR: ^~~~~~~~~~~~~~~
 import library "extern_decl_copy";
@@ -484,140 +484,65 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_extern_decl_then_decl.carbon
 // CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1;
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2;
-// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_decl_then_extern_decl.carbon
 // CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1;
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2;
-// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_extern_decl_then_def.carbon
 // CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %import_ref.3 = import_ref ir2, inst+3, unloaded
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.3
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.3
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_import_ownership_conflict.carbon
 // CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT:   %C.3: type = class_type @C.3 [template]
-// CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
-// CHECK:STDOUT:   %import_ref.3: type = import_ref ir3, inst+2, loaded [template = constants.%C.3]
-// CHECK:STDOUT:   %C.decl.3: type = class_decl @C.3 [template = constants.%C.3] {}
-// CHECK:STDOUT:   %import_ref.4 = import_ref ir3, inst+3, unloaded
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir3, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1;
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.4
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.3 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.4
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_extern_decl_copy.carbon
 // CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1]
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1;
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2;
-// CHECK:STDOUT:
 // CHECK:STDOUT: --- extern_decl_after_import_extern_decl.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {

+ 445 - 0
toolchain/check/testdata/class/import_indirect.carbon

@@ -0,0 +1,445 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+
+// Triangle:
+//
+//     a    <-- Define
+//     |\
+//     | b  <-- Re-export
+//     |/
+//     X    <-- Use both
+//
+// Diamond:
+//
+//     a    <-- Define
+//    / \
+//   b   c  <-- Re-export
+//    \ /
+//     X    <-- Use both
+
+// ============================================================================
+// Setup files
+// ============================================================================
+
+// --- a.carbon
+
+library "a" api;
+
+class C {}
+
+// --- b.carbon
+
+library "b" api;
+
+import library "a";
+
+alias D = C;
+
+var b_val: C = {};
+var b_ptr: D* = &b_val;
+
+// --- c.carbon
+
+library "c" api;
+
+import library "a";
+
+alias E = C;
+
+var c_val: C = {};
+var c_ptr: E* = &c_val;
+
+// ============================================================================
+// Test files
+// ============================================================================
+
+// --- triangle.carbon
+
+library "triangle" api;
+
+import library "a";
+import library "b";
+
+var val: C = {};
+var ptr: D* = &val;
+
+// --- triangle_reverse.carbon
+
+library "triangle_reverse" api;
+
+import library "b";
+import library "a";
+
+var val: C = {};
+var ptr: D* = &val;
+
+// --- diamond.carbon
+
+library "diamond" api;
+
+import library "b";
+import library "c";
+
+var val: D = {};
+var ptr: E* = &val;
+
+// --- diamond_reverse.carbon
+
+library "diamond_reverse" api;
+
+import library "c";
+import library "b";
+
+var val: D = {};
+var ptr: E* = &val;
+
+// CHECK:STDOUT: --- a.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .C = %C.decl
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = constants.%C
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- b.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .C = %import_ref.1
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .D = %D
+// CHECK:STDOUT:     .b_val = %b_val
+// CHECK:STDOUT:     .b_ptr = %b_ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C]
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+3, unloaded
+// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %D: type = bind_alias D, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %b_val.var: ref C = var b_val
+// CHECK:STDOUT:   %b_val: ref C = bind_name b_val, %b_val.var
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %D [template = constants.%C]
+// CHECK:STDOUT:   %.loc9: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %b_ptr.var: ref C* = var b_ptr
+// CHECK:STDOUT:   %b_ptr: ref C* = bind_name b_ptr, %b_ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc8_17.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc8_17.2: init C = class_init (), file.%b_val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc8_18: init C = converted %.loc8_17.1, %.loc8_17.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%b_val.var, %.loc8_18
+// CHECK:STDOUT:   %b_val.ref: ref C = name_ref b_val, file.%b_val
+// CHECK:STDOUT:   %.loc9: C* = addr_of %b_val.ref
+// CHECK:STDOUT:   assign file.%b_ptr.var, %.loc9
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- c.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .C = %import_ref.1
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .E = %E
+// CHECK:STDOUT:     .c_val = %c_val
+// CHECK:STDOUT:     .c_ptr = %c_ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C]
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+3, unloaded
+// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %E: type = bind_alias E, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %c_val.var: ref C = var c_val
+// CHECK:STDOUT:   %c_val: ref C = bind_name c_val, %c_val.var
+// CHECK:STDOUT:   %E.ref: type = name_ref E, %E [template = constants.%C]
+// CHECK:STDOUT:   %.loc9: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %c_ptr.var: ref C* = var c_ptr
+// CHECK:STDOUT:   %c_ptr: ref C* = bind_name c_ptr, %c_ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.2
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc8_17.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc8_17.2: init C = class_init (), file.%c_val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc8_18: init C = converted %.loc8_17.1, %.loc8_17.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%c_val.var, %.loc8_18
+// CHECK:STDOUT:   %c_val.ref: ref C = name_ref c_val, file.%c_val
+// CHECK:STDOUT:   %.loc9: C* = addr_of %c_val.ref
+// CHECK:STDOUT:   assign file.%c_ptr.var, %.loc9
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- triangle.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .C = %import_ref.1
+// CHECK:STDOUT:     .D = %import_ref.2
+// CHECK:STDOUT:     .b_val = %import_ref.3
+// CHECK:STDOUT:     .b_ptr = %import_ref.4
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .val = %val
+// CHECK:STDOUT:     .ptr = %ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_15 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+8, loc_23 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir2, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.4 = import_ref ir2, inst+23, unloaded
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.5 = import_ref ir1, inst+3, unloaded
+// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %val.var: ref C = var val
+// CHECK:STDOUT:   %val: ref C = bind_name val, %val.var
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %import_ref.2 [template = constants.%C]
+// CHECK:STDOUT:   %.loc8: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %ptr.var: ref C* = var ptr
+// CHECK:STDOUT:   %ptr: ref C* = bind_name ptr, %ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.5
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc7_15.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%val.var, %.loc7_16
+// CHECK:STDOUT:   %val.ref: ref C = name_ref val, file.%val
+// CHECK:STDOUT:   %.loc8: C* = addr_of %val.ref
+// CHECK:STDOUT:   assign file.%ptr.var, %.loc8
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- triangle_reverse.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .D = %import_ref.1
+// CHECK:STDOUT:     .b_val = %import_ref.2
+// CHECK:STDOUT:     .b_ptr = %import_ref.3
+// CHECK:STDOUT:     .C = %import_ref.4
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .val = %val
+// CHECK:STDOUT:     .ptr = %ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+8, loc_23 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir1, inst+23, unloaded
+// CHECK:STDOUT:   %import_ref.4: type = import_ref ir2, inst+2, loc_15 [template = constants.%C]
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.5 = import_ref ir2, inst+3, unloaded
+// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.4 [template = constants.%C]
+// CHECK:STDOUT:   %val.var: ref C = var val
+// CHECK:STDOUT:   %val: ref C = bind_name val, %val.var
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %.loc8: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %ptr.var: ref C* = var ptr
+// CHECK:STDOUT:   %ptr: ref C* = bind_name ptr, %ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.5
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc7_15.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%val.var, %.loc7_16
+// CHECK:STDOUT:   %val.ref: ref C = name_ref val, file.%val
+// CHECK:STDOUT:   %.loc8: C* = addr_of %val.ref
+// CHECK:STDOUT:   assign file.%ptr.var, %.loc8
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- diamond.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .D = %import_ref.1
+// CHECK:STDOUT:     .b_val = %import_ref.2
+// CHECK:STDOUT:     .b_ptr = %import_ref.3
+// CHECK:STDOUT:     .E = %import_ref.4
+// CHECK:STDOUT:     .c_val = %import_ref.5
+// CHECK:STDOUT:     .c_ptr = %import_ref.6
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .val = %val
+// CHECK:STDOUT:     .ptr = %ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+8, loc_15 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir1, inst+23, unloaded
+// CHECK:STDOUT:   %import_ref.4: type = import_ref ir2, inst+8, loc_23 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.5 = import_ref ir2, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.6 = import_ref ir2, inst+23, unloaded
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.7 = import_ref ir1, inst+6, unloaded
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %val.var: ref C = var val
+// CHECK:STDOUT:   %val: ref C = bind_name val, %val.var
+// CHECK:STDOUT:   %E.ref: type = name_ref E, %import_ref.4 [template = constants.%C]
+// CHECK:STDOUT:   %.loc8: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %ptr.var: ref C* = var ptr
+// CHECK:STDOUT:   %ptr: ref C* = bind_name ptr, %ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.7
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc7_15.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%val.var, %.loc7_16
+// CHECK:STDOUT:   %val.ref: ref C = name_ref val, file.%val
+// CHECK:STDOUT:   %.loc8: C* = addr_of %val.ref
+// CHECK:STDOUT:   assign file.%ptr.var, %.loc8
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: --- diamond_reverse.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %struct: C = struct_value () [template]
+// CHECK:STDOUT:   %.4: type = ptr_type C [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .E = %import_ref.1
+// CHECK:STDOUT:     .c_val = %import_ref.2
+// CHECK:STDOUT:     .c_ptr = %import_ref.3
+// CHECK:STDOUT:     .D = %import_ref.4
+// CHECK:STDOUT:     .b_val = %import_ref.5
+// CHECK:STDOUT:     .b_ptr = %import_ref.6
+// CHECK:STDOUT:     .Core = %Core
+// CHECK:STDOUT:     .val = %val
+// CHECK:STDOUT:     .ptr = %ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+8, loc_23 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir1, inst+23, unloaded
+// CHECK:STDOUT:   %import_ref.4: type = import_ref ir2, inst+8, loc_15 [template = constants.%C]
+// CHECK:STDOUT:   %import_ref.5 = import_ref ir2, inst+13, unloaded
+// CHECK:STDOUT:   %import_ref.6 = import_ref ir2, inst+23, unloaded
+// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %import_ref.7 = import_ref ir2, inst+6, unloaded
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %import_ref.4 [template = constants.%C]
+// CHECK:STDOUT:   %val.var: ref C = var val
+// CHECK:STDOUT:   %val: ref C = bind_name val, %val.var
+// CHECK:STDOUT:   %E.ref: type = name_ref E, %import_ref.1 [template = constants.%C]
+// CHECK:STDOUT:   %.loc8: type = ptr_type C [template = constants.%.4]
+// CHECK:STDOUT:   %ptr.var: ref C* = var ptr
+// CHECK:STDOUT:   %ptr: ref C* = bind_name ptr, %ptr.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: class @C {
+// CHECK:STDOUT: !members:
+// CHECK:STDOUT:   .Self = file.%import_ref.7
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc7_15.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct]
+// CHECK:STDOUT:   %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct]
+// CHECK:STDOUT:   assign file.%val.var, %.loc7_16
+// CHECK:STDOUT:   %val.ref: ref C = name_ref val, file.%val
+// CHECK:STDOUT:   %.loc8: C* = addr_of %val.ref
+// CHECK:STDOUT:   assign file.%ptr.var, %.loc8
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 0 - 171
toolchain/check/testdata/class/import_triangle.carbon

@@ -1,171 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// AUTOUPDATE
-
-// --- a.carbon
-
-library "a" api;
-
-class C {}
-
-// --- b.carbon
-
-library "b" api;
-
-import library "a";
-
-alias D = C;
-
-var c1: C = {};
-var d1: D* = &c1;
-
-// --- fail_c.carbon
-
-library "c" api;
-
-import library "a";
-import library "b";
-
-var c2: C = {};
-// CHECK:STDERR: fail_c.carbon:[[@LINE+3]]:1: ERROR: Cannot implicitly convert from `C*` to `C*`.
-// CHECK:STDERR: var d2: D* = &c2;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
-var d2: D* = &c2;
-
-// CHECK:STDOUT: --- a.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %C.decl
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
-// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = constants.%C
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: --- b.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %.2: type = tuple_type () [template]
-// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
-// CHECK:STDOUT:   %struct: C = struct_value () [template]
-// CHECK:STDOUT:   %.4: type = ptr_type C [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .C = %import_ref.1
-// CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .D = %D
-// CHECK:STDOUT:     .c1 = %c1
-// CHECK:STDOUT:     .d1 = %d1
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C]
-// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
-// CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+3, unloaded
-// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C]
-// CHECK:STDOUT:   %D: type = bind_alias D, %import_ref.1 [template = constants.%C]
-// CHECK:STDOUT:   %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C]
-// CHECK:STDOUT:   %c1.var: ref C = var c1
-// CHECK:STDOUT:   %c1: ref C = bind_name c1, %c1.var
-// CHECK:STDOUT:   %D.ref: type = name_ref D, %D [template = constants.%C]
-// CHECK:STDOUT:   %.loc9: type = ptr_type C [template = constants.%.4]
-// CHECK:STDOUT:   %d1.var: ref C* = var d1
-// CHECK:STDOUT:   %d1: ref C* = bind_name d1, %d1.var
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.2
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @__global_init() {
-// CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc8_14.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc8_14.2: init C = class_init (), file.%c1.var [template = constants.%struct]
-// CHECK:STDOUT:   %.loc8_15: init C = converted %.loc8_14.1, %.loc8_14.2 [template = constants.%struct]
-// CHECK:STDOUT:   assign file.%c1.var, %.loc8_15
-// CHECK:STDOUT:   %c1.ref: ref C = name_ref c1, file.%c1
-// CHECK:STDOUT:   %.loc9: C* = addr_of %c1.ref
-// CHECK:STDOUT:   assign file.%d1.var, %.loc9
-// CHECK:STDOUT:   return
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_c.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %C.1: type = class_type @C.1 [template]
-// CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %.2: type = tuple_type () [template]
-// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
-// CHECK:STDOUT:   %struct: C = struct_value () [template]
-// CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type C [template]
-// CHECK:STDOUT:   %.5: type = ptr_type C [template]
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .C = %import_ref.1
-// CHECK:STDOUT:     .D = %import_ref.2
-// CHECK:STDOUT:     .c1 = %import_ref.3
-// CHECK:STDOUT:     .d1 = %import_ref.4
-// CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .c2 = %c2
-// CHECK:STDOUT:     .d2 = %d2
-// CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+2, loc_15 [template = constants.%C.1]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+8, loc_23 [template = constants.%C.2]
-// CHECK:STDOUT:   %import_ref.3 = import_ref ir2, inst+13, unloaded
-// CHECK:STDOUT:   %import_ref.4 = import_ref ir2, inst+23, unloaded
-// CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
-// CHECK:STDOUT:   %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {}
-// CHECK:STDOUT:   %import_ref.5 = import_ref ir1, inst+3, unloaded
-// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C.1]
-// CHECK:STDOUT:   %c2.var: ref C = var c2
-// CHECK:STDOUT:   %c2: ref C = bind_name c2, %c2.var
-// CHECK:STDOUT:   %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {}
-// CHECK:STDOUT:   %import_ref.6 = import_ref ir2, inst+6, unloaded
-// CHECK:STDOUT:   %D.ref: type = name_ref D, %import_ref.2 [template = constants.%C.2]
-// CHECK:STDOUT:   %.loc11: type = ptr_type C [template = constants.%.4]
-// CHECK:STDOUT:   %d2.var: ref C* = var d2
-// CHECK:STDOUT:   %d2: ref C* = bind_name d2, %d2.var
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.5
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: class @C.2 {
-// CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Self = file.%import_ref.6
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @__global_init() {
-// CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc7_14.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc7_14.2: init C = class_init (), file.%c2.var [template = constants.%struct]
-// CHECK:STDOUT:   %.loc7_15: init C = converted %.loc7_14.1, %.loc7_14.2 [template = constants.%struct]
-// CHECK:STDOUT:   assign file.%c2.var, %.loc7_15
-// CHECK:STDOUT:   %c2.ref: ref C = name_ref c2, file.%c2
-// CHECK:STDOUT:   %.loc11: C* = addr_of %c2.ref
-// CHECK:STDOUT:   assign file.%d2.var, <error>
-// CHECK:STDOUT:   return
-// CHECK:STDOUT: }
-// CHECK:STDOUT:

+ 294 - 144
toolchain/check/testdata/function/declaration/import.carbon

@@ -84,11 +84,76 @@ var c: {.c: i32} = C((1,));
 var d: () = D();
 var e: () = NS.E();
 
-// --- merge.carbon
+// --- fail_todo_merge.carbon
 
 library "merge" api;
 
 import library "api";
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+65]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn A();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE-7]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:4:1: Name is previously declared here.
+// CHECK:STDERR: fn A();
+// CHECK:STDERR: ^~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+52]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:5:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE-20]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:5:1: Name is previously declared here.
+// CHECK:STDERR: fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+39]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:6:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE-33]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:6:1: Name is previously declared here.
+// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+26]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:7:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE-46]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:7:1: Name is previously declared here.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+13]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:10:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE-59]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:10:1: Name is previously declared here.
+// CHECK:STDERR: fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~
+// CHECK:STDERR:
 import library "extern_api";
 
 var a: () = A();
@@ -97,11 +162,76 @@ var c: {.c: i32} = C((1,));
 var d: () = D();
 var e: () = NS.E();
 
-// --- merge_reverse.carbon
+// --- fail_todo_merge_reverse.carbon
 
 library "merge_reverse" api;
 
 import library "extern_api";
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+65]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: fn A();
+// CHECK:STDERR: ^~~~~~~
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE-7]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:4:1: Name is previously declared here.
+// CHECK:STDERR: extern fn A();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+52]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:5:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE-20]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:5:1: Name is previously declared here.
+// CHECK:STDERR: extern fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+39]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:6:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE-33]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:6:1: Name is previously declared here.
+// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+26]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:7:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE-46]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:7:1: Name is previously declared here.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+13]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:10:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~
+// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE-59]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:10:1: Name is previously declared here.
+// CHECK:STDERR: extern fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
 import library "api";
 
 var a: () = A();
@@ -162,12 +292,13 @@ import library "api";
 
 var a: () = A();
 
-// CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE+6]]:1: ERROR: Redeclaration of imported entity that was previously used.
+// CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE+7]]:1: ERROR: Redeclaration of imported entity that was previously used.
 // CHECK:STDERR: extern fn A();
 // CHECK:STDERR: ^~~~~~~~~~~~~~
 // CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE-5]]:13: Import used here.
 // CHECK:STDERR: var a: () = A();
 // CHECK:STDERR:             ^
+// CHECK:STDERR:
 extern fn A();
 
 // --- unloaded.carbon
@@ -182,11 +313,75 @@ library "unloaded_extern" api;
 
 import library "extern_api";
 
-// --- loaded_merge.carbon
+// --- fail_todo_loaded_merge.carbon
 
 library "loaded_merge" api;
 
 import library "api";
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+64]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn A();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE-7]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:4:1: Name is previously declared here.
+// CHECK:STDERR: fn A();
+// CHECK:STDERR: ^~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+51]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:5:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE-20]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:5:1: Name is previously declared here.
+// CHECK:STDERR: fn B(b: i32) -> i32;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+38]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:6:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE-33]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:6:1: Name is previously declared here.
+// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+25]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:7:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE-46]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:7:1: Name is previously declared here.
+// CHECK:STDERR: extern fn D();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR:
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+12]]:1: In import.
+// CHECK:STDERR: import library "extern_api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: extern_api.carbon:10:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE-59]]:1: In import.
+// CHECK:STDERR: import library "api";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: api.carbon:10:1: Name is previously declared here.
+// CHECK:STDERR: fn NS.E();
+// CHECK:STDERR: ^~~~~~~~~~
 import library "extern_api";
 
 // CHECK:STDOUT: --- api.carbon
@@ -588,14 +783,14 @@ import library "extern_api";
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- merge.carbon
+// CHECK:STDOUT: --- fail_todo_merge.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.1: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.2: type = struct_type {.c: i32} [template]
-// CHECK:STDOUT:   %.3: type = tuple_type () [template]
-// CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.1: type = tuple_type () [template]
+// CHECK:STDOUT:   %.2: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.3: type = struct_type {.c: i32} [template]
+// CHECK:STDOUT:   %.4: type = tuple_type (i32) [template]
+// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -612,103 +807,93 @@ import library "extern_api";
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:     .e = %e
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loc_19 [template = imports.%A.1]
-// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir1, inst+6, loc_28 [template = imports.%B.1]
-// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir1, inst+18, loc_43 [template = imports.%C.1]
-// CHECK:STDOUT:   %import_ref.4: <function> = import_ref ir1, inst+19, loc_57 [template = imports.%D.1]
+// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loc_19 [template = imports.%A]
+// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir1, inst+6, loc_28 [template = imports.%B]
+// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir1, inst+18, loc_43 [template = imports.%C]
+// CHECK:STDOUT:   %import_ref.4: <function> = import_ref ir1, inst+19, loc_57 [template = imports.%D]
 // CHECK:STDOUT:   %import_ref.5: <namespace> = import_ref ir1, inst+20, loaded
 // CHECK:STDOUT:   %NS: <namespace> = namespace %import_ref.5, [template] {
 // CHECK:STDOUT:     .E = %import_ref.6
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.6: <function> = import_ref ir1, inst+21, loc_69 [template = imports.%E.1]
-// CHECK:STDOUT:   %import_ref.7: <function> = import_ref ir2, inst+2, loaded [template = imports.%A.2]
-// CHECK:STDOUT:   %import_ref.8: <function> = import_ref ir2, inst+6, loaded [template = imports.%B.2]
-// CHECK:STDOUT:   %import_ref.9: <function> = import_ref ir2, inst+18, loaded [template = imports.%C.2]
-// CHECK:STDOUT:   %import_ref.10: <function> = import_ref ir2, inst+19, loaded [template = imports.%D.2]
-// CHECK:STDOUT:   %import_ref.11: <function> = import_ref ir2, inst+21, loaded [template = imports.%E.2]
+// CHECK:STDOUT:   %import_ref.6: <function> = import_ref ir1, inst+21, loc_69 [template = imports.%E]
+// CHECK:STDOUT:   %import_ref.7 = import_ref ir2, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.8 = import_ref ir2, inst+6, unloaded
+// CHECK:STDOUT:   %import_ref.9 = import_ref ir2, inst+18, unloaded
+// CHECK:STDOUT:   %import_ref.10 = import_ref ir2, inst+19, unloaded
+// CHECK:STDOUT:   %import_ref.11 = import_ref ir2, inst+21, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
-// CHECK:STDOUT:   %.loc7_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc72_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc72_9.2: type = converted %.loc72_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc9: type = struct_type {.c: i32} [template = constants.%.2]
+// CHECK:STDOUT:   %.loc74: type = struct_type {.c: i32} [template = constants.%.3]
 // CHECK:STDOUT:   %c.var: ref {.c: i32} = var c
 // CHECK:STDOUT:   %c: ref {.c: i32} = bind_name c, %c.var
-// CHECK:STDOUT:   %.loc10_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc75_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %d.var: ref () = var d
 // CHECK:STDOUT:   %d: ref () = bind_name d, %d.var
-// CHECK:STDOUT:   %.loc11_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc11_9.2: type = converted %.loc11_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc76_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc76_9.2: type = converted %.loc76_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %e.var: ref () = var e
 // CHECK:STDOUT:   %e: ref () = bind_name e, %e.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @A.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @A.2();
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @B.1(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @B.2(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @C.1(%c: (i32,)) -> {.c: i32};
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32};
+// CHECK:STDOUT: fn @A();
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.1();
+// CHECK:STDOUT: fn @B(%b: i32) -> i32;
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.2();
+// CHECK:STDOUT: fn @C(%c: (i32,)) -> {.c: i32};
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @E.1();
+// CHECK:STDOUT: extern fn @D();
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @E.2();
+// CHECK:STDOUT: fn @E();
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %A.ref: <function> = name_ref A, file.%import_ref.1 [template = imports.%A.1]
+// CHECK:STDOUT:   %A.ref: <function> = name_ref A, file.%import_ref.1 [template = imports.%A]
 // CHECK:STDOUT:   %A.call: init () = call %A.ref()
 // CHECK:STDOUT:   assign file.%a.var, %A.call
-// CHECK:STDOUT:   %B.ref: <function> = name_ref B, file.%import_ref.2 [template = imports.%B.1]
-// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %B.call: init i32 = call %B.ref(%.loc8)
+// CHECK:STDOUT:   %B.ref: <function> = name_ref B, file.%import_ref.2 [template = imports.%B]
+// CHECK:STDOUT:   %.loc73: i32 = int_literal 1 [template = constants.%.2]
+// CHECK:STDOUT:   %B.call: init i32 = call %B.ref(%.loc73)
 // CHECK:STDOUT:   assign file.%b.var, %B.call
-// CHECK:STDOUT:   %C.ref: <function> = name_ref C, file.%import_ref.3 [template = imports.%C.1]
-// CHECK:STDOUT:   %.loc9_23: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc9_25: (i32,) = tuple_literal (%.loc9_23)
-// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.loc9_23) [template = constants.%tuple]
-// CHECK:STDOUT:   %.loc9_21: (i32,) = converted %.loc9_25, %tuple [template = constants.%tuple]
-// CHECK:STDOUT:   %C.call: init {.c: i32} = call %C.ref(%.loc9_21)
+// CHECK:STDOUT:   %C.ref: <function> = name_ref C, file.%import_ref.3 [template = imports.%C]
+// CHECK:STDOUT:   %.loc74_23: i32 = int_literal 1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc74_25: (i32,) = tuple_literal (%.loc74_23)
+// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.loc74_23) [template = constants.%tuple]
+// CHECK:STDOUT:   %.loc74_21: (i32,) = converted %.loc74_25, %tuple [template = constants.%tuple]
+// CHECK:STDOUT:   %C.call: init {.c: i32} = call %C.ref(%.loc74_21)
 // CHECK:STDOUT:   assign file.%c.var, %C.call
-// CHECK:STDOUT:   %D.ref: <function> = name_ref D, file.%import_ref.4 [template = imports.%D.1]
+// CHECK:STDOUT:   %D.ref: <function> = name_ref D, file.%import_ref.4 [template = imports.%D]
 // CHECK:STDOUT:   %D.call: init () = call %D.ref()
 // CHECK:STDOUT:   assign file.%d.var, %D.call
 // CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, file.%NS [template = file.%NS]
-// CHECK:STDOUT:   %E.ref: <function> = name_ref E, file.%import_ref.6 [template = imports.%E.1]
+// CHECK:STDOUT:   %E.ref: <function> = name_ref E, file.%import_ref.6 [template = imports.%E]
 // CHECK:STDOUT:   %E.call: init () = call %E.ref()
 // CHECK:STDOUT:   assign file.%e.var, %E.call
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- merge_reverse.carbon
+// CHECK:STDOUT: --- fail_todo_merge_reverse.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.1: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.2: type = struct_type {.c: i32} [template]
-// CHECK:STDOUT:   %.3: type = tuple_type () [template]
-// CHECK:STDOUT:   %.4: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.1: type = tuple_type () [template]
+// CHECK:STDOUT:   %.2: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.3: type = struct_type {.c: i32} [template]
+// CHECK:STDOUT:   %.4: type = tuple_type (i32) [template]
+// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.2) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .A = %import_ref.1
+// CHECK:STDOUT:     .B = %import_ref.2
+// CHECK:STDOUT:     .C = %import_ref.3
 // CHECK:STDOUT:     .D = %import_ref.4
 // CHECK:STDOUT:     .NS = %NS
-// CHECK:STDOUT:     .A = imports.%A.2
-// CHECK:STDOUT:     .B = imports.%B.2
-// CHECK:STDOUT:     .C = imports.%C.2
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = %b
@@ -716,81 +901,71 @@ import library "extern_api";
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:     .e = %e
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loaded [template = imports.%A.1]
-// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir1, inst+6, loaded [template = imports.%B.1]
-// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir1, inst+18, loaded [template = imports.%C.1]
-// CHECK:STDOUT:   %import_ref.4: <function> = import_ref ir1, inst+19, loc_57 [template = imports.%D.1]
+// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loc_19 [template = imports.%A]
+// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir1, inst+6, loc_28 [template = imports.%B]
+// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir1, inst+18, loc_43 [template = imports.%C]
+// CHECK:STDOUT:   %import_ref.4: <function> = import_ref ir1, inst+19, loc_57 [template = imports.%D]
 // CHECK:STDOUT:   %import_ref.5: <namespace> = import_ref ir1, inst+20, loaded
 // CHECK:STDOUT:   %NS: <namespace> = namespace %import_ref.5, [template] {
-// CHECK:STDOUT:     .E = imports.%E.2
+// CHECK:STDOUT:     .E = %import_ref.6
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.6: <function> = import_ref ir1, inst+21, loaded [template = imports.%E.1]
-// CHECK:STDOUT:   %import_ref.7: <function> = import_ref ir2, inst+2, loaded [template = imports.%A.2]
-// CHECK:STDOUT:   %import_ref.8: <function> = import_ref ir2, inst+6, loaded [template = imports.%B.2]
-// CHECK:STDOUT:   %import_ref.9: <function> = import_ref ir2, inst+18, loaded [template = imports.%C.2]
-// CHECK:STDOUT:   %import_ref.10: <function> = import_ref ir2, inst+19, loaded [template = imports.%D.2]
-// CHECK:STDOUT:   %import_ref.11: <function> = import_ref ir2, inst+21, loaded [template = imports.%E.2]
+// CHECK:STDOUT:   %import_ref.6: <function> = import_ref ir1, inst+21, loc_69 [template = imports.%E]
+// CHECK:STDOUT:   %import_ref.7 = import_ref ir2, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.8 = import_ref ir2, inst+6, unloaded
+// CHECK:STDOUT:   %import_ref.9 = import_ref ir2, inst+18, unloaded
+// CHECK:STDOUT:   %import_ref.10 = import_ref ir2, inst+19, unloaded
+// CHECK:STDOUT:   %import_ref.11 = import_ref ir2, inst+21, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
-// CHECK:STDOUT:   %.loc7_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc72_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc72_9.2: type = converted %.loc72_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %a.var: ref () = var a
 // CHECK:STDOUT:   %a: ref () = bind_name a, %a.var
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %.loc9: type = struct_type {.c: i32} [template = constants.%.2]
+// CHECK:STDOUT:   %.loc74: type = struct_type {.c: i32} [template = constants.%.3]
 // CHECK:STDOUT:   %c.var: ref {.c: i32} = var c
 // CHECK:STDOUT:   %c: ref {.c: i32} = bind_name c, %c.var
-// CHECK:STDOUT:   %.loc10_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc10_9.2: type = converted %.loc10_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc75_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %d.var: ref () = var d
 // CHECK:STDOUT:   %d: ref () = bind_name d, %d.var
-// CHECK:STDOUT:   %.loc11_9.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc11_9.2: type = converted %.loc11_9.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc76_9.1: () = tuple_literal ()
+// CHECK:STDOUT:   %.loc76_9.2: type = converted %.loc76_9.1, constants.%.1 [template = constants.%.1]
 // CHECK:STDOUT:   %e.var: ref () = var e
 // CHECK:STDOUT:   %e: ref () = bind_name e, %e.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @A.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @A.2();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @B.1(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @B.2(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @C.1(%c: (i32,)) -> {.c: i32};
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32};
+// CHECK:STDOUT: extern fn @A();
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.1();
+// CHECK:STDOUT: extern fn @B(%b: i32) -> i32;
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.2();
+// CHECK:STDOUT: extern fn @C(%c: (i32,)) -> {.c: i32};
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @E.1();
+// CHECK:STDOUT: extern fn @D();
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @E.2();
+// CHECK:STDOUT: extern fn @E();
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %A.ref: <function> = name_ref A, imports.%A.2 [template = imports.%A.2]
+// CHECK:STDOUT:   %A.ref: <function> = name_ref A, file.%import_ref.1 [template = imports.%A]
 // CHECK:STDOUT:   %A.call: init () = call %A.ref()
 // CHECK:STDOUT:   assign file.%a.var, %A.call
-// CHECK:STDOUT:   %B.ref: <function> = name_ref B, imports.%B.2 [template = imports.%B.2]
-// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %B.call: init i32 = call %B.ref(%.loc8)
+// CHECK:STDOUT:   %B.ref: <function> = name_ref B, file.%import_ref.2 [template = imports.%B]
+// CHECK:STDOUT:   %.loc73: i32 = int_literal 1 [template = constants.%.2]
+// CHECK:STDOUT:   %B.call: init i32 = call %B.ref(%.loc73)
 // CHECK:STDOUT:   assign file.%b.var, %B.call
-// CHECK:STDOUT:   %C.ref: <function> = name_ref C, imports.%C.2 [template = imports.%C.2]
-// CHECK:STDOUT:   %.loc9_23: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc9_25: (i32,) = tuple_literal (%.loc9_23)
-// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.loc9_23) [template = constants.%tuple]
-// CHECK:STDOUT:   %.loc9_21: (i32,) = converted %.loc9_25, %tuple [template = constants.%tuple]
-// CHECK:STDOUT:   %C.call: init {.c: i32} = call %C.ref(%.loc9_21)
+// CHECK:STDOUT:   %C.ref: <function> = name_ref C, file.%import_ref.3 [template = imports.%C]
+// CHECK:STDOUT:   %.loc74_23: i32 = int_literal 1 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc74_25: (i32,) = tuple_literal (%.loc74_23)
+// CHECK:STDOUT:   %tuple: (i32,) = tuple_value (%.loc74_23) [template = constants.%tuple]
+// CHECK:STDOUT:   %.loc74_21: (i32,) = converted %.loc74_25, %tuple [template = constants.%tuple]
+// CHECK:STDOUT:   %C.call: init {.c: i32} = call %C.ref(%.loc74_21)
 // CHECK:STDOUT:   assign file.%c.var, %C.call
-// CHECK:STDOUT:   %D.ref: <function> = name_ref D, file.%import_ref.4 [template = imports.%D.1]
+// CHECK:STDOUT:   %D.ref: <function> = name_ref D, file.%import_ref.4 [template = imports.%D]
 // CHECK:STDOUT:   %D.call: init () = call %D.ref()
 // CHECK:STDOUT:   assign file.%d.var, %D.call
 // CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, file.%NS [template = file.%NS]
-// CHECK:STDOUT:   %E.ref: <function> = name_ref E, imports.%E.2 [template = imports.%E.2]
+// CHECK:STDOUT:   %E.ref: <function> = name_ref E, file.%import_ref.6 [template = imports.%E]
 // CHECK:STDOUT:   %E.call: init () = call %E.ref()
 // CHECK:STDOUT:   assign file.%e.var, %E.call
 // CHECK:STDOUT:   return
@@ -975,12 +1150,7 @@ import library "extern_api";
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- loaded_merge.carbon
-// CHECK:STDOUT:
-// CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.1: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.2: type = struct_type {.c: i32} [template]
-// CHECK:STDOUT: }
+// CHECK:STDOUT: --- fail_todo_loaded_merge.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
@@ -991,40 +1161,20 @@ import library "extern_api";
 // CHECK:STDOUT:     .NS = %NS
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loaded [template = imports.%A.1]
-// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir1, inst+6, loaded [template = imports.%B.1]
-// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir1, inst+18, loaded [template = imports.%C.1]
-// CHECK:STDOUT:   %import_ref.4: <function> = import_ref ir1, inst+19, loaded [template = imports.%D.1]
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+6, unloaded
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir1, inst+18, unloaded
+// CHECK:STDOUT:   %import_ref.4 = import_ref ir1, inst+19, unloaded
 // CHECK:STDOUT:   %import_ref.5: <namespace> = import_ref ir1, inst+20, loaded
 // CHECK:STDOUT:   %NS: <namespace> = namespace %import_ref.5, [template] {
 // CHECK:STDOUT:     .E = %import_ref.6
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.6: <function> = import_ref ir1, inst+21, loaded [template = imports.%E.1]
-// CHECK:STDOUT:   %import_ref.7: <function> = import_ref ir2, inst+2, loaded [template = imports.%A.2]
-// CHECK:STDOUT:   %import_ref.8: <function> = import_ref ir2, inst+6, loaded [template = imports.%B.2]
-// CHECK:STDOUT:   %import_ref.9: <function> = import_ref ir2, inst+18, loaded [template = imports.%C.2]
-// CHECK:STDOUT:   %import_ref.10: <function> = import_ref ir2, inst+19, loaded [template = imports.%D.2]
-// CHECK:STDOUT:   %import_ref.11: <function> = import_ref ir2, inst+21, loaded [template = imports.%E.2]
+// CHECK:STDOUT:   %import_ref.6 = import_ref ir1, inst+21, unloaded
+// CHECK:STDOUT:   %import_ref.7 = import_ref ir2, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.8 = import_ref ir2, inst+6, unloaded
+// CHECK:STDOUT:   %import_ref.9 = import_ref ir2, inst+18, unloaded
+// CHECK:STDOUT:   %import_ref.10 = import_ref ir2, inst+19, unloaded
+// CHECK:STDOUT:   %import_ref.11 = import_ref ir2, inst+21, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @A.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @A.2();
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @B.1(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @B.2(%b: i32) -> i32;
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @C.1(%c: (i32,)) -> {.c: i32};
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32};
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @D.2();
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @E.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @E.2();
-// CHECK:STDOUT:

+ 1 - 3
toolchain/check/testdata/namespace/fail_conflict_in_imports_namespace_first.carbon

@@ -86,13 +86,11 @@ fn NS.Bar() {}
 // CHECK:STDOUT:     .Bar = %Bar
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %import_ref.2 = import_ref ir1, inst+3, unloaded
-// CHECK:STDOUT:   %import_ref.3: <function> = import_ref ir2, inst+2, loaded [template = imports.%NS]
+// CHECK:STDOUT:   %import_ref.3 = import_ref ir2, inst+2, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Bar: <function> = fn_decl @Bar [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @NS();
-// CHECK:STDOUT:
 // CHECK:STDOUT: fn @Bar() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   return

+ 28 - 16
toolchain/check/testdata/packages/cross_package_import.carbon

@@ -54,14 +54,30 @@ fn Run() {
   Other.F2();
 }
 
-// --- main_use_other_extern.carbon
+// --- fail_todo_main_use_other_extern.carbon
 
 library "use_other_extern" api;
 
 import Other library "fn";
+// CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE+12]]:1: In import.
+// CHECK:STDERR: import Other library "fn_extern";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: other_fn_extern.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
+// CHECK:STDERR: extern fn F();
+// CHECK:STDERR: ^~~~~~~~~~~~~~
+// CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE-7]]:1: In import.
+// CHECK:STDERR: import Other library "fn";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: other_fn.carbon:4:1: Name is previously declared here.
+// CHECK:STDERR: fn F() {}
+// CHECK:STDERR: ^~~~~~~~
 import Other library "fn_extern";
 
 fn Run() {
+  // CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE+4]]:3: In name lookup for `F`.
+  // CHECK:STDERR:   Other.F();
+  // CHECK:STDERR:   ^~~~~~~
+  // CHECK:STDERR:
   Other.F();
 }
 
@@ -80,13 +96,13 @@ import Other library "fn";
 // CHECK:STDERR: fail_main_use_other_ambiguous.carbon:[[@LINE+12]]:1: In import.
 // CHECK:STDERR: import Other library "fn_conflict";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: other_fn_conflict.carbon:4:1: ERROR: Function redeclaration differs because of parameter count of 1.
+// CHECK:STDERR: other_fn_conflict.carbon:4:1: ERROR: Duplicate name being declared in the same scope.
 // CHECK:STDERR: fn F(x: i32) {}
 // CHECK:STDERR: ^~~~~~~~~~~~~~
 // CHECK:STDERR: fail_main_use_other_ambiguous.carbon:[[@LINE-7]]:1: In import.
 // CHECK:STDERR: import Other library "fn";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: other_fn.carbon:4:1: Previously declared with parameter count of 0.
+// CHECK:STDERR: other_fn.carbon:4:1: Name is previously declared here.
 // CHECK:STDERR: fn F() {}
 // CHECK:STDERR: ^~~~~~~~
 import Other library "fn_conflict";
@@ -269,7 +285,7 @@ fn Other.G() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F2();
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- main_use_other_extern.carbon
+// CHECK:STDOUT: --- fail_todo_main_use_other_extern.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = tuple_type () [template]
@@ -284,21 +300,19 @@ fn Other.G() {}
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Other: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template] {}
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir2, inst+2, loc_22 [template = imports.%F.1]
-// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir3, inst+2, loaded [template = imports.%F.2]
+// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir2, inst+2, loc_22 [template = imports.%F]
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir3, inst+2, unloaded
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Other.ref: <namespace> = name_ref Other, file.%Other [template = file.%Other]
-// CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%import_ref.1 [template = imports.%F.1]
+// CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%import_ref.1 [template = imports.%F]
 // CHECK:STDOUT:   %F.call: init () = call %F.ref()
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: extern fn @F.2();
+// CHECK:STDOUT: fn @F();
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- main_unused_other_ambiguous.carbon
 // CHECK:STDOUT:
@@ -326,21 +340,19 @@ fn Other.G() {}
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Other: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template] {}
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir2, inst+2, loc_22 [template = imports.%F.1]
-// CHECK:STDOUT:   %import_ref.2: <function> = import_ref ir3, inst+4, loaded [template = imports.%F.2]
+// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir2, inst+2, loc_22 [template = imports.%F]
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir3, inst+4, unloaded
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Other.ref: <namespace> = name_ref Other, file.%Other [template = file.%Other]
-// CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%import_ref.1 [template = imports.%F.1]
+// CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%import_ref.1 [template = imports.%F]
 // CHECK:STDOUT:   %F.call: init () = call %F.ref()
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.1();
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.2(%x: i32);
+// CHECK:STDOUT: fn @F();
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_main_namespace_conflict.carbon
 // CHECK:STDOUT:

+ 2 - 4
toolchain/check/testdata/packages/fail_conflict_no_namespaces.carbon

@@ -67,10 +67,8 @@ import library "var";
 // CHECK:STDOUT:     .Foo = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: <function> = import_ref ir1, inst+2, loaded [template = imports.%Foo]
-// CHECK:STDOUT:   %import_ref.2: ref i32 = import_ref ir2, inst+3, loaded
+// CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+2, unloaded
+// CHECK:STDOUT:   %import_ref.2 = import_ref ir2, inst+3, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Foo();
-// CHECK:STDOUT: