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

Use constant evaluation to determine the identity of types. (#3617)

Remove the type canonicalization mechanism and instead rely on constant
canonicalization to deduplicate types.

Rename the `Canonicalize*Type` functions to reflect that they're no
longer performing canonicalization. Switch code that creates types due
to semantic checking, rather than due to source syntax, to directly
create type constants through evaluation rather than creating an
instruction and evaluating it to produce a separate constant
representation.

The mapping from `const (const T)` that was previously performed by type
canonicalization is now implemented in expression evaluation instead.

The value `<error>` is now treated as a constant value, with a special
property that an instruction involving `<error>` that could possibly be
constant evaluates to `<error>`. This helps avoid producing follow-on
errors when an error occurs as a subexpression of an expression, such as
a type, that is intended to be constant.
Richard Smith 2 лет назад
Родитель
Сommit
b138c90c9e
100 измененных файлов с 558 добавлено и 835 удалено
  1. 47 181
      toolchain/check/context.cpp
  2. 28 54
      toolchain/check/context.h
  3. 7 4
      toolchain/check/convert.cpp
  4. 96 23
      toolchain/check/eval.cpp
  5. 2 6
      toolchain/check/handle_binding_pattern.cpp
  6. 1 1
      toolchain/check/handle_call_expr.cpp
  7. 4 10
      toolchain/check/handle_class.cpp
  8. 1 1
      toolchain/check/handle_function.cpp
  9. 1 1
      toolchain/check/handle_paren.cpp
  10. 1 1
      toolchain/check/handle_struct.cpp
  11. 3 4
      toolchain/check/testdata/array/fail_incomplete_element.carbon
  12. 1 1
      toolchain/check/testdata/as/fail_no_conversion.carbon
  13. 1 1
      toolchain/check/testdata/as/fail_not_type.carbon
  14. 6 7
      toolchain/check/testdata/as/identity.carbon
  15. 8 9
      toolchain/check/testdata/as/tuple.carbon
  16. 9 0
      toolchain/check/testdata/basics/builtin_insts.carbon
  17. 1 1
      toolchain/check/testdata/basics/fail_name_lookup.carbon
  18. 4 0
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  19. 4 0
      toolchain/check/testdata/basics/raw_ir.carbon
  20. 7 12
      toolchain/check/testdata/class/base.carbon
  21. 13 21
      toolchain/check/testdata/class/base_field.carbon
  22. 3 6
      toolchain/check/testdata/class/base_function_unqualified.carbon
  23. 5 9
      toolchain/check/testdata/class/base_method.carbon
  24. 9 16
      toolchain/check/testdata/class/base_method_shadow.carbon
  25. 3 5
      toolchain/check/testdata/class/basic.carbon
  26. 16 24
      toolchain/check/testdata/class/derived_to_base.carbon
  27. 7 12
      toolchain/check/testdata/class/fail_abstract.carbon
  28. 0 1
      toolchain/check/testdata/class/fail_addr_not_self.carbon
  29. 0 1
      toolchain/check/testdata/class/fail_addr_self.carbon
  30. 27 45
      toolchain/check/testdata/class/fail_base_bad_type.carbon
  31. 3 7
      toolchain/check/testdata/class/fail_base_method_define.carbon
  32. 12 21
      toolchain/check/testdata/class/fail_base_modifiers.carbon
  33. 3 6
      toolchain/check/testdata/class/fail_base_no_extend.carbon
  34. 8 14
      toolchain/check/testdata/class/fail_base_repeated.carbon
  35. 7 10
      toolchain/check/testdata/class/fail_base_unbound.carbon
  36. 9 17
      toolchain/check/testdata/class/fail_derived_to_base.carbon
  37. 4 7
      toolchain/check/testdata/class/fail_field_modifiers.carbon
  38. 5 6
      toolchain/check/testdata/class/fail_incomplete.carbon
  39. 13 16
      toolchain/check/testdata/class/fail_init.carbon
  40. 6 9
      toolchain/check/testdata/class/fail_init_as_inplace.carbon
  41. 5 9
      toolchain/check/testdata/class/fail_memaccess_category.carbon
  42. 1 2
      toolchain/check/testdata/class/fail_member_of_let.carbon
  43. 3 4
      toolchain/check/testdata/class/fail_method.carbon
  44. 0 3
      toolchain/check/testdata/class/fail_method_modifiers.carbon
  45. 0 6
      toolchain/check/testdata/class/fail_modifiers.carbon
  46. 0 1
      toolchain/check/testdata/class/fail_out_of_line_decl.carbon
  47. 0 7
      toolchain/check/testdata/class/fail_redeclaration_introducer.carbon
  48. 0 7
      toolchain/check/testdata/class/fail_redeclaration_scope.carbon
  49. 2 3
      toolchain/check/testdata/class/fail_redefinition.carbon
  50. 2 3
      toolchain/check/testdata/class/fail_reorder.carbon
  51. 1 2
      toolchain/check/testdata/class/fail_scope.carbon
  52. 1 3
      toolchain/check/testdata/class/fail_self.carbon
  53. 0 1
      toolchain/check/testdata/class/fail_todo_generic.carbon
  54. 4 9
      toolchain/check/testdata/class/fail_todo_modifiers.carbon
  55. 5 7
      toolchain/check/testdata/class/fail_unbound_field.carbon
  56. 3 5
      toolchain/check/testdata/class/fail_unknown_member.carbon
  57. 5 8
      toolchain/check/testdata/class/field_access.carbon
  58. 6 9
      toolchain/check/testdata/class/field_access_in_value.carbon
  59. 0 1
      toolchain/check/testdata/class/forward_declared.carbon
  60. 5 8
      toolchain/check/testdata/class/init.carbon
  61. 5 8
      toolchain/check/testdata/class/init_as.carbon
  62. 10 16
      toolchain/check/testdata/class/init_nested.carbon
  63. 4 6
      toolchain/check/testdata/class/method.carbon
  64. 18 26
      toolchain/check/testdata/class/nested.carbon
  65. 3 6
      toolchain/check/testdata/class/nested_name.carbon
  66. 2 4
      toolchain/check/testdata/class/raw_self.carbon
  67. 2 3
      toolchain/check/testdata/class/raw_self_type.carbon
  68. 0 1
      toolchain/check/testdata/class/redeclaration.carbon
  69. 0 3
      toolchain/check/testdata/class/redeclaration_introducer.carbon
  70. 0 1
      toolchain/check/testdata/class/reenter_scope.carbon
  71. 1 2
      toolchain/check/testdata/class/scope.carbon
  72. 2 4
      toolchain/check/testdata/class/self.carbon
  73. 5 9
      toolchain/check/testdata/class/self_conversion.carbon
  74. 3 5
      toolchain/check/testdata/class/self_type.carbon
  75. 1 2
      toolchain/check/testdata/class/static_method.carbon
  76. 0 1
      toolchain/check/testdata/const/collapse.carbon
  77. 4 5
      toolchain/check/testdata/const/fail_collapse.carbon
  78. 1 1
      toolchain/check/testdata/function/generic/fail_type_param_mismatch.carbon
  79. 1 1
      toolchain/check/testdata/if/fail_scope.carbon
  80. 1 2
      toolchain/check/testdata/if_expr/fail_not_in_function.carbon
  81. 1 2
      toolchain/check/testdata/index/fail_invalid_base.carbon
  82. 1 1
      toolchain/check/testdata/index/fail_name_not_found.carbon
  83. 1 1
      toolchain/check/testdata/index/fail_tuple_index_error.carbon
  84. 0 1
      toolchain/check/testdata/interface/fail_duplicate.carbon
  85. 2 2
      toolchain/check/testdata/let/fail_generic.carbon
  86. 2 2
      toolchain/check/testdata/let/fail_use_in_init.carbon
  87. 2 2
      toolchain/check/testdata/operators/fail_assignment_to_error.carbon
  88. 1 1
      toolchain/check/testdata/operators/fail_type_mismatch.carbon
  89. 1 1
      toolchain/check/testdata/package_expr/fail_not_found.carbon
  90. 1 2
      toolchain/check/testdata/package_expr/syntax.carbon
  91. 1 1
      toolchain/check/testdata/packages/fail_name_with_import_failure.carbon
  92. 5 5
      toolchain/check/testdata/pointer/fail_address_of_error.carbon
  93. 11 10
      toolchain/check/testdata/pointer/fail_address_of_value.carbon
  94. 2 2
      toolchain/check/testdata/pointer/fail_deref_error.carbon
  95. 23 9
      toolchain/check/testdata/return/fail_let_in_type.carbon
  96. 5 8
      toolchain/check/testdata/return/fail_return_with_returned_var.carbon
  97. 1 1
      toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon
  98. 1 1
      toolchain/check/testdata/return/fail_returned_var_type.carbon
  99. 5 8
      toolchain/check/testdata/return/returned_var.carbon
  100. 1 1
      toolchain/check/testdata/struct/fail_access_into_invalid.carbon

+ 47 - 181
toolchain/check/context.cpp

@@ -38,11 +38,14 @@ Context::Context(const Lex::TokenizedBuffer& tokens, DiagnosticEmitter& emitter,
       args_type_info_stack_("args_type_info_stack_", sem_ir, vlog_stream),
       decl_name_stack_(this),
       lexical_lookup_(sem_ir_->identifiers()) {
-  // Inserts the "Error" and "Type" types as "used types" so that
-  // canonicalization can skip them. We don't emit either for lowering.
-  canonical_types_.insert({SemIR::InstId::BuiltinError, SemIR::TypeId::Error});
-  canonical_types_.insert(
-      {SemIR::InstId::BuiltinTypeType, SemIR::TypeId::TypeType});
+  // Map the builtin `<error>` and `type` type constants to their corresponding
+  // special `TypeId` values.
+  type_ids_for_type_constants_.insert(
+      {SemIR::ConstantId::ForTemplateConstant(SemIR::InstId::BuiltinError),
+       SemIR::TypeId::Error});
+  type_ids_for_type_constants_.insert(
+      {SemIR::ConstantId::ForTemplateConstant(SemIR::InstId::BuiltinTypeType),
+       SemIR::TypeId::TypeType});
 }
 
 auto Context::TODO(Parse::NodeId parse_node, std::string label) -> bool {
@@ -489,13 +492,6 @@ auto Context::SetReturnedVarOrGetExisting(SemIR::InstId inst_id)
   return SemIR::InstId::Invalid;
 }
 
-auto Context::FollowNameRefs(SemIR::InstId inst_id) -> SemIR::InstId {
-  while (auto name_ref = insts().Get(inst_id).TryAs<SemIR::NameRef>()) {
-    inst_id = name_ref->value_id;
-  }
-  return inst_id;
-}
-
 template <typename BranchNode, typename... Args>
 static auto AddDominatedBlockAndBranchImpl(Context& context,
                                            Parse::NodeId parse_node,
@@ -778,7 +774,7 @@ class TypeCompleter {
   // state, such as empty structs and tuples.
   auto MakeEmptyValueRepr() const -> SemIR::ValueRepr {
     return {.kind = SemIR::ValueRepr::None,
-            .type_id = context_.CanonicalizeTupleType({})};
+            .type_id = context_.GetTupleType({})};
   }
 
   // Makes a value representation that uses pass-by-copy, copying the given
@@ -904,7 +900,7 @@ class TypeCompleter {
 
     auto value_rep = same_as_object_rep
                          ? type_id
-                         : context_.CanonicalizeStructType(
+                         : context_.GetStructType(
                                context_.inst_blocks().Add(value_rep_fields));
     return BuildStructOrTupleValueRepr(fields.size(), value_rep,
                                        same_as_object_rep);
@@ -934,7 +930,7 @@ class TypeCompleter {
 
     auto value_rep = same_as_object_rep
                          ? type_id
-                         : context_.CanonicalizeTupleType(value_rep_elements);
+                         : context_.GetTupleType(value_rep_elements);
     return BuildStructOrTupleValueRepr(elements.size(), value_rep,
                                        same_as_object_rep);
   }
@@ -1072,193 +1068,63 @@ auto Context::TryToCompleteType(
   return TypeCompleter(*this, diagnoser).Complete(type_id);
 }
 
-auto Context::CanonicalizeTypeImpl(
-    SemIR::InstKind kind,
-    llvm::function_ref<bool(llvm::FoldingSetNodeID& canonical_id)> profile_type,
-    llvm::function_ref<SemIR::InstId()> make_inst) -> SemIR::TypeId {
-  llvm::FoldingSetNodeID canonical_id;
-  kind.Profile(canonical_id);
-  if (!profile_type(canonical_id)) {
-    return SemIR::TypeId::Error;
-  }
-
-  void* insert_pos;
-  auto* node =
-      canonical_type_nodes_.FindNodeOrInsertPos(canonical_id, insert_pos);
-  if (node != nullptr) {
-    return node->type_id();
-  }
-
-  auto inst_id = make_inst();
-  auto type_id = types().Add({.inst_id = inst_id});
-  CARBON_CHECK(canonical_types_.insert({inst_id, type_id}).second);
-  type_node_storage_.push_back(
-      std::make_unique<TypeNode>(canonical_id, type_id));
-
-  // In a debug build, check that our insertion position is still valid. It
-  // could have been invalidated by a misbehaving `make_inst`.
-  CARBON_DCHECK([&] {
-    void* check_insert_pos;
-    auto* check_node = canonical_type_nodes_.FindNodeOrInsertPos(
-        canonical_id, check_insert_pos);
-    return !check_node && insert_pos == check_insert_pos;
-  }()) << "Type was created recursively during canonicalization";
-
-  canonical_type_nodes_.InsertNode(type_node_storage_.back().get(), insert_pos);
-  return type_id;
-}
-
-// Compute a fingerprint for a tuple type, for use as a key in a folding set.
-static auto ProfileTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids,
-                             llvm::FoldingSetNodeID& canonical_id) -> void {
-  for (auto type_id : type_ids) {
-    canonical_id.AddInteger(type_id.index);
-  }
-}
+auto Context::GetTypeIdForTypeConstant(SemIR::ConstantId constant_id)
+    -> SemIR::TypeId {
+  CARBON_CHECK(constant_id.is_constant()) << "Canonicalizing non-constant type";
 
-// Compute a fingerprint for a type, for use as a key in a folding set. Returns
-// false if not supported, which is presently the case for compile-time
-// expressions.
-// TODO: Once support is more complete, in particular ensuring that various
-// valid compile-time expressions are supported, it may be desirable to switch
-// the default to a CARBON_FATAL error.
-static auto ProfileType(Context& semantics_context, SemIR::Inst inst,
-                        llvm::FoldingSetNodeID& canonical_id) -> bool {
-  switch (inst.kind()) {
-    case SemIR::ArrayType::Kind: {
-      auto array_type = inst.As<SemIR::ArrayType>();
-      canonical_id.AddInteger(
-          semantics_context.sem_ir().GetArrayBoundValue(array_type.bound_id));
-      canonical_id.AddInteger(array_type.element_type_id.index);
-      break;
-    }
-    case SemIR::Builtin::Kind:
-      canonical_id.AddInteger(inst.As<SemIR::Builtin>().builtin_kind.AsInt());
-      break;
-    case SemIR::ClassType::Kind:
-      canonical_id.AddInteger(inst.As<SemIR::ClassType>().class_id.index);
-      break;
-    case SemIR::CrossRef::Kind: {
-      // TODO: Cross-references should be canonicalized by looking at their
-      // target rather than treating them as new unique types.
-      auto xref = inst.As<SemIR::CrossRef>();
-      canonical_id.AddInteger(xref.ir_id.index);
-      canonical_id.AddInteger(xref.inst_id.index);
-      break;
-    }
-    case SemIR::ConstType::Kind:
-      canonical_id.AddInteger(
-          semantics_context
-              .GetUnqualifiedType(inst.As<SemIR::ConstType>().inner_id)
-              .index);
-      break;
-    case SemIR::BindSymbolicName::Kind:
-      // TODO: Use de Bruijn levels or similar to identify equivalent type
-      // bindings across redeclarations.
-      canonical_id.AddInteger(
-          inst.As<SemIR::BindSymbolicName>().bind_name_id.index);
-      break;
-    case SemIR::PointerType::Kind:
-      canonical_id.AddInteger(inst.As<SemIR::PointerType>().pointee_id.index);
-      break;
-    case SemIR::StructType::Kind: {
-      auto fields = semantics_context.inst_blocks().Get(
-          inst.As<SemIR::StructType>().fields_id);
-      for (const auto& field_id : fields) {
-        auto field =
-            semantics_context.insts().GetAs<SemIR::StructTypeField>(field_id);
-        canonical_id.AddInteger(field.name_id.index);
-        canonical_id.AddInteger(field.field_type_id.index);
-      }
-      break;
-    }
-    case SemIR::TupleType::Kind:
-      ProfileTupleType(semantics_context.type_blocks().Get(
-                           inst.As<SemIR::TupleType>().elements_id),
-                       canonical_id);
-      break;
-    case SemIR::UnboundElementType::Kind: {
-      auto unbound_field_type = inst.As<SemIR::UnboundElementType>();
-      canonical_id.AddInteger(unbound_field_type.class_type_id.index);
-      canonical_id.AddInteger(unbound_field_type.element_type_id.index);
-      break;
-    }
-    default: {
-      // Right now, this is only expected to occur in calls from
-      // ExprAsType. Diagnostics are issued there.
-      return false;
-    }
+  auto [it, added] = type_ids_for_type_constants_.insert(
+      {constant_id, SemIR::TypeId::Invalid});
+  if (added) {
+    // TODO: Store the full `constant_id` on the TypeInfo.
+    it->second = types().Add({.inst_id = constant_id.inst_id()});
   }
-  return true;
+  return it->second;
 }
 
-auto Context::CanonicalizeTypeAndAddInstIfNew(SemIR::Inst inst)
+template <typename InstT, typename... EachArgT>
+static auto GetTypeImpl(Context& context, EachArgT... each_arg)
     -> SemIR::TypeId {
-  auto profile_node = [&](llvm::FoldingSetNodeID& canonical_id) {
-    return ProfileType(*this, inst, canonical_id);
-  };
-  auto make_inst = [&] {
-    // TODO: Properly determine whether types are symbolic.
-    return AddConstant(inst, /*is_symbolic=*/false).inst_id();
-  };
-  return CanonicalizeTypeImpl(inst.kind(), profile_node, make_inst);
+  // TODO: Remove inst_id parameter from TryEvalInst.
+  return context.GetTypeIdForTypeConstant(
+      TryEvalInst(context, SemIR::InstId::Invalid,
+                  InstT{SemIR::TypeId::TypeType, each_arg...}));
 }
 
-auto Context::CanonicalizeType(SemIR::InstId inst_id) -> SemIR::TypeId {
-  while (auto converted = insts().Get(inst_id).TryAs<SemIR::Converted>()) {
-    inst_id = converted->result_id;
-  }
-  inst_id = FollowNameRefs(inst_id);
-
-  auto it = canonical_types_.find(inst_id);
-  if (it != canonical_types_.end()) {
-    return it->second;
-  }
-
-  auto inst = insts().Get(inst_id);
-  auto profile_node = [&](llvm::FoldingSetNodeID& canonical_id) {
-    return ProfileType(*this, inst, canonical_id);
-  };
-  auto make_inst = [&] { return inst_id; };
-  return CanonicalizeTypeImpl(inst.kind(), profile_node, make_inst);
-}
-
-auto Context::CanonicalizeStructType(SemIR::InstBlockId refs_id)
-    -> SemIR::TypeId {
-  return CanonicalizeTypeAndAddInstIfNew(
-      SemIR::StructType{SemIR::TypeId::TypeType, refs_id});
+auto Context::GetStructType(SemIR::InstBlockId refs_id) -> SemIR::TypeId {
+  return GetTypeImpl<SemIR::StructType>(*this, refs_id);
 }
 
-auto Context::CanonicalizeTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids)
+auto Context::GetTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids)
     -> SemIR::TypeId {
-  // Defer allocating a SemIR::TypeBlockId until we know this is a new type.
-  auto profile_tuple = [&](llvm::FoldingSetNodeID& canonical_id) {
-    ProfileTupleType(type_ids, canonical_id);
-    return true;
-  };
-  auto make_tuple_inst = [&] {
-    // TODO: Properly determine when types are symbolic.
-    return AddConstant(SemIR::TupleType{SemIR::TypeId::TypeType,
-                                        type_blocks().Add(type_ids)},
-                       /*is_symbolic=*/false)
-        .inst_id();
-  };
-  return CanonicalizeTypeImpl(SemIR::TupleType::Kind, profile_tuple,
-                              make_tuple_inst);
+  // TODO: Deduplicate the type block here. Currently requesting the same tuple
+  // type more than once will create multiple type blocks, all but one of which
+  // is unused.
+  return GetTypeImpl<SemIR::TupleType>(*this, type_blocks().Add(type_ids));
 }
 
 auto Context::GetBuiltinType(SemIR::BuiltinKind kind) -> SemIR::TypeId {
   CARBON_CHECK(kind != SemIR::BuiltinKind::Invalid);
-  auto type_id = CanonicalizeType(SemIR::InstId::ForBuiltin(kind));
+  auto type_id = GetTypeIdForTypeConstant(
+      constant_values().Get(SemIR::InstId::ForBuiltin(kind)));
   // To keep client code simpler, complete builtin types before returning them.
   bool complete = TryToCompleteType(type_id);
   CARBON_CHECK(complete) << "Failed to complete builtin type";
   return type_id;
 }
 
+auto Context::GetClassType(SemIR::ClassId class_id) -> SemIR::TypeId {
+  return GetTypeImpl<SemIR::ClassType>(*this, class_id);
+}
+
 auto Context::GetPointerType(SemIR::TypeId pointee_type_id) -> SemIR::TypeId {
-  return CanonicalizeTypeAndAddInstIfNew(
-      SemIR::PointerType{SemIR::TypeId::TypeType, pointee_type_id});
+  return GetTypeImpl<SemIR::PointerType>(*this, pointee_type_id);
+}
+
+auto Context::GetUnboundElementType(SemIR::TypeId class_type_id,
+                                    SemIR::TypeId element_type_id)
+    -> SemIR::TypeId {
+  return GetTypeImpl<SemIR::UnboundElementType>(*this, class_type_id,
+                                                element_type_id);
 }
 
 auto Context::GetUnqualifiedType(SemIR::TypeId type_id) -> SemIR::TypeId {

+ 28 - 54
toolchain/check/context.h

@@ -219,13 +219,6 @@ class Context {
   // is already a `returned var`, returns it instead.
   auto SetReturnedVarOrGetExisting(SemIR::InstId inst_id) -> SemIR::InstId;
 
-  // Follows NameRef instructions to find the value named by a given
-  // instruction.
-  auto FollowNameRefs(SemIR::InstId inst_id) -> SemIR::InstId;
-
-  // Gets the constant value of the given instruction, if it has one.
-  auto GetConstantValue(SemIR::InstId inst_id) -> SemIR::InstId;
-
   // Adds a `Branch` instruction branching to a new instruction block, and
   // returns the ID of the new block. All paths to the branch target must go
   // through the current block, though not necessarily through this branch.
@@ -272,22 +265,8 @@ class Context {
   // Returns whether the current position in the current block is reachable.
   auto is_current_position_reachable() -> bool;
 
-  // Canonicalizes a type which is tracked as a single instruction.
-  auto CanonicalizeType(SemIR::InstId inst_id) -> SemIR::TypeId;
-
-  // Handles canonicalization of struct types. This may create a new struct type
-  // when it has a new structure, or reference an existing struct type when it
-  // duplicates a prior type.
-  //
-  // Individual struct type fields aren't canonicalized because they may have
-  // name conflicts or other diagnostics during creation, which can use the
-  // parse node.
-  auto CanonicalizeStructType(SemIR::InstBlockId refs_id) -> SemIR::TypeId;
-
-  // Handles canonicalization of tuple types. This may create a new tuple type
-  // if the `type_ids` doesn't match an existing tuple type.
-  auto CanonicalizeTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids)
-      -> SemIR::TypeId;
+  // Returns the type ID for a constant of type `type`.
+  auto GetTypeIdForTypeConstant(SemIR::ConstantId constant_id) -> SemIR::TypeId;
 
   // Attempts to complete the type `type_id`. Returns `true` if the type is
   // complete, or `false` if it could not be completed. A complete type has
@@ -311,12 +290,29 @@ class Context {
                                                  : SemIR::TypeId::Error;
   }
 
+  // TODO: Consider moving these `Get*Type` functions to a separate class.
+
   // Gets a builtin type. The returned type will be complete.
   auto GetBuiltinType(SemIR::BuiltinKind kind) -> SemIR::TypeId;
 
+  // Returns a class type for the class described by `class_id`.
+  // TODO: Support generic arguments.
+  auto GetClassType(SemIR::ClassId class_id) -> SemIR::TypeId;
+
   // Returns a pointer type whose pointee type is `pointee_type_id`.
   auto GetPointerType(SemIR::TypeId pointee_type_id) -> SemIR::TypeId;
 
+  // Returns a struct type with the given fields, which should be a block of
+  // `StructTypeField`s.
+  auto GetStructType(SemIR::InstBlockId refs_id) -> SemIR::TypeId;
+
+  // Returns a tuple type with the given element types.
+  auto GetTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids) -> SemIR::TypeId;
+
+  // Returns an unbound element type.
+  auto GetUnboundElementType(SemIR::TypeId class_type_id,
+                             SemIR::TypeId element_type_id) -> SemIR::TypeId;
+
   // Removes any top-level `const` qualifiers from a type.
   auto GetUnqualifiedType(SemIR::TypeId type_id) -> SemIR::TypeId;
 
@@ -484,27 +480,6 @@ class Context {
     // TODO: This likely needs to track things which need to be destructed.
   };
 
-  // Forms a canonical type ID for a type. This function is given two
-  // callbacks:
-  //
-  // `profile_type(canonical_id)` is called to build a fingerprint for this
-  // type. The ID should be distinct for all distinct type values with the same
-  // `kind`.
-  //
-  // `make_inst()` is called to obtain a `SemIR::InstId` that describes the
-  // type. It is only called if the type does not already exist, so can be used
-  // to lazily build the `SemIR::Inst`. `make_inst()` is not permitted to
-  // directly or indirectly canonicalize any types.
-  auto CanonicalizeTypeImpl(
-      SemIR::InstKind kind,
-      llvm::function_ref<bool(llvm::FoldingSetNodeID& canonical_id)>
-          profile_type,
-      llvm::function_ref<SemIR::InstId()> make_inst) -> SemIR::TypeId;
-
-  // Forms a canonical type ID for a type. If the type is new, adds the
-  // instruction to the current block.
-  auto CanonicalizeTypeAndAddInstIfNew(SemIR::Inst inst) -> SemIR::TypeId;
-
   // If the passed in instruction ID is a LazyImportRef, resolves it for use.
   // Called when name lookup intends to return an inst_id.
   auto ResolveIfLazyImportRef(SemIR::InstId inst_id) -> void;
@@ -577,16 +552,15 @@ class Context {
   // pushed or popped.
   bool lexical_lookup_has_load_error_ = false;
 
-  // Cache of the mapping from instructions to types, to avoid recomputing the
-  // folding set ID.
-  llvm::DenseMap<SemIR::InstId, SemIR::TypeId> canonical_types_;
-
-  // Tracks the canonical representation of types that have been defined.
-  llvm::FoldingSet<TypeNode> canonical_type_nodes_;
-
-  // Storage for the nodes in canonical_type_nodes_. This stores in pointers so
-  // that FoldingSet can have stable pointers.
-  llvm::SmallVector<std::unique_ptr<TypeNode>> type_node_storage_;
+  // Cache of reverse mapping from type constants to types.
+  //
+  // TODO: Instead of mapping to a dense `TypeId` space, we could make `TypeId`
+  // be a thin wrapper around `ConstantId` and only perform the lookup only when
+  // we want to access the completeness and value representation of a type. It's
+  // not clear whether that would result in more or fewer lookups.
+  //
+  // TODO: Should this be part of the `TypeStore`?
+  llvm::DenseMap<SemIR::ConstantId, SemIR::TypeId> type_ids_for_type_constants_;
 
   // The list which will form NodeBlockId::Exports.
   llvm::SmallVector<SemIR::InstId> exports_;

+ 7 - 4
toolchain/check/convert.cpp

@@ -820,7 +820,7 @@ static auto PerformBuiltinConversion(Context& context, Parse::NodeId parse_node,
         // iterative approach.
         type_ids.push_back(ExprAsType(context, parse_node, tuple_inst_id));
       }
-      auto tuple_type_id = context.CanonicalizeTupleType(type_ids);
+      auto tuple_type_id = context.GetTupleType(type_ids);
       return sem_ir.types().GetInstId(tuple_type_id);
     }
 
@@ -1220,13 +1220,16 @@ auto ExprAsType(Context& context, Parse::NodeId parse_node,
   if (type_inst_id == SemIR::InstId::BuiltinError) {
     return SemIR::TypeId::Error;
   }
-  auto type_id = context.CanonicalizeType(type_inst_id);
-  if (type_id == SemIR::TypeId::Error) {
+
+  auto type_const_id = context.constant_values().Get(type_inst_id);
+  if (!type_const_id.is_constant()) {
     CARBON_DIAGNOSTIC(TypeExprEvaluationFailure, Error,
                       "Cannot evaluate type expression.");
     context.emitter().Emit(parse_node, TypeExprEvaluationFailure);
+    return SemIR::TypeId::Error;
   }
-  return type_id;
+
+  return context.GetTypeIdForTypeConstant(type_const_id);
 }
 
 }  // namespace Carbon::Check

+ 96 - 23
toolchain/check/eval.cpp

@@ -4,31 +4,87 @@
 
 #include "toolchain/check/eval.h"
 
+#include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/typed_insts.h"
 #include "toolchain/sem_ir/value_stores.h"
 
 namespace Carbon::Check {
 
+namespace {
+// The evaluation phase for an expression, computed by evaluation. These are
+// ordered so that the phase of an expression is the numerically highest phase
+// of its constituent evaluations. Note that an expression with any runtime
+// component is known to have Runtime phase even if it involves an evaluation
+// with UnknownDueToError phase.
+enum class Phase : uint8_t {
+  // Value could be entirely and concretely computed.
+  Template,
+  // Evaluation phase is symbolic because the expression involves a reference to
+  // a symbolic binding.
+  Symbolic,
+  // The evaluation phase is unknown because evaluation encountered an
+  // already-diagnosed semantic or syntax error. This is treated as being
+  // potentially constant, but with an unknown phase.
+  UnknownDueToError,
+  // The epxression has runtime phase because of a non-constant subexpression.
+  Runtime,
+};
+}  // namespace
+
+// Gets the phase in which the value of a constant will become available.
+static auto GetPhase(SemIR::ConstantId constant_id) -> Phase {
+  if (!constant_id.is_constant()) {
+    return Phase::Runtime;
+  } else if (constant_id == SemIR::ConstantId::Error) {
+    return Phase::UnknownDueToError;
+  } else if (constant_id.is_template()) {
+    return Phase::Template;
+  } else {
+    return Phase::Symbolic;
+  }
+}
+
+// Returns the later of two phases.
+static auto LatestPhase(Phase a, Phase b) -> Phase {
+  return static_cast<Phase>(
+      std::max(static_cast<uint8_t>(a), static_cast<uint8_t>(b)));
+}
+
+// Forms a `constant_id` describing a given evaluation result.
+static auto MakeConstantResult(Context& context, SemIR::Inst inst, Phase phase)
+    -> SemIR::ConstantId {
+  switch (phase) {
+    case Phase::Template:
+      return context.AddConstant(inst, /*is_symbolic=*/false);
+    case Phase::Symbolic:
+      return context.AddConstant(inst, /*is_symbolic=*/true);
+    case Phase::UnknownDueToError:
+      return SemIR::ConstantId::Error;
+    case Phase::Runtime:
+      return SemIR::ConstantId::NotConstant;
+  }
+}
+
 // `GetConstantValue` checks to see whether the provided ID describes a value
 // with constant phase, and if so, returns the corresponding constant value.
 // Overloads are provided for different kinds of ID.
 
 // If the given instruction is constant, returns its constant value.
 static auto GetConstantValue(Context& context, SemIR::InstId inst_id,
-                             bool* is_symbolic) -> SemIR::InstId {
+                             Phase* phase) -> SemIR::InstId {
   auto const_id = context.constant_values().Get(inst_id);
-  *is_symbolic |= const_id.is_symbolic();
+  *phase = LatestPhase(*phase, GetPhase(const_id));
   return const_id.inst_id();
 }
 
 // If the given instruction block contains only constants, returns a
 // corresponding block of those values.
 static auto GetConstantValue(Context& context, SemIR::InstBlockId inst_block_id,
-                             bool* is_symbolic) -> SemIR::InstBlockId {
+                             Phase* phase) -> SemIR::InstBlockId {
   auto insts = context.inst_blocks().Get(inst_block_id);
   llvm::SmallVector<SemIR::InstId> const_insts;
   for (auto inst_id : insts) {
-    auto const_inst_id = GetConstantValue(context, inst_id, is_symbolic);
+    auto const_inst_id = GetConstantValue(context, inst_id, phase);
     if (!const_inst_id.is_valid()) {
       return SemIR::InstBlockId::Invalid;
     }
@@ -52,9 +108,9 @@ static auto GetConstantValue(Context& context, SemIR::InstBlockId inst_block_id,
 // has runtime phase.
 template <typename InstT, typename FieldIdT>
 static auto ReplaceFieldWithConstantValue(Context& context, InstT* inst,
-                                          FieldIdT InstT::*field,
-                                          bool* is_symbolic) -> bool {
-  auto unwrapped = GetConstantValue(context, inst->*field, is_symbolic);
+                                          FieldIdT InstT::*field, Phase* phase)
+    -> bool {
+  auto unwrapped = GetConstantValue(context, inst->*field, phase);
   if (!unwrapped.is_valid()) {
     return false;
   }
@@ -72,13 +128,14 @@ static auto RebuildIfFieldsAreConstant(Context& context, SemIR::Inst inst,
   // Build a constant instruction by replacing each non-constant operand with
   // its constant value.
   auto typed_inst = inst.As<InstT>();
-  bool is_symbolic = false;
+  Phase phase = Phase::Template;
   if ((ReplaceFieldWithConstantValue(context, &typed_inst, each_field_id,
-                                     &is_symbolic) &&
+                                     &phase) &&
        ...)) {
-    return context.AddConstant(typed_inst, is_symbolic);
+    return MakeConstantResult(context, typed_inst, phase);
   }
-  return SemIR::ConstantId::NotConstant;
+  return phase == Phase::UnknownDueToError ? SemIR::ConstantId::Error
+                                           : SemIR::ConstantId::NotConstant;
 }
 
 auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
@@ -116,13 +173,12 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
     // These cases are always constants.
     case SemIR::Builtin::Kind:
     case SemIR::ClassType::Kind:
-    case SemIR::ConstType::Kind:
     case SemIR::PointerType::Kind:
     case SemIR::StructTypeField::Kind:
     case SemIR::TupleType::Kind:
     case SemIR::UnboundElementType::Kind:
       // TODO: Propagate symbolic / template nature from operands.
-      return context.AddConstant(inst, /*is_symbolic=*/false);
+      return MakeConstantResult(context, inst, Phase::Template);
 
     // These cases are treated as being the unique canonical definition of the
     // corresponding constant value.
@@ -142,7 +198,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       // TODO: Convert literals into a canonical form. Currently we can form two
       // different `i32` constants with the same value if they are represented
       // by `APInt`s with different bit widths.
-      return context.AddConstant(inst, /*is_symbolic=*/false);
+      return MakeConstantResult(context, inst, Phase::Template);
 
     // TODO: These need special handling.
     case SemIR::ArrayIndex::Kind:
@@ -184,19 +240,36 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
       return context.constant_values().Get(
           inst.As<SemIR::Converted>().result_id);
 
+    // `not true` -> `false`, `not false` -> `true`.
+    // All other uses of unary `not` are non-constant.
     case SemIR::UnaryOperatorNot::Kind: {
       auto const_id = context.constant_values().Get(
           inst.As<SemIR::UnaryOperatorNot>().operand_id);
-      if (!const_id.is_template()) {
-        break;
+      auto phase = GetPhase(const_id);
+      if (phase == Phase::Template) {
+        auto value =
+            context.insts().GetAs<SemIR::BoolLiteral>(const_id.inst_id());
+        value.value =
+            (value.value == SemIR::BoolValue::False ? SemIR::BoolValue::True
+                                                    : SemIR::BoolValue::False);
+        return MakeConstantResult(context, value, Phase::Template);
+      }
+      if (phase == Phase::UnknownDueToError) {
+        return SemIR::ConstantId::Error;
+      }
+      break;
+    }
+
+    // `const (const T)` evaluates to `const T`. Otherwise, `const T` evaluates
+    // to itself.
+    case SemIR::ConstType::Kind: {
+      auto inner_id = context.constant_values().Get(
+          context.types().GetInstId(inst.As<SemIR::ConstType>().inner_id));
+      if (inner_id.is_constant() &&
+          context.insts().Get(inner_id.inst_id()).Is<SemIR::ConstType>()) {
+        return inner_id;
       }
-      // A template constant of bool type is always a bool literal.
-      auto value =
-          context.insts().GetAs<SemIR::BoolLiteral>(const_id.inst_id());
-      value.value =
-          (value.value == SemIR::BoolValue::False ? SemIR::BoolValue::True
-                                                  : SemIR::BoolValue::False);
-      return context.AddConstant(value, /*is_symbolic=*/false);
+      return MakeConstantResult(context, inst, GetPhase(inner_id));
     }
 
     // These cases are either not expressions or not constant.

+ 2 - 6
toolchain/check/handle_binding_pattern.cpp

@@ -90,12 +90,8 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId parse_node,
       } else if (enclosing_class_decl) {
         auto& class_info =
             context.classes().Get(enclosing_class_decl->class_id);
-        auto field_type_inst_id = context.AddInst(
-            {binding_id,
-             SemIR::UnboundElementType{
-                 context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
-                 class_info.self_type_id, cast_type_id}});
-        value_type_id = context.CanonicalizeType(field_type_inst_id);
+        value_type_id = context.GetUnboundElementType(class_info.self_type_id,
+                                                      cast_type_id);
         value_id = context.AddInst(
             {binding_id, SemIR::FieldDecl{
                              value_type_id, name_id,

+ 1 - 1
toolchain/check/handle_call_expr.cpp

@@ -73,7 +73,7 @@ auto HandleCallExpr(Context& context, Parse::CallExprId parse_node) -> bool {
   // tuple type.
   SemIR::TypeId type_id = callable.return_type_id;
   if (!type_id.is_valid()) {
-    type_id = context.CanonicalizeTupleType({});
+    type_id = context.GetTupleType({});
   }
 
   // If there is a return slot, build storage for the result.

+ 4 - 10
toolchain/check/handle_class.cpp

@@ -104,10 +104,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId parse_node)
 
     // Build the `Self` type.
     auto& class_info = context.classes().Get(class_decl.class_id);
-    class_info.self_type_id = context.CanonicalizeType(context.AddInst(
-        {parse_node,
-         SemIR::ClassType{context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
-                          class_decl.class_id}}));
+    class_info.self_type_id = context.GetClassType(class_decl.class_id);
   }
 
   // Write the class ID into the ClassDecl.
@@ -291,11 +288,8 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId parse_node) -> bool {
 
   // The `base` value in the class scope has an unbound element type. Instance
   // binding will be performed when it's found by name lookup into an instance.
-  auto field_type_inst_id = context.AddInst(
-      {parse_node, SemIR::UnboundElementType{
-                       context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
-                       class_info.self_type_id, base_info.type_id}});
-  auto field_type_id = context.CanonicalizeType(field_type_inst_id);
+  auto field_type_id =
+      context.GetUnboundElementType(class_info.self_type_id, base_info.type_id);
   class_info.base_id = context.AddInst(
       {parse_node,
        SemIR::BaseDecl{field_type_id, base_info.type_id,
@@ -338,7 +332,7 @@ auto HandleClassDefinition(Context& context,
 
   // The class type is now fully defined.
   auto& class_info = context.classes().Get(class_id);
-  class_info.object_repr_id = context.CanonicalizeStructType(fields_id);
+  class_info.object_repr_id = context.GetStructType(fields_id);
   return true;
 }
 

+ 1 - 1
toolchain/check/handle_function.cpp

@@ -191,7 +191,7 @@ static auto BuildFunctionDecl(Context& context,
         (return_slot_id.is_valid() &&
          return_type_id !=
              context.GetBuiltinType(SemIR::BuiltinKind::BoolType) &&
-         return_type_id != context.CanonicalizeTupleType({}))) {
+         return_type_id != context.GetTupleType({}))) {
       CARBON_DIAGNOSTIC(InvalidMainRunSignature, Error,
                         "Invalid signature for `Main.Run` function. Expected "
                         "`fn ()` or `fn () -> i32`.");

+ 1 - 1
toolchain/check/handle_paren.cpp

@@ -43,7 +43,7 @@ auto HandleTupleLiteral(Context& context, Parse::TupleLiteralId parse_node)
   for (auto inst : inst_block) {
     type_ids.push_back(context.insts().Get(inst).type_id());
   }
-  auto type_id = context.CanonicalizeTupleType(type_ids);
+  auto type_id = context.GetTupleType(type_ids);
 
   auto value_id =
       context.AddInst({parse_node, SemIR::TupleLiteral{type_id, refs_id}});

+ 1 - 1
toolchain/check/handle_struct.cpp

@@ -104,7 +104,7 @@ auto HandleStructLiteral(Context& context, Parse::StructLiteralId parse_node)
     return true;
   }
 
-  auto type_id = context.CanonicalizeStructType(type_block_id);
+  auto type_id = context.GetStructType(type_block_id);
 
   auto value_id =
       context.AddInst({parse_node, SemIR::StructLiteral{type_id, refs_id}});

+ 3 - 4
toolchain/check/testdata/array/fail_incomplete_element.carbon

@@ -33,19 +33,18 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Incomplete = %Incomplete.decl, .a = %a, .p = %p} [template]
 // CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, ()
-// CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template = constants.%Incomplete]
-// CHECK:STDOUT:   %Incomplete.ref.loc15: type = name_ref Incomplete, %Incomplete [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Incomplete.ref.loc15: type = name_ref Incomplete, constants.%Incomplete [template = constants.%Incomplete]
 // CHECK:STDOUT:   %.loc15_21: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc15_22: type = array_type %.loc15_21, Incomplete [template = constants.%.2]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
-// CHECK:STDOUT:   %Incomplete.ref.loc20: type = name_ref Incomplete, %Incomplete [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Incomplete.ref.loc20: type = name_ref Incomplete, constants.%Incomplete [template = constants.%Incomplete]
 // CHECK:STDOUT:   %.loc20_18: type = ptr_type Incomplete [template = constants.%.3]
 // CHECK:STDOUT:   %p.var: ref Incomplete* = var p
 // CHECK:STDOUT:   %p: ref Incomplete* = bind_name p, %p.var
 // CHECK:STDOUT:   %a.ref: ref <error> = name_ref a, %a
 // CHECK:STDOUT:   %.loc20_25: i32 = int_literal 0 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc20_22: <error>* = addr_of <error>
+// CHECK:STDOUT:   %.loc20_22: <error>* = addr_of <error> [template = <error>]
 // CHECK:STDOUT:   assign %p.var, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/as/fail_no_conversion.carbon

@@ -25,6 +25,6 @@ let n: (i32, i32) = 1 as (i32, i32);
 // CHECK:STDOUT:   %.loc10_21: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_35.1: (type, type) = tuple_literal (i32, i32)
 // CHECK:STDOUT:   %.loc10_35.2: type = converted %.loc10_35.1, constants.%.2 [template = constants.%.2]
-// CHECK:STDOUT:   %n: (i32, i32) = bind_name n, <error>
+// CHECK:STDOUT:   %n: (i32, i32) = bind_name n, <error> [template = <error>]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/as/fail_not_type.carbon

@@ -20,6 +20,6 @@ let n: i32 = 1 as 2;
 // CHECK:STDOUT:   package: <namespace> = namespace package, {} [template]
 // CHECK:STDOUT:   %.loc10_14: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc10_19: i32 = int_literal 2 [template = constants.%.2]
-// CHECK:STDOUT:   %n: i32 = bind_name n, <error>
+// CHECK:STDOUT:   %n: i32 = bind_name n, <error> [template = <error>]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 6 - 7
toolchain/check/testdata/as/identity.carbon

@@ -37,7 +37,6 @@ fn Initializing() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.X = %X.decl, .Value = %Value, .Reference = %Reference, .Make = %Make, .Initializing = %Initializing} [template]
 // CHECK:STDOUT:   %X.decl = class_decl @X, ()
-// CHECK:STDOUT:   %X: type = class_type @X [template = constants.%X]
 // CHECK:STDOUT:   %Value: <function> = fn_decl @Value [template]
 // CHECK:STDOUT:   %Reference: <function> = fn_decl @Reference [template]
 // CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
@@ -51,20 +50,20 @@ fn Initializing() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Value(%n: X) {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %X.ref.loc14_10: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc14_10: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %n.ref: X = name_ref n, %n
-// CHECK:STDOUT:   %X.ref.loc14_19: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc14_19: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %m: X = bind_name m, %n.ref
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Reference(%p: X*) {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %X.ref.loc18_10: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc18_10: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc18_11: type = ptr_type X [template = constants.%.4]
 // CHECK:STDOUT:   %p.ref: X* = name_ref p, %p
 // CHECK:STDOUT:   %.loc18_17: ref X = deref %p.ref
-// CHECK:STDOUT:   %X.ref.loc18_23: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc18_23: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc18_15: X* = addr_of %.loc18_17
 // CHECK:STDOUT:   %q: X* = bind_name q, %.loc18_15
 // CHECK:STDOUT:   return
@@ -74,13 +73,13 @@ fn Initializing() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Initializing() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %X.ref.loc24_10: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc24_10: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %x.var: ref X = var x
 // CHECK:STDOUT:   %x: ref X = bind_name x, %x.var
 // CHECK:STDOUT:   %Make.ref: <function> = name_ref Make, file.%Make [template = file.%Make]
 // CHECK:STDOUT:   %.loc24_7: ref X = splice_block %x.var {}
 // CHECK:STDOUT:   %.loc24_19: init X = call %Make.ref() to %.loc24_7
-// CHECK:STDOUT:   %X.ref.loc24_25: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc24_25: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   assign %x.var, %.loc24_19
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 8 - 9
toolchain/check/testdata/as/tuple.carbon

@@ -36,7 +36,6 @@ fn Var() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.X = %X.decl, .Make = %Make, .Let = %Let, .Var = %Var} [template]
 // CHECK:STDOUT:   %X.decl = class_decl @X, ()
-// CHECK:STDOUT:   %X: type = class_type @X [template = constants.%X]
 // CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
 // CHECK:STDOUT:   %Let: <function> = fn_decl @Let [template]
 // CHECK:STDOUT:   %Var: <function> = fn_decl @Var [template]
@@ -51,8 +50,8 @@ fn Var() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Let() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %X.ref.loc15_11: type = name_ref X, file.%X [template = constants.%X]
-// CHECK:STDOUT:   %X.ref.loc15_14: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc15_11: type = name_ref X, constants.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc15_14: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc15_15.1: (type, type) = tuple_literal (%X.ref.loc15_11, %X.ref.loc15_14)
 // CHECK:STDOUT:   %.loc15_15.2: type = converted %.loc15_15.1, constants.%.5 [template = constants.%.5]
 // CHECK:STDOUT:   %Make.ref.loc15_20: <function> = name_ref Make, file.%Make [template = file.%Make]
@@ -62,8 +61,8 @@ fn Var() {
 // CHECK:STDOUT:   %.loc15_32.1: ref X = temporary_storage
 // CHECK:STDOUT:   %.loc15_32.2: init X = call %Make.ref.loc15_28() to %.loc15_32.1
 // CHECK:STDOUT:   %.loc15_34.1: (X, X) = tuple_literal (%.loc15_24.2, %.loc15_32.2)
-// CHECK:STDOUT:   %X.ref.loc15_40: type = name_ref X, file.%X [template = constants.%X]
-// CHECK:STDOUT:   %X.ref.loc15_43: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc15_40: type = name_ref X, constants.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc15_43: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc15_44.1: (type, type) = tuple_literal (%X.ref.loc15_40, %X.ref.loc15_43)
 // CHECK:STDOUT:   %.loc15_44.2: type = converted %.loc15_44.1, constants.%.5 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc15_24.3: ref X = temporary %.loc15_24.1, %.loc15_24.2
@@ -78,8 +77,8 @@ fn Var() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Var() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %X.ref.loc20_11: type = name_ref X, file.%X [template = constants.%X]
-// CHECK:STDOUT:   %X.ref.loc20_14: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc20_11: type = name_ref X, constants.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc20_14: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc20_15.1: (type, type) = tuple_literal (%X.ref.loc20_11, %X.ref.loc20_14)
 // CHECK:STDOUT:   %.loc20_15.2: type = converted %.loc20_15.1, constants.%.5 [template = constants.%.5]
 // CHECK:STDOUT:   %b.var: ref (X, X) = var b
@@ -91,8 +90,8 @@ fn Var() {
 // CHECK:STDOUT:   %.loc20_34.2: ref X = tuple_access %b.var, element1
 // CHECK:STDOUT:   %.loc20_32: init X = call %Make.ref.loc20_28() to %.loc20_34.2
 // CHECK:STDOUT:   %.loc20_34.3: (X, X) = tuple_literal (%.loc20_24, %.loc20_32)
-// CHECK:STDOUT:   %X.ref.loc20_40: type = name_ref X, file.%X [template = constants.%X]
-// CHECK:STDOUT:   %X.ref.loc20_43: type = name_ref X, file.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc20_40: type = name_ref X, constants.%X [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc20_43: type = name_ref X, constants.%X [template = constants.%X]
 // CHECK:STDOUT:   %.loc20_44.1: (type, type) = tuple_literal (%X.ref.loc20_40, %X.ref.loc20_43)
 // CHECK:STDOUT:   %.loc20_44.2: type = converted %.loc20_44.1, constants.%.5 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc20_34.4: init (X, X) = tuple_init (%.loc20_24, %.loc20_32) to %b.var

+ 9 - 0
toolchain/check/testdata/basics/builtin_insts.carbon

@@ -30,6 +30,15 @@
 // CHECK:STDOUT:     instNamespaceType: {kind: CrossRef, arg0: ir0, arg1: instNamespaceType, type: typeTypeType}
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: namePackageNamespace, arg1: name_scope0, type: type0}
 // CHECK:STDOUT:   constant_values:
+// CHECK:STDOUT:     instTypeType:    template instTypeType
+// CHECK:STDOUT:     instError:       template instError
+// CHECK:STDOUT:     instBoolType:    template instBoolType
+// CHECK:STDOUT:     instIntType:     template instIntType
+// CHECK:STDOUT:     instFloatType:   template instFloatType
+// CHECK:STDOUT:     instStringType:  template instStringType
+// CHECK:STDOUT:     instFunctionType: template instFunctionType
+// CHECK:STDOUT:     instBoundMethodType: template instBoundMethodType
+// CHECK:STDOUT:     instNamespaceType: template instNamespaceType
 // CHECK:STDOUT:     inst+0:          template inst+0
 // CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     empty:           {}

+ 1 - 1
toolchain/check/testdata/basics/fail_name_lookup.carbon

@@ -20,7 +20,7 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error>
+// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 0
toolchain/check/testdata/basics/raw_and_textual_ir.carbon

@@ -40,6 +40,10 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:       0:               type1
 // CHECK:STDOUT:       1:               type1
 // CHECK:STDOUT:       2:               type3
+// CHECK:STDOUT:     typeBlock2:
+// CHECK:STDOUT:       0:               type1
+// CHECK:STDOUT:       1:               type1
+// CHECK:STDOUT:       2:               type3
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: namePackageNamespace, arg1: name_scope0, type: type0}
 // CHECK:STDOUT:     inst+1:          {kind: Param, arg0: name1, type: type1}

+ 4 - 0
toolchain/check/testdata/basics/raw_ir.carbon

@@ -40,6 +40,10 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:       0:               type1
 // CHECK:STDOUT:       1:               type1
 // CHECK:STDOUT:       2:               type3
+// CHECK:STDOUT:     typeBlock2:
+// CHECK:STDOUT:       0:               type1
+// CHECK:STDOUT:       1:               type1
+// CHECK:STDOUT:       2:               type3
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: namePackageNamespace, arg1: name_scope0, type: type0}
 // CHECK:STDOUT:     inst+1:          {kind: Param, arg0: name1, type: type1}

+ 7 - 12
toolchain/check/testdata/class/base.carbon

@@ -47,32 +47,27 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
 // CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Base> = field_decl b, element0 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Base> = bind_name b, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl b, element0 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Base> = bind_name b, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .b = %b
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
-// CHECK:STDOUT:   %.loc12_20.1: type = unbound_element_type Derived, Base [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_20.2: <unbound element of class Derived> = base_decl Base, element0 [template]
-// CHECK:STDOUT:   %.loc14_8.1: type = unbound_element_type Derived, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc14_8.2: <unbound element of class Derived> = field_decl d, element1 [template]
-// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc14_8.2 [template = %.loc14_8.2]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
+// CHECK:STDOUT:   %.loc14: <unbound element of class Derived> = field_decl d, element1 [template]
+// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc14 [template = %.loc14]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_20.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .d = %d
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }

+ 13 - 21
toolchain/check/testdata/class/base_field.carbon

@@ -42,22 +42,17 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Derived = %Derived.decl, .Access = %Access} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Base> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Base> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Base> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
-// CHECK:STDOUT:   %.loc10_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc10_8.2: <unbound element of class Base> = field_decl c, element2 [template]
-// CHECK:STDOUT:   %c: <unbound element of class Base> = bind_name c, %.loc10_8.2 [template = %.loc10_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Base> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Base> = bind_name b, %.loc9 [template = %.loc9]
+// CHECK:STDOUT:   %.loc10: <unbound element of class Base> = field_decl c, element2 [template]
+// CHECK:STDOUT:   %c: <unbound element of class Base> = bind_name c, %.loc10 [template = %.loc10]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -66,18 +61,15 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
-// CHECK:STDOUT:   %.loc14_20.1: type = unbound_element_type Derived, Base [template = constants.%.4]
-// CHECK:STDOUT:   %.loc14_20.2: <unbound element of class Derived> = base_decl Base, element0 [template]
-// CHECK:STDOUT:   %.loc16_8.1: type = unbound_element_type Derived, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc16_8.2: <unbound element of class Derived> = field_decl d, element1 [template]
-// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc16_8.2 [template = %.loc16_8.2]
-// CHECK:STDOUT:   %.loc17_8.1: type = unbound_element_type Derived, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc17_8.2: <unbound element of class Derived> = field_decl e, element2 [template]
-// CHECK:STDOUT:   %e: <unbound element of class Derived> = bind_name e, %.loc17_8.2 [template = %.loc17_8.2]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %.loc14: <unbound element of class Derived> = base_decl Base, element0 [template]
+// CHECK:STDOUT:   %.loc16: <unbound element of class Derived> = field_decl d, element1 [template]
+// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc16 [template = %.loc16]
+// CHECK:STDOUT:   %.loc17: <unbound element of class Derived> = field_decl e, element2 [template]
+// CHECK:STDOUT:   %e: <unbound element of class Derived> = bind_name e, %.loc17 [template = %.loc17]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc14_20.2
+// CHECK:STDOUT:   .base = %.loc14
 // CHECK:STDOUT:   .d = %d
 // CHECK:STDOUT:   .e = %e
 // CHECK:STDOUT:   extend name_scope1

+ 3 - 6
toolchain/check/testdata/class/base_function_unqualified.carbon

@@ -34,9 +34,7 @@ fn Derived.H() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Derived = %Derived.decl} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -48,14 +46,13 @@ fn Derived.H() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
-// CHECK:STDOUT:   %.loc12_20.1: type = unbound_element_type Derived, Base [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_20.2: <unbound element of class Derived> = base_decl Base, element0 [template]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_20.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT:   .H = %H
 // CHECK:STDOUT:   extend name_scope1

+ 5 - 9
toolchain/check/testdata/class/base_method.carbon

@@ -43,17 +43,14 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Base> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -62,12 +59,11 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
-// CHECK:STDOUT:   %.loc18_20.1: type = unbound_element_type Derived, Base [template = constants.%.6]
-// CHECK:STDOUT:   %.loc18_20.2: <unbound element of class Derived> = base_decl Base, element0 [template]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %.loc18: <unbound element of class Derived> = base_decl Base, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc18_20.2
+// CHECK:STDOUT:   .base = %.loc18
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 9 - 16
toolchain/check/testdata/class/base_method_shadow.carbon

@@ -57,13 +57,9 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl, .B = %B.decl, .C = %C.decl, .D = %D.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   %A.decl = class_decl @A, ()
-// CHECK:STDOUT:   %A: type = class_type @A [template = constants.%A]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %D.decl = class_decl @D, ()
-// CHECK:STDOUT:   %D: type = class_type @D [template = constants.%D]
 // CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -75,36 +71,33 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
-// CHECK:STDOUT:   %.loc12_17.1: type = unbound_element_type B, A [template = constants.%.5]
-// CHECK:STDOUT:   %.loc12_17.2: <unbound element of class B> = base_decl A, element0 [template]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
+// CHECK:STDOUT:   %.loc12: <unbound element of class B> = base_decl A, element0 [template]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_17.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc17_17.1: type = unbound_element_type C, B [template = constants.%.10]
-// CHECK:STDOUT:   %.loc17_17.2: <unbound element of class C> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc17: <unbound element of class C> = base_decl B, element0 [template]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.3 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc17_17.2
+// CHECK:STDOUT:   .base = %.loc17
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @D {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc22_17.1: type = unbound_element_type D, B [template = constants.%.13]
-// CHECK:STDOUT:   %.loc22_17.2: <unbound element of class D> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc22: <unbound element of class D> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc22_17.2
+// CHECK:STDOUT:   .base = %.loc22
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 5
toolchain/check/testdata/class/basic.carbon

@@ -34,7 +34,6 @@ fn Run() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
 // CHECK:STDOUT: }
@@ -42,9 +41,8 @@ fn Run() -> i32 {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %.loc14_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc14_8.2: <unbound element of class Class> = field_decl k, element0 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc14_8.2 [template = %.loc14_8.2]
+// CHECK:STDOUT:   %.loc14: <unbound element of class Class> = field_decl k, element0 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc14 [template = %.loc14]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
@@ -66,7 +64,7 @@ fn Run() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %F.ref: <function> = name_ref F, @Class.%F [template = @Class.%F]
 // CHECK:STDOUT:   %.loc22_18: i32 = int_literal 4 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc22_17.1: init i32 = call %F.ref(%.loc22_18)

+ 16 - 24
toolchain/check/testdata/class/derived_to_base.carbon

@@ -68,11 +68,8 @@ fn ConvertInit() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl, .B = %B.decl, .C = %C.decl, .ConvertCToB = %ConvertCToB, .ConvertBToA = %ConvertBToA, .ConvertCToA = %ConvertCToA, .ConvertValue = %ConvertValue, .ConvertRef = %ConvertRef, .ConvertInit = %ConvertInit} [template]
 // CHECK:STDOUT:   %A.decl = class_decl @A, ()
-// CHECK:STDOUT:   %A: type = class_type @A [template = constants.%A]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %ConvertCToB: <function> = fn_decl @ConvertCToB [template]
 // CHECK:STDOUT:   %ConvertBToA: <function> = fn_decl @ConvertBToA [template]
 // CHECK:STDOUT:   %ConvertCToA: <function> = fn_decl @ConvertCToA [template]
@@ -82,38 +79,33 @@ fn ConvertInit() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type A, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class A> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class A> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class A> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class A> = bind_name a, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
-// CHECK:STDOUT:   %.loc12_17.1: type = unbound_element_type B, A [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_17.2: <unbound element of class B> = base_decl A, element0 [template]
-// CHECK:STDOUT:   %.loc13_8.1: type = unbound_element_type B, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc13_8.2: <unbound element of class B> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class B> = bind_name b, %.loc13_8.2 [template = %.loc13_8.2]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
+// CHECK:STDOUT:   %.loc12: <unbound element of class B> = base_decl A, element0 [template]
+// CHECK:STDOUT:   %.loc13: <unbound element of class B> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class B> = bind_name b, %.loc13 [template = %.loc13]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_17.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .b = %b
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc17_17.1: type = unbound_element_type C, B [template = constants.%.10]
-// CHECK:STDOUT:   %.loc17_17.2: <unbound element of class C> = base_decl B, element0 [template]
-// CHECK:STDOUT:   %.loc18_8.1: type = unbound_element_type C, i32 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc18_8.2: <unbound element of class C> = field_decl c, element1 [template]
-// CHECK:STDOUT:   %c: <unbound element of class C> = bind_name c, %.loc18_8.2 [template = %.loc18_8.2]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc17: <unbound element of class C> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %.loc18: <unbound element of class C> = field_decl c, element1 [template]
+// CHECK:STDOUT:   %c: <unbound element of class C> = bind_name c, %.loc18 [template = %.loc18]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc17_17.2
+// CHECK:STDOUT:   .base = %.loc17
 // CHECK:STDOUT:   .c = %c
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }
@@ -151,7 +143,7 @@ fn ConvertInit() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @ConvertValue(%c: C) {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
 // CHECK:STDOUT:   %c.ref: C = name_ref c, %c
 // CHECK:STDOUT:   %.loc26_15.1: ref B = class_element_access %c.ref, element0
 // CHECK:STDOUT:   %.loc26_15.2: ref A = class_element_access %.loc26_15.1, element0
@@ -165,7 +157,7 @@ fn ConvertInit() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %c.ref: C* = name_ref c, %c
 // CHECK:STDOUT:   %.loc30_12.1: ref C = deref %c.ref
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
 // CHECK:STDOUT:   %.loc30_15.1: ref B = class_element_access %.loc30_12.1, element0
 // CHECK:STDOUT:   %.loc30_15.2: ref A = class_element_access %.loc30_15.1, element0
 // CHECK:STDOUT:   %.loc30_12.2: ref A = converted %.loc30_12.1, %.loc30_15.2
@@ -175,14 +167,14 @@ fn ConvertInit() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @ConvertInit() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
 // CHECK:STDOUT:   %.loc34_38: i32 = int_literal 1 [template = constants.%.19]
 // CHECK:STDOUT:   %.loc34_39.1: {.a: i32} = struct_literal (%.loc34_38)
 // CHECK:STDOUT:   %.loc34_47: i32 = int_literal 2 [template = constants.%.20]
 // CHECK:STDOUT:   %.loc34_48.1: {.base: {.a: i32}, .b: i32} = struct_literal (%.loc34_39.1, %.loc34_47)
 // CHECK:STDOUT:   %.loc34_56: i32 = int_literal 3 [template = constants.%.22]
 // CHECK:STDOUT:   %.loc34_57.1: {.base: {.base: {.a: i32}, .b: i32}, .c: i32} = struct_literal (%.loc34_48.1, %.loc34_56)
-// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C [template = constants.%C]
+// CHECK:STDOUT:   %C.ref: type = name_ref C, constants.%C [template = constants.%C]
 // CHECK:STDOUT:   %.loc34_57.2: ref C = temporary_storage
 // CHECK:STDOUT:   %.loc34_57.3: ref B = class_element_access %.loc34_57.2, element0
 // CHECK:STDOUT:   %.loc34_48.2: ref A = class_element_access %.loc34_57.3, element0

+ 7 - 12
toolchain/check/testdata/class/fail_abstract.carbon

@@ -51,32 +51,27 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Abstract = %Abstract.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
 // CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract, ()
-// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [template = constants.%Abstract]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
 // CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Abstract {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Abstract, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Abstract> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Abstract> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Abstract> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Abstract> = bind_name a, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract [template = constants.%Abstract]
-// CHECK:STDOUT:   %.loc12_24.1: type = unbound_element_type Derived, Abstract [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_24.2: <unbound element of class Derived> = base_decl Abstract, element0 [template]
-// CHECK:STDOUT:   %.loc14_8.1: type = unbound_element_type Derived, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc14_8.2: <unbound element of class Derived> = field_decl d, element1 [template]
-// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc14_8.2 [template = %.loc14_8.2]
+// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, constants.%Abstract [template = constants.%Abstract]
+// CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Abstract, element0 [template]
+// CHECK:STDOUT:   %.loc14: <unbound element of class Derived> = field_decl d, element1 [template]
+// CHECK:STDOUT:   %d: <unbound element of class Derived> = bind_name d, %.loc14 [template = %.loc14]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_24.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .d = %d
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }

+ 0 - 1
toolchain/check/testdata/class/fail_addr_not_self.carbon

@@ -27,7 +27,6 @@ class Class {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {

+ 0 - 1
toolchain/check/testdata/class/fail_addr_self.carbon

@@ -51,7 +51,6 @@ fn F(c: Class, p: Class*) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 27 - 45
toolchain/check/testdata/class/fail_base_bad_type.carbon

@@ -170,35 +170,25 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Final = %Final.decl, .DeriveFromError = %DeriveFromError.decl, .AccessMemberWithInvalidBaseError = %AccessMemberWithInvalidBaseError, .DeriveFromNonType = %DeriveFromNonType.decl, .AccessMemberWithInvalidBasNonType = %AccessMemberWithInvalidBasNonType, .DeriveFromi32 = %DeriveFromi32.decl, .ConvertToBadBasei32 = %ConvertToBadBasei32, .AccessMemberWithInvalidBasei32 = %AccessMemberWithInvalidBasei32, .DeriveFromTuple = %DeriveFromTuple.decl, .ConvertToBadBaseTuple = %ConvertToBadBaseTuple, .AccessMemberWithInvalidBaseTuple = %AccessMemberWithInvalidBaseTuple, .DeriveFromStruct = %DeriveFromStruct.decl, .ConvertToBadBaseStruct = %ConvertToBadBaseStruct, .AccessMemberWithInvalidBaseStruct = %AccessMemberWithInvalidBaseStruct, .Incomplete = %Incomplete.decl, .DeriveFromIncomplete = %DeriveFromIncomplete.decl, .ConvertToBadBaseIncomplete = %ConvertToBadBaseIncomplete, .AccessMemberWithInvalidBaseIncomplete = %AccessMemberWithInvalidBaseIncomplete, .DeriveFromFinal = %DeriveFromFinal.decl, .ConvertToBadBaseFinal = %ConvertToBadBaseFinal, .AccessMemberWithInvalidBaseFinal_WithMember = %AccessMemberWithInvalidBaseFinal_WithMember, .AccessMemberWithInvalidBaseFinal_NoMember = %AccessMemberWithInvalidBaseFinal_NoMember} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Final.decl = class_decl @Final, ()
-// CHECK:STDOUT:   %Final: type = class_type @Final [template = constants.%Final]
 // CHECK:STDOUT:   %DeriveFromError.decl = class_decl @DeriveFromError, ()
-// CHECK:STDOUT:   %DeriveFromError: type = class_type @DeriveFromError [template = constants.%DeriveFromError]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseError: <function> = fn_decl @AccessMemberWithInvalidBaseError [template]
 // CHECK:STDOUT:   %DeriveFromNonType.decl = class_decl @DeriveFromNonType, ()
-// CHECK:STDOUT:   %DeriveFromNonType: type = class_type @DeriveFromNonType [template = constants.%DeriveFromNonType]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBasNonType: <function> = fn_decl @AccessMemberWithInvalidBasNonType [template]
 // CHECK:STDOUT:   %DeriveFromi32.decl = class_decl @DeriveFromi32, ()
-// CHECK:STDOUT:   %DeriveFromi32: type = class_type @DeriveFromi32 [template = constants.%DeriveFromi32]
 // CHECK:STDOUT:   %ConvertToBadBasei32: <function> = fn_decl @ConvertToBadBasei32 [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBasei32: <function> = fn_decl @AccessMemberWithInvalidBasei32 [template]
 // CHECK:STDOUT:   %DeriveFromTuple.decl = class_decl @DeriveFromTuple, ()
-// CHECK:STDOUT:   %DeriveFromTuple: type = class_type @DeriveFromTuple [template = constants.%DeriveFromTuple]
 // CHECK:STDOUT:   %ConvertToBadBaseTuple: <function> = fn_decl @ConvertToBadBaseTuple [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseTuple: <function> = fn_decl @AccessMemberWithInvalidBaseTuple [template]
 // CHECK:STDOUT:   %DeriveFromStruct.decl = class_decl @DeriveFromStruct, ()
-// CHECK:STDOUT:   %DeriveFromStruct: type = class_type @DeriveFromStruct [template = constants.%DeriveFromStruct]
 // CHECK:STDOUT:   %ConvertToBadBaseStruct: <function> = fn_decl @ConvertToBadBaseStruct [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseStruct: <function> = fn_decl @AccessMemberWithInvalidBaseStruct [template]
 // CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, ()
-// CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template = constants.%Incomplete]
 // CHECK:STDOUT:   %DeriveFromIncomplete.decl = class_decl @DeriveFromIncomplete, ()
-// CHECK:STDOUT:   %DeriveFromIncomplete: type = class_type @DeriveFromIncomplete [template = constants.%DeriveFromIncomplete]
 // CHECK:STDOUT:   %ConvertToBadBaseIncomplete: <function> = fn_decl @ConvertToBadBaseIncomplete [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseIncomplete: <function> = fn_decl @AccessMemberWithInvalidBaseIncomplete [template]
 // CHECK:STDOUT:   %DeriveFromFinal.decl = class_decl @DeriveFromFinal, ()
-// CHECK:STDOUT:   %DeriveFromFinal: type = class_type @DeriveFromFinal [template = constants.%DeriveFromFinal]
 // CHECK:STDOUT:   %ConvertToBadBaseFinal: <function> = fn_decl @ConvertToBadBaseFinal [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_WithMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember [template]
 // CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_NoMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember [template]
@@ -210,84 +200,76 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Final {
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Final, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Final> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Final> = bind_name a, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Final> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Final> = bind_name a, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromError {
-// CHECK:STDOUT:   %error.ref: <error> = name_ref error, <error>
-// CHECK:STDOUT:   %.loc16_21.1: type = unbound_element_type DeriveFromError, <error> [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_21.2: <unbound element of class DeriveFromError> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %error.ref: <error> = name_ref error, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc16: <unbound element of class DeriveFromError> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc16_21.2
+// CHECK:STDOUT:   .base = %.loc16
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromNonType {
 // CHECK:STDOUT:   %.loc26_16: i32 = int_literal 32 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc26_18.1: type = unbound_element_type DeriveFromNonType, <error> [template = constants.%.9]
-// CHECK:STDOUT:   %.loc26_18.2: <unbound element of class DeriveFromNonType> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %.loc26_18: <unbound element of class DeriveFromNonType> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc26_18.2
+// CHECK:STDOUT:   .base = %.loc26_18
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromi32 {
-// CHECK:STDOUT:   %.loc35_19.1: type = unbound_element_type DeriveFromi32, <error> [template = constants.%.11]
-// CHECK:STDOUT:   %.loc35_19.2: <unbound element of class DeriveFromi32> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %.loc35: <unbound element of class DeriveFromi32> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc35_19.2
+// CHECK:STDOUT:   .base = %.loc35
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromTuple {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
 // CHECK:STDOUT:   %.loc51_22.1: (type,) = tuple_literal (%Base.ref)
 // CHECK:STDOUT:   %.loc51_22.2: type = converted %.loc51_22.1, constants.%.15 [template = constants.%.15]
-// CHECK:STDOUT:   %.loc51_23.1: type = unbound_element_type DeriveFromTuple, <error> [template = constants.%.19]
-// CHECK:STDOUT:   %.loc51_23.2: <unbound element of class DeriveFromTuple> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %.loc51_23: <unbound element of class DeriveFromTuple> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc51_23.2
+// CHECK:STDOUT:   .base = %.loc51_23
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromStruct {
 // CHECK:STDOUT:   %.loc67_33: type = struct_type {.a: i32, .b: i32} [template = constants.%.22]
-// CHECK:STDOUT:   %.loc67_34.1: type = unbound_element_type DeriveFromStruct, <error> [template = constants.%.24]
-// CHECK:STDOUT:   %.loc67_34.2: <unbound element of class DeriveFromStruct> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %.loc67_34: <unbound element of class DeriveFromStruct> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc67_34.2
+// CHECK:STDOUT:   .base = %.loc67_34
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Incomplete;
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromIncomplete {
-// CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete [template = constants.%Incomplete]
-// CHECK:STDOUT:   %.loc87_26.1: type = unbound_element_type DeriveFromIncomplete, <error> [template = constants.%.26]
-// CHECK:STDOUT:   %.loc87_26.2: <unbound element of class DeriveFromIncomplete> = base_decl <error>, element0 [template]
+// CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, constants.%Incomplete [template = constants.%Incomplete]
+// CHECK:STDOUT:   %.loc87: <unbound element of class DeriveFromIncomplete> = base_decl <error>, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc87_26.2
+// CHECK:STDOUT:   .base = %.loc87
 // CHECK:STDOUT:   has_error
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DeriveFromFinal {
-// CHECK:STDOUT:   %Final.ref: type = name_ref Final, file.%Final [template = constants.%Final]
-// CHECK:STDOUT:   %.loc101_21.1: type = unbound_element_type DeriveFromFinal, Final [template = constants.%.30]
-// CHECK:STDOUT:   %.loc101_21.2: <unbound element of class DeriveFromFinal> = base_decl Final, element0 [template]
+// CHECK:STDOUT:   %Final.ref: type = name_ref Final, constants.%Final [template = constants.%Final]
+// CHECK:STDOUT:   %.loc101: <unbound element of class DeriveFromFinal> = base_decl Final, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc101_21.2
+// CHECK:STDOUT:   .base = %.loc101
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -295,7 +277,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromError* = name_ref p, %p
 // CHECK:STDOUT:   %.loc20: ref DeriveFromError = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -303,7 +285,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromNonType* = name_ref p, %p
 // CHECK:STDOUT:   %.loc29: ref DeriveFromNonType = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -317,7 +299,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromi32* = name_ref p, %p
 // CHECK:STDOUT:   %.loc45: ref DeriveFromi32 = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -331,7 +313,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromTuple* = name_ref p, %p
 // CHECK:STDOUT:   %.loc59: ref DeriveFromTuple = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -345,7 +327,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromStruct* = name_ref p, %p
 // CHECK:STDOUT:   %.loc76: ref DeriveFromStruct = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -359,7 +341,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromIncomplete* = name_ref p, %p
 // CHECK:STDOUT:   %.loc95: ref DeriveFromIncomplete = deref %p.ref
-// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -388,7 +370,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: DeriveFromFinal* = name_ref p, %p
 // CHECK:STDOUT:   %.loc117: ref DeriveFromFinal = deref %p.ref
-// CHECK:STDOUT:   %b.ref: <error> = name_ref b, <error>
+// CHECK:STDOUT:   %b.ref: <error> = name_ref b, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 7
toolchain/check/testdata/class/fail_base_method_define.carbon

@@ -42,9 +42,7 @@ fn D.C.F() {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B = %B.decl, .D = %D.decl} [template]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %D.decl = class_decl @D, ()
-// CHECK:STDOUT:   %D: type = class_type @D [template = constants.%D]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.3 [template]
 // CHECK:STDOUT:   %.loc27: <function> = fn_decl @.1 [template]
 // CHECK:STDOUT: }
@@ -52,7 +50,6 @@ fn D.C.F() {}
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
@@ -67,12 +64,11 @@ fn D.C.F() {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @D {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc16_17.1: type = unbound_element_type D, B [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_17.2: <unbound element of class D> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc16: <unbound element of class D> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc16_17.2
+// CHECK:STDOUT:   .base = %.loc16
 // CHECK:STDOUT:   .F = file.%F
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }

+ 12 - 21
toolchain/check/testdata/class/fail_base_modifiers.carbon

@@ -64,15 +64,10 @@ class C4 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B = %B.decl, .C1 = %C1.decl, .C2 = %C2.decl, .C3 = %C3.decl, .C4 = %C4.decl} [template]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C1.decl = class_decl @C1, ()
-// CHECK:STDOUT:   %C1: type = class_type @C1 [template = constants.%C1]
 // CHECK:STDOUT:   %C2.decl = class_decl @C2, ()
-// CHECK:STDOUT:   %C2: type = class_type @C2 [template = constants.%C2]
 // CHECK:STDOUT:   %C3.decl = class_decl @C3, ()
-// CHECK:STDOUT:   %C3: type = class_type @C3 [template = constants.%C3]
 // CHECK:STDOUT:   %C4.decl = class_decl @C4, ()
-// CHECK:STDOUT:   %C4: type = class_type @C4 [template = constants.%C4]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
@@ -81,41 +76,37 @@ class C4 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C1 {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc13_25.1: type = unbound_element_type C1, B [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_25.2: <unbound element of class C1> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc13: <unbound element of class C1> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc13_25.2
+// CHECK:STDOUT:   .base = %.loc13
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C2 {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc23_19.1: type = unbound_element_type C2, B [template = constants.%.6]
-// CHECK:STDOUT:   %.loc23_19.2: <unbound element of class C2> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc23: <unbound element of class C2> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc23_19.2
+// CHECK:STDOUT:   .base = %.loc23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C3 {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc33_25.1: type = unbound_element_type C3, B [template = constants.%.7]
-// CHECK:STDOUT:   %.loc33_25.2: <unbound element of class C3> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc33: <unbound element of class C3> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc33_25.2
+// CHECK:STDOUT:   .base = %.loc33
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C4 {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc43_24.1: type = unbound_element_type C4, B [template = constants.%.8]
-// CHECK:STDOUT:   %.loc43_24.2: <unbound element of class C4> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc43: <unbound element of class C4> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc43_24.2
+// CHECK:STDOUT:   .base = %.loc43
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 6
toolchain/check/testdata/class/fail_base_no_extend.carbon

@@ -28,9 +28,7 @@ class C {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B = %B.decl, .C = %C.decl} [template]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
@@ -39,11 +37,10 @@ class C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc13_10.1: type = unbound_element_type C, B [template = constants.%.4]
-// CHECK:STDOUT:   %.loc13_10.2: <unbound element of class C> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc13: <unbound element of class C> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc13_10.2
+// CHECK:STDOUT:   .base = %.loc13
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 8 - 14
toolchain/check/testdata/class/fail_base_repeated.carbon

@@ -48,13 +48,9 @@ class D {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B1 = %B1.decl, .B2 = %B2.decl, .C = %C.decl, .D = %D.decl} [template]
 // CHECK:STDOUT:   %B1.decl = class_decl @B1, ()
-// CHECK:STDOUT:   %B1: type = class_type @B1 [template = constants.%B1]
 // CHECK:STDOUT:   %B2.decl = class_decl @B2, ()
-// CHECK:STDOUT:   %B2: type = class_type @B2 [template = constants.%B2]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %D.decl = class_decl @D, ()
-// CHECK:STDOUT:   %D: type = class_type @D [template = constants.%D]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B1 {
@@ -68,24 +64,22 @@ class D {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %B1.ref: type = name_ref B1, file.%B1 [template = constants.%B1]
-// CHECK:STDOUT:   %.loc11_18.1: type = unbound_element_type C, B1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc11_18.2: <unbound element of class C> = base_decl B1, element0 [template]
-// CHECK:STDOUT:   %B2.ref: type = name_ref B2, file.%B2 [template = constants.%B2]
+// CHECK:STDOUT:   %B1.ref: type = name_ref B1, constants.%B1 [template = constants.%B1]
+// CHECK:STDOUT:   %.loc11: <unbound element of class C> = base_decl B1, element0 [template]
+// CHECK:STDOUT:   %B2.ref: type = name_ref B2, constants.%B2 [template = constants.%B2]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc11_18.2
+// CHECK:STDOUT:   .base = %.loc11
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @D {
-// CHECK:STDOUT:   %B1.ref.loc23: type = name_ref B1, file.%B1 [template = constants.%B1]
-// CHECK:STDOUT:   %.loc23_18.1: type = unbound_element_type D, B1 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc23_18.2: <unbound element of class D> = base_decl B1, element0 [template]
-// CHECK:STDOUT:   %B1.ref.loc30: type = name_ref B1, file.%B1 [template = constants.%B1]
+// CHECK:STDOUT:   %B1.ref.loc23: type = name_ref B1, constants.%B1 [template = constants.%B1]
+// CHECK:STDOUT:   %.loc23: <unbound element of class D> = base_decl B1, element0 [template]
+// CHECK:STDOUT:   %B1.ref.loc30: type = name_ref B1, constants.%B1 [template = constants.%B1]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc23_18.2
+// CHECK:STDOUT:   .base = %.loc23
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 7 - 10
toolchain/check/testdata/class/fail_base_unbound.carbon

@@ -30,13 +30,11 @@ let b: B = C.base;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.B = %B.decl, .C = %C.decl} [template]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
-// CHECK:STDOUT:   %B.ref: type = name_ref B, %B [template = constants.%B]
-// CHECK:STDOUT:   %C.ref: type = name_ref C, %C [template = constants.%C]
-// CHECK:STDOUT:   %base.ref: <unbound element of class C> = name_ref base, @C.%.loc10_17.2 [template = @C.%.loc10_17.2]
-// CHECK:STDOUT:   %b: B = bind_name b, <error>
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %C.ref: type = name_ref C, constants.%C [template = constants.%C]
+// CHECK:STDOUT:   %base.ref: <unbound element of class C> = name_ref base, @C.%.loc10 [template = @C.%.loc10]
+// CHECK:STDOUT:   %b: B = bind_name b, <error> [template = <error>]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
@@ -45,12 +43,11 @@ let b: B = C.base;
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B [template = constants.%B]
-// CHECK:STDOUT:   %.loc10_17.1: type = unbound_element_type C, B [template = constants.%.4]
-// CHECK:STDOUT:   %.loc10_17.2: <unbound element of class C> = base_decl B, element0 [template]
+// CHECK:STDOUT:   %B.ref: type = name_ref B, constants.%B [template = constants.%B]
+// CHECK:STDOUT:   %.loc10: <unbound element of class C> = base_decl B, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc10_17.2
+// CHECK:STDOUT:   .base = %.loc10
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 9 - 17
toolchain/check/testdata/class/fail_derived_to_base.carbon

@@ -55,45 +55,37 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A1 = %A1.decl, .A2 = %A2.decl, .B2 = %B2.decl, .ConvertUnrelated = %ConvertUnrelated, .Incomplete = %Incomplete.decl, .ConvertIncomplete = %ConvertIncomplete} [template]
 // CHECK:STDOUT:   %A1.decl = class_decl @A1, ()
-// CHECK:STDOUT:   %A1: type = class_type @A1 [template = constants.%A1]
 // CHECK:STDOUT:   %A2.decl = class_decl @A2, ()
-// CHECK:STDOUT:   %A2: type = class_type @A2 [template = constants.%A2]
 // CHECK:STDOUT:   %B2.decl = class_decl @B2, ()
-// CHECK:STDOUT:   %B2: type = class_type @B2 [template = constants.%B2]
 // CHECK:STDOUT:   %ConvertUnrelated: <function> = fn_decl @ConvertUnrelated [template]
 // CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, ()
-// CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template = constants.%Incomplete]
 // CHECK:STDOUT:   %ConvertIncomplete: <function> = fn_decl @ConvertIncomplete [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A1 {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type A1, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class A1> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class A1> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class A1> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class A1> = bind_name a, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A2 {
-// CHECK:STDOUT:   %.loc12_8.1: type = unbound_element_type A2, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc12_8.2: <unbound element of class A2> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class A2> = bind_name a, %.loc12_8.2 [template = %.loc12_8.2]
+// CHECK:STDOUT:   %.loc12: <unbound element of class A2> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class A2> = bind_name a, %.loc12 [template = %.loc12]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B2 {
-// CHECK:STDOUT:   %A2.ref: type = name_ref A2, file.%A2 [template = constants.%A2]
-// CHECK:STDOUT:   %.loc16_18.1: type = unbound_element_type B2, A2 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc16_18.2: <unbound element of class B2> = base_decl A2, element0 [template]
-// CHECK:STDOUT:   %.loc17_8.1: type = unbound_element_type B2, i32 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc17_8.2: <unbound element of class B2> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class B2> = bind_name b, %.loc17_8.2 [template = %.loc17_8.2]
+// CHECK:STDOUT:   %A2.ref: type = name_ref A2, constants.%A2 [template = constants.%A2]
+// CHECK:STDOUT:   %.loc16: <unbound element of class B2> = base_decl A2, element0 [template]
+// CHECK:STDOUT:   %.loc17: <unbound element of class B2> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class B2> = bind_name b, %.loc17 [template = %.loc17]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc16_18.2
+// CHECK:STDOUT:   .base = %.loc16
 // CHECK:STDOUT:   .b = %b
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }

+ 4 - 7
toolchain/check/testdata/class/fail_field_modifiers.carbon

@@ -40,16 +40,13 @@ class Class {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc12_16.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc12_16.2: <unbound element of class Class> = field_decl j, element0 [template]
-// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc12_16.2 [template = %.loc12_16.2]
-// CHECK:STDOUT:   %.loc17_14.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc17_14.2: <unbound element of class Class> = field_decl k, element1 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc17_14.2 [template = %.loc17_14.2]
+// CHECK:STDOUT:   %.loc12: <unbound element of class Class> = field_decl j, element0 [template]
+// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc12 [template = %.loc12]
+// CHECK:STDOUT:   %.loc17: <unbound element of class Class> = field_decl k, element1 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc17 [template = %.loc17]
 // CHECK:STDOUT:   %.loc22: i32 = int_literal 0 [template = constants.%.2]
 // CHECK:STDOUT:   %l: i32 = bind_name l, %.loc22 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc27: i32 = int_literal 1 [template = constants.%.3]

+ 5 - 6
toolchain/check/testdata/class/fail_incomplete.carbon

@@ -127,10 +127,9 @@ fn CallReturnIncomplete() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .CallClassFunction = %CallClassFunction, .global_var = %global_var, .ConvertFromStruct = %ConvertFromStruct, .MemberAccess = %MemberAccess, .Copy = %Copy, .Let = %Let, .TakeIncomplete = %TakeIncomplete, .ReturnIncomplete = %ReturnIncomplete, .CallTakeIncomplete = %CallTakeIncomplete, .CallReturnIncomplete = %CallReturnIncomplete} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc15: <function> = fn_decl @.1 [template]
 // CHECK:STDOUT:   %CallClassFunction: <function> = fn_decl @CallClassFunction [template]
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %global_var.var: ref <error> = var global_var
 // CHECK:STDOUT:   %global_var: ref <error> = bind_name global_var, %global_var.var
 // CHECK:STDOUT:   %ConvertFromStruct: <function> = fn_decl @ConvertFromStruct [template]
@@ -152,8 +151,8 @@ fn CallReturnIncomplete() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @CallClassFunction() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
-// CHECK:STDOUT:   %Function.ref: <error> = name_ref Function, <error>
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Function.ref: <error> = name_ref Function, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -179,10 +178,10 @@ fn CallReturnIncomplete() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Let(%p: Class*) {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %p.ref: Class* = name_ref p, %p
 // CHECK:STDOUT:   %.loc75: ref Class = deref %p.ref
-// CHECK:STDOUT:   %c: <error> = bind_name c, <error>
+// CHECK:STDOUT:   %c: <error> = bind_name c, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 13 - 16
toolchain/check/testdata/class/fail_init.carbon

@@ -42,17 +42,14 @@ fn F() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Class> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -63,27 +60,27 @@ fn F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc16_9: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc16_10.1: {.a: i32} = struct_literal (%.loc16_9)
-// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc16_10.2: ref Class = temporary_storage
-// CHECK:STDOUT:   %.loc16_10.3: ref Class = temporary %.loc16_10.2, <error>
-// CHECK:STDOUT:   %.loc16_10.4: ref Class = converted %.loc16_10.1, %.loc16_10.3
+// CHECK:STDOUT:   %.loc16_10.3: ref Class = temporary %.loc16_10.2, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc16_10.4: ref Class = converted %.loc16_10.1, %.loc16_10.3 [template = <error>]
 // CHECK:STDOUT:   %.loc20_9: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc20_17: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc20_18.1: {.a: i32, .c: i32} = struct_literal (%.loc20_9, %.loc20_17)
-// CHECK:STDOUT:   %Class.ref.loc20: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc20: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc20_18.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc20_18.3: ref i32 = class_element_access %.loc20_18.2, element0
 // CHECK:STDOUT:   %.loc20_18.4: init i32 = initialize_from %.loc20_9 to %.loc20_18.3
-// CHECK:STDOUT:   %.loc20_18.5: ref Class = temporary %.loc20_18.2, <error>
-// CHECK:STDOUT:   %.loc20_18.6: ref Class = converted %.loc20_18.1, %.loc20_18.5
+// CHECK:STDOUT:   %.loc20_18.5: ref Class = temporary %.loc20_18.2, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc20_18.6: ref Class = converted %.loc20_18.1, %.loc20_18.5 [template = <error>]
 // CHECK:STDOUT:   %.loc24_9: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc24_17: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc24_25: i32 = int_literal 3 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc24_26.1: {.a: i32, .b: i32, .c: i32} = struct_literal (%.loc24_9, %.loc24_17, %.loc24_25)
-// CHECK:STDOUT:   %Class.ref.loc24: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc24: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc24_26.2: ref Class = temporary_storage
-// CHECK:STDOUT:   %.loc24_26.3: ref Class = temporary %.loc24_26.2, <error>
-// CHECK:STDOUT:   %.loc24_26.4: ref Class = converted %.loc24_26.1, %.loc24_26.3
+// CHECK:STDOUT:   %.loc24_26.3: ref Class = temporary %.loc24_26.2, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc24_26.4: ref Class = converted %.loc24_26.1, %.loc24_26.3 [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 6 - 9
toolchain/check/testdata/class/fail_init_as_inplace.carbon

@@ -38,18 +38,15 @@ fn F() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .G = %G, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Class> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -60,13 +57,13 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref.loc21_10: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc21_10: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %c.var: ref Class = var c
 // CHECK:STDOUT:   %c: ref Class = bind_name c, %c.var
 // CHECK:STDOUT:   %.loc21_24: i32 = int_literal 1 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc21_32: i32 = int_literal 2 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc21_33.1: {.a: i32, .b: i32} = struct_literal (%.loc21_24, %.loc21_32)
-// CHECK:STDOUT:   %Class.ref.loc21_38: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc21_38: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc21_33.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc21_33.3: ref i32 = class_element_access %.loc21_33.2, element0
 // CHECK:STDOUT:   %.loc21_33.4: init i32 = initialize_from %.loc21_24 to %.loc21_33.3

+ 5 - 9
toolchain/check/testdata/class/fail_memaccess_category.carbon

@@ -44,17 +44,14 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT:   %.4: type = ptr_type {} [template]
 // CHECK:STDOUT:   %.5: type = unbound_element_type B, A [template]
 // CHECK:STDOUT:   %.6: type = struct_type {.a: A} [template]
-// CHECK:STDOUT:   %.7: type = struct_type {.a: A} [template]
-// CHECK:STDOUT:   %.8: type = struct_type {.a: {}*} [template]
-// CHECK:STDOUT:   %.9: type = ptr_type {.a: A} [template]
+// CHECK:STDOUT:   %.7: type = struct_type {.a: {}*} [template]
+// CHECK:STDOUT:   %.8: type = ptr_type {.a: A} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl, .B = %B.decl, .F = %F} [template]
 // CHECK:STDOUT:   %A.decl = class_decl @A, ()
-// CHECK:STDOUT:   %A: type = class_type @A [template = constants.%A]
 // CHECK:STDOUT:   %B.decl = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -66,10 +63,9 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A [template = constants.%A]
-// CHECK:STDOUT:   %.loc12_8.1: type = unbound_element_type B, A [template = constants.%.5]
-// CHECK:STDOUT:   %.loc12_8.2: <unbound element of class B> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class B> = bind_name a, %.loc12_8.2 [template = %.loc12_8.2]
+// CHECK:STDOUT:   %A.ref: type = name_ref A, constants.%A [template = constants.%A]
+// CHECK:STDOUT:   %.loc12: <unbound element of class B> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class B> = bind_name a, %.loc12 [template = %.loc12]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a

+ 1 - 2
toolchain/check/testdata/class/fail_member_of_let.carbon

@@ -28,8 +28,7 @@ fn T.F() {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %T: type = bind_name T, %Class.ref [template = constants.%Class]
 // CHECK:STDOUT:   %.loc19: <function> = fn_decl @.1 [template]
 // CHECK:STDOUT: }

+ 3 - 4
toolchain/check/testdata/class/fail_method.carbon

@@ -42,7 +42,6 @@ fn F(c: Class) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -67,13 +66,13 @@ fn F(c: Class) {
 // CHECK:STDOUT:   %c.ref.loc14: Class = name_ref c, %c
 // CHECK:STDOUT:   %.loc14_4: <bound method> = bound_method %c.ref.loc14, @Class.%WithSelf
 // CHECK:STDOUT:   %.loc14_13: init () = call %.loc14_4(%c.ref.loc14)
-// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %NoSelf.ref.loc16: <function> = name_ref NoSelf, @Class.%NoSelf [template = @Class.%NoSelf]
 // CHECK:STDOUT:   %.loc16: init () = call %NoSelf.ref.loc16()
-// CHECK:STDOUT:   %Class.ref.loc23: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc23: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %WithSelf.ref.loc23: <function> = name_ref WithSelf, @Class.%WithSelf [template = @Class.%WithSelf]
 // CHECK:STDOUT:   %.loc23: init () = call %WithSelf.ref.loc23(<invalid>)
-// CHECK:STDOUT:   %Class.ref.loc30: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc30: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %WithSelf.ref.loc30: <function> = name_ref WithSelf, @Class.%WithSelf [template = @Class.%WithSelf]
 // CHECK:STDOUT:   %c.ref.loc30: Class = name_ref c, %c
 // CHECK:STDOUT:   %.loc30: init () = call %WithSelf.ref.loc30(<invalid>)

+ 0 - 3
toolchain/check/testdata/class/fail_method_modifiers.carbon

@@ -59,11 +59,8 @@ base class BaseClass {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.FinalClass = %FinalClass.decl, .AbstractClass = %AbstractClass.decl, .BaseClass = %BaseClass.decl} [template]
 // CHECK:STDOUT:   %FinalClass.decl = class_decl @FinalClass, ()
-// CHECK:STDOUT:   %FinalClass: type = class_type @FinalClass [template = constants.%FinalClass]
 // CHECK:STDOUT:   %AbstractClass.decl = class_decl @AbstractClass, ()
-// CHECK:STDOUT:   %AbstractClass: type = class_type @AbstractClass [template = constants.%AbstractClass]
 // CHECK:STDOUT:   %BaseClass.decl = class_decl @BaseClass, ()
-// CHECK:STDOUT:   %BaseClass: type = class_type @BaseClass [template = constants.%BaseClass]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @FinalClass {

+ 0 - 6
toolchain/check/testdata/class/fail_modifiers.carbon

@@ -79,17 +79,11 @@ abstract base class AbstractAndBase {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.DuplicatePrivate = %DuplicatePrivate.decl, .TwoAccess = %TwoAccess.decl, .TwoAbstract = %TwoAbstract.decl, .Virtual = %Virtual.decl, .WrongOrder = %WrongOrder.decl, .AbstractAndBase = %AbstractAndBase.decl} [template]
 // CHECK:STDOUT:   %DuplicatePrivate.decl = class_decl @DuplicatePrivate, ()
-// CHECK:STDOUT:   %DuplicatePrivate: type = class_type @DuplicatePrivate [template = constants.%DuplicatePrivate]
 // CHECK:STDOUT:   %TwoAccess.decl = class_decl @TwoAccess, ()
-// CHECK:STDOUT:   %TwoAccess: type = class_type @TwoAccess [template = constants.%TwoAccess]
 // CHECK:STDOUT:   %TwoAbstract.decl = class_decl @TwoAbstract, ()
-// CHECK:STDOUT:   %TwoAbstract: type = class_type @TwoAbstract [template = constants.%TwoAbstract]
 // CHECK:STDOUT:   %Virtual.decl = class_decl @Virtual, ()
-// CHECK:STDOUT:   %Virtual: type = class_type @Virtual [template = constants.%Virtual]
 // CHECK:STDOUT:   %WrongOrder.decl = class_decl @WrongOrder, ()
-// CHECK:STDOUT:   %WrongOrder: type = class_type @WrongOrder [template = constants.%WrongOrder]
 // CHECK:STDOUT:   %AbstractAndBase.decl = class_decl @AbstractAndBase, ()
-// CHECK:STDOUT:   %AbstractAndBase: type = class_type @AbstractAndBase [template = constants.%AbstractAndBase]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DuplicatePrivate;

+ 0 - 1
toolchain/check/testdata/class/fail_out_of_line_decl.carbon

@@ -21,7 +21,6 @@ fn C.F() {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.C = %C.decl} [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 0 - 7
toolchain/check/testdata/class/fail_redeclaration_introducer.carbon

@@ -90,25 +90,18 @@ base class G;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl.loc7, .B = %B.decl.loc16, .C = %C.decl.loc25, .D = %D.decl.loc34, .E = %E.decl.loc43, .F = %F.decl.loc52, .G = %G.decl.loc61} [template]
 // CHECK:STDOUT:   %A.decl.loc7 = class_decl @A, ()
-// CHECK:STDOUT:   %A: type = class_type @A [template = constants.%A]
 // CHECK:STDOUT:   %A.decl.loc14 = class_decl @A, ()
 // CHECK:STDOUT:   %B.decl.loc16 = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %B.decl.loc23 = class_decl @B, ()
 // CHECK:STDOUT:   %C.decl.loc25 = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %C.decl.loc32 = class_decl @C, ()
 // CHECK:STDOUT:   %D.decl.loc34 = class_decl @D, ()
-// CHECK:STDOUT:   %D: type = class_type @D [template = constants.%D]
 // CHECK:STDOUT:   %D.decl.loc41 = class_decl @D, ()
 // CHECK:STDOUT:   %E.decl.loc43 = class_decl @E, ()
-// CHECK:STDOUT:   %E: type = class_type @E [template = constants.%E]
 // CHECK:STDOUT:   %E.decl.loc50 = class_decl @E, ()
 // CHECK:STDOUT:   %F.decl.loc52 = class_decl @F, ()
-// CHECK:STDOUT:   %F: type = class_type @F [template = constants.%F]
 // CHECK:STDOUT:   %F.decl.loc59 = class_decl @F, ()
 // CHECK:STDOUT:   %G.decl.loc61 = class_decl @G, ()
-// CHECK:STDOUT:   %G: type = class_type @G [template = constants.%G]
 // CHECK:STDOUT:   %G.decl.loc68 = class_decl @G, ()
 // CHECK:STDOUT:   %G.decl.loc75 = class_decl @G, ()
 // CHECK:STDOUT: }

+ 0 - 7
toolchain/check/testdata/class/fail_redeclaration_scope.carbon

@@ -37,17 +37,13 @@ class Y {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl.loc7, .X = %X.decl, .Y = %Y.decl} [template]
 // CHECK:STDOUT:   %A.decl.loc7 = class_decl @A.1, ()
-// CHECK:STDOUT:   %A: type = class_type @A.1 [template = constants.%A.1]
 // CHECK:STDOUT:   %X.decl = class_decl @X, ()
-// CHECK:STDOUT:   %X: type = class_type @X [template = constants.%X]
 // CHECK:STDOUT:   %A.decl.loc15 = class_decl @A.1, ()
 // CHECK:STDOUT:   %Y.decl = class_decl @Y, ()
-// CHECK:STDOUT:   %Y: type = class_type @Y [template = constants.%Y]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A.1 {
 // CHECK:STDOUT:   %B.decl = class_decl @B.2, ()
-// CHECK:STDOUT:   %B: type = class_type @B.2 [template = constants.%B.2]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .B = %B.decl
@@ -55,7 +51,6 @@ class Y {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @X {
 // CHECK:STDOUT:   %A.decl = class_decl @A.2, ()
-// CHECK:STDOUT:   %A: type = class_type @A.2 [template = constants.%A.2]
 // CHECK:STDOUT:   %B.decl = class_decl @B.1, ()
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -64,7 +59,6 @@ class Y {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A.2 {
 // CHECK:STDOUT:   %B.decl = class_decl @B.1, ()
-// CHECK:STDOUT:   %B: type = class_type @B.1 [template = constants.%B.1]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .B = %B.decl
@@ -79,7 +73,6 @@ class Y {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Y {
 // CHECK:STDOUT:   %.decl = class_decl @.1, ()
-// CHECK:STDOUT:   %.loc21: type = class_type @.1 [template = constants.%.2]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: }

+ 2 - 3
toolchain/check/testdata/class/fail_redefinition.carbon

@@ -34,7 +34,6 @@ fn Class.H() {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl.loc7} [template]
 // CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Class.decl.loc18 = class_decl @Class, ()
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
@@ -46,8 +45,8 @@ fn Class.H() {}
 // CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .F = <unexpected instref inst+4>
-// CHECK:STDOUT:   .H = <unexpected instref inst+5>
+// CHECK:STDOUT:   .F = <unexpected instref inst+3>
+// CHECK:STDOUT:   .H = <unexpected instref inst+4>
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 3
toolchain/check/testdata/class/fail_reorder.carbon

@@ -36,7 +36,6 @@ class Class {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
@@ -50,8 +49,8 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
-// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error>
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 2
toolchain/check/testdata/class/fail_scope.carbon

@@ -28,7 +28,6 @@ fn G() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -47,7 +46,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error>
+// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 3
toolchain/check/testdata/class/fail_self.carbon

@@ -63,11 +63,9 @@ fn CallWrongSelf(ws: WrongSelf) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .WrongSelf = %WrongSelf.decl, .CallWrongSelf = %CallWrongSelf} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT:   %WrongSelf.decl = class_decl @WrongSelf, ()
-// CHECK:STDOUT:   %WrongSelf: type = class_type @WrongSelf [template = constants.%WrongSelf]
 // CHECK:STDOUT:   %CallWrongSelf: <function> = fn_decl @CallWrongSelf [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -94,7 +92,7 @@ fn CallWrongSelf(ws: WrongSelf) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> %return: Class {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %self.var: ref Class = var self
 // CHECK:STDOUT:   %self: ref Class = bind_name self, %self.var
 // CHECK:STDOUT:   %self.ref: ref Class = name_ref self, %self

+ 0 - 1
toolchain/check/testdata/class/fail_todo_generic.carbon

@@ -21,7 +21,6 @@ class C[]();
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.C = %C.decl} [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;

+ 4 - 9
toolchain/check/testdata/class/fail_todo_modifiers.carbon

@@ -72,22 +72,17 @@ abstract class Abstract {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Access = %Access.decl, .Base = %Base.decl, .Abstract = %Abstract.decl} [template]
 // CHECK:STDOUT:   %Access.decl = class_decl @Access, ()
-// CHECK:STDOUT:   %Access: type = class_type @Access [template = constants.%Access]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract, ()
-// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [template = constants.%Abstract]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Access {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %.loc22_16.1: type = unbound_element_type Access, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc22_16.2: <unbound element of class Access> = field_decl k, element0 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Access> = bind_name k, %.loc22_16.2 [template = %.loc22_16.2]
-// CHECK:STDOUT:   %.loc27_18.1: type = unbound_element_type Access, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc27_18.2: <unbound element of class Access> = field_decl l, element1 [template]
-// CHECK:STDOUT:   %l: <unbound element of class Access> = bind_name l, %.loc27_18.2 [template = %.loc27_18.2]
+// CHECK:STDOUT:   %.loc22: <unbound element of class Access> = field_decl k, element0 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Access> = bind_name k, %.loc22 [template = %.loc22]
+// CHECK:STDOUT:   %.loc27: <unbound element of class Access> = field_decl l, element1 [template]
+// CHECK:STDOUT:   %l: <unbound element of class Access> = bind_name l, %.loc27 [template = %.loc27]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F

+ 5 - 7
toolchain/check/testdata/class/fail_unbound_field.carbon

@@ -32,14 +32,12 @@ fn G() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_12.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_12.2: <unbound element of class Class> = field_decl field, element0 [template]
-// CHECK:STDOUT:   %field: <unbound element of class Class> = bind_name field, %.loc8_12.2 [template = %.loc8_12.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl field, element0 [template]
+// CHECK:STDOUT:   %field: <unbound element of class Class> = bind_name field, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -49,14 +47,14 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %field.ref: <unbound element of class Class> = name_ref field, @Class.%field [template = @Class.%.loc8_12.2]
+// CHECK:STDOUT:   %field.ref: <unbound element of class Class> = name_ref field, @Class.%field [template = @Class.%.loc8]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
-// CHECK:STDOUT:   %field.ref: <unbound element of class Class> = name_ref field, @Class.%field [template = @Class.%.loc8_12.2]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %field.ref: <unbound element of class Class> = name_ref field, @Class.%field [template = @Class.%.loc8]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 5
toolchain/check/testdata/class/fail_unknown_member.carbon

@@ -28,14 +28,12 @@ fn G(c: Class) -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl n, element0 [template]
-// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl n, element0 [template]
+// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .n = %n
@@ -44,7 +42,7 @@ fn G(c: Class) -> i32 {
 // CHECK:STDOUT: fn @G(%c: Class) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %c.ref: Class = name_ref c, %c
-// CHECK:STDOUT:   %something.ref: <error> = name_ref something, <error>
+// CHECK:STDOUT:   %something.ref: <error> = name_ref something, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 8
toolchain/check/testdata/class/field_access.carbon

@@ -31,17 +31,14 @@ fn Run() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl j, element0 [template]
-// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl k, element1 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl j, element0 [template]
+// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Class> = field_decl k, element1 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .j = %j
@@ -50,7 +47,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %c.var: ref Class = var c
 // CHECK:STDOUT:   %c: ref Class = bind_name c, %c.var
 // CHECK:STDOUT:   %c.ref.loc14: ref Class = name_ref c, %c

+ 6 - 9
toolchain/check/testdata/class/field_access_in_value.carbon

@@ -32,17 +32,14 @@ fn Test() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Test = %Test} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Test: <function> = fn_decl @Test [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl j, element0 [template]
-// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl k, element1 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl j, element0 [template]
+// CHECK:STDOUT:   %j: <unbound element of class Class> = bind_name j, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Class> = field_decl k, element1 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .j = %j
@@ -51,7 +48,7 @@ fn Test() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Test() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref.loc13: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc13: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %cv.var: ref Class = var cv
 // CHECK:STDOUT:   %cv: ref Class = bind_name cv, %cv.var
 // CHECK:STDOUT:   %cv.ref.loc14: ref Class = name_ref cv, %cv
@@ -62,7 +59,7 @@ fn Test() {
 // CHECK:STDOUT:   %.loc15_5: ref i32 = class_element_access %cv.ref.loc15, element1
 // CHECK:STDOUT:   %.loc15_10: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   assign %.loc15_5, %.loc15_10
-// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc16: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %cv.ref.loc16: ref Class = name_ref cv, %cv
 // CHECK:STDOUT:   %.loc16: Class = bind_value %cv.ref.loc16
 // CHECK:STDOUT:   %c: Class = bind_name c, %.loc16

+ 0 - 1
toolchain/check/testdata/class/forward_declared.carbon

@@ -18,7 +18,6 @@ fn F(p: Class*) -> Class* { return p; }
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 8
toolchain/check/testdata/class/init.carbon

@@ -32,20 +32,17 @@ fn MakeReorder(n: i32, next: Class*) -> Class {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Make = %Make, .MakeReorder = %MakeReorder} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
 // CHECK:STDOUT:   %MakeReorder: <function> = fn_decl @MakeReorder [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl n, element0 [template]
-// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl n, element0 [template]
+// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc9_18: type = ptr_type Class [template = constants.%.2]
-// CHECK:STDOUT:   %.loc9_11.1: type = unbound_element_type Class, Class* [template = constants.%.3]
-// CHECK:STDOUT:   %.loc9_11.2: <unbound element of class Class> = field_decl next, element1 [template]
-// CHECK:STDOUT:   %next: <unbound element of class Class> = bind_name next, %.loc9_11.2 [template = %.loc9_11.2]
+// CHECK:STDOUT:   %.loc9_11: <unbound element of class Class> = field_decl next, element1 [template]
+// CHECK:STDOUT:   %next: <unbound element of class Class> = bind_name next, %.loc9_11 [template = %.loc9_11]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .n = %n

+ 5 - 8
toolchain/check/testdata/class/init_as.carbon

@@ -27,17 +27,14 @@ fn F() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Class> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Class> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Class> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Class> = bind_name b, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -49,7 +46,7 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.loc13_17: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc13_25: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_26.1: {.a: i32, .b: i32} = struct_literal (%.loc13_17, %.loc13_25)
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc13_26.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc13_26.3: ref i32 = class_element_access %.loc13_26.2, element0
 // CHECK:STDOUT:   %.loc13_26.4: init i32 = initialize_from %.loc13_17 to %.loc13_26.3

+ 10 - 16
toolchain/check/testdata/class/init_nested.carbon

@@ -38,20 +38,16 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Inner = %Inner.decl, .MakeInner = %MakeInner, .Outer = %Outer.decl, .MakeOuter = %MakeOuter} [template]
 // CHECK:STDOUT:   %Inner.decl = class_decl @Inner, ()
-// CHECK:STDOUT:   %Inner: type = class_type @Inner [template = constants.%Inner]
 // CHECK:STDOUT:   %MakeInner: <function> = fn_decl @MakeInner [template]
 // CHECK:STDOUT:   %Outer.decl = class_decl @Outer, ()
-// CHECK:STDOUT:   %Outer: type = class_type @Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %MakeOuter: <function> = fn_decl @MakeOuter [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Inner {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Inner, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Inner> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Inner> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Inner, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Inner> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class Inner> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Inner> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Inner> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Inner> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class Inner> = bind_name b, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -59,14 +55,12 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Outer {
-// CHECK:STDOUT:   %Inner.ref.loc15: type = name_ref Inner, file.%Inner [template = constants.%Inner]
-// CHECK:STDOUT:   %.loc15_8.1: type = unbound_element_type Outer, Inner [template = constants.%.4]
-// CHECK:STDOUT:   %.loc15_8.2: <unbound element of class Outer> = field_decl c, element0 [template]
-// CHECK:STDOUT:   %c: <unbound element of class Outer> = bind_name c, %.loc15_8.2 [template = %.loc15_8.2]
-// CHECK:STDOUT:   %Inner.ref.loc16: type = name_ref Inner, file.%Inner [template = constants.%Inner]
-// CHECK:STDOUT:   %.loc16_8.1: type = unbound_element_type Outer, Inner [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_8.2: <unbound element of class Outer> = field_decl d, element1 [template]
-// CHECK:STDOUT:   %d: <unbound element of class Outer> = bind_name d, %.loc16_8.2 [template = %.loc16_8.2]
+// CHECK:STDOUT:   %Inner.ref.loc15: type = name_ref Inner, constants.%Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %.loc15: <unbound element of class Outer> = field_decl c, element0 [template]
+// CHECK:STDOUT:   %c: <unbound element of class Outer> = bind_name c, %.loc15 [template = %.loc15]
+// CHECK:STDOUT:   %Inner.ref.loc16: type = name_ref Inner, constants.%Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %.loc16: <unbound element of class Outer> = field_decl d, element1 [template]
+// CHECK:STDOUT:   %d: <unbound element of class Outer> = bind_name d, %.loc16 [template = %.loc16]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .c = %c

+ 4 - 6
toolchain/check/testdata/class/method.carbon

@@ -62,7 +62,6 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Call = %Call, .CallOnConstBoundMethod = %CallOnConstBoundMethod, .CallWithAddr = %CallWithAddr, .CallFThroughPointer = %CallFThroughPointer, .CallGThroughPointer = %CallGThroughPointer, .Make = %Make, .CallFOnInitializingExpr = %CallFOnInitializingExpr, .CallGOnInitializingExpr = %CallGOnInitializingExpr} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
 // CHECK:STDOUT:   %CallOnConstBoundMethod: <function> = fn_decl @CallOnConstBoundMethod [template]
@@ -77,9 +76,8 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %.loc11_8.1: type = unbound_element_type Class, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc11_8.2: <unbound element of class Class> = field_decl k, element0 [template]
-// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc11_8.2 [template = %.loc11_8.2]
+// CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl k, element0 [template]
+// CHECK:STDOUT:   %k: <unbound element of class Class> = bind_name k, %.loc11 [template = %.loc11]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
@@ -111,7 +109,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc25_17: i32 = int_literal 1 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc25_18.1: {.k: i32} = struct_literal (%.loc25_17)
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc25_18.2: ref Class = temporary_storage
 // CHECK:STDOUT:   %.loc25_18.3: ref i32 = class_element_access %.loc25_18.2, element0
 // CHECK:STDOUT:   %.loc25_18.4: init i32 = initialize_from %.loc25_17 to %.loc25_18.3
@@ -128,7 +126,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @CallWithAddr() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %c.var: ref Class = var c
 // CHECK:STDOUT:   %c: ref Class = bind_name c, %c.var
 // CHECK:STDOUT:   %c.ref: ref Class = name_ref c, %c

+ 18 - 26
toolchain/check/testdata/class/nested.carbon

@@ -48,28 +48,23 @@ fn F(a: Outer*) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Outer = %Outer.decl, .F = %F} [template]
 // CHECK:STDOUT:   %Outer.decl = class_decl @Outer, ()
-// CHECK:STDOUT:   %Outer: type = class_type @Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Outer {
 // CHECK:STDOUT:   %Inner.decl = class_decl @Inner, ()
-// CHECK:STDOUT:   %Inner: type = class_type @Inner [template = constants.%Inner]
-// CHECK:STDOUT:   %Self.ref: type = name_ref Self, file.%Outer [template = constants.%Outer]
+// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %.loc14_15: type = ptr_type Outer [template = constants.%.3]
-// CHECK:STDOUT:   %.loc14_9.1: type = unbound_element_type Outer, Outer* [template = constants.%.6]
-// CHECK:STDOUT:   %.loc14_9.2: <unbound element of class Outer> = field_decl po, element0 [template]
-// CHECK:STDOUT:   %po: <unbound element of class Outer> = bind_name po, %.loc14_9.2 [template = %.loc14_9.2]
-// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer [template = constants.%Outer]
+// CHECK:STDOUT:   %.loc14_9: <unbound element of class Outer> = field_decl po, element0 [template]
+// CHECK:STDOUT:   %po: <unbound element of class Outer> = bind_name po, %.loc14_9 [template = %.loc14_9]
+// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, constants.%Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %.loc15_16: type = ptr_type Outer [template = constants.%.3]
-// CHECK:STDOUT:   %.loc15_9.1: type = unbound_element_type Outer, Outer* [template = constants.%.6]
-// CHECK:STDOUT:   %.loc15_9.2: <unbound element of class Outer> = field_decl qo, element1 [template]
-// CHECK:STDOUT:   %qo: <unbound element of class Outer> = bind_name qo, %.loc15_9.2 [template = %.loc15_9.2]
-// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, %Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %.loc15_9: <unbound element of class Outer> = field_decl qo, element1 [template]
+// CHECK:STDOUT:   %qo: <unbound element of class Outer> = bind_name qo, %.loc15_9 [template = %.loc15_9]
+// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, constants.%Inner [template = constants.%Inner]
 // CHECK:STDOUT:   %.loc16_16: type = ptr_type Inner [template = constants.%.1]
-// CHECK:STDOUT:   %.loc16_9.1: type = unbound_element_type Outer, Inner* [template = constants.%.7]
-// CHECK:STDOUT:   %.loc16_9.2: <unbound element of class Outer> = field_decl pi, element2 [template]
-// CHECK:STDOUT:   %pi: <unbound element of class Outer> = bind_name pi, %.loc16_9.2 [template = %.loc16_9.2]
+// CHECK:STDOUT:   %.loc16_9: <unbound element of class Outer> = field_decl pi, element2 [template]
+// CHECK:STDOUT:   %pi: <unbound element of class Outer> = bind_name pi, %.loc16_9 [template = %.loc16_9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Inner = %Inner.decl
@@ -79,21 +74,18 @@ fn F(a: Outer*) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Inner {
-// CHECK:STDOUT:   %Self.ref: type = name_ref Self, @Outer.%Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Inner [template = constants.%Inner]
 // CHECK:STDOUT:   %.loc9_17: type = ptr_type Inner [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_11.1: type = unbound_element_type Inner, Inner* [template = constants.%.2]
-// CHECK:STDOUT:   %.loc9_11.2: <unbound element of class Inner> = field_decl pi, element0 [template]
-// CHECK:STDOUT:   %pi: <unbound element of class Inner> = bind_name pi, %.loc9_11.2 [template = %.loc9_11.2]
-// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer [template = constants.%Outer]
+// CHECK:STDOUT:   %.loc9_11: <unbound element of class Inner> = field_decl pi, element0 [template]
+// CHECK:STDOUT:   %pi: <unbound element of class Inner> = bind_name pi, %.loc9_11 [template = %.loc9_11]
+// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, constants.%Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %.loc10_18: type = ptr_type Outer [template = constants.%.3]
-// CHECK:STDOUT:   %.loc10_11.1: type = unbound_element_type Inner, Outer* [template = constants.%.4]
-// CHECK:STDOUT:   %.loc10_11.2: <unbound element of class Inner> = field_decl po, element1 [template]
-// CHECK:STDOUT:   %po: <unbound element of class Inner> = bind_name po, %.loc10_11.2 [template = %.loc10_11.2]
-// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %.loc10_11: <unbound element of class Inner> = field_decl po, element1 [template]
+// CHECK:STDOUT:   %po: <unbound element of class Inner> = bind_name po, %.loc10_11 [template = %.loc10_11]
+// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, constants.%Inner [template = constants.%Inner]
 // CHECK:STDOUT:   %.loc11_18: type = ptr_type Inner [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_11.1: type = unbound_element_type Inner, Inner* [template = constants.%.2]
-// CHECK:STDOUT:   %.loc11_11.2: <unbound element of class Inner> = field_decl qi, element2 [template]
-// CHECK:STDOUT:   %qi: <unbound element of class Inner> = bind_name qi, %.loc11_11.2 [template = %.loc11_11.2]
+// CHECK:STDOUT:   %.loc11_11: <unbound element of class Inner> = field_decl qi, element2 [template]
+// CHECK:STDOUT:   %qi: <unbound element of class Inner> = bind_name qi, %.loc11_11 [template = %.loc11_11]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .pi = %pi

+ 3 - 6
toolchain/check/testdata/class/nested_name.carbon

@@ -34,23 +34,20 @@ fn G(o: Outer) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Outer = %Outer.decl, .F = %F, .G = %G} [template]
 // CHECK:STDOUT:   %Outer.decl = class_decl @Outer, ()
-// CHECK:STDOUT:   %Outer: type = class_type @Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Outer {
 // CHECK:STDOUT:   %Inner.decl = class_decl @Inner, ()
-// CHECK:STDOUT:   %Inner: type = class_type @Inner [template = constants.%Inner]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Inner = %Inner.decl
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Inner {
-// CHECK:STDOUT:   %.loc9_10.1: type = unbound_element_type Inner, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_10.2: <unbound element of class Inner> = field_decl n, element0 [template]
-// CHECK:STDOUT:   %n: <unbound element of class Inner> = bind_name n, %.loc9_10.2 [template = %.loc9_10.2]
+// CHECK:STDOUT:   %.loc9: <unbound element of class Inner> = field_decl n, element0 [template]
+// CHECK:STDOUT:   %n: <unbound element of class Inner> = bind_name n, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .n = %n
@@ -67,7 +64,7 @@ fn G(o: Outer) {
 // CHECK:STDOUT: fn @G(%o: Outer) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %o.ref: Outer = name_ref o, %o
-// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner [template = constants.%Inner]
+// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, constants.%Inner [template = constants.%Inner]
 // CHECK:STDOUT:   %i.var: ref Inner = var i
 // CHECK:STDOUT:   %i: ref Inner = bind_name i, %i.var
 // CHECK:STDOUT:   return

+ 2 - 4
toolchain/check/testdata/class/raw_self.carbon

@@ -34,7 +34,6 @@ fn Class.G[self: Class](r#self: i32) -> (i32, i32) {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
@@ -42,9 +41,8 @@ fn Class.G[self: Class](r#self: i32) -> (i32, i32) {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %.loc10_8.1: type = unbound_element_type Class, i32 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc10_8.2: <unbound element of class Class> = field_decl n, element0 [template]
-// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc10_8.2 [template = %.loc10_8.2]
+// CHECK:STDOUT:   %.loc10: <unbound element of class Class> = field_decl n, element0 [template]
+// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc10 [template = %.loc10]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F

+ 2 - 3
toolchain/check/testdata/class/raw_self_type.carbon

@@ -22,7 +22,6 @@ class Class {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
@@ -34,11 +33,11 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Self.ref.loc9: type = name_ref Self, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Self.ref.loc9: type = name_ref Self, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc9: type = ptr_type Class [template = constants.%.1]
 // CHECK:STDOUT:   %Self.var: ref Class* = var r#Self
 // CHECK:STDOUT:   %Self: ref Class* = bind_name r#Self, %Self.var
-// CHECK:STDOUT:   %Self.ref.loc10_12: type = name_ref Self, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Self.ref.loc10_12: type = name_ref Self, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc10_16: type = ptr_type Class [template = constants.%.1]
 // CHECK:STDOUT:   %p.var: ref Class* = var p
 // CHECK:STDOUT:   %p: ref Class* = bind_name p, %p.var

+ 0 - 1
toolchain/check/testdata/class/redeclaration.carbon

@@ -22,7 +22,6 @@ fn Class.F() {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl.loc7} [template]
 // CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Class.decl.loc9 = class_decl @Class, ()
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }

+ 0 - 3
toolchain/check/testdata/class/redeclaration_introducer.carbon

@@ -24,11 +24,8 @@ abstract class C {}
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.A = %A.decl.loc7, .B = %B.decl.loc8, .C = %C.decl.loc9} [template]
 // CHECK:STDOUT:   %A.decl.loc7 = class_decl @A, ()
-// CHECK:STDOUT:   %A: type = class_type @A [template = constants.%A]
 // CHECK:STDOUT:   %B.decl.loc8 = class_decl @B, ()
-// CHECK:STDOUT:   %B: type = class_type @B [template = constants.%B]
 // CHECK:STDOUT:   %C.decl.loc9 = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %A.decl.loc11 = class_decl @A, ()
 // CHECK:STDOUT:   %B.decl.loc12 = class_decl @B, ()
 // CHECK:STDOUT:   %C.decl.loc13 = class_decl @C, ()

+ 0 - 1
toolchain/check/testdata/class/reenter_scope.carbon

@@ -23,7 +23,6 @@ fn Class.F() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 2
toolchain/check/testdata/class/scope.carbon

@@ -35,7 +35,6 @@ fn Run() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .F = %F, .Run = %Run} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
 // CHECK:STDOUT: }
@@ -79,7 +78,7 @@ fn Run() {
 // CHECK:STDOUT:   assign %a.var, %.loc22
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %F.ref.loc23: <function> = name_ref F, @Class.%F [template = @Class.%F]
 // CHECK:STDOUT:   %.loc23: init i32 = call %F.ref.loc23()
 // CHECK:STDOUT:   assign %b.var, %.loc23

+ 2 - 4
toolchain/check/testdata/class/self.carbon

@@ -32,7 +32,6 @@ fn Class.G[addr self: Class*]() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
@@ -40,9 +39,8 @@ fn Class.G[addr self: Class*]() -> i32 {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %.loc11_8.1: type = unbound_element_type Class, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc11_8.2: <unbound element of class Class> = field_decl n, element0 [template]
-// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc11_8.2 [template = %.loc11_8.2]
+// CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl n, element0 [template]
+// CHECK:STDOUT:   %n: <unbound element of class Class> = bind_name n, %.loc11 [template = %.loc11]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F

+ 5 - 9
toolchain/check/testdata/class/self_conversion.carbon

@@ -49,32 +49,28 @@ fn Call(p: Derived*) -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   %Base.decl = class_decl @Base, ()
-// CHECK:STDOUT:   %Base: type = class_type @Base [template = constants.%Base]
 // CHECK:STDOUT:   %Derived.decl = class_decl @Derived, ()
-// CHECK:STDOUT:   %Derived: type = class_type @Derived [template = constants.%Derived]
 // CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase [template]
 // CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase [template]
 // CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type Base, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class Base> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class Base> = bind_name a, %.loc8 [template = %.loc8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base [template = constants.%Base]
-// CHECK:STDOUT:   %.loc12_20.1: type = unbound_element_type Derived, Base [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_20.2: <unbound element of class Derived> = base_decl Base, element0 [template]
+// CHECK:STDOUT:   %Base.ref: type = name_ref Base, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
 // CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase [template]
 // CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .base = %.loc12_20.2
+// CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .SelfBase = %SelfBase
 // CHECK:STDOUT:   .AddrSelfBase = %AddrSelfBase
 // CHECK:STDOUT:   extend name_scope1

+ 3 - 5
toolchain/check/testdata/class/self_type.carbon

@@ -29,17 +29,15 @@ fn Class.F[self: Class]() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Self.ref: type = name_ref Self, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc9_14: type = ptr_type Class [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type Class, Class* [template = constants.%.2]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class Class> = field_decl p, element0 [template]
-// CHECK:STDOUT:   %p: <unbound element of class Class> = bind_name p, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc9_8: <unbound element of class Class> = field_decl p, element0 [template]
+// CHECK:STDOUT:   %p: <unbound element of class Class> = bind_name p, %.loc9_8 [template = %.loc9_8]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F

+ 1 - 2
toolchain/check/testdata/class/static_method.carbon

@@ -25,7 +25,6 @@ fn Run() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -40,7 +39,7 @@ fn Run() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref: type = name_ref Class, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %c.var: ref Class = var c
 // CHECK:STDOUT:   %c: ref Class = bind_name c, %c.var
 // CHECK:STDOUT:   %c.ref: ref Class = name_ref c, %c

+ 0 - 1
toolchain/check/testdata/const/collapse.carbon

@@ -18,7 +18,6 @@ fn F(p: const i32**) -> const (const i32)** {
 // CHECK:STDOUT:   %.1: type = const_type i32 [template]
 // CHECK:STDOUT:   %.2: type = ptr_type const i32 [template]
 // CHECK:STDOUT:   %.3: type = ptr_type const i32* [template]
-// CHECK:STDOUT:   %.4: type = const_type const i32 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {

+ 4 - 5
toolchain/check/testdata/const/fail_collapse.carbon

@@ -18,11 +18,10 @@ fn G(p: const (const i32)**) -> i32** {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %.1: type = const_type i32 [template]
-// CHECK:STDOUT:   %.2: type = const_type const i32 [template]
-// CHECK:STDOUT:   %.3: type = ptr_type const i32 [template]
-// CHECK:STDOUT:   %.4: type = ptr_type const i32* [template]
-// CHECK:STDOUT:   %.5: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.6: type = ptr_type i32* [template]
+// CHECK:STDOUT:   %.2: type = ptr_type const i32 [template]
+// CHECK:STDOUT:   %.3: type = ptr_type const i32* [template]
+// CHECK:STDOUT:   %.4: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.5: type = ptr_type i32* [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {

+ 1 - 1
toolchain/check/testdata/function/generic/fail_type_param_mismatch.carbon

@@ -33,7 +33,7 @@ fn F(T:! type, U:! type) {
 // CHECK:STDOUT:   %p.ref: ref T* = name_ref p, %p
 // CHECK:STDOUT:   %.loc12_15: T* = bind_value %p.ref
 // CHECK:STDOUT:   %.loc12_14: ref T = deref %.loc12_15
-// CHECK:STDOUT:   %n: U = bind_name n, <error>
+// CHECK:STDOUT:   %n: U = bind_name n, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/if/fail_scope.carbon

@@ -41,7 +41,7 @@ fn VarScope(b: bool) -> i32 {
 // CHECK:STDOUT:   return %.loc10
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else:
-// CHECK:STDOUT:   %n.ref.loc15: <error> = name_ref n, <error>
+// CHECK:STDOUT:   %n.ref.loc15: <error> = name_ref n, <error> [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 2
toolchain/check/testdata/if_expr/fail_not_in_function.carbon

@@ -48,7 +48,6 @@ class C {
 // CHECK:STDOUT:   %.loc17: i32 = block_arg <unexpected instblockref block5>
 // CHECK:STDOUT:   %x: i32 = bind_name x, %.loc17
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -56,6 +55,6 @@ class C {
 // CHECK:STDOUT:   if %.loc33 br !if.expr.then else br !if.expr.else
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .n = <unexpected instref inst+27>
+// CHECK:STDOUT:   .n = <unexpected instref inst+25>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 2
toolchain/check/testdata/index/fail_invalid_base.carbon

@@ -39,7 +39,6 @@ var d: i32 = {.a: i32, .b: i32}[0];
 // CHECK:STDOUT:   %.4: type = struct_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.5: type = ptr_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT:   %.6: {.a: i32, .b: i32} = struct_value (%.2, %.3) [template]
-// CHECK:STDOUT:   %.7: type = struct_type {.a: i32, .b: i32} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -67,7 +66,7 @@ var d: i32 = {.a: i32, .b: i32}[0];
 // CHECK:STDOUT:   assign %c.var, <error>
 // CHECK:STDOUT:   %d.var: ref i32 = var d
 // CHECK:STDOUT:   %d: ref i32 = bind_name d, %d.var
-// CHECK:STDOUT:   %.loc31_31: type = struct_type {.a: i32, .b: i32} [template = constants.%.7]
+// CHECK:STDOUT:   %.loc31_31: type = struct_type {.a: i32, .b: i32} [template = constants.%.4]
 // CHECK:STDOUT:   %.loc31_33: i32 = int_literal 0 [template = constants.%.1]
 // CHECK:STDOUT:   assign %d.var, <error>
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/index/fail_name_not_found.carbon

@@ -26,7 +26,7 @@ fn Main() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
-// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error>
+// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc11: i32 = int_literal 0 [template = constants.%.1]
 // CHECK:STDOUT:   assign %b.var, <error>
 // CHECK:STDOUT:   return

+ 1 - 1
toolchain/check/testdata/index/fail_tuple_index_error.carbon

@@ -39,7 +39,7 @@ var b: i32 = a[oops];
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref (i32, i32) = name_ref a, %a
-// CHECK:STDOUT:   %oops.ref: <error> = name_ref oops, <error>
+// CHECK:STDOUT:   %oops.ref: <error> = name_ref oops, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc11: ref <error> = tuple_index %a.ref, %oops.ref
 // CHECK:STDOUT:   assign %b.var, <error>
 // CHECK:STDOUT: }

+ 0 - 1
toolchain/check/testdata/interface/fail_duplicate.carbon

@@ -49,7 +49,6 @@ interface Class { }
 // CHECK:STDOUT:   %Function: <function> = fn_decl @Function [template]
 // CHECK:STDOUT:   %.decl.loc27 = interface_decl @.1, ()
 // CHECK:STDOUT:   %Class.decl = class_decl @Class, ()
-// CHECK:STDOUT:   %Class: type = class_type @Class [template = constants.%Class]
 // CHECK:STDOUT:   %.decl.loc37 = interface_decl @.2, ()
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/let/fail_generic.carbon

@@ -33,8 +33,8 @@ fn F(a: i32) -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, i32 [symbolic]
 // CHECK:STDOUT:   %T.ref: type = name_ref T, %T [symbolic = %T]
 // CHECK:STDOUT:   %.loc13: i32 = int_literal 5 [template = constants.%.1]
-// CHECK:STDOUT:   %x: T = bind_name x, <error>
-// CHECK:STDOUT:   %x.ref: T = name_ref x, %x
+// CHECK:STDOUT:   %x: T = bind_name x, <error> [template = <error>]
+// CHECK:STDOUT:   %x.ref: T = name_ref x, %x [template = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/let/fail_use_in_init.carbon

@@ -20,8 +20,8 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error>
-// CHECK:STDOUT:   %a: i32 = bind_name a, <error>
+// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error> [template = <error>]
+// CHECK:STDOUT:   %a: i32 = bind_name a, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/operators/fail_assignment_to_error.carbon

@@ -28,10 +28,10 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %undeclared.ref: <error> = name_ref undeclared, <error>
+// CHECK:STDOUT:   %undeclared.ref: <error> = name_ref undeclared, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc11: i32 = int_literal 42 [template = constants.%.1]
 // CHECK:STDOUT:   assign %undeclared.ref, <error>
-// CHECK:STDOUT:   %also_undeclared.ref: <error> = name_ref also_undeclared, <error>
+// CHECK:STDOUT:   %also_undeclared.ref: <error> = name_ref also_undeclared, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc15_3: ref <error> = deref <error>
 // CHECK:STDOUT:   %.loc15_22: i32 = int_literal 42 [template = constants.%.1]
 // CHECK:STDOUT:   assign %.loc15_3, <error>

+ 1 - 1
toolchain/check/testdata/operators/fail_type_mismatch.carbon

@@ -27,7 +27,7 @@ fn Main() {
 // CHECK:STDOUT:   %x.var: ref bool = var x
 // CHECK:STDOUT:   %x: ref bool = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc11_21: i32 = int_literal 12 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_17: <error> = not <error>
+// CHECK:STDOUT:   %.loc11_17: <error> = not <error> [template = <error>]
 // CHECK:STDOUT:   assign %x.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/package_expr/fail_not_found.carbon

@@ -23,7 +23,7 @@ fn Main() {
 // CHECK:STDOUT:   %y.var: ref i32 = var y
 // CHECK:STDOUT:   %y: ref i32 = bind_name y, %y.var
 // CHECK:STDOUT:   %package.ref: <namespace> = name_ref package, package [template = package]
-// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error>
+// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [template = <error>]
 // CHECK:STDOUT:   assign %y.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 1 - 2
toolchain/check/testdata/package_expr/syntax.carbon

@@ -116,7 +116,6 @@ fn Main() {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.NS = %.loc4, .Main = %Main} [template]
 // CHECK:STDOUT:   %.loc4: <namespace> = namespace NS, {.C = %C.decl} [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %Main: <function> = fn_decl @Main [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -136,7 +135,7 @@ fn Main() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %package.ref: <namespace> = name_ref package, package [template = package]
 // CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, file.%.loc4 [template = file.%.loc4]
-// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C [template = constants.%C]
+// CHECK:STDOUT:   %C.ref: type = name_ref C, constants.%C [template = constants.%C]
 // CHECK:STDOUT:   %Foo.ref: <function> = name_ref Foo, @C.%Foo [template = @C.%Foo]
 // CHECK:STDOUT:   %.loc11: init () = call %Foo.ref()
 // CHECK:STDOUT:   return

+ 1 - 1
toolchain/check/testdata/packages/fail_name_with_import_failure.carbon

@@ -25,7 +25,7 @@ var a: () = A();
 // CHECK:STDOUT:   %.loc7_9.2: type = converted %.loc7_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:   %A.ref: <error> = name_ref A, <error>
+// CHECK:STDOUT:   %A.ref: <error> = name_ref A, <error> [template = <error>]
 // CHECK:STDOUT:   assign %a.var, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 5
toolchain/check/testdata/pointer/fail_address_of_error.carbon

@@ -32,11 +32,11 @@ fn Test() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Test() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %undeclared.ref.loc11: <error> = name_ref undeclared, <error>
-// CHECK:STDOUT:   %.loc11: <error>* = addr_of %undeclared.ref.loc11
-// CHECK:STDOUT:   %undeclared.ref.loc18: <error> = name_ref undeclared, <error>
-// CHECK:STDOUT:   %.loc18_5: <error>* = addr_of %undeclared.ref.loc18
-// CHECK:STDOUT:   %.loc18_3: <error>** = addr_of %.loc18_5
+// CHECK:STDOUT:   %undeclared.ref.loc11: <error> = name_ref undeclared, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc11: <error>* = addr_of %undeclared.ref.loc11 [template = <error>]
+// CHECK:STDOUT:   %undeclared.ref.loc18: <error> = name_ref undeclared, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc18_5: <error>* = addr_of %undeclared.ref.loc18 [template = <error>]
+// CHECK:STDOUT:   %.loc18_3: <error>** = addr_of %.loc18_5 [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 10
toolchain/check/testdata/pointer/fail_address_of_value.carbon

@@ -107,10 +107,11 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %.20: bool = bool_literal false [template]
 // CHECK:STDOUT:   %.21: bool* = addr_of %.20 [template]
 // CHECK:STDOUT:   %.22: type = ptr_type type [template]
-// CHECK:STDOUT:   %.23: type = const_type i32 [template]
-// CHECK:STDOUT:   %.24: type = ptr_type const i32 [template]
-// CHECK:STDOUT:   %.25: type* = addr_of %.24 [template]
-// CHECK:STDOUT:   %.26: (i32, i32) = tuple_value (%.14, %.15) [template]
+// CHECK:STDOUT:   %.23: type* = addr_of i32 [template]
+// CHECK:STDOUT:   %.24: type = const_type i32 [template]
+// CHECK:STDOUT:   %.25: type = ptr_type const i32 [template]
+// CHECK:STDOUT:   %.26: type* = addr_of %.25 [template]
+// CHECK:STDOUT:   %.27: (i32, i32) = tuple_value (%.14, %.15) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -184,10 +185,10 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @AddressOfType() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc64: type* = addr_of i32
-// CHECK:STDOUT:   %.loc68_5: type = const_type i32 [template = constants.%.23]
-// CHECK:STDOUT:   %.loc68_14: type = ptr_type const i32 [template = constants.%.24]
-// CHECK:STDOUT:   %.loc68_3: type* = addr_of %.loc68_14 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc64: type* = addr_of i32 [template = constants.%.23]
+// CHECK:STDOUT:   %.loc68_5: type = const_type i32 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc68_14: type = ptr_type const i32 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc68_3: type* = addr_of %.loc68_14 [template = constants.%.26]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -197,8 +198,8 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %.loc75_9: i32 = int_literal 2 [template = constants.%.15]
 // CHECK:STDOUT:   %.loc75_10.1: (i32, i32) = tuple_literal (%.loc75_6, %.loc75_9)
 // CHECK:STDOUT:   %.loc75_12: i32 = int_literal 0 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc75_10.2: (i32, i32) = tuple_value (%.loc75_6, %.loc75_9) [template = constants.%.26]
-// CHECK:STDOUT:   %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2 [template = constants.%.26]
+// CHECK:STDOUT:   %.loc75_10.2: (i32, i32) = tuple_value (%.loc75_6, %.loc75_9) [template = constants.%.27]
+// CHECK:STDOUT:   %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2 [template = constants.%.27]
 // CHECK:STDOUT:   %.loc75_13: i32 = tuple_index %.loc75_10.3, %.loc75_12
 // CHECK:STDOUT:   %.loc75_3: i32* = addr_of %.loc75_13
 // CHECK:STDOUT:   return

+ 2 - 2
toolchain/check/testdata/pointer/fail_deref_error.carbon

@@ -13,8 +13,8 @@ let n: i32 = *undeclared;
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {} [template]
-// CHECK:STDOUT:   %undeclared.ref: <error> = name_ref undeclared, <error>
+// CHECK:STDOUT:   %undeclared.ref: <error> = name_ref undeclared, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc10: ref <error> = deref <error>
-// CHECK:STDOUT:   %n: i32 = bind_name n, <error>
+// CHECK:STDOUT:   %n: i32 = bind_name n, <error> [template = <error>]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 9
toolchain/check/testdata/return/fail_let_in_type.carbon

@@ -4,13 +4,24 @@
 //
 // AUTOUPDATE
 
-// TODO: This should probably work, it just doesn't right now.
+// TODO: This should require `:!` rather than just `:`.
 let x: type = i32;
-// CHECK:STDERR: fail_let_in_type.carbon:[[@LINE+3]]:13: ERROR: Cannot evaluate type expression.
-// CHECK:STDERR: fn Six() -> x { return 6; }
-// CHECK:STDERR:             ^
 fn Six() -> x { return 6; }
 
+// TODO: This should probably work.
+let y:! type = i32;
+// CHECK:STDERR: fail_let_in_type.carbon:[[@LINE+3]]:23: ERROR: Cannot implicitly convert from `i32` to `y`.
+// CHECK:STDERR: fn HalfDozen() -> y { return 6; }
+// CHECK:STDERR:                       ^~~~~~~~~
+fn HalfDozen() -> y { return 6; }
+
+// TODO: This should work.
+// CHECK:STDERR: fail_let_in_type.carbon:[[@LINE+3]]:5: ERROR: Semantics TODO: `HandleTemplate`.
+// CHECK:STDERR: let template z:! type = i32;
+// CHECK:STDERR:     ^~~~~~~~~~~~~~~~~
+let template z:! type = i32;
+fn FirstPerfectNumber() -> z { return 6; }
+
 // CHECK:STDOUT: --- fail_let_in_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
@@ -18,14 +29,17 @@ fn Six() -> x { return 6; }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
-// CHECK:STDOUT:   package: <namespace> = namespace package, {.Six = %Six} [template]
-// CHECK:STDOUT:   %x: type = bind_name x, i32
-// CHECK:STDOUT:   %Six: <function> = fn_decl @Six [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Six() -> <error> {
+// CHECK:STDOUT: fn @Six() -> i32 {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc9: i32 = int_literal 6 [template = constants.%.1]
+// CHECK:STDOUT:   return %.loc9
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @HalfDozen() -> y {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc12: i32 = int_literal 6 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc16: i32 = int_literal 6 [template = constants.%.1]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 5 - 8
toolchain/check/testdata/return/fail_return_with_returned_var.carbon

@@ -43,17 +43,14 @@ fn G() -> C {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.F = %F, .C = %C.decl, .G = %G} [template]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc18_16.1: type = unbound_element_type C, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc18_16.2: <unbound element of class C> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class C> = bind_name a, %.loc18_16.2 [template = %.loc18_16.2]
-// CHECK:STDOUT:   %.loc18_28.1: type = unbound_element_type C, i32 [template = constants.%.3]
-// CHECK:STDOUT:   %.loc18_28.2: <unbound element of class C> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class C> = bind_name b, %.loc18_28.2 [template = %.loc18_28.2]
+// CHECK:STDOUT:   %.loc18_16: <unbound element of class C> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class C> = bind_name a, %.loc18_16 [template = %.loc18_16]
+// CHECK:STDOUT:   %.loc18_28: <unbound element of class C> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class C> = bind_name b, %.loc18_28 [template = %.loc18_28]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -72,7 +69,7 @@ fn G() -> C {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> %return: C {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C [template = constants.%C]
+// CHECK:STDOUT:   %C.ref: type = name_ref C, constants.%C [template = constants.%C]
 // CHECK:STDOUT:   %c: ref C = bind_name c, %return
 // CHECK:STDOUT:   %.loc20_29: i32 = int_literal 1 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc20_37: i32 = int_literal 2 [template = constants.%.6]

+ 1 - 1
toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon

@@ -30,7 +30,7 @@ fn Procedure() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc14_20.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc14_20.2: type = converted %.loc14_20.1, constants.%.1 [template = constants.%.1]
-// CHECK:STDOUT:   %v: () = bind_name v, <error>
+// CHECK:STDOUT:   %v: () = bind_name v, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc14_25: () = tuple_literal ()
 // CHECK:STDOUT:   assign <error>, <error>
 // CHECK:STDOUT:   return

+ 1 - 1
toolchain/check/testdata/return/fail_returned_var_type.carbon

@@ -28,7 +28,7 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Mismatch() -> i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %v: f64 = bind_name v, <error>
+// CHECK:STDOUT:   %v: f64 = bind_name v, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc14: f64 = real_literal 0e-1 [template = constants.%.1]
 // CHECK:STDOUT:   assign <error>, <error>
 // CHECK:STDOUT:   return <error>

+ 5 - 8
toolchain/check/testdata/return/returned_var.carbon

@@ -34,18 +34,15 @@ fn G() -> i32 {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace package, {.C = %C.decl, .F = %F, .G = %G} [template]
 // CHECK:STDOUT:   %C.decl = class_decl @C, ()
-// CHECK:STDOUT:   %C: type = class_type @C [template = constants.%C]
 // CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
 // CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc8_8.1: type = unbound_element_type C, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc8_8.2: <unbound element of class C> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %a: <unbound element of class C> = bind_name a, %.loc8_8.2 [template = %.loc8_8.2]
-// CHECK:STDOUT:   %.loc9_8.1: type = unbound_element_type C, i32 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_8.2: <unbound element of class C> = field_decl b, element1 [template]
-// CHECK:STDOUT:   %b: <unbound element of class C> = bind_name b, %.loc9_8.2 [template = %.loc9_8.2]
+// CHECK:STDOUT:   %.loc8: <unbound element of class C> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %a: <unbound element of class C> = bind_name a, %.loc8 [template = %.loc8]
+// CHECK:STDOUT:   %.loc9: <unbound element of class C> = field_decl b, element1 [template]
+// CHECK:STDOUT:   %b: <unbound element of class C> = bind_name b, %.loc9 [template = %.loc9]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %a
@@ -54,7 +51,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> %return: C {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C [template = constants.%C]
+// CHECK:STDOUT:   %C.ref: type = name_ref C, constants.%C [template = constants.%C]
 // CHECK:STDOUT:   %result: ref C = bind_name result, %return
 // CHECK:STDOUT:   %.loc13_34: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_42: i32 = int_literal 2 [template = constants.%.5]

+ 1 - 1
toolchain/check/testdata/struct/fail_access_into_invalid.carbon

@@ -19,7 +19,7 @@ fn F() { a.b; }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error>
+// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

Некоторые файлы не были показаны из-за большого количества измененных файлов