Переглянути джерело

Remove ExternDecl and ExternType (#3909)

These should no longer be helpful under the new `extern` strategy.
Jon Ross-Perkins 2 роки тому
батько
коміт
377262d358

+ 0 - 1
toolchain/check/context.cpp

@@ -992,7 +992,6 @@ class TypeCompleter {
         // For symbolic types, we arbitrarily pick a copy representation.
         return MakeCopyValueRepr(type_id);
 
-      case SemIR::ExternType::Kind:
       case SemIR::FloatType::Kind:
       case SemIR::IntType::Kind:
       case SemIR::PointerType::Kind:

+ 0 - 10
toolchain/check/eval.cpp

@@ -897,15 +897,6 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::BoundMethod::object_id,
                                         &SemIR::BoundMethod::function_id);
-    case CARBON_KIND(SemIR::ExternDecl extern_decl): {
-      // Return an extern form of the declaration's constant value.
-      auto non_extern_type_id = context.GetTypeIdForTypeConstant(
-          context.constant_values().Get(extern_decl.decl_id));
-      return MakeConstantResult(
-          context,
-          SemIR::ExternType{SemIR::TypeId::TypeType, non_extern_type_id},
-          Phase::Template);
-    }
     case SemIR::InterfaceWitness::Kind:
       return RebuildIfFieldsAreConstant(context, inst,
                                         &SemIR::InterfaceWitness::elements_id);
@@ -984,7 +975,6 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     }
 
     case SemIR::ClassType::Kind:
-    case SemIR::ExternType::Kind:
     case SemIR::InterfaceType::Kind:
       CARBON_FATAL() << inst.kind()
                      << " is only created during corresponding Decl handling.";

+ 5 - 16
toolchain/check/handle_class.cpp

@@ -69,9 +69,10 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
     }
 
     if (prev_class_id.is_valid()) {
+      // TODO: Fix prev_is_extern logic.
       if (MergeClassRedecl(context, node_id, class_info,
                            /*new_is_import=*/false, is_definition, is_extern,
-                           prev_class_id, prev_inst_for_merge.is_extern,
+                           prev_class_id, /*prev_is_extern=*/false,
                            prev_inst_for_merge.import_ir_inst_id)) {
         // When merging, use the existing entity rather than adding a new one.
         class_decl.class_id = prev_class_id;
@@ -128,6 +129,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
                                      SemIR::ClassId::Invalid, decl_block_id};
   auto class_decl_id = context.AddPlaceholderInst({node_id, class_decl});
 
+  // TODO: Store state regarding is_extern.
   SemIR::Class class_info = {
       .name_id = name_context.name_id_for_new_inst(),
       .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(),
@@ -136,15 +138,8 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
       .decl_id = class_decl_id,
       .inheritance_kind = inheritance_kind};
 
-  auto extern_decl_id = SemIR::InstId::Invalid;
-  if (is_extern) {
-    extern_decl_id = context.AddPlaceholderInst(
-        {node_id, SemIR::ExternDecl{SemIR::TypeId::TypeType, class_decl_id}});
-  }
-
-  MergeOrAddName(context, node_id, name_context,
-                 extern_decl_id.is_valid() ? extern_decl_id : class_decl_id,
-                 class_decl, class_info, is_definition, is_extern);
+  MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl,
+                 class_info, is_definition, is_extern);
 
   // Create a new class if this isn't a valid redeclaration.
   bool is_new_class = !class_decl.class_id.is_valid();
@@ -164,12 +159,6 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
     class_info.self_type_id = context.GetTypeIdForTypeInst(class_decl_id);
   }
 
-  if (is_extern) {
-    context.ReplaceInstBeforeConstantUse(
-        extern_decl_id,
-        SemIR::ExternDecl{SemIR::TypeId::TypeType, class_decl_id});
-  }
-
   return {class_decl.class_id, class_decl_id};
 }
 

+ 0 - 2
toolchain/check/handle_function.cpp

@@ -118,8 +118,6 @@ static auto BuildFunctionDecl(Context& context,
   auto function_decl = SemIR::FunctionDecl{
       context.GetBuiltinType(SemIR::BuiltinKind::FunctionType),
       SemIR::FunctionId::Invalid, decl_block_id};
-  // TODO: Should Function replace is_extern with ExternDecl, similar to
-  // ClassDecl?
   auto function_info = SemIR::Function{
       .name_id = name_context.name_id_for_new_inst(),
       .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(),

+ 0 - 5
toolchain/check/import.cpp

@@ -36,11 +36,6 @@ static auto GetImportName(const SemIR::File& import_sem_ir,
       return {class_info.name_id, class_info.enclosing_scope_id};
     }
 
-    case CARBON_KIND(SemIR::ExternDecl extern_decl): {
-      return GetImportName(import_sem_ir,
-                           import_sem_ir.insts().Get(extern_decl.decl_id));
-    }
-
     case CARBON_KIND(SemIR::FunctionDecl function_decl): {
       const auto& function =
           import_sem_ir.functions().Get(function_decl.function_id);

+ 0 - 16
toolchain/check/import_ref.cpp

@@ -410,9 +410,6 @@ class ImportRefResolver {
       case CARBON_KIND(SemIR::ConstType inst): {
         return TryResolveTypedInst(inst);
       }
-      case CARBON_KIND(SemIR::ExternDecl inst): {
-        return TryResolveTypedInst(inst);
-      }
       case CARBON_KIND(SemIR::FieldDecl inst): {
         return TryResolveTypedInst(inst, inst_id);
       }
@@ -675,19 +672,6 @@ class ImportRefResolver {
                     SemIR::ConstType{SemIR::TypeId::TypeType, inner_type_id})};
   }
 
-  auto TryResolveTypedInst(SemIR::ExternDecl inst) -> ResolveResult {
-    auto initial_work = work_stack_.size();
-    CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
-    auto decl_const_id = GetLocalConstantId(inst.decl_id);
-    if (HasNewWork(initial_work)) {
-      return ResolveResult::Retry();
-    }
-    auto extern_id = context_.AddInstInNoBlock(SemIR::LocIdAndInst::Untyped(
-        AddImportIRInst(inst.decl_id),
-        SemIR::ExternDecl{SemIR::TypeId::TypeType, decl_const_id.inst_id()}));
-    return {context_.constant_values().Get(extern_id)};
-  }
-
   auto TryResolveTypedInst(SemIR::FieldDecl inst, SemIR::InstId import_inst_id)
       -> ResolveResult {
     auto initial_work = work_stack_.size();

+ 7 - 24
toolchain/check/merge.cpp

@@ -128,15 +128,9 @@ auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind,
 auto ResolvePrevInstForMerge(Context& context, Parse::NodeId node_id,
                              SemIR::InstId prev_inst_id) -> InstForMerge {
   InstForMerge result = {.inst = context.insts().Get(prev_inst_id),
-                         .import_ir_inst_id = SemIR::ImportIRInstId::Invalid,
-                         .is_extern = false};
+                         .import_ir_inst_id = SemIR::ImportIRInstId::Invalid};
 
   CARBON_KIND_SWITCH(result.inst) {
-    case CARBON_KIND(SemIR::ExternDecl extern_decl): {
-      result.is_extern = true;
-      result.inst = context.insts().Get(extern_decl.decl_id);
-      break;
-    }
     case CARBON_KIND(SemIR::ImportRefUsed import_ref): {
       CARBON_DIAGNOSTIC(
           RedeclOfUsedImport, Error,
@@ -154,10 +148,6 @@ auto ResolvePrevInstForMerge(Context& context, Parse::NodeId node_id,
       result.import_ir_inst_id = import_ref.import_ir_inst_id;
       result.inst = context.insts().Get(
           context.constant_values().Get(prev_inst_id).inst_id());
-      if (auto extern_type = result.inst.TryAs<SemIR::ExternType>()) {
-        result.inst =
-            context.types().GetAsInst(extern_type->non_extern_type_id);
-      }
       break;
     }
     default:
@@ -200,17 +190,9 @@ static auto ResolveMergeableInst(Context& context, SemIR::InstId inst_id)
     return std::nullopt;
   }
 
-  InstForMerge result = {
-      .inst = context.insts().Get(const_id.inst_id()),
-      .import_ir_inst_id = inst.As<SemIR::AnyImportRef>().import_ir_inst_id,
-      .is_extern = false};
-
-  if (auto extern_type = result.inst.TryAs<SemIR::ExternType>()) {
-    result.is_extern = true;
-    result.inst = context.types().GetAsInst(extern_type->non_extern_type_id);
-  }
-
-  return result;
+  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,
@@ -263,10 +245,11 @@ auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
       }
 
       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_inst->is_extern, prev_type->class_id,
-                       prev_inst->is_extern, prev_inst->import_ir_inst_id);
+                       /*new_is_extern=*/false, prev_type->class_id,
+                       /*prev_is_extern=*/false, prev_inst->import_ir_inst_id);
       return;
     }
     default:

+ 0 - 2
toolchain/check/merge.h

@@ -40,8 +40,6 @@ struct InstForMerge {
   // The imported instruction, or invalid if not an import. This should
   // typically only be used for the ImportIRId, but we only load it if needed.
   SemIR::ImportIRInstId import_ir_inst_id;
-  // True if an `extern` declaration.
-  bool is_extern;
 };
 
 // Resolves prev_inst_id for merging (or name conflicts). This handles imports

+ 41 - 23
toolchain/check/testdata/class/cross_package_import.carbon

@@ -44,19 +44,41 @@ library "extern" api;
 
 import Other library "extern";
 
-// CHECK:STDERR: fail_extern.carbon:[[@LINE+4]]:1: ERROR: Cannot implicitly convert from `{}` to `extern C`.
+// CHECK:STDERR: fail_extern.carbon:[[@LINE+10]]:8: ERROR: Variable has incomplete type `C`.
 // CHECK:STDERR: var c: Other.C = {};
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:        ^~~~~~~
+// CHECK:STDERR: fail_extern.carbon:[[@LINE-5]]:1: In import.
+// CHECK:STDERR: import Other library "extern";
+// CHECK:STDERR: ^~~~~~
+// CHECK:STDERR: other_extern.carbon:4:1: Class was forward declared here.
+// CHECK:STDERR: extern class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
 var c: Other.C = {};
 
-// --- merge_define_extern.carbon
+// --- fail_todo_merge_define_extern.carbon
 
 library "merge_define_extern" api;
 
 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: 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: class C {}
+// CHECK:STDERR: ^~~~~~~~~
 import Other library "extern";
 
+// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+4]]:8: In name lookup for `C`.
+// CHECK:STDERR: var c: Other.C = {};
+// CHECK:STDERR:        ^~~~~~~
+// CHECK:STDERR:
 var c: Other.C = {};
 
 // --- fail_conflict.carbon
@@ -108,17 +130,15 @@ var c: Other.C = {};
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %.loc4
+// 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:   %.loc4: type = extern_decl %C.decl [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -184,8 +204,7 @@ var c: Other.C = {};
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
-// CHECK:STDOUT:   %.2: type = struct_type {} [template]
+// CHECK:STDOUT:   %.1: type = struct_type {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -197,32 +216,31 @@ 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: type = import_ref ir2, inst+3, loc_14 [template = constants.%.1]
+// CHECK:STDOUT:   %import_ref: type = import_ref ir2, inst+2, loc_14 [template = constants.%C]
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref [template = constants.%.1]
-// CHECK:STDOUT:   %c.var: ref extern C = var c
-// CHECK:STDOUT:   %c: ref extern C = bind_name c, %c.var
+// CHECK:STDOUT:   %C.ref: type = name_ref C, %import_ref [template = constants.%C]
+// CHECK:STDOUT:   %c.var: ref <error> = var c
+// CHECK:STDOUT:   %c: ref <error> = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc10: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc16: {} = struct_literal ()
 // CHECK:STDOUT:   assign file.%c.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- merge_define_extern.carbon
+// 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:   %.1: type = struct_type {} [template]
 // CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT:   %.2: type = extern_type C [template]
-// CHECK:STDOUT:   %.3: type = tuple_type () [template]
-// CHECK:STDOUT:   %.4: type = ptr_type {} [template]
-// CHECK:STDOUT:   %.5: C = struct_value () [template]
+// CHECK:STDOUT:   %.2: type = tuple_type () [template]
+// CHECK:STDOUT:   %.3: type = ptr_type {} [template]
+// CHECK:STDOUT:   %.4: C = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -237,7 +255,7 @@ var c: Other.C = {};
 // 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.2 = import_ref ir2, inst+3, unloaded
-// CHECK:STDOUT:   %import_ref.3: type = import_ref ir3, inst+3, loaded [template = constants.%.2]
+// 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:   %c.var: ref C = var c
@@ -253,10 +271,10 @@ var c: Other.C = {};
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc7_19.1: {} = struct_literal ()
-// CHECK:STDOUT:   %.loc7_19.2: init C = class_init (), file.%c.var [template = constants.%.5]
-// CHECK:STDOUT:   %.loc7_20: init C = converted %.loc7_19.1, %.loc7_19.2 [template = constants.%.5]
-// CHECK:STDOUT:   assign file.%c.var, %.loc7_20
+// CHECK:STDOUT:   %.loc23_19.1: {} = struct_literal ()
+// CHECK:STDOUT:   %.loc23_19.2: init C = class_init (), file.%c.var [template = constants.%.4]
+// CHECK:STDOUT:   %.loc23_20: init C = converted %.loc23_19.1, %.loc23_19.2 [template = constants.%.4]
+// CHECK:STDOUT:   assign file.%c.var, %.loc23_20
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 107 - 78
toolchain/check/testdata/class/extern.carbon

@@ -41,12 +41,12 @@ class C {}
 library "fail_decl_fn_in_extern" api;
 
 extern class C;
-// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+7]]:6: ERROR: Name qualifiers are only allowed for entities that provide a scope.
-// CHECK:STDERR: fn C.F();
-// CHECK:STDERR:      ^
-// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+4]]:4: Non-scope entity referenced here.
+// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+7]]:4: ERROR: Cannot declare a member of incomplete class `C`.
 // CHECK:STDERR: fn C.F();
 // CHECK:STDERR:    ^
+// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE-4]]:1: Class was forward declared here.
+// CHECK:STDERR: extern class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
 // CHECK:STDERR:
 fn C.F();
 
@@ -100,18 +100,11 @@ class C {
   extern class D;
 }
 
-// --- fail_def_after_extern_decl.carbon
+// --- todo_fail_def_after_extern_decl.carbon
 
 library "fail_def_after_extern_decl" api;
 
 extern class C;
-// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `class C` in the same library must match use of `extern`.
-// CHECK:STDERR: class C {}
-// CHECK:STDERR: ^~~~~~~~~
-// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here.
-// CHECK:STDERR: extern class C;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~
-// CHECK:STDERR:
 class C {}
 
 // --- fail_extern_decl_after_decl.carbon
@@ -128,25 +121,64 @@ class C;
 // CHECK:STDERR:
 extern class C;
 
-// --- import_extern_decl_then_decl.carbon
+// --- fail_todo_import_extern_decl_then_decl.carbon
 
 library "import_extern_decl_then_decl" api;
 
 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: 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 class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
+// CHECK:STDERR:
 import library "decl";
 
-// --- import_decl_then_extern_decl.carbon
+// --- fail_todo_import_decl_then_extern_decl.carbon
 
 library "import_decl_then_extern_decl" api;
 
 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 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: class C;
+// CHECK:STDERR: ^~~~~~~~
+// CHECK:STDERR:
 import library "extern_decl";
 
-// --- import_extern_decl_then_def.carbon
+// --- fail_todo_import_extern_decl_then_def.carbon
 
 library "import_extern_decl_then_def" api;
 
 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: 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 class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
+// CHECK:STDERR:
 import library "def";
 
 // --- fail_import_ownership_conflict.carbon
@@ -154,26 +186,52 @@ import library "def";
 library "fail_import_ownership_conflict" api;
 
 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: 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 class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
+// CHECK:STDERR:
 import library "decl";
-// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+12]]:1: In import.
+// 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: class C {}
 // CHECK:STDERR: ^~~~~~~~~
-// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-7]]:1: In import.
-// CHECK:STDERR: import library "decl";
+// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-21]]:1: In import.
+// CHECK:STDERR: import library "extern_decl";
 // CHECK:STDERR: ^~~~~~
-// CHECK:STDERR: decl.carbon:4:1: Previously declared here.
-// CHECK:STDERR: class C;
-// CHECK:STDERR: ^~~~~~~~
+// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here.
+// CHECK:STDERR: extern class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
+// CHECK:STDERR:
 import library "def";
 
-// --- import_extern_decl_copy.carbon
+// --- fail_todo_import_extern_decl_copy.carbon
 
 library "import_extern_decl_copy" api;
 
 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 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 class C;
+// CHECK:STDERR: ^~~~~~~~~~~~~~~
 import library "extern_decl_copy";
 
 // --- extern_decl_after_import_extern_decl.carbon
@@ -229,17 +287,15 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %.loc4
+// 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:   %.loc4: type = extern_decl %C.decl [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -248,17 +304,15 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %.loc4
+// 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:   %.loc4: type = extern_decl %C.decl [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -288,17 +342,15 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %.loc4
+// 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:   %.loc4: type = extern_decl %C.decl [template = constants.%.1]
 // CHECK:STDOUT:   %.loc12: <function> = fn_decl @.1 [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -331,19 +383,16 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %.loc4
+// CHECK:STDOUT:     .C = %C.decl.loc4
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
 // CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %.loc12: type = extern_decl %C.decl.loc12 [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -352,17 +401,15 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = %Core
-// CHECK:STDOUT:     .C = %C.decl.loc12
+// CHECK:STDOUT:     .C = %C.decl.loc4
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
 // CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -395,23 +442,21 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @D;
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_def_after_extern_decl.carbon
+// CHECK:STDOUT: --- todo_fail_def_after_extern_decl.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
-// CHECK:STDOUT:   %.2: type = struct_type {} [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.loc12
+// CHECK:STDOUT:     .C = %C.decl.loc4
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %.loc4: type = extern_decl %C.decl.loc4 [template = constants.%.1]
-// CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
+// CHECK:STDOUT:   %C.decl.loc5: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -423,7 +468,6 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -434,25 +478,23 @@ extern class C;
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [template = constants.%C] {}
-// CHECK:STDOUT:   %.loc12: type = extern_decl %C.decl.loc12 [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- import_extern_decl_then_decl.carbon
+// 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:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .C = %import_ref.2
+// CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+3, loaded [template = constants.%.1]
+// 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] {}
@@ -463,11 +505,10 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C.2;
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- import_decl_then_extern_decl.carbon
+// 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:   %.1: type = extern_type C [template]
 // CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -477,7 +518,7 @@ extern class C;
 // 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+3, loaded [template = constants.%.1]
+// 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:   %Core: <namespace> = namespace [template] {}
@@ -487,21 +528,20 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C.2;
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- import_extern_decl_then_def.carbon
+// 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:   %.2: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .C = %import_ref.2
+// CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+3, loaded [template = constants.%.2]
+// 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
@@ -524,17 +564,16 @@ extern class C;
 // 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:   %.1: type = extern_type C [template]
 // CHECK:STDOUT:   %C.3: type = class_type @C.3 [template]
-// CHECK:STDOUT:   %.2: type = struct_type {} [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.2
+// CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+3, loaded [template = constants.%.1]
+// 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] {}
@@ -544,25 +583,23 @@ extern class C;
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @C.1 {
+// 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.2;
-// CHECK:STDOUT:
 // CHECK:STDOUT: class @C.3 {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = file.%import_ref.4
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- import_extern_decl_copy.carbon
+// 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:   %.1: type = extern_type C [template]
 // CHECK:STDOUT:   %C.2: type = class_type @C.2 [template]
-// CHECK:STDOUT:   %.2: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -570,8 +607,8 @@ extern class C;
 // CHECK:STDOUT:     .C = %import_ref.1
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+3, loaded [template = constants.%.2]
-// CHECK:STDOUT:   %import_ref.2: type = import_ref ir2, inst+3, loaded [template = constants.%.1]
+// 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:   %Core: <namespace> = namespace [template] {}
@@ -585,7 +622,6 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -593,12 +629,11 @@ extern class C;
 // CHECK:STDOUT:     .Core = %Core
 // CHECK:STDOUT:     .C = %C.decl.loc6
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+3, loaded [template = constants.%.1]
+// CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+2, loaded [template = constants.%C]
 // CHECK:STDOUT:   %Core: <namespace> = namespace [template] {}
 // CHECK:STDOUT:   %C.decl.loc6: type = class_decl @C [template = constants.%C] {
 // CHECK:STDOUT:     %C.decl.1: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -607,7 +642,6 @@ extern class C;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
-// CHECK:STDOUT:   %.1: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -620,7 +654,6 @@ extern class C;
 // CHECK:STDOUT:   %C.decl.loc6: type = class_decl @C [template = constants.%C] {
 // CHECK:STDOUT:     %C.decl.1: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
@@ -630,7 +663,6 @@ extern class C;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %.2: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -644,7 +676,6 @@ extern class C;
 // CHECK:STDOUT:   %C.decl.loc6: type = class_decl @C [template = constants.%C] {
 // CHECK:STDOUT:     %C.decl.1: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.2]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -657,7 +688,6 @@ extern class C;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [template]
 // CHECK:STDOUT:   %.1: type = struct_type {} [template]
-// CHECK:STDOUT:   %.2: type = extern_type C [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -671,7 +701,6 @@ extern class C;
 // CHECK:STDOUT:   %C.decl.loc6: type = class_decl @C [template = constants.%C] {
 // CHECK:STDOUT:     %C.decl.1: type = class_decl @C [template = constants.%C] {}
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc6: type = extern_decl %C.decl.loc6 [template = constants.%.2]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {

+ 0 - 2
toolchain/lower/file_context.cpp

@@ -339,8 +339,6 @@ auto FileContext::BuildType(SemIR::InstId inst_id) -> llvm::Type* {
     }
     case SemIR::ConstType::Kind:
       return GetType(inst.As<SemIR::ConstType>().inner_id);
-    case SemIR::ExternType::Kind:
-      CARBON_FATAL() << "Lowering extern types not supported.";
     case SemIR::FloatType::Kind:
       // TODO: Handle different sizes.
       return llvm::Type::getDoubleTy(*llvm_context_);

+ 0 - 5
toolchain/lower/handle_aggregates.cpp

@@ -12,11 +12,6 @@
 
 namespace Carbon::Lower {
 
-auto HandleExternDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
-                      SemIR::ExternDecl /*inst*/) -> void {
-  // No action to perform.
-}
-
 auto HandleClassDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
                      SemIR::ClassDecl /*inst*/) -> void {
   // No action to perform.

+ 0 - 5
toolchain/lower/handle_type.cpp

@@ -27,11 +27,6 @@ auto HandleConstType(FunctionContext& context, SemIR::InstId inst_id,
   context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleExternType(FunctionContext& context, SemIR::InstId inst_id,
-                      SemIR::ExternType /*inst*/) -> void {
-  context.SetLocal(inst_id, context.GetTypeAsValue());
-}
-
 auto HandleFacetTypeAccess(FunctionContext& context, SemIR::InstId inst_id,
                            SemIR::FacetTypeAccess /*inst*/) -> void {
   context.SetLocal(inst_id, context.GetTypeAsValue());

+ 0 - 9
toolchain/sem_ir/file.cpp

@@ -179,7 +179,6 @@ static auto GetTypePrecedence(InstKind kind) -> int {
     case BindSymbolicName::Kind:
     case Builtin::Kind:
     case ClassType::Kind:
-    case ExternType::Kind:
     case FloatType::Kind:
     case InterfaceType::Kind:
     case InterfaceWitnessAccess::Kind:
@@ -296,11 +295,6 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
         }
         break;
       }
-      case CARBON_KIND(ExternType inst): {
-        out << "extern ";
-        push_inst_id(sem_ir.types().GetInstId(inst.non_extern_type_id));
-        break;
-      }
       case CARBON_KIND(FacetTypeAccess inst): {
         // Print `T as type` as simply `T`.
         push_inst_id(inst.facet_id);
@@ -434,7 +428,6 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
       case ClassInit::Kind:
       case Converted::Kind:
       case Deref::Kind:
-      case ExternDecl::Kind:
       case FieldDecl::Kind:
       case FloatLiteral::Kind:
       case FunctionDecl::Kind:
@@ -556,8 +549,6 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
       case ClassDecl::Kind:
       case ClassType::Kind:
       case ConstType::Kind:
-      case ExternDecl::Kind:
-      case ExternType::Kind:
       case FacetTypeAccess::Kind:
       case FloatLiteral::Kind:
       case FloatType::Kind:

+ 0 - 2
toolchain/sem_ir/inst_kind.def

@@ -68,8 +68,6 @@ CARBON_SEM_IR_INST_KIND_IMPL(ClassType, TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(ConstType, TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(Converted, NOT_TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(Deref, NOT_TYPE)
-CARBON_SEM_IR_INST_KIND_IMPL(ExternDecl, NOT_TYPE)
-CARBON_SEM_IR_INST_KIND_IMPL(ExternType, TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(FacetTypeAccess, NOT_TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(FloatLiteral, NOT_TYPE)
 CARBON_SEM_IR_INST_KIND_IMPL(FloatType, TYPE)

+ 0 - 16
toolchain/sem_ir/typed_insts.h

@@ -438,22 +438,6 @@ struct Deref {
   InstId pointer_id;
 };
 
-struct ExternDecl {
-  static constexpr auto Kind =
-      InstKind::ExternDecl.Define<Parse::NodeId>("extern_decl");
-
-  TypeId type_id;
-  InstId decl_id;
-};
-
-struct ExternType {
-  static constexpr auto Kind = InstKind::ExternType.Define<Parse::NodeId>(
-      "extern_type", InstConstantKind::Always);
-
-  TypeId type_id;
-  TypeId non_extern_type_id;
-};
-
 // Represents accessing the `type` field in a facet value, which is notionally a
 // pair of a type and a witness.
 struct FacetTypeAccess {