Jelajahi Sumber

Model `var` as a pattern operator (#4720)

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Geoff Romer 1 tahun lalu
induk
melakukan
13434f0e8a
100 mengubah file dengan 2837 tambahan dan 802 penghapusan
  1. 5 0
      common/array_stack.h
  2. 2 0
      toolchain/check/BUILD
  3. 9 0
      toolchain/check/context.cpp
  4. 14 0
      toolchain/check/context.h
  5. 1 1
      toolchain/check/decl_introducer_state.h
  6. 2 0
      toolchain/check/eval.cpp
  7. 82 0
      toolchain/check/full_pattern_stack.h
  8. 130 95
      toolchain/check/handle_binding_pattern.cpp
  9. 1 0
      toolchain/check/handle_impl.cpp
  10. 127 135
      toolchain/check/handle_let_and_var.cpp
  11. 5 0
      toolchain/check/handle_modifier.cpp
  12. 1 0
      toolchain/check/handle_name.cpp
  13. 4 3
      toolchain/check/keyword_modifier_set.h
  14. 1 0
      toolchain/check/name_component.cpp
  15. 1 0
      toolchain/check/node_stack.h
  16. 61 8
      toolchain/check/pattern_match.cpp
  17. 5 0
      toolchain/check/pattern_match.h
  18. 12 28
      toolchain/check/return.cpp
  19. 13 9
      toolchain/check/return.h
  20. 7 1
      toolchain/check/scope_stack.h
  21. 12 2
      toolchain/check/testdata/alias/fail_bool_value.carbon
  22. 11 8
      toolchain/check/testdata/alias/no_prelude/alias_of_alias.carbon
  23. 28 5
      toolchain/check/testdata/alias/no_prelude/export_name.carbon
  24. 16 7
      toolchain/check/testdata/alias/no_prelude/fail_aliased_name_in_diag.carbon
  25. 14 4
      toolchain/check/testdata/alias/no_prelude/fail_name_conflict.carbon
  26. 21 4
      toolchain/check/testdata/alias/no_prelude/fail_not_constant.carbon
  27. 56 8
      toolchain/check/testdata/alias/no_prelude/import.carbon
  28. 22 4
      toolchain/check/testdata/alias/no_prelude/import_access.carbon
  29. 33 9
      toolchain/check/testdata/alias/no_prelude/import_order.carbon
  30. 23 13
      toolchain/check/testdata/alias/no_prelude/in_namespace.carbon
  31. 11 3
      toolchain/check/testdata/alias/no_prelude/local.carbon
  32. 19 3
      toolchain/check/testdata/array/array_in_place.carbon
  33. 36 11
      toolchain/check/testdata/array/array_vs_tuple.carbon
  34. 13 3
      toolchain/check/testdata/array/assign_return_value.carbon
  35. 29 4
      toolchain/check/testdata/array/assign_var.carbon
  36. 41 6
      toolchain/check/testdata/array/base.carbon
  37. 87 6
      toolchain/check/testdata/array/canonicalize_index.carbon
  38. 43 1
      toolchain/check/testdata/array/fail_bound_negative.carbon
  39. 26 2
      toolchain/check/testdata/array/fail_bound_overflow.carbon
  40. 21 2
      toolchain/check/testdata/array/fail_incomplete_element.carbon
  41. 12 1
      toolchain/check/testdata/array/fail_invalid_type.carbon
  42. 10 0
      toolchain/check/testdata/array/fail_out_of_bound.carbon
  43. 20 2
      toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon
  44. 64 0
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  45. 17 8
      toolchain/check/testdata/array/generic_empty.carbon
  46. 20 2
      toolchain/check/testdata/array/index_not_literal.carbon
  47. 29 11
      toolchain/check/testdata/array/init_dependent_bound.carbon
  48. 12 2
      toolchain/check/testdata/array/nine_elements.carbon
  49. 130 41
      toolchain/check/testdata/as/adapter_conversion.carbon
  50. 5 2
      toolchain/check/testdata/as/as_type.carbon
  51. 14 3
      toolchain/check/testdata/as/fail_no_conversion.carbon
  52. 9 2
      toolchain/check/testdata/as/fail_not_type.carbon
  53. 26 10
      toolchain/check/testdata/as/identity.carbon
  54. 25 6
      toolchain/check/testdata/as/no_prelude/tuple.carbon
  55. 15 4
      toolchain/check/testdata/as/overloaded.carbon
  56. 30 2
      toolchain/check/testdata/basics/builtin_types.carbon
  57. 6 2
      toolchain/check/testdata/basics/fail_non_type_as_type.carbon
  58. 75 33
      toolchain/check/testdata/basics/fail_numeric_literal_overflow.carbon
  59. 31 6
      toolchain/check/testdata/basics/numeric_literals.carbon
  60. 16 0
      toolchain/check/testdata/basics/parens.carbon
  61. 48 0
      toolchain/check/testdata/basics/type_literals.carbon
  62. 122 0
      toolchain/check/testdata/builtins/bool/eq.carbon
  63. 10 0
      toolchain/check/testdata/builtins/bool/make_type.carbon
  64. 122 0
      toolchain/check/testdata/builtins/bool/neq.carbon
  65. 10 0
      toolchain/check/testdata/builtins/float/add.carbon
  66. 36 8
      toolchain/check/testdata/builtins/float/div.carbon
  67. 67 2
      toolchain/check/testdata/builtins/float/make_type.carbon
  68. 10 0
      toolchain/check/testdata/builtins/float/mul.carbon
  69. 13 4
      toolchain/check/testdata/builtins/float/negate.carbon
  70. 10 0
      toolchain/check/testdata/builtins/float/sub.carbon
  71. 20 6
      toolchain/check/testdata/builtins/read/int.carbon
  72. 107 29
      toolchain/check/testdata/class/access_modifers.carbon
  73. 10 2
      toolchain/check/testdata/class/adapter/adapt.carbon
  74. 103 45
      toolchain/check/testdata/class/adapter/adapt_copy.carbon
  75. 21 5
      toolchain/check/testdata/class/adapter/extend_adapt.carbon
  76. 25 5
      toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon
  77. 142 84
      toolchain/check/testdata/class/adapter/init_adapt.carbon
  78. 17 5
      toolchain/check/testdata/class/base.carbon
  79. 26 6
      toolchain/check/testdata/class/base_field.carbon
  80. 6 2
      toolchain/check/testdata/class/base_method.carbon
  81. 5 1
      toolchain/check/testdata/class/basic.carbon
  82. 6 2
      toolchain/check/testdata/class/complete_in_member_fn.carbon
  83. 29 9
      toolchain/check/testdata/class/compound_field.carbon
  84. 44 7
      toolchain/check/testdata/class/cross_package_import.carbon
  85. 32 14
      toolchain/check/testdata/class/derived_to_base.carbon
  86. 41 8
      toolchain/check/testdata/class/fail_abstract.carbon
  87. 6 2
      toolchain/check/testdata/class/fail_base_bad_type.carbon
  88. 6 2
      toolchain/check/testdata/class/fail_base_unbound.carbon
  89. 11 3
      toolchain/check/testdata/class/fail_compound_type_mismatch.carbon
  90. 5 1
      toolchain/check/testdata/class/fail_convert_to_invalid.carbon
  91. 15 3
      toolchain/check/testdata/class/fail_derived_to_base.carbon
  92. 5 1
      toolchain/check/testdata/class/fail_extend_cycle.carbon
  93. 30 8
      toolchain/check/testdata/class/fail_field_modifiers.carbon
  94. 5 1
      toolchain/check/testdata/class/fail_generic_method.carbon
  95. 6 1
      toolchain/check/testdata/class/fail_import_misuses.carbon
  96. 17 4
      toolchain/check/testdata/class/fail_incomplete.carbon
  97. 10 2
      toolchain/check/testdata/class/fail_init.carbon
  98. 17 4
      toolchain/check/testdata/class/fail_init_as_inplace.carbon
  99. 6 2
      toolchain/check/testdata/class/fail_memaccess_category.carbon
  100. 5 2
      toolchain/check/testdata/class/fail_member_of_let.carbon

+ 5 - 0
common/array_stack.h

@@ -47,6 +47,11 @@ class ArrayStack {
     return llvm::ArrayRef(values_).slice(array_offsets_.back());
   }
 
+  auto PeekArray() -> llvm::MutableArrayRef<ValueT> {
+    CARBON_CHECK(!array_offsets_.empty());
+    return llvm::MutableArrayRef(values_).slice(array_offsets_.back());
+  }
+
   // Returns the array at a specific index.
   auto PeekArrayAt(int index) const -> llvm::ArrayRef<ValueT> {
     auto ref = llvm::ArrayRef(values_).slice(array_offsets_[index]);

+ 2 - 0
toolchain/check/BUILD

@@ -74,6 +74,7 @@ cc_library(
         "//common:array_stack",
         "//common:check",
         "//common:map",
+        "//common:set",
         "//common:vlog",
         "//toolchain/base:index_base",
         "//toolchain/base:kind_switch",
@@ -254,6 +255,7 @@ cc_library(
     name = "scope_stack",
     srcs = ["scope_stack.cpp"],
     hdrs = [
+        "full_pattern_stack.h",
         "lexical_lookup.h",
         "scope_index.h",
         "scope_stack.h",

+ 9 - 0
toolchain/check/context.cpp

@@ -395,6 +395,14 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
     }
   }
 
+  if (lexical_result == SemIR::InstId::InitTombstone) {
+    CARBON_DIAGNOSTIC(UsedBeforeInitialization, Error,
+                      "`{0}` used before initialization", SemIR::NameId);
+    emitter_->Emit(node_id, UsedBeforeInitialization, name_id);
+    return {.specific_id = SemIR::SpecificId::Invalid,
+            .inst_id = SemIR::ErrorInst::SingletonInstId};
+  }
+
   if (lexical_result.is_valid()) {
     // A lexical scope never needs an associated specific. If there's a
     // lexically enclosing generic, then it also encloses the point of use of
@@ -776,6 +784,7 @@ auto Context::AddConvergenceBlockAndPush(Parse::NodeId node_id, int num_blocks)
       if (new_block_id == SemIR::InstBlockId::Unreachable) {
         new_block_id = inst_blocks().AddDefaultValue();
       }
+      CARBON_CHECK(node_id.is_valid());
       AddInst<SemIR::Branch>(node_id, {.target_id = new_block_id});
     }
     inst_block_stack().Pop();

+ 14 - 0
toolchain/check/context.h

@@ -11,6 +11,7 @@
 #include "toolchain/check/decl_introducer_state.h"
 #include "toolchain/check/decl_name_stack.h"
 #include "toolchain/check/diagnostic_helpers.h"
+#include "toolchain/check/full_pattern_stack.h"
 #include "toolchain/check/generic_region_stack.h"
 #include "toolchain/check/global_init.h"
 #include "toolchain/check/inst_block_stack.h"
@@ -714,6 +715,14 @@ class Context {
     return bind_name_map_;
   }
 
+  auto var_storage_map() -> Map<SemIR::InstId, SemIR::InstId>& {
+    return var_storage_map_;
+  }
+
+  auto full_pattern_stack() -> FullPatternStack& {
+    return scope_stack_.full_pattern_stack();
+  }
+
  private:
   // A FoldingSet node for a type.
   class TypeNode : public llvm::FastFoldingSetNode {
@@ -831,6 +840,11 @@ class Context {
 
   Map<SemIR::InstId, BindingPatternInfo> bind_name_map_;
 
+  // Map from VarPattern insts to the corresponding VarStorage insts. The
+  // VarStorage insts are allocated, emitted, and stored in the map after
+  // processing the enclosing full-pattern.
+  Map<SemIR::InstId, SemIR::InstId> var_storage_map_;
+
   // Stack of single-entry regions being built.
   ArrayStack<SemIR::InstBlockId> region_stack_;
 };

+ 1 - 1
toolchain/check/decl_introducer_state.h

@@ -15,7 +15,7 @@ namespace Carbon::Check {
 // declaration and the keyword modifiers that apply to that declaration
 // introducer.
 struct DeclIntroducerState {
-  auto modifier_node_id(ModifierOrder order) -> Parse::NodeId {
+  auto modifier_node_id(ModifierOrder order) const -> Parse::NodeId {
     return ordered_modifier_node_ids[static_cast<int8_t>(order)];
   }
   auto set_modifier_node_id(ModifierOrder order, Parse::NodeId node_id)

+ 2 - 0
toolchain/check/eval.cpp

@@ -2076,6 +2076,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
     case SemIR::BranchIf::Kind:
     case SemIR::BranchWithArg::Kind:
     case SemIR::ImportDecl::Kind:
+    case SemIR::NameBindingDecl::Kind:
     case SemIR::OutParam::Kind:
     case SemIR::OutParamPattern::Kind:
     case SemIR::RequirementEquivalent::Kind:
@@ -2087,6 +2088,7 @@ static auto TryEvalInstInContext(EvalContext& eval_context,
     case SemIR::StructLiteral::Kind:
     case SemIR::TupleLiteral::Kind:
     case SemIR::ValueParam::Kind:
+    case SemIR::VarPattern::Kind:
     case SemIR::VarStorage::Kind:
       break;
 

+ 82 - 0
toolchain/check/full_pattern_stack.h

@@ -0,0 +1,82 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_
+#define CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_
+
+#include "common/array_stack.h"
+#include "common/check.h"
+#include "toolchain/check/lexical_lookup.h"
+#include "toolchain/sem_ir/ids.h"
+
+namespace Carbon::Check {
+
+// Stack of full-patterns currently being checked. When a pattern
+// is followed by an explicit initializer, name bindings should not be used
+// within that initializer, although they are usable before it (within the
+// pattern) and after it. This class keeps track of those state transitions.
+// It is structured as a stack to handle situations like a pattern that
+// contains an initializer, or a pattern in a lambda in an expression pattern.
+//
+// TODO: Unify this with Context::pattern_block_stack, or differentiate them
+// more clearly (and consider unifying this with ScopeStack instead).
+class FullPatternStack {
+ public:
+  explicit FullPatternStack(LexicalLookup* lookup) : lookup_(lookup) {}
+
+  // Marks the possible start of a new full-pattern (i.e. a pattern which occurs
+  // in a non-pattern context).
+  auto PushFullPattern() -> void { bind_name_stack_.PushArray(); }
+
+  // Marks the start of the initializer for the full-pattern at the top of the
+  // stack.
+  auto StartPatternInitializer() -> void {
+    for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {
+      CARBON_CHECK(inst_id == SemIR::InstId::InitTombstone);
+      auto& lookup_result = lookup_->Get(name_id);
+      if (!lookup_result.empty()) {
+        // TODO: find a way to preserve location information, so that we can
+        // provide good diagnostics for a redeclaration of `name_id` in
+        // the initializer, if that becomes possible.
+        std::swap(lookup_result.back().inst_id, inst_id);
+      }
+    }
+  }
+
+  // Marks the end of the initializer for the full-pattern at the top of the
+  // stack.
+  auto EndPatternInitializer() -> void {
+    for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {
+      auto& lookup_result = lookup_->Get(name_id);
+      if (!lookup_result.empty()) {
+        std::swap(lookup_result.back().inst_id, inst_id);
+      }
+      CARBON_CHECK(inst_id == SemIR::InstId::InitTombstone);
+    }
+  }
+
+  // Marks the end of checking for the full-pattern at the top of the stack.
+  // This cannot be called while processing an initializer for the top
+  // pattern.
+  auto PopFullPattern() -> void { bind_name_stack_.PopArray(); }
+
+  // Records that `bind_inst_id` was introduced by the full-pattern at the
+  // top of the stack.
+  auto AddBindName(SemIR::NameId name_id) -> void {
+    bind_name_stack_.AppendToTop(
+        {.name_id = name_id, .inst_id = SemIR::InstId::InitTombstone});
+  }
+
+ private:
+  LexicalLookup* lookup_;
+  struct LookupEntry {
+    SemIR::NameId name_id;
+    SemIR::InstId inst_id;
+  };
+  ArrayStack<LookupEntry> bind_name_stack_;
+};
+
+}  // namespace Carbon::Check
+
+#endif  // CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_

+ 130 - 95
toolchain/check/handle_binding_pattern.cpp

@@ -5,6 +5,7 @@
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
 #include "toolchain/check/handle.h"
+#include "toolchain/check/interface.h"
 #include "toolchain/check/return.h"
 #include "toolchain/diagnostics/format_providers.h"
 #include "toolchain/sem_ir/ids.h"
@@ -14,6 +15,7 @@ namespace Carbon::Check {
 
 static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
                                     bool is_generic) -> bool {
+  // TODO: split this into smaller, more focused functions.
   auto [type_node, parsed_type_id] = context.node_stack().PopExprWithNodeId();
   auto [cast_type_inst_id, cast_type_id] =
       ExprAsType(context, type_node, parsed_type_id);
@@ -39,9 +41,12 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
 
   bool needs_compile_time_binding = is_generic && !is_associated_constant;
 
-  // Create the appropriate kind of binding for this pattern.
-  auto make_bind_name = [&](SemIR::TypeId type_id,
-                            SemIR::InstId value_id) -> SemIR::LocIdAndInst {
+  const DeclIntroducerState& introducer =
+      context.decl_introducer_state_stack().innermost();
+
+  auto make_binding_pattern = [&]() -> SemIR::InstId {
+    auto bind_id = SemIR::InstId::Invalid;
+    auto binding_pattern_id = SemIR::InstId::Invalid;
     // TODO: Eventually the name will need to support associations with other
     // scopes, but right now we don't support qualified names here.
     auto entity_name_id = context.entity_names().Add(
@@ -54,25 +59,43 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
                            : SemIR::CompileTimeBindIndex::Invalid});
     if (is_generic) {
       // TODO: Create a `BindTemplateName` instead inside a `template` pattern.
-      return SemIR::LocIdAndInst(
-          name_node, SemIR::BindSymbolicName{.type_id = type_id,
-                                             .entity_name_id = entity_name_id,
-                                             .value_id = value_id});
+      bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst(
+          name_node,
+          SemIR::BindSymbolicName{.type_id = cast_type_id,
+                                  .entity_name_id = entity_name_id,
+                                  .value_id = SemIR::InstId::Invalid}));
+      binding_pattern_id =
+          context.AddPatternInst<SemIR::SymbolicBindingPattern>(
+              name_node,
+              {.type_id = cast_type_id, .entity_name_id = entity_name_id});
     } else {
-      return SemIR::LocIdAndInst(
-          name_node, SemIR::BindName{.type_id = type_id,
+      bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst(
+          name_node, SemIR::BindName{.type_id = cast_type_id,
                                      .entity_name_id = entity_name_id,
-                                     .value_id = value_id});
+                                     .value_id = SemIR::InstId::Invalid}));
+      binding_pattern_id = context.AddPatternInst<SemIR::BindingPattern>(
+          name_node,
+          {.type_id = cast_type_id, .entity_name_id = entity_name_id});
     }
-  };
 
-  // Push the binding onto the node stack and, if necessary, onto the scope
-  // stack.
-  auto push_bind_name = [&](SemIR::InstId bind_id) {
-    context.node_stack().Push(node_id, bind_id);
+    // Add name to lookup immediately, so it can be used in the rest of the
+    // enclosing pattern.
     if (needs_compile_time_binding) {
       context.scope_stack().PushCompileTimeBinding(bind_id);
     }
+    auto name_context =
+        context.decl_name_stack().MakeUnqualifiedName(node_id, name_id);
+    context.decl_name_stack().AddNameOrDiagnose(
+        name_context, bind_id, introducer.modifier_set.GetAccessKind());
+    context.full_pattern_stack().AddBindName(name_id);
+
+    bool inserted = context.bind_name_map()
+                        .Insert(binding_pattern_id,
+                                {.bind_name_id = bind_id,
+                                 .type_expr_region_id = type_expr_region_id})
+                        .is_inserted();
+    CARBON_CHECK(inserted);
+    return binding_pattern_id;
   };
 
   // A `self` binding can only appear in an implicit parameter list.
@@ -84,12 +107,84 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
     context.emitter().Emit(node_id, SelfOutsideImplicitParamList);
   }
 
-  // Allocate an instruction of the appropriate kind, linked to the name for
-  // error locations.
   // TODO: The node stack is a fragile way of getting context information.
   // Get this information from somewhere else.
-  switch (auto context_node_kind = context.node_stack().PeekNodeKind()) {
-    case Parse::NodeKind::ReturnedModifier:
+  auto context_node_kind = context.node_stack().PeekNodeKind();
+
+  // A `var` binding in a class scope declares a field, not a true binding,
+  // so we handle it separately.
+  if (auto parent_class_decl = context.GetCurrentScopeAs<SemIR::ClassDecl>();
+      parent_class_decl.has_value() &&
+      context_node_kind == Parse::NodeKind::VariableIntroducer) {
+    cast_type_id = context.AsConcreteType(
+        cast_type_id, type_node,
+        [&] {
+          CARBON_DIAGNOSTIC(IncompleteTypeInFieldDecl, Error,
+                            "field has incomplete type {0}", SemIR::TypeId);
+          return context.emitter().Build(type_node, IncompleteTypeInFieldDecl,
+                                         cast_type_id);
+        },
+        [&] {
+          CARBON_DIAGNOSTIC(AbstractTypeInFieldDecl, Error,
+                            "field has abstract type {0}", SemIR::TypeId);
+          return context.emitter().Build(type_node, AbstractTypeInFieldDecl,
+                                         cast_type_id);
+        });
+    auto binding_id =
+        is_generic ? Parse::NodeId::Invalid
+                   : context.parse_tree().As<Parse::BindingPatternId>(node_id);
+    auto& class_info = context.classes().Get(parent_class_decl->class_id);
+    auto field_type_id =
+        context.GetUnboundElementType(class_info.self_type_id, cast_type_id);
+    auto field_id = context.AddInst<SemIR::FieldDecl>(
+        binding_id, {.type_id = field_type_id,
+                     .name_id = name_id,
+                     .index = SemIR::ElementIndex::Invalid});
+    context.field_decls_stack().AppendToTop(field_id);
+
+    context.node_stack().Push(node_id, field_id);
+    auto name_context =
+        context.decl_name_stack().MakeUnqualifiedName(node_id, name_id);
+    context.decl_name_stack().AddNameOrDiagnose(
+        name_context, field_id, introducer.modifier_set.GetAccessKind());
+    return true;
+  }
+
+  // A binding in an interface scope declares an associated constant, not a
+  // true binding, so we handle it separately.
+  if (auto parent_interface_decl =
+          context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
+      parent_interface_decl.has_value() && is_generic) {
+    cast_type_id = context.AsCompleteType(cast_type_id, type_node, [&] {
+      CARBON_DIAGNOSTIC(IncompleteTypeInAssociatedDecl, Error,
+                        "associated constant has incomplete type {0}",
+                        SemIR::TypeId);
+      return context.emitter().Build(type_node, IncompleteTypeInAssociatedDecl,
+                                     cast_type_id);
+    });
+    context.entity_names().Add(
+        {.name_id = name_id,
+         .parent_scope_id = context.scope_stack().PeekNameScopeId(),
+         .bind_index = SemIR::CompileTimeBindIndex::Invalid});
+
+    SemIR::InstId decl_id = context.AddInst<SemIR::AssociatedConstantDecl>(
+        context.parse_tree().As<Parse::CompileTimeBindingPatternId>(node_id),
+        {cast_type_id, name_id});
+    context.node_stack().Push(node_id, decl_id);
+
+    // Add an associated entity name to the interface scope.
+    auto assoc_id = BuildAssociatedEntity(
+        context, parent_interface_decl->interface_id, decl_id);
+    auto name_context =
+        context.decl_name_stack().MakeUnqualifiedName(node_id, name_id);
+    context.decl_name_stack().AddNameOrDiagnose(
+        name_context, assoc_id, introducer.modifier_set.GetAccessKind());
+    return true;
+  }
+
+  // Allocate an instruction of the appropriate kind, linked to the name for
+  // error locations.
+  switch (context_node_kind) {
     case Parse::NodeKind::VariableIntroducer: {
       if (is_generic) {
         CARBON_DIAGNOSTIC(
@@ -99,64 +194,36 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
         // Prevent lambda helpers from creating a compile time binding.
         needs_compile_time_binding = false;
       }
-      auto binding_id =
-          is_generic
-              ? Parse::NodeId::Invalid
-              : context.parse_tree().As<Parse::BindingPatternId>(node_id);
 
-      // A `var` declaration at class scope introduces a field.
-      auto parent_class_decl = context.GetCurrentScopeAs<SemIR::ClassDecl>();
       cast_type_id = context.AsConcreteType(
           cast_type_id, type_node,
           [&] {
             CARBON_DIAGNOSTIC(IncompleteTypeInVarDecl, Error,
-                              "{0:field|variable} has incomplete type {1}",
-                              BoolAsSelect, SemIR::TypeId);
+                              "variable has incomplete type {0}",
+                              SemIR::TypeId);
             return context.emitter().Build(type_node, IncompleteTypeInVarDecl,
-                                           parent_class_decl.has_value(),
                                            cast_type_id);
           },
           [&] {
             CARBON_DIAGNOSTIC(AbstractTypeInVarDecl, Error,
-                              "{0:field|variable} has abstract type {1}",
-                              BoolAsSelect, SemIR::TypeId);
+                              "variable has abstract type {0}", SemIR::TypeId);
             return context.emitter().Build(type_node, AbstractTypeInVarDecl,
-                                           parent_class_decl.has_value(),
                                            cast_type_id);
           });
-      if (parent_class_decl) {
-        CARBON_CHECK(context_node_kind == Parse::NodeKind::VariableIntroducer,
-                     "`returned var` at class scope");
-        auto& class_info = context.classes().Get(parent_class_decl->class_id);
-        auto field_type_id = context.GetUnboundElementType(
-            class_info.self_type_id, cast_type_id);
-        auto field_id = context.AddInst<SemIR::FieldDecl>(
-            binding_id, {.type_id = field_type_id,
-                         .name_id = name_id,
-                         .index = SemIR::ElementIndex::Invalid});
-        context.field_decls_stack().AppendToTop(field_id);
-
-        context.node_stack().Push(node_id, field_id);
-        break;
-      }
 
-      SemIR::InstId value_id = SemIR::InstId::Invalid;
-      if (context_node_kind == Parse::NodeKind::ReturnedModifier) {
+      auto binding_pattern_id = make_binding_pattern();
+      if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Returned)) {
         // TODO: Should we check this for the `var` as a whole, rather than for
         // the name binding?
-        value_id =
-            CheckReturnedVar(context, context.node_stack().PeekNodeId(),
-                             name_node, name_id, type_node, cast_type_id);
-      } else {
-        value_id = context.AddInst<SemIR::VarStorage>(
-            name_node, {.type_id = cast_type_id, .name_id = name_id});
-      }
-      auto bind_id = context.AddInst(make_bind_name(cast_type_id, value_id));
-      push_bind_name(bind_id);
-
-      if (context_node_kind == Parse::NodeKind::ReturnedModifier) {
-        RegisterReturnedVar(context, bind_id);
+        auto bind_id = context.bind_name_map()
+                           .Lookup(binding_pattern_id)
+                           .value()
+                           .bind_name_id;
+        RegisterReturnedVar(context,
+                            introducer.modifier_node_id(ModifierOrder::Decl),
+                            type_node, cast_type_id, bind_id);
       }
+      context.node_stack().Push(node_id, binding_pattern_id);
       break;
     }
 
@@ -168,7 +235,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
       // parameters.
       auto param_pattern_id = SemIR::InstId::Invalid;
       bool had_error = false;
-      switch (context.decl_introducer_state_stack().innermost().kind) {
+      switch (introducer.kind) {
         case Lex::TokenKind::Fn: {
           if (context_node_kind == Parse::NodeKind::ImplicitParamListStart &&
               !(is_generic || name_id == SemIR::NameId::SelfValue)) {
@@ -205,33 +272,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
         // try constructing a generic based on it.
         param_pattern_id = SemIR::ErrorInst::SingletonInstId;
       } else {
-        auto bind_id = context.AddInstInNoBlock(
-            make_bind_name(cast_type_id, SemIR::InstId::Invalid));
-        if (needs_compile_time_binding) {
-          context.scope_stack().PushCompileTimeBinding(bind_id);
-        }
-        // TODO: Bindings should come into scope immediately in other contexts
-        // too.
-        context.AddNameToLookup(name_id, bind_id);
-        auto entity_name_id =
-            context.insts().GetAs<SemIR::AnyBindName>(bind_id).entity_name_id;
-        auto pattern_inst_id = SemIR::InstId::Invalid;
-        if (is_generic) {
-          pattern_inst_id =
-              context.AddPatternInst<SemIR::SymbolicBindingPattern>(
-                  name_node,
-                  {.type_id = cast_type_id, .entity_name_id = entity_name_id});
-        } else {
-          pattern_inst_id = context.AddPatternInst<SemIR::BindingPattern>(
-              name_node,
-              {.type_id = cast_type_id, .entity_name_id = entity_name_id});
-        }
-        bool inserted = context.bind_name_map()
-                            .Insert(pattern_inst_id, {.bind_name_id = bind_id,
-                                                      .type_expr_region_id =
-                                                          type_expr_region_id})
-                            .is_inserted();
-        CARBON_CHECK(inserted);
+        auto pattern_inst_id = make_binding_pattern();
         param_pattern_id = context.AddPatternInst<SemIR::ValueParamPattern>(
             node_id,
             {
@@ -257,13 +298,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
         return context.emitter().Build(type_node, IncompleteTypeInLetDecl,
                                        cast_type_inst_id);
       });
-      // Create the instruction, but don't add it to a block until after we've
-      // formed its initializer.
-      // TODO: For general pattern parsing, we'll need to create a block to hold
-      // the `let` pattern before we see the initializer.
-      auto bind_id = context.AddPlaceholderInstInNoBlock(
-          make_bind_name(cast_type_id, SemIR::InstId::Invalid));
-      push_bind_name(bind_id);
+      context.node_stack().Push(node_id, make_binding_pattern());
       break;
     }
 

+ 1 - 0
toolchain/check/handle_impl.cpp

@@ -42,6 +42,7 @@ auto HandleParseNode(Context& context, Parse::ImplIntroducerId node_id)
   // TODO: Instead use a separate parse node kinds for `impl` and `impl forall`,
   // and only push a pattern block in `forall` case.
   context.pattern_block_stack().Push();
+  context.full_pattern_stack().PushFullPattern();
   return true;
 }
 

+ 127 - 135
toolchain/check/handle_let_and_var.cpp

@@ -8,6 +8,8 @@
 #include "toolchain/check/handle.h"
 #include "toolchain/check/interface.h"
 #include "toolchain/check/modifiers.h"
+#include "toolchain/check/pattern_match.h"
+#include "toolchain/check/return.h"
 #include "toolchain/diagnostics/diagnostic_emitter.h"
 #include "toolchain/lex/token_kind.h"
 #include "toolchain/sem_ir/inst.h"
@@ -22,6 +24,7 @@ static auto HandleIntroducer(Context& context, Parse::NodeId node_id) -> bool {
   // Push a bracketing node and pattern block to establish the pattern context.
   context.node_stack().Push(node_id);
   context.pattern_block_stack().Push();
+  context.full_pattern_stack().PushFullPattern();
   context.BeginSubpattern();
   return true;
 }
@@ -35,18 +38,91 @@ auto HandleParseNode(Context& context, Parse::VariableIntroducerId node_id)
   return HandleIntroducer<Lex::TokenKind::Var>(context, node_id);
 }
 
-auto HandleParseNode(Context& context, Parse::ReturnedModifierId node_id)
+// Returns a VarStorage inst for the given pattern. If the pattern
+// is the body of a returned var, this reuses the return slot, and otherwise it
+// adds a new inst.
+static auto GetOrAddStorage(Context& context, SemIR::InstId pattern_id)
+    -> SemIR::InstId {
+  if (context.decl_introducer_state_stack().innermost().modifier_set.HasAnyOf(
+          KeywordModifierSet::Returned)) {
+    auto& function = GetCurrentFunctionForReturn(context);
+    auto return_info =
+        SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(), function);
+    if (return_info.has_return_slot()) {
+      return GetCurrentReturnSlot(context);
+    }
+  }
+  auto pattern = context.insts().GetWithLocId(pattern_id);
+  auto subpattern =
+      context.insts().Get(pattern.inst.As<SemIR::VarPattern>().subpattern_id);
+
+  // Try to populate name_id on a best-effort basis.
+  auto name_id = SemIR::NameId::Invalid;
+  if (auto binding_pattern = subpattern.TryAs<SemIR::BindingPattern>()) {
+    name_id =
+        context.entity_names().Get(binding_pattern->entity_name_id).name_id;
+  }
+  return context.AddInst(SemIR::LocIdAndInst::UncheckedLoc(
+      pattern.loc_id, SemIR::VarStorage{.type_id = subpattern.type_id(),
+                                        .pretty_name_id = name_id}));
+}
+
+auto HandleParseNode(Context& context, Parse::VariablePatternId node_id)
     -> bool {
-  // This is pushed to be seen by HandleBindingPattern.
-  context.node_stack().Push(node_id);
+  auto subpattern_id = SemIR::InstId::Invalid;
+  if (context.node_stack().PeekIs(Parse::NodeKind::TuplePattern)) {
+    context.node_stack().PopAndIgnore();
+    CARBON_CHECK(
+        context.node_stack().PeekIs(Parse::NodeKind::TuplePatternStart));
+    context.node_stack().PopAndIgnore();
+    context.inst_block_stack().PopAndDiscard();
+    context.TODO(node_id, "tuple pattern in let/var");
+    subpattern_id = SemIR::ErrorInst::SingletonInstId;
+  } else {
+    subpattern_id = context.node_stack().PopPattern();
+  }
+  auto type_id = context.insts().Get(subpattern_id).type_id();
+
+  auto pattern_id = context.AddPatternInst<SemIR::VarPattern>(
+      node_id, {.type_id = type_id, .subpattern_id = subpattern_id});
+  context.node_stack().Push(node_id, pattern_id);
   return true;
 }
 
+// Handle the end of the full-pattern of a let/var declaration (before the
+// start of the initializer, if any).
+static auto EndFullPattern(Context& context) -> void {
+  if (context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
+    // Don't emit NameBindingDecl for an associated constant, because it will
+    // always be empty.
+    context.pattern_block_stack().PopAndDiscard();
+    return;
+  }
+  auto pattern_block_id = context.pattern_block_stack().Pop();
+  context.AddInst<SemIR::NameBindingDecl>(
+      context.node_stack().PeekNodeId(),
+      {.pattern_block_id = pattern_block_id});
+
+  // We need to emit the VarStorage insts early, because they may be output
+  // arguments for the initializer. However, we can't emit them when we emit
+  // the corresponding `VarPattern`s because they're part of the pattern match,
+  // not part of the pattern.
+  // TODO: find a way to do this without walking the whole pattern block.
+  for (auto inst_id : context.inst_blocks().Get(pattern_block_id)) {
+    if (context.insts().Is<SemIR::VarPattern>(inst_id)) {
+      context.var_storage_map().Insert(inst_id,
+                                       GetOrAddStorage(context, inst_id));
+    }
+  }
+}
+
 static auto HandleInitializer(Context& context, Parse::NodeId node_id) -> bool {
+  EndFullPattern(context);
   if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
     context.global_init().Resume();
   }
   context.node_stack().Push(node_id);
+  context.full_pattern_stack().StartPatternInitializer();
   return true;
 }
 
@@ -60,73 +136,6 @@ auto HandleParseNode(Context& context, Parse::VariableInitializerId node_id)
   return HandleInitializer(context, node_id);
 }
 
-// Builds an associated constant declaration for a `let`.
-static auto BuildAssociatedConstantDecl(Context& context,
-                                        Parse::LetDeclId node_id,
-                                        SemIR::InstId pattern_id,
-                                        SemIR::LocIdAndInst pattern,
-                                        SemIR::InterfaceId interface_id,
-                                        SemIR::AccessKind access_kind) -> void {
-  auto& interface_info = context.interfaces().Get(interface_id);
-
-  auto binding_pattern = pattern.inst.TryAs<SemIR::BindSymbolicName>();
-  if (!binding_pattern) {
-    CARBON_DIAGNOSTIC(ExpectedSymbolicBindingInAssociatedConstant, Error,
-                      "pattern in associated constant declaration must be a "
-                      "single `:!` binding");
-    context.emitter().Emit(pattern.loc_id,
-                           ExpectedSymbolicBindingInAssociatedConstant);
-    context.name_scopes().Get(interface_info.scope_id).set_has_error();
-    return;
-  }
-
-  // Replace the tentative BindName instruction with the associated constant
-  // declaration.
-  auto name_id =
-      context.entity_names().Get(binding_pattern->entity_name_id).name_id;
-  context.ReplaceLocIdAndInstBeforeConstantUse(
-      pattern_id,
-      SemIR::LocIdAndInst(node_id, SemIR::AssociatedConstantDecl{
-                                       binding_pattern->type_id, name_id}));
-  auto decl_id = pattern_id;
-  context.inst_block_stack().AddInstId(decl_id);
-
-  // Add an associated entity name to the interface scope.
-  auto assoc_id = BuildAssociatedEntity(context, interface_id, decl_id);
-  auto name_context =
-      context.decl_name_stack().MakeUnqualifiedName(pattern.loc_id, name_id);
-  context.decl_name_stack().AddNameOrDiagnose(name_context, assoc_id,
-                                              access_kind);
-}
-
-// Adds name bindings. Returns the resulting ID for the references.
-static auto HandleNameBinding(Context& context, SemIR::InstId pattern_id,
-                              SemIR::AccessKind access_kind) -> SemIR::InstId {
-  // Extract the name binding.
-  if (auto bind_name =
-          context.insts().TryGetAs<SemIR::AnyBindName>(pattern_id)) {
-    // Form a corresponding name in the current context, and bind the name to
-    // the variable.
-    auto name_context = context.decl_name_stack().MakeUnqualifiedName(
-        context.insts().GetLocId(pattern_id),
-        context.entity_names().Get(bind_name->entity_name_id).name_id);
-    context.decl_name_stack().AddNameOrDiagnose(name_context, pattern_id,
-                                                access_kind);
-    return bind_name->value_id;
-  } else if (auto field_decl =
-                 context.insts().TryGetAs<SemIR::FieldDecl>(pattern_id)) {
-    // Introduce the field name into the class.
-    auto name_context = context.decl_name_stack().MakeUnqualifiedName(
-        context.insts().GetLocId(pattern_id), field_decl->name_id);
-    context.decl_name_stack().AddNameOrDiagnose(name_context, pattern_id,
-                                                access_kind);
-    return pattern_id;
-  } else {
-    // TODO: Handle other kinds of pattern.
-    return pattern_id;
-  }
-}
-
 namespace {
 // State from HandleDecl, returned for type-specific handling.
 struct DeclInfo {
@@ -148,15 +157,18 @@ static auto HandleDecl(Context& context, NodeT node_id)
     -> std::optional<DeclInfo> {
   std::optional<DeclInfo> decl_info = DeclInfo();
 
-  // TODO: Update binding-pattern handling to use the pattern block even in
-  // a let/var context, and then consume it here.
-  context.pattern_block_stack().PopAndDiscard();
-
   // Handle the optional initializer.
   if (context.node_stack().PeekNextIs(InitializerNodeKind)) {
     decl_info->init_id = context.node_stack().PopExpr();
     context.node_stack().PopAndDiscardSoloNodeId<InitializerNodeKind>();
+    if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
+      context.global_init().Suspend();
+    }
+    context.full_pattern_stack().EndPatternInitializer();
+  } else {
+    EndFullPattern(context);
   }
+  context.full_pattern_stack().PopFullPattern();
 
   if (context.node_stack().PeekIs(Parse::NodeKind::TuplePattern)) {
     if (decl_info->init_id &&
@@ -170,12 +182,6 @@ static auto HandleDecl(Context& context, NodeT node_id)
 
   decl_info->pattern_id = context.node_stack().PopPattern();
 
-  if constexpr (IntroducerTokenKind == Lex::TokenKind::Var) {
-    // Pop the `returned` modifier if present.
-    context.node_stack()
-        .PopAndDiscardSoloNodeIdIf<Parse::NodeKind::ReturnedModifier>();
-  }
-
   context.node_stack().PopAndDiscardSoloNodeId<IntroducerNodeKind>();
 
   // Process declaration modifiers.
@@ -193,6 +199,32 @@ static auto HandleDecl(Context& context, NodeT node_id)
   return decl_info;
 }
 
+static auto HandleAssociatedConstantDecl(Context& context,
+                                         Parse::LetDeclId node_id,
+                                         DeclInfo decl_info,
+                                         SemIR::InterfaceDecl interface_scope)
+    -> void {
+  auto pattern = context.insts().GetWithLocId(decl_info.pattern_id);
+
+  if (decl_info.init_id) {
+    // Convert the value to match the type of the pattern.
+    ConvertToValueOfType(context, node_id, *decl_info.init_id,
+                         pattern.inst.type_id());
+  }
+
+  if (auto decl = pattern.inst.TryAs<SemIR::AssociatedConstantDecl>();
+      !decl.has_value()) {
+    CARBON_DIAGNOSTIC(ExpectedSymbolicBindingInAssociatedConstant, Error,
+                      "pattern in associated constant declaration must be a "
+                      "single `:!` binding");
+    context.emitter().Emit(pattern.loc_id,
+                           ExpectedSymbolicBindingInAssociatedConstant);
+    context.name_scopes()
+        .Get(context.interfaces().Get(interface_scope.interface_id).scope_id)
+        .set_has_error();
+  }
+}
+
 auto HandleParseNode(Context& context, Parse::LetDeclId node_id) -> bool {
   auto decl_info =
       HandleDecl<Lex::TokenKind::Let, Parse::NodeKind::LetIntroducer,
@@ -213,52 +245,24 @@ auto HandleParseNode(Context& context, Parse::LetDeclId node_id) -> bool {
                  "interface modifier");
   }
 
-  auto pattern = context.insts().GetWithLocId(decl_info->pattern_id);
-
-  if (decl_info->init_id) {
-    // Convert the value to match the type of the pattern.
-    decl_info->init_id = ConvertToValueOfType(
-        context, node_id, *decl_info->init_id, pattern.inst.type_id());
-  }
-
-  auto interface_scope = context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
-
   // At interface scope, we are forming an associated constant, which has
   // different rules.
-  if (interface_scope) {
-    BuildAssociatedConstantDecl(
-        context, node_id, decl_info->pattern_id, pattern,
-        interface_scope->interface_id,
-        decl_info->introducer.modifier_set.GetAccessKind());
+  if (auto interface_scope = context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
+      interface_scope) {
+    HandleAssociatedConstantDecl(context, node_id, *decl_info,
+                                 *interface_scope);
     return true;
   }
 
-  if (!decl_info->init_id) {
+  if (decl_info->init_id) {
+    LocalPatternMatch(context, decl_info->pattern_id, *decl_info->init_id);
+  } else {
     CARBON_DIAGNOSTIC(
         ExpectedInitializerAfterLet, Error,
         "expected `=`; `let` declaration must have an initializer");
     context.emitter().Emit(TokenOnly(node_id), ExpectedInitializerAfterLet);
   }
 
-  // Update the binding with its value and add it to the current block, after
-  // the computation of the value.
-  // TODO: Support other kinds of pattern here.
-  auto bind_name = pattern.inst.As<SemIR::AnyBindName>();
-  CARBON_CHECK(!bind_name.value_id.is_valid(),
-               "Binding should not already have a value!");
-  bind_name.value_id = decl_info->init_id ? *decl_info->init_id
-                                          : SemIR::ErrorInst::SingletonInstId;
-  context.ReplaceInstBeforeConstantUse(decl_info->pattern_id, bind_name);
-  context.inst_block_stack().AddInstId(decl_info->pattern_id);
-
-  HandleNameBinding(context, decl_info->pattern_id,
-                    decl_info->introducer.modifier_set.GetAccessKind());
-
-  if (decl_info->init_id &&
-      context.scope_stack().PeekIndex() == ScopeIndex::Package) {
-    context.global_init().Suspend();
-  }
-
   return true;
 }
 
@@ -270,32 +274,20 @@ auto HandleParseNode(Context& context, Parse::VariableDeclId node_id) -> bool {
     return false;
   }
 
-  LimitModifiersOnDecl(context, decl_info->introducer,
-                       KeywordModifierSet::Access);
-
-  decl_info->pattern_id =
-      HandleNameBinding(context, decl_info->pattern_id,
-                        decl_info->introducer.modifier_set.GetAccessKind());
+  LimitModifiersOnDecl(
+      context, decl_info->introducer,
+      KeywordModifierSet::Access | KeywordModifierSet::Returned);
 
-  // If there was an initializer, assign it to the storage.
-  if (decl_info->init_id) {
-    if (context.GetCurrentScopeAs<SemIR::ClassDecl>()) {
+  if (context.GetCurrentScopeAs<SemIR::ClassDecl>()) {
+    if (decl_info->init_id) {
       // TODO: In a class scope, we should instead save the initializer
       // somewhere so that we can use it as a default.
       context.TODO(node_id, "Field initializer");
-    } else {
-      decl_info->init_id = Initialize(context, node_id, decl_info->pattern_id,
-                                      *decl_info->init_id);
-      // TODO: Consider using different instruction kinds for assignment
-      // versus initialization.
-      context.AddInst<SemIR::Assign>(node_id, {.lhs_id = decl_info->pattern_id,
-                                               .rhs_id = *decl_info->init_id});
-    }
-
-    if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
-      context.global_init().Suspend();
     }
+    return true;
   }
+  LocalPatternMatch(context, decl_info->pattern_id,
+                    decl_info->init_id.value_or(SemIR::InstId::Invalid));
 
   return true;
 }

+ 5 - 0
toolchain/check/handle_modifier.cpp

@@ -119,4 +119,9 @@ auto HandleParseNode(Context& context, Parse::ExternModifierId node_id)
   return HandleModifier(context, node_id, KeywordModifierSet::Extern);
 }
 
+auto HandleParseNode(Context& context, Parse::ReturnedModifierId node_id)
+    -> bool {
+  return HandleModifier(context, node_id, KeywordModifierSet::Returned);
+}
+
 }  // namespace Carbon::Check

+ 1 - 0
toolchain/check/handle_name.cpp

@@ -143,6 +143,7 @@ auto HandleParseNode(Context& context,
                      Parse::IdentifierNameBeforeParamsId node_id) -> bool {
   // Push a pattern block stack entry to handle the parameter pattern.
   context.pattern_block_stack().Push();
+  context.full_pattern_stack().PushFullPattern();
   return HandleIdentifierName(context, node_id);
 }
 

+ 4 - 3
toolchain/check/keyword_modifier_set.h

@@ -45,6 +45,7 @@ class KeywordModifierSet {
     Final = 1 << 8,
     Impl = 1 << 9,
     Virtual = 1 << 10,
+    Returned = 1 << 11,
 
     // Sets of modifiers:
     Access = Private | Protected,
@@ -52,10 +53,10 @@ class KeywordModifierSet {
     Method = Abstract | Impl | Virtual,
     ImplDecl = Extend | Final,
     Interface = Default | Final,
-    Decl = Class | Method | ImplDecl | Interface | Export,
+    Decl = Class | Method | ImplDecl | Interface | Export | Returned,
     None = 0,
 
-    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Virtual)
+    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Returned)
   };
 
   // Default construct to empty.
@@ -112,7 +113,7 @@ class KeywordModifierSet {
   }
 
   // Returns the access kind from modifiers.
-  auto GetAccessKind() -> SemIR::AccessKind {
+  auto GetAccessKind() const -> SemIR::AccessKind {
     if (HasAnyOf(KeywordModifierSet::Protected)) {
       return SemIR::AccessKind::Protected;
     }

+ 1 - 0
toolchain/check/name_component.cpp

@@ -50,6 +50,7 @@ auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
         CalleePatternMatch(context, *implicit_param_patterns_id,
                            *param_patterns_id, return_slot_pattern_id);
     pattern_block_id = context.pattern_block_stack().Pop();
+    context.full_pattern_stack().PopFullPattern();
   }
 
   auto [name_loc_id, name_id] =

+ 1 - 0
toolchain/check/node_stack.h

@@ -406,6 +406,7 @@ class NodeStack {
         case Parse::NodeKind::ShortCircuitOperandAnd:
         case Parse::NodeKind::ShortCircuitOperandOr:
         case Parse::NodeKind::StructLiteralField:
+        case Parse::NodeKind::VariablePattern:
         case Parse::NodeKind::WhereOperand:
           return Id::KindFor<SemIR::InstId>();
         case Parse::NodeKind::IfCondition:

+ 61 - 8
toolchain/check/pattern_match.cpp

@@ -46,7 +46,9 @@ enum class MatchKind : uint8_t {
   // against the portion of the pattern below the ParamPattern insts.
   Callee,
 
-  // TODO: Add enumerator for non-function-call pattern match.
+  // Local pattern matching is pattern matching outside of a function call,
+  // such as in a let/var declaration.
+  Local,
 };
 
 // The collected state of a pattern-matching operation.
@@ -140,7 +142,7 @@ auto MatchContext::EmitPatternMatch(Context& context,
   CARBON_KIND_SWITCH(pattern.inst) {
     case SemIR::BindingPattern::Kind:
     case SemIR::SymbolicBindingPattern::Kind: {
-      CARBON_CHECK(kind_ == MatchKind::Callee);
+      auto binding_pattern = pattern.inst.As<SemIR::AnyBindingPattern>();
       // We're logically consuming this map entry, so we invalidate it in order
       // to avoid accidentally consuming it twice.
       auto [bind_name_id, type_expr_region_id] = std::exchange(
@@ -148,19 +150,34 @@ auto MatchContext::EmitPatternMatch(Context& context,
           {.bind_name_id = SemIR::InstId::Invalid,
            .type_expr_region_id = SemIR::ExprRegionId::Invalid});
       context.InsertHere(type_expr_region_id);
+      auto value_id = entry.scrutinee_id;
+      switch (kind_) {
+        case MatchKind::Local: {
+          value_id = ConvertToValueOrRefOfType(
+              context, context.insts().GetLocId(entry.scrutinee_id),
+              entry.scrutinee_id, binding_pattern.type_id);
+          break;
+        }
+        case MatchKind::Callee: {
+          if (context.insts()
+                  .GetAs<SemIR::AnyParam>(value_id)
+                  .runtime_index.is_valid()) {
+            results_.push_back(value_id);
+          }
+          break;
+        }
+        case MatchKind::Caller:
+          CARBON_FATAL("Found binding pattern during caller pattern match");
+      }
       auto bind_name = context.insts().GetAs<SemIR::AnyBindName>(bind_name_id);
       CARBON_CHECK(!bind_name.value_id.is_valid());
-      bind_name.value_id = entry.scrutinee_id;
+      bind_name.value_id = value_id;
       context.ReplaceInstBeforeConstantUse(bind_name_id, bind_name);
       context.inst_block_stack().AddInstId(bind_name_id);
-      if (context.insts()
-              .GetAs<SemIR::AnyParam>(entry.scrutinee_id)
-              .runtime_index.is_valid()) {
-        results_.push_back(entry.scrutinee_id);
-      }
       break;
     }
     case CARBON_KIND(SemIR::AddrPattern addr_pattern): {
+      CARBON_CHECK(kind_ != MatchKind::Local);
       if (kind_ == MatchKind::Callee) {
         // We're emitting pattern-match IR for the callee, but we're still on
         // the caller side of the pattern, so we traverse without emitting any
@@ -233,6 +250,9 @@ auto MatchContext::EmitPatternMatch(Context& context,
                     .pretty_name_id = GetPrettyName(context, param_pattern)})});
           break;
         }
+        case MatchKind::Local: {
+          CARBON_FATAL("Found ValueParamPattern during local pattern match");
+        }
       }
       break;
     }
@@ -267,6 +287,9 @@ auto MatchContext::EmitPatternMatch(Context& context,
                     .pretty_name_id = GetPrettyName(context, param_pattern)})});
           break;
         }
+        case MatchKind::Local: {
+          CARBON_FATAL("Found OutParamPattern during local pattern match");
+        }
       }
       break;
     }
@@ -284,6 +307,29 @@ auto MatchContext::EmitPatternMatch(Context& context,
       results_.push_back(entry.scrutinee_id);
       break;
     }
+    case CARBON_KIND(SemIR::VarPattern var_pattern): {
+      auto var_id = context.var_storage_map().Lookup(entry.pattern_id).value();
+      // TODO: Find a more efficient way to put these insts in the global_init
+      // block (or drop the distinction between the global_init block and the
+      // file scope?)
+      if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
+        context.global_init().Resume();
+      }
+      if (entry.scrutinee_id.is_valid()) {
+        auto init_id =
+            Initialize(context, pattern.loc_id, var_id, entry.scrutinee_id);
+        // TODO: Consider using different instruction kinds for assignment
+        // versus initialization.
+        context.AddInst<SemIR::Assign>(pattern.loc_id,
+                                       {.lhs_id = var_id, .rhs_id = init_id});
+      }
+      AddWork(
+          {.pattern_id = var_pattern.subpattern_id, .scrutinee_id = var_id});
+      if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
+        context.global_init().Suspend();
+      }
+      break;
+    }
     default: {
       CARBON_FATAL("Inst kind not handled: {0}", pattern.inst.kind());
     }
@@ -366,4 +412,11 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
   return match.DoWork(context);
 }
 
+auto LocalPatternMatch(Context& context, SemIR::InstId pattern_id,
+                       SemIR::InstId scrutinee_id) -> void {
+  MatchContext match(MatchKind::Local);
+  match.AddWork({.pattern_id = pattern_id, .scrutinee_id = scrutinee_id});
+  match.DoWork(context);
+}
+
 }  // namespace Carbon::Check

+ 5 - 0
toolchain/check/pattern_match.h

@@ -43,6 +43,11 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
                         llvm::ArrayRef<SemIR::InstId> arg_refs,
                         SemIR::InstId return_slot_arg_id) -> SemIR::InstBlockId;
 
+// Emits the pattern-match IR for a local pattern matching operation with the
+// given pattern and scrutinee.
+auto LocalPatternMatch(Context& context, SemIR::InstId pattern_id,
+                       SemIR::InstId scrutinee_id) -> void;
+
 }  // namespace Carbon::Check
 
 #endif  // CARBON_TOOLCHAIN_CHECK_PATTERN_MATCH_H_

+ 12 - 28
toolchain/check/return.cpp

@@ -10,7 +10,7 @@
 namespace Carbon::Check {
 
 // Gets the function that lexically encloses the current location.
-static auto GetCurrentFunction(Context& context) -> SemIR::Function& {
+auto GetCurrentFunctionForReturn(Context& context) -> SemIR::Function& {
   CARBON_CHECK(!context.return_scope_stack().empty(),
                "Handling return but not in a function");
   auto function_id = context.insts()
@@ -20,9 +20,7 @@ static auto GetCurrentFunction(Context& context) -> SemIR::Function& {
   return context.functions().Get(function_id);
 }
 
-// Gets the return slot of the function that lexically encloses the current
-// location.
-static auto GetCurrentReturnSlot(Context& context) -> SemIR::InstId {
+auto GetCurrentReturnSlot(Context& context) -> SemIR::InstId {
   // TODO: this does some unnecessary work to compute non-lexical scopes,
   // so a separate API on ScopeStack could be more efficient.
   auto return_slot_id = context.scope_stack()
@@ -70,18 +68,15 @@ static auto NoteReturnedVar(Context::DiagnosticBuilder& diag,
   diag.Note(returned_var_id, ReturnedVarHere);
 }
 
-auto CheckReturnedVar(Context& context, Parse::NodeId returned_node,
-                      Parse::NodeId name_node, SemIR::NameId name_id,
-                      Parse::NodeId type_node, SemIR::TypeId type_id)
-    -> SemIR::InstId {
-  auto& function = GetCurrentFunction(context);
+auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,
+                         Parse::NodeId type_node, SemIR::TypeId type_id,
+                         SemIR::InstId bind_id) -> void {
+  auto& function = GetCurrentFunctionForReturn(context);
   auto return_info =
       SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(), function);
   if (!return_info.is_valid()) {
-    // We already diagnosed this when we started defining the function. Create a
-    // placeholder for error recovery.
-    return context.AddInst<SemIR::VarStorage>(
-        name_node, {.type_id = type_id, .name_id = name_id});
+    // We already diagnosed this when we started defining the function.
+    return;
   }
 
   // A `returned var` requires an explicit return type.
@@ -92,7 +87,7 @@ auto CheckReturnedVar(Context& context, Parse::NodeId returned_node,
         context.emitter().Build(returned_node, ReturnedVarWithNoReturnType);
     NoteNoReturnTypeProvided(diag, function);
     diag.Emit();
-    return SemIR::ErrorInst::SingletonInstId;
+    return;
   }
 
   // The declared type of the var must match the return type of the function.
@@ -105,19 +100,8 @@ auto CheckReturnedVar(Context& context, Parse::NodeId returned_node,
         context.emitter().Build(type_node, ReturnedVarWrongType, type_id);
     NoteReturnType(context, diag, function);
     diag.Emit();
-    return SemIR::ErrorInst::SingletonInstId;
   }
 
-  // The variable aliases the return slot if there is one. If not, it has its
-  // own storage.
-  if (return_info.has_return_slot()) {
-    return GetCurrentReturnSlot(context);
-  }
-  return context.AddInst<SemIR::VarStorage>(
-      name_node, {.type_id = type_id, .name_id = name_id});
-}
-
-auto RegisterReturnedVar(Context& context, SemIR::InstId bind_id) -> void {
   auto existing_id = context.scope_stack().SetReturnedVarOrGetExisting(bind_id);
   if (existing_id.is_valid()) {
     CARBON_DIAGNOSTIC(ReturnedVarShadowed, Error,
@@ -131,7 +115,7 @@ auto RegisterReturnedVar(Context& context, SemIR::InstId bind_id) -> void {
 
 auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id)
     -> void {
-  const auto& function = GetCurrentFunction(context);
+  const auto& function = GetCurrentFunctionForReturn(context);
   auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());
 
   if (return_type_id.is_valid()) {
@@ -147,7 +131,7 @@ auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id)
 
 auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id,
                          SemIR::InstId expr_id) -> void {
-  const auto& function = GetCurrentFunction(context);
+  const auto& function = GetCurrentFunctionForReturn(context);
   auto returned_var_id = GetCurrentReturnedVar(context);
   auto return_slot_id = SemIR::InstId::Invalid;
   auto return_info =
@@ -189,7 +173,7 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id,
 
 auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)
     -> void {
-  const auto& function = GetCurrentFunction(context);
+  const auto& function = GetCurrentFunctionForReturn(context);
   auto returned_var_id = GetCurrentReturnedVar(context);
 
   if (!returned_var_id.is_valid()) {

+ 13 - 9
toolchain/check/return.h

@@ -10,15 +10,19 @@
 
 namespace Carbon::Check {
 
-// Checks a `returned var` binding and returns the location of the return
-// value storage that the name should bind to.
-auto CheckReturnedVar(Context& context, Parse::NodeId returned_node,
-                      Parse::NodeId name_node, SemIR::NameId name_id,
-                      Parse::NodeId type_node, SemIR::TypeId type_id)
-    -> SemIR::InstId;
-
-// Registers the given binding as the current `returned var` in this scope.
-auto RegisterReturnedVar(Context& context, SemIR::InstId bind_id) -> void;
+// Gets the function that a `return` statement in the current context would
+// return from.
+auto GetCurrentFunctionForReturn(Context& context) -> SemIR::Function&;
+
+// Gets the return slot of the function that lexically encloses the current
+// location.
+auto GetCurrentReturnSlot(Context& context) -> SemIR::InstId;
+
+// Checks a `returned var` binding and registers it as the current `returned
+// var` in this scope.
+auto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,
+                         Parse::NodeId type_node, SemIR::TypeId type_id,
+                         SemIR::InstId bind_id) -> void;
 
 // Checks and builds SemIR for a `return;` statement.
 auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id)

+ 7 - 1
toolchain/check/scope_stack.h

@@ -8,6 +8,7 @@
 #include "common/array_stack.h"
 #include "common/set.h"
 #include "llvm/ADT/SmallVector.h"
+#include "toolchain/check/full_pattern_stack.h"
 #include "toolchain/check/lexical_lookup.h"
 #include "toolchain/check/scope_index.h"
 #include "toolchain/sem_ir/file.h"
@@ -20,7 +21,7 @@ namespace Carbon::Check {
 class ScopeStack {
  public:
   explicit ScopeStack(const CanonicalValueStore<IdentifierId>& identifiers)
-      : lexical_lookup_(identifiers) {}
+      : lexical_lookup_(identifiers), full_pattern_stack_(&lexical_lookup_) {}
 
   // A scope in which `break` and `continue` can be used.
   struct BreakContinueScope {
@@ -166,6 +167,8 @@ class ScopeStack {
     return compile_time_binding_stack_;
   }
 
+  auto full_pattern_stack() -> FullPatternStack& { return full_pattern_stack_; }
+
  private:
   // An entry in scope_stack_.
   struct ScopeStackEntry {
@@ -244,6 +247,9 @@ class ScopeStack {
 
   // Tracks lexical lookup results.
   LexicalLookup lexical_lookup_;
+
+  // Stack of full-patterns currently being checked.
+  FullPatternStack full_pattern_stack_;
 };
 
 struct ScopeStack::SuspendedScope {

+ 12 - 2
toolchain/check/testdata/alias/fail_bool_value.carbon

@@ -19,6 +19,8 @@ let a_test: bool = a;
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %false: bool = bool_literal false [template]
+// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [template]
+// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -33,17 +35,25 @@ let a_test: bool = a;
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .a = %a
-// CHECK:STDOUT:     .a_test = @__global_init.%a_test
+// CHECK:STDOUT:     .a_test = %a_test
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %false: bool = bool_literal false [template = constants.%false]
 // CHECK:STDOUT:   %a: <error> = bind_alias a, <error> [template = <error>]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_test.patt: bool = binding_pattern a_test
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_13.1: type = splice_block %.loc16_13.3 [template = bool] {
+// CHECK:STDOUT:     %bool.make_type: init type = call constants.%Bool() [template = bool]
+// CHECK:STDOUT:     %.loc16_13.2: type = value_of_initializer %bool.make_type [template = bool]
+// CHECK:STDOUT:     %.loc16_13.3: type = converted %bool.make_type, %.loc16_13.2 [template = bool]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a_test: bool = bind_name a_test, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: <error> = name_ref a, file.%a [template = <error>]
-// CHECK:STDOUT:   %a_test: bool = bind_name a_test, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 8
toolchain/check/testdata/alias/no_prelude/alias_of_alias.carbon

@@ -29,7 +29,7 @@ let d: c = {};
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:     .c = %c
-// CHECK:STDOUT:     .d = @__global_init.%d
+// CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
@@ -38,6 +38,15 @@ let d: c = {};
 // CHECK:STDOUT:   %b: type = bind_alias b, %a [template = constants.%C]
 // CHECK:STDOUT:   %b.ref: type = name_ref b, %b [template = constants.%C]
 // CHECK:STDOUT:   %c: type = bind_alias c, %b [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C = binding_pattern d
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %c.ref: type = name_ref c, %c [template = constants.%C]
+// CHECK:STDOUT:   %.loc15_13.1: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc15_13.2: init %C = class_init (), %.loc15_13.1 [template = constants.%C.val]
+// CHECK:STDOUT:   %.loc15_13.3: ref %C = temporary %.loc15_13.1, %.loc15_13.2
+// CHECK:STDOUT:   %.loc15_13.4: ref %C = converted @__global_init.%.loc15, %.loc15_13.3
+// CHECK:STDOUT:   %d: ref %C = bind_name d, %.loc15_13.4
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -47,13 +56,7 @@ let d: c = {};
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc15_13.1: %empty_struct_type = struct_literal ()
-// CHECK:STDOUT:   %.loc15_13.2: ref %C = temporary_storage
-// CHECK:STDOUT:   %.loc15_13.3: init %C = class_init (), %.loc15_13.2 [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc15_13.4: ref %C = temporary %.loc15_13.2, %.loc15_13.3
-// CHECK:STDOUT:   %.loc15_14.1: ref %C = converted %.loc15_13.1, %.loc15_13.4
-// CHECK:STDOUT:   %.loc15_14.2: %C = bind_value %.loc15_14.1
-// CHECK:STDOUT:   %d: %C = bind_name d, %.loc15_14.2
+// CHECK:STDOUT:   %.loc15: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 28 - 5
toolchain/check/testdata/alias/no_prelude/export_name.carbon

@@ -166,7 +166,12 @@ var d: D* = &c;
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C = binding_pattern d
+// CHECK:STDOUT:     %.loc6: %C = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %C = var d
+// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%import_ref.c3f [template = constants.%C]
 // CHECK:STDOUT:   %d: ref %C = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -178,8 +183,8 @@ var d: D* = &c;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc6_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc6_13.2: init %C = class_init (), file.%d.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc6_14: init %C = converted %.loc6_13.1, %.loc6_13.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%d.var, %.loc6_14
+// CHECK:STDOUT:   %.loc6_1: init %C = converted %.loc6_13.1, %.loc6_13.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%d.var, %.loc6_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -199,8 +204,13 @@ var d: D* = &c;
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: <error> = binding_pattern c
+// CHECK:STDOUT:     %.loc10: <error> = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref <error> = var c
-// CHECK:STDOUT:   %c: ref <error> = bind_name c, %c.var
+// CHECK:STDOUT:   %C.ref: <error> = name_ref C, <error> [template = <error>]
+// CHECK:STDOUT:   %c: <error> = bind_name c, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -234,9 +244,22 @@ var d: D* = &c;
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:     %.loc7: %C = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C = var c
+// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%import_ref.06e [template = constants.%C]
 // CHECK:STDOUT:   %c: ref %C = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %ptr.019 = binding_pattern d
+// CHECK:STDOUT:     %.loc8_1: %ptr.019 = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %ptr.019 = var d
+// CHECK:STDOUT:   %.loc8_9: type = splice_block %ptr [template = constants.%ptr.019] {
+// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%import_ref.c3f [template = constants.%C]
+// CHECK:STDOUT:     %ptr: type = ptr_type %C [template = constants.%ptr.019]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %ptr.019 = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -248,8 +271,8 @@ var d: D* = &c;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc7_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc7_13.2: init %C = class_init (), file.%c.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc7_14: init %C = converted %.loc7_13.1, %.loc7_13.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%c.var, %.loc7_14
+// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_13.1, %.loc7_13.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%c.var, %.loc7_1
 // CHECK:STDOUT:   %c.ref: ref %C = name_ref c, file.%c
 // CHECK:STDOUT:   %addr: %ptr.019 = addr_of %c.ref
 // CHECK:STDOUT:   assign file.%d.var, %addr

+ 16 - 7
toolchain/check/testdata/alias/no_prelude/fail_aliased_name_in_diag.carbon

@@ -14,9 +14,9 @@ class D {}
 alias c = C;
 var d: D = {};
 
-// CHECK:STDERR: fail_aliased_name_in_diag.carbon:[[@LINE+4]]:1: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound]
+// CHECK:STDERR: fail_aliased_name_in_diag.carbon:[[@LINE+4]]:16: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound]
 // CHECK:STDERR: let c_var: c = d;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR:                ^
 // CHECK:STDERR:
 let c_var: c = d;
 
@@ -36,14 +36,25 @@ let c_var: c = d;
 // CHECK:STDOUT:     .D = %D.decl
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:     .d = %d
-// CHECK:STDOUT:     .c_var = @__global_init.%c_var
+// CHECK:STDOUT:     .c_var = %c_var
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %D.decl: type = class_decl @D [template = constants.%D] {} {}
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %c: type = bind_alias c, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %D = binding_pattern d
+// CHECK:STDOUT:     %.loc15: %D = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %D = var d
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %D.decl [template = constants.%D]
 // CHECK:STDOUT:   %d: ref %D = bind_name d, %d.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c_var.patt: %C = binding_pattern c_var
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %c.ref: type = name_ref c, %c [template = constants.%C]
+// CHECK:STDOUT:   %.loc21: %C = converted @__global_init.%d.ref, <error> [template = <error>]
+// CHECK:STDOUT:   %c_var: %C = bind_name c_var, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
@@ -60,11 +71,9 @@ let c_var: c = d;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc15_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc15_13.2: init %D = class_init (), file.%d.var [template = constants.%D.val]
-// CHECK:STDOUT:   %.loc15_14: init %D = converted %.loc15_13.1, %.loc15_13.2 [template = constants.%D.val]
-// CHECK:STDOUT:   assign file.%d.var, %.loc15_14
+// CHECK:STDOUT:   %.loc15_1: init %D = converted %.loc15_13.1, %.loc15_13.2 [template = constants.%D.val]
+// CHECK:STDOUT:   assign file.%d.var, %.loc15_1
 // CHECK:STDOUT:   %d.ref: ref %D = name_ref d, file.%d
-// CHECK:STDOUT:   %.loc21: %C = converted %d.ref, <error> [template = <error>]
-// CHECK:STDOUT:   %c_var: %C = bind_name c_var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 14 - 4
toolchain/check/testdata/alias/no_prelude/fail_name_conflict.carbon

@@ -48,9 +48,19 @@ alias b = C;
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %a.loc13: type = bind_alias a, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C = binding_pattern a
+// CHECK:STDOUT:     %.loc21: %C = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %C = var a
+// CHECK:STDOUT:   %C.ref.loc21: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %a.loc21: ref %C = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C = binding_pattern b
+// CHECK:STDOUT:     %.loc23: %C = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %C = var b
+// CHECK:STDOUT:   %C.ref.loc23: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %b: ref %C = bind_name b, %b.var
 // CHECK:STDOUT:   %C.ref.loc31: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %.loc31: type = bind_alias <invalid>, %C.decl [template = constants.%C]
@@ -65,12 +75,12 @@ alias b = C;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc21_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc21_13.2: init %C = class_init (), file.%a.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc21_14: init %C = converted %.loc21_13.1, %.loc21_13.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%a.var, %.loc21_14
+// CHECK:STDOUT:   %.loc21_1: init %C = converted %.loc21_13.1, %.loc21_13.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%a.var, %.loc21_1
 // CHECK:STDOUT:   %.loc23_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc23_13.2: init %C = class_init (), file.%b.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc23_14: init %C = converted %.loc23_13.1, %.loc23_13.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%b.var, %.loc23_14
+// CHECK:STDOUT:   %.loc23_1: init %C = converted %.loc23_13.1, %.loc23_13.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%b.var, %.loc23_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 4
toolchain/check/testdata/alias/no_prelude/fail_not_constant.carbon

@@ -37,17 +37,34 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %empty_tuple.type = binding_pattern a
+// CHECK:STDOUT:     %.loc12_3.1: %empty_tuple.type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var a
-// CHECK:STDOUT:   %a: ref %empty_tuple.type = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc12_16.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc12_16.2: init %empty_tuple.type = tuple_init () to %a.var [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc12_17: init %empty_tuple.type = converted %.loc12_16.1, %.loc12_16.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   assign %a.var, %.loc12_17
+// CHECK:STDOUT:   %.loc12_3.2: init %empty_tuple.type = converted %.loc12_16.1, %.loc12_16.2 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   assign %a.var, %.loc12_3.2
+// CHECK:STDOUT:   %.loc12_11.1: type = splice_block %.loc12_11.3 [template = constants.%empty_tuple.type] {
+// CHECK:STDOUT:     %.loc12_11.2: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc12_11.3: type = converted %.loc12_11.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: ref %empty_tuple.type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %ptr = binding_pattern b
+// CHECK:STDOUT:     %.loc13_3: %ptr = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %ptr = var b
-// CHECK:STDOUT:   %b: ref %ptr = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: ref %empty_tuple.type = name_ref a, %a
 // CHECK:STDOUT:   %addr: %ptr = addr_of %a.ref
 // CHECK:STDOUT:   assign %b.var, %addr
+// CHECK:STDOUT:   %.loc13_12.1: type = splice_block %ptr [template = constants.%ptr] {
+// CHECK:STDOUT:     %.loc13_11: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc13_12.2: type = converted %.loc13_11, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %ptr: type = ptr_type %empty_tuple.type [template = constants.%ptr]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: ref %ptr = bind_name b, %b.var
 // CHECK:STDOUT:   %b.ref: ref %ptr = name_ref b, %b
 // CHECK:STDOUT:   %.loc18_14: %ptr = bind_value %b.ref
 // CHECK:STDOUT:   %.loc18_13: ref %empty_tuple.type = deref %.loc18_14

+ 56 - 8
toolchain/check/testdata/alias/no_prelude/import.carbon

@@ -83,9 +83,17 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
-// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %c_alias: type = bind_alias c_alias, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %ptr = binding_pattern a
+// CHECK:STDOUT:     %.loc8_1: %ptr = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %ptr = var a
+// CHECK:STDOUT:   %.loc8_9: type = splice_block %ptr [template = constants.%ptr] {
+// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %ptr: type = ptr_type %C [template = constants.%ptr]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %ptr = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -119,9 +127,17 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
-// CHECK:STDOUT:   %c_alias.ref: type = name_ref c_alias, imports.%import_ref.204 [template = constants.%C]
+// CHECK:STDOUT:   %c_alias.ref.loc6: type = name_ref c_alias, imports.%import_ref.204 [template = constants.%C]
 // CHECK:STDOUT:   %c_alias_alias: type = bind_alias c_alias_alias, imports.%import_ref.204 [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %ptr = binding_pattern b
+// CHECK:STDOUT:     %.loc8_1: %ptr = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %ptr = var b
+// CHECK:STDOUT:   %.loc8_15: type = splice_block %ptr [template = constants.%ptr] {
+// CHECK:STDOUT:     %c_alias.ref.loc8: type = name_ref c_alias, imports.%import_ref.204 [template = constants.%C]
+// CHECK:STDOUT:     %ptr: type = ptr_type %C [template = constants.%ptr]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %ptr = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -151,7 +167,15 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %ptr = binding_pattern c
+// CHECK:STDOUT:     %.loc6_1: %ptr = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %ptr = var c
+// CHECK:STDOUT:   %.loc6_21: type = splice_block %ptr [template = constants.%ptr] {
+// CHECK:STDOUT:     %c_alias_alias.ref: type = name_ref c_alias_alias, imports.%import_ref.3fd [template = constants.%C]
+// CHECK:STDOUT:     %ptr: type = ptr_type %C [template = constants.%ptr]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %ptr = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -171,7 +195,15 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .a_alias = %a_alias
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %empty_tuple.type = binding_pattern a
+// CHECK:STDOUT:     %.loc4_1: %empty_tuple.type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var a
+// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [template = constants.%empty_tuple.type] {
+// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %empty_tuple.type = bind_name a, %a.var
 // CHECK:STDOUT:   %a.ref: ref %empty_tuple.type = name_ref a, %a
 // CHECK:STDOUT:   %a_alias: ref %empty_tuple.type = bind_alias a_alias, %a
@@ -181,8 +213,8 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc4_14.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc4_14.2: init %empty_tuple.type = tuple_init () to file.%a.var [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc4_15: init %empty_tuple.type = converted %.loc4_14.1, %.loc4_14.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   assign file.%a.var, %.loc4_15
+// CHECK:STDOUT:   %.loc4_1: init %empty_tuple.type = converted %.loc4_14.1, %.loc4_14.2 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   assign file.%a.var, %.loc4_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -208,7 +240,15 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:   %default.import = import <invalid>
 // CHECK:STDOUT:   %a_alias.ref: ref %empty_tuple.type = name_ref a_alias, imports.%import_ref.22c
 // CHECK:STDOUT:   %a_alias_alias: ref %empty_tuple.type = bind_alias a_alias_alias, imports.%import_ref.22c
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %empty_tuple.type = binding_pattern b
+// CHECK:STDOUT:     %.loc8_1: %empty_tuple.type = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %empty_tuple.type = var b
+// CHECK:STDOUT:   %.loc8_9.1: type = splice_block %.loc8_9.3 [template = constants.%empty_tuple.type] {
+// CHECK:STDOUT:     %.loc8_9.2: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc8_9.3: type = converted %.loc8_9.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %empty_tuple.type = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -216,8 +256,8 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a_alias.ref: ref %empty_tuple.type = name_ref a_alias, imports.%import_ref.22c
 // CHECK:STDOUT:   %.loc8_13: init %empty_tuple.type = tuple_init () to file.%b.var [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc8_20: init %empty_tuple.type = converted %a_alias.ref, %.loc8_13 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   assign file.%b.var, %.loc8_20
+// CHECK:STDOUT:   %.loc8_1: init %empty_tuple.type = converted %a_alias.ref, %.loc8_13 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   assign file.%b.var, %.loc8_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -240,7 +280,15 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %empty_tuple.type = binding_pattern c
+// CHECK:STDOUT:     %.loc11_1: %empty_tuple.type = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %empty_tuple.type = var c
+// CHECK:STDOUT:   %.loc11_9.1: type = splice_block %.loc11_9.3 [template = constants.%empty_tuple.type] {
+// CHECK:STDOUT:     %.loc11_9.2: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc11_9.3: type = converted %.loc11_9.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %empty_tuple.type = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -248,8 +296,8 @@ var c: () = a_alias_alias;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a_alias_alias.ref: ref %empty_tuple.type = name_ref a_alias_alias, imports.%import_ref.692 [template = <error>]
 // CHECK:STDOUT:   %.loc11_13: init %empty_tuple.type = tuple_init () to file.%c.var [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc11_26: init %empty_tuple.type = converted %a_alias_alias.ref, %.loc11_13 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   assign file.%c.var, %.loc11_26
+// CHECK:STDOUT:   %.loc11_1: init %empty_tuple.type = converted %a_alias_alias.ref, %.loc11_13 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   assign file.%c.var, %.loc11_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 22 - 4
toolchain/check/testdata/alias/no_prelude/import_access.carbon

@@ -99,7 +99,12 @@ var inst: Test.A = {};
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Test.import = import Test
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %inst.patt: %C = binding_pattern inst
+// CHECK:STDOUT:     %.loc4: %C = var_pattern %inst.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %inst.var: ref %C = var inst
+// CHECK:STDOUT:   %A.ref: type = name_ref A, imports.%import_ref.323 [template = constants.%C]
 // CHECK:STDOUT:   %inst: ref %C = bind_name inst, %inst.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -111,8 +116,8 @@ var inst: Test.A = {};
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc4_16.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc4_16.2: init %C = class_init (), file.%inst.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc4_17: init %C = converted %.loc4_16.1, %.loc4_16.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%inst.var, %.loc4_17
+// CHECK:STDOUT:   %.loc4_1: init %C = converted %.loc4_16.1, %.loc4_16.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%inst.var, %.loc4_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -132,8 +137,13 @@ var inst: Test.A = {};
 // CHECK:STDOUT:     .inst = %inst
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %inst.patt: <error> = binding_pattern inst
+// CHECK:STDOUT:     %.loc10: <error> = var_pattern %inst.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %inst.var: ref <error> = var inst
-// CHECK:STDOUT:   %inst: ref <error> = bind_name inst, %inst.var
+// CHECK:STDOUT:   %A.ref: <error> = name_ref A, <error> [template = <error>]
+// CHECK:STDOUT:   %inst: <error> = bind_name inst, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -161,8 +171,16 @@ var inst: Test.A = {};
 // CHECK:STDOUT:     .inst = %inst
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Test.import = import Test
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %inst.patt: <error> = binding_pattern inst
+// CHECK:STDOUT:     %.loc10: <error> = var_pattern %inst.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %inst.var: ref <error> = var inst
-// CHECK:STDOUT:   %inst: ref <error> = bind_name inst, %inst.var
+// CHECK:STDOUT:   %.1: <error> = splice_block <error> [template = <error>] {
+// CHECK:STDOUT:     %Test.ref: <namespace> = name_ref Test, imports.%Test [template = imports.%Test]
+// CHECK:STDOUT:     %A.ref: <error> = name_ref A, <error> [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %inst: <error> = bind_name inst, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {

+ 33 - 9
toolchain/check/testdata/alias/no_prelude/import_order.carbon

@@ -60,7 +60,11 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc4: %C.elem = field_decl v, element0 [template]
+// CHECK:STDOUT:   %.loc4_16: %C.elem = field_decl v, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc4_11: %C.elem = var_pattern %.loc4_16
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [template = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -100,13 +104,33 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:     .a_val = %a_val
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d_val.patt: %C = binding_pattern d_val
+// CHECK:STDOUT:     %.loc7: %C = var_pattern %d_val.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d_val.var: ref %C = var d_val
+// CHECK:STDOUT:   %d.ref: type = name_ref d, imports.%import_ref.14f [template = constants.%C]
 // CHECK:STDOUT:   %d_val: ref %C = bind_name d_val, %d_val.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c_val.patt: %C = binding_pattern c_val
+// CHECK:STDOUT:     %.loc8: %C = var_pattern %c_val.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c_val.var: ref %C = var c_val
+// CHECK:STDOUT:   %c.ref: type = name_ref c, imports.%import_ref.610 [template = constants.%C]
 // CHECK:STDOUT:   %c_val: ref %C = bind_name c_val, %c_val.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_val.patt: %C = binding_pattern b_val
+// CHECK:STDOUT:     %.loc9: %C = var_pattern %b_val.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b_val.var: ref %C = var b_val
+// CHECK:STDOUT:   %b.ref: type = name_ref b, imports.%import_ref.fb0 [template = constants.%C]
 // CHECK:STDOUT:   %b_val: ref %C = bind_name b_val, %b_val.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_val.patt: %C = binding_pattern a_val
+// CHECK:STDOUT:     %.loc10: %C = var_pattern %a_val.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a_val.var: ref %C = var a_val
+// CHECK:STDOUT:   %a.ref: type = name_ref a, imports.%import_ref.e38 [template = constants.%C]
 // CHECK:STDOUT:   %a_val: ref %C = bind_name a_val, %a_val.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -122,8 +146,8 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:   %.loc7_23.2: init %empty_tuple.type = tuple_init () to %.loc7_24.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc7_24.3: init %empty_tuple.type = converted %.loc7_23.1, %.loc7_23.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc7_24.4: init %C = class_init (%.loc7_24.3), file.%d_val.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc7_25: init %C = converted %.loc7_24.1, %.loc7_24.4 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%d_val.var, %.loc7_25
+// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_24.1, %.loc7_24.4 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%d_val.var, %.loc7_1
 // CHECK:STDOUT:   %d_val.ref: ref %C = name_ref d_val, file.%d_val
 // CHECK:STDOUT:   %v.ref.loc8: %C.elem = name_ref v, imports.%import_ref.f99 [template = imports.%.2fc]
 // CHECK:STDOUT:   %.loc8_27.1: ref %empty_tuple.type = class_element_access %d_val.ref, element0
@@ -132,8 +156,8 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:   %.loc8_27.2: init %empty_tuple.type = tuple_init () to %.loc8_29.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc8_29.3: init %empty_tuple.type = converted %.loc8_27.1, %.loc8_27.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc8_29.4: init %C = class_init (%.loc8_29.3), file.%c_val.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc8_30: init %C = converted %.loc8_29.1, %.loc8_29.4 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%c_val.var, %.loc8_30
+// CHECK:STDOUT:   %.loc8_1: init %C = converted %.loc8_29.1, %.loc8_29.4 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%c_val.var, %.loc8_1
 // CHECK:STDOUT:   %c_val.ref: ref %C = name_ref c_val, file.%c_val
 // CHECK:STDOUT:   %v.ref.loc9: %C.elem = name_ref v, imports.%import_ref.f99 [template = imports.%.2fc]
 // CHECK:STDOUT:   %.loc9_27.1: ref %empty_tuple.type = class_element_access %c_val.ref, element0
@@ -142,8 +166,8 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:   %.loc9_27.2: init %empty_tuple.type = tuple_init () to %.loc9_29.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc9_29.3: init %empty_tuple.type = converted %.loc9_27.1, %.loc9_27.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc9_29.4: init %C = class_init (%.loc9_29.3), file.%b_val.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc9_30: init %C = converted %.loc9_29.1, %.loc9_29.4 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%b_val.var, %.loc9_30
+// CHECK:STDOUT:   %.loc9_1: init %C = converted %.loc9_29.1, %.loc9_29.4 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%b_val.var, %.loc9_1
 // CHECK:STDOUT:   %b_val.ref: ref %C = name_ref b_val, file.%b_val
 // CHECK:STDOUT:   %v.ref.loc10: %C.elem = name_ref v, imports.%import_ref.f99 [template = imports.%.2fc]
 // CHECK:STDOUT:   %.loc10_27.1: ref %empty_tuple.type = class_element_access %b_val.ref, element0
@@ -152,8 +176,8 @@ var a_val: a = {.v = b_val.v};
 // CHECK:STDOUT:   %.loc10_27.2: init %empty_tuple.type = tuple_init () to %.loc10_29.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc10_29.3: init %empty_tuple.type = converted %.loc10_27.1, %.loc10_27.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc10_29.4: init %C = class_init (%.loc10_29.3), file.%a_val.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc10_30: init %C = converted %.loc10_29.1, %.loc10_29.4 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%a_val.var, %.loc10_30
+// CHECK:STDOUT:   %.loc10_1: init %C = converted %.loc10_29.1, %.loc10_29.4 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%a_val.var, %.loc10_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 13
toolchain/check/testdata/alias/no_prelude/in_namespace.carbon

@@ -37,7 +37,7 @@ fn F() -> NS.a {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:     .NS = %NS
-// CHECK:STDOUT:     .b = @__global_init.%b
+// CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:     .F = %F.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
@@ -46,6 +46,21 @@ fn F() -> NS.a {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %a: type = bind_alias a, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_10: type = splice_block %a.ref [template = constants.%C] {
+// CHECK:STDOUT:     %NS.ref: <namespace> = name_ref NS, %NS [template = %NS]
+// CHECK:STDOUT:     %a.ref: type = name_ref a, %a [template = constants.%C]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_23.1: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc16_23.2: ref %empty_tuple.type = class_element_access %.loc16_23.1, element0
+// CHECK:STDOUT:   %.loc16_22: init %empty_tuple.type = tuple_init () to %.loc16_23.2 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   %.loc16_23.3: init %empty_tuple.type = converted @__global_init.%.loc16_22, %.loc16_22 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   %.loc16_23.4: init %C = class_init (%.loc16_23.3), %.loc16_23.1 [template = constants.%C.val]
+// CHECK:STDOUT:   %.loc16_23.5: ref %C = temporary %.loc16_23.1, %.loc16_23.4
+// CHECK:STDOUT:   %.loc16_23.6: ref %C = converted @__global_init.%.loc16_23, %.loc16_23.5
+// CHECK:STDOUT:   %b: ref %C = bind_name b, %.loc16_23.6
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %return.patt: %C = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %C = out_param_pattern %return.patt, runtime_param0
@@ -58,7 +73,11 @@ fn F() -> NS.a {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc11: %C.elem = field_decl v, element0 [template]
+// CHECK:STDOUT:   %.loc11_16: %C.elem = field_decl v, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc11_11: %C.elem = var_pattern %.loc11_16
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [template = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -77,17 +96,8 @@ fn F() -> NS.a {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc16_22.1: %empty_tuple.type = tuple_literal ()
-// CHECK:STDOUT:   %.loc16_23.1: %struct_type.v = struct_literal (%.loc16_22.1)
-// CHECK:STDOUT:   %.loc16_23.2: ref %C = temporary_storage
-// CHECK:STDOUT:   %.loc16_23.3: ref %empty_tuple.type = class_element_access %.loc16_23.2, element0
-// CHECK:STDOUT:   %.loc16_22.2: init %empty_tuple.type = tuple_init () to %.loc16_23.3 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc16_23.4: init %empty_tuple.type = converted %.loc16_22.1, %.loc16_22.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc16_23.5: init %C = class_init (%.loc16_23.4), %.loc16_23.2 [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc16_23.6: ref %C = temporary %.loc16_23.2, %.loc16_23.5
-// CHECK:STDOUT:   %.loc16_24.1: ref %C = converted %.loc16_23.1, %.loc16_23.6
-// CHECK:STDOUT:   %.loc16_24.2: %C = bind_value %.loc16_24.1
-// CHECK:STDOUT:   %b: %C = bind_name b, %.loc16_24.2
+// CHECK:STDOUT:   %.loc16_22: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:   %.loc16_23: %struct_type.v = struct_literal (%.loc16_22)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 3
toolchain/check/testdata/alias/no_prelude/local.carbon

@@ -40,12 +40,20 @@ fn F() -> () {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> %empty_tuple.type {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %empty_tuple.type = binding_pattern a
+// CHECK:STDOUT:     %.loc12_3.1: %empty_tuple.type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var a
-// CHECK:STDOUT:   %a: ref %empty_tuple.type = bind_name a, %a.var
 // CHECK:STDOUT:   %.loc12_16.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc12_16.2: init %empty_tuple.type = tuple_init () to %a.var [template = constants.%empty_tuple]
-// CHECK:STDOUT:   %.loc12_17: init %empty_tuple.type = converted %.loc12_16.1, %.loc12_16.2 [template = constants.%empty_tuple]
-// CHECK:STDOUT:   assign %a.var, %.loc12_17
+// CHECK:STDOUT:   %.loc12_3.2: init %empty_tuple.type = converted %.loc12_16.1, %.loc12_16.2 [template = constants.%empty_tuple]
+// CHECK:STDOUT:   assign %a.var, %.loc12_3.2
+// CHECK:STDOUT:   %.loc12_11.1: type = splice_block %.loc12_11.3 [template = constants.%empty_tuple.type] {
+// CHECK:STDOUT:     %.loc12_11.2: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %.loc12_11.3: type = converted %.loc12_11.2, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: ref %empty_tuple.type = bind_name a, %a.var
 // CHECK:STDOUT:   %a.ref: ref %empty_tuple.type = name_ref a, %a
 // CHECK:STDOUT:   %b: ref %empty_tuple.type = bind_alias b, %a
 // CHECK:STDOUT:   %b.ref: ref %empty_tuple.type = name_ref b, %b

+ 19 - 3
toolchain/check/testdata/array/array_in_place.carbon

@@ -69,8 +69,11 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %v.patt: %array_type = binding_pattern v
+// CHECK:STDOUT:     %.loc14_3.1: %array_type = var_pattern %v.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %array_type = var v
-// CHECK:STDOUT:   %v: ref %array_type = bind_name v, %v.var
 // CHECK:STDOUT:   %F.ref.loc14_34: %F.type = name_ref F, file.%F.decl [template = constants.%F]
 // CHECK:STDOUT:   %.loc14_42.1: ref %tuple.type.189 = splice_block %.loc14_42.2 {
 // CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0]
@@ -85,8 +88,21 @@ fn G() {
 // CHECK:STDOUT:   %F.call.loc14_41: init %tuple.type.189 = call %F.ref.loc14_39() to %.loc14_42.3
 // CHECK:STDOUT:   %.loc14_42.5: %tuple.type.99b = tuple_literal (%F.call.loc14_36, %F.call.loc14_41)
 // CHECK:STDOUT:   %.loc14_42.6: init %array_type = array_init (%F.call.loc14_36, %F.call.loc14_41) to %v.var
-// CHECK:STDOUT:   %.loc14_43: init %array_type = converted %.loc14_42.5, %.loc14_42.6
-// CHECK:STDOUT:   assign %v.var, %.loc14_43
+// CHECK:STDOUT:   %.loc14_3.2: init %array_type = converted %.loc14_42.5, %.loc14_42.6
+// CHECK:STDOUT:   assign %v.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_29: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc14_12: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_12: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc14_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc14_22: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_22: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc14_25.1: %tuple.type.ff9 = tuple_literal (%i32.loc14_12, %i32.loc14_17, %i32.loc14_22)
+// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2]
+// CHECK:STDOUT:     %.loc14_25.2: type = converted %.loc14_25.1, constants.%tuple.type.189 [template = constants.%tuple.type.189]
+// CHECK:STDOUT:     %array_type: type = array_type %int_2, %tuple.type.189 [template = constants.%array_type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %v: ref %array_type = bind_name v, %v.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 36 - 11
toolchain/check/testdata/array/array_vs_tuple.carbon

@@ -41,6 +41,7 @@ fn G() {
 // CHECK:STDOUT:   %Convert.specific_fn.b42: <specific function> = specific_function %Convert.bound.b30, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [template]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [template]
+// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [template]
 // CHECK:STDOUT:   %tuple.type.189: type = tuple_type (%i32, %i32, %i32) [template]
 // CHECK:STDOUT:   %tuple: %tuple.type.189 = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [template]
 // CHECK:STDOUT: }
@@ -65,12 +66,15 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc13_3.1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
-// CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
 // CHECK:STDOUT:   %int_1.loc13_22: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_2.loc13_25: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
-// CHECK:STDOUT:   %int_3.loc13: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
-// CHECK:STDOUT:   %.loc13_29.1: %tuple.type.37f = tuple_literal (%int_1.loc13_22, %int_2.loc13_25, %int_3.loc13)
+// CHECK:STDOUT:   %int_3.loc13_28: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:   %.loc13_29.1: %tuple.type.37f = tuple_literal (%int_1.loc13_22, %int_2.loc13_25, %int_3.loc13_28)
 // CHECK:STDOUT:   %impl.elem0.loc13_29.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc13_29.1: <bound method> = bound_method %int_1.loc13_22, %impl.elem0.loc13_29.1 [template = constants.%Convert.bound.ab5]
 // CHECK:STDOUT:   %Convert.specific_fn.loc13_29.1: <specific function> = specific_function %Convert.bound.loc13_29.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
@@ -88,18 +92,28 @@ fn G() {
 // CHECK:STDOUT:   %.loc13_29.6: ref %i32 = array_index %a.var, %int_1.loc13_29
 // CHECK:STDOUT:   %.loc13_29.7: init %i32 = initialize_from %.loc13_29.5 to %.loc13_29.6 [template = constants.%int_2.ef8]
 // CHECK:STDOUT:   %impl.elem0.loc13_29.3: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc13_29.3: <bound method> = bound_method %int_3.loc13, %impl.elem0.loc13_29.3 [template = constants.%Convert.bound.b30]
+// CHECK:STDOUT:   %Convert.bound.loc13_29.3: <bound method> = bound_method %int_3.loc13_28, %impl.elem0.loc13_29.3 [template = constants.%Convert.bound.b30]
 // CHECK:STDOUT:   %Convert.specific_fn.loc13_29.3: <specific function> = specific_function %Convert.bound.loc13_29.3, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.b42]
-// CHECK:STDOUT:   %int.convert_checked.loc13_29.3: init %i32 = call %Convert.specific_fn.loc13_29.3(%int_3.loc13) [template = constants.%int_3.822]
-// CHECK:STDOUT:   %.loc13_29.8: init %i32 = converted %int_3.loc13, %int.convert_checked.loc13_29.3 [template = constants.%int_3.822]
+// CHECK:STDOUT:   %int.convert_checked.loc13_29.3: init %i32 = call %Convert.specific_fn.loc13_29.3(%int_3.loc13_28) [template = constants.%int_3.822]
+// CHECK:STDOUT:   %.loc13_29.8: init %i32 = converted %int_3.loc13_28, %int.convert_checked.loc13_29.3 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %int_2.loc13_29: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
 // CHECK:STDOUT:   %.loc13_29.9: ref %i32 = array_index %a.var, %int_2.loc13_29
 // CHECK:STDOUT:   %.loc13_29.10: init %i32 = initialize_from %.loc13_29.8 to %.loc13_29.9 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc13_29.11: init %array_type = array_init (%.loc13_29.4, %.loc13_29.7, %.loc13_29.10) to %a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc13_30: init %array_type = converted %.loc13_29.1, %.loc13_29.11 [template = constants.%array]
-// CHECK:STDOUT:   assign %a.var, %.loc13_30
+// CHECK:STDOUT:   %.loc13_3.2: init %array_type = converted %.loc13_29.1, %.loc13_29.11 [template = constants.%array]
+// CHECK:STDOUT:   assign %a.var, %.loc13_3.2
+// CHECK:STDOUT:   %.loc13_17: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc13: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc13: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc13_16: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type: type = array_type %int_3.loc13_16, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %tuple.type.189 = binding_pattern b
+// CHECK:STDOUT:     %.loc14_3.1: %tuple.type.189 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %tuple.type.189 = var b
-// CHECK:STDOUT:   %b: ref %tuple.type.189 = bind_name b, %b.var
 // CHECK:STDOUT:   %int_1.loc14: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_2.loc14: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
 // CHECK:STDOUT:   %int_3.loc14: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
@@ -126,8 +140,19 @@ fn G() {
 // CHECK:STDOUT:   %tuple.elem2: ref %i32 = tuple_access %b.var, element2
 // CHECK:STDOUT:   %.loc14_36.7: init %i32 = initialize_from %.loc14_36.6 to %tuple.elem2 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc14_36.8: init %tuple.type.189 = tuple_init (%.loc14_36.3, %.loc14_36.5, %.loc14_36.7) to %b.var [template = constants.%tuple]
-// CHECK:STDOUT:   %.loc14_37: init %tuple.type.189 = converted %.loc14_36.1, %.loc14_36.8 [template = constants.%tuple]
-// CHECK:STDOUT:   assign %b.var, %.loc14_37
+// CHECK:STDOUT:   %.loc14_3.2: init %tuple.type.189 = converted %.loc14_36.1, %.loc14_36.8 [template = constants.%tuple]
+// CHECK:STDOUT:   assign %b.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_24.1: type = splice_block %.loc14_24.3 [template = constants.%tuple.type.189] {
+// CHECK:STDOUT:     %int_32.loc14_11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc14_16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc14_21: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14_21: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc14_24.2: %tuple.type.ff9 = tuple_literal (%i32.loc14_11, %i32.loc14_16, %i32.loc14_21)
+// CHECK:STDOUT:     %.loc14_24.3: type = converted %.loc14_24.2, constants.%tuple.type.189 [template = constants.%tuple.type.189]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: ref %tuple.type.189 = bind_name b, %b.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 13 - 3
toolchain/check/testdata/array/assign_return_value.carbon

@@ -86,8 +86,11 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %t.patt: %array_type = binding_pattern t
+// CHECK:STDOUT:     %.loc14_3.1: %array_type = var_pattern %t.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %t.var: ref %array_type = var t
-// CHECK:STDOUT:   %t: ref %array_type = bind_name t, %t.var
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [template = constants.%F]
 // CHECK:STDOUT:   %F.call: init %tuple.type.a1c = call %F.ref()
 // CHECK:STDOUT:   %.loc14_23.1: ref %tuple.type.a1c = temporary_storage
@@ -98,8 +101,15 @@ fn Run() {
 // CHECK:STDOUT:   %.loc14_23.4: ref %i32 = array_index %t.var, %int_0
 // CHECK:STDOUT:   %.loc14_23.5: init %i32 = initialize_from %.loc14_23.3 to %.loc14_23.4
 // CHECK:STDOUT:   %.loc14_23.6: init %array_type = array_init (%.loc14_23.5) to %t.var
-// CHECK:STDOUT:   %.loc14_24: init %array_type = converted %F.call, %.loc14_23.6
-// CHECK:STDOUT:   assign %t.var, %.loc14_24
+// CHECK:STDOUT:   %.loc14_3.2: init %array_type = converted %F.call, %.loc14_23.6
+// CHECK:STDOUT:   assign %t.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_17: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %array_type: type = array_type %int_1, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %t: ref %array_type = bind_name t, %t.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 29 - 4
toolchain/check/testdata/array/assign_var.carbon

@@ -16,6 +16,7 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [template]
+// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [template]
 // CHECK:STDOUT:   %tuple.type.189: type = tuple_type (%i32, %i32, %i32) [template]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [template]
 // CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [template]
@@ -55,9 +56,33 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %tuple.type.189 = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %tuple.type.189 = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %tuple.type.189 = var a
+// CHECK:STDOUT:   %.loc11_22.1: type = splice_block %.loc11_22.3 [template = constants.%tuple.type.189] {
+// CHECK:STDOUT:     %int_32.loc11_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc11_14: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11_14: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc11_19: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11_19: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc11_22.2: %tuple.type.ff9 = tuple_literal (%i32.loc11_9, %i32.loc11_14, %i32.loc11_19)
+// CHECK:STDOUT:     %.loc11_22.3: type = converted %.loc11_22.2, constants.%tuple.type.189 [template = constants.%tuple.type.189]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %tuple.type.189 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %array_type = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %array_type = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %array_type = var b
+// CHECK:STDOUT:   %.loc12_15: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc12: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc12: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type: type = array_type %int_3, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %array_type = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -89,8 +114,8 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %tuple.elem2.loc11: ref %i32 = tuple_access file.%a.var, element2
 // CHECK:STDOUT:   %.loc11_34.7: init %i32 = initialize_from %.loc11_34.6 to %tuple.elem2.loc11 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc11_34.8: init %tuple.type.189 = tuple_init (%.loc11_34.3, %.loc11_34.5, %.loc11_34.7) to file.%a.var [template = constants.%tuple]
-// CHECK:STDOUT:   %.loc11_35: init %tuple.type.189 = converted %.loc11_34.1, %.loc11_34.8 [template = constants.%tuple]
-// CHECK:STDOUT:   assign file.%a.var, %.loc11_35
+// CHECK:STDOUT:   %.loc11_1: init %tuple.type.189 = converted %.loc11_34.1, %.loc11_34.8 [template = constants.%tuple]
+// CHECK:STDOUT:   assign file.%a.var, %.loc11_1
 // CHECK:STDOUT:   %a.ref: ref %tuple.type.189 = name_ref a, file.%a
 // CHECK:STDOUT:   %tuple.elem0.loc12: ref %i32 = tuple_access %a.ref, element0
 // CHECK:STDOUT:   %.loc12_19.1: %i32 = bind_value %tuple.elem0.loc12
@@ -108,8 +133,8 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.loc12_19.8: ref %i32 = array_index file.%b.var, %int_2.loc12
 // CHECK:STDOUT:   %.loc12_19.9: init %i32 = initialize_from %.loc12_19.7 to %.loc12_19.8
 // CHECK:STDOUT:   %.loc12_19.10: init %array_type = array_init (%.loc12_19.3, %.loc12_19.6, %.loc12_19.9) to file.%b.var
-// CHECK:STDOUT:   %.loc12_20: init %array_type = converted %a.ref, %.loc12_19.10
-// CHECK:STDOUT:   assign file.%b.var, %.loc12_20
+// CHECK:STDOUT:   %.loc12_1: init %array_type = converted %a.ref, %.loc12_19.10
+// CHECK:STDOUT:   assign file.%b.var, %.loc12_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 41 - 6
toolchain/check/testdata/array/base.carbon

@@ -30,6 +30,9 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [template]
 // CHECK:STDOUT:   %array.237: %array_type.0cb = tuple_value (%int_1.5d2) [template]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
+// CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template]
 // CHECK:STDOUT:   %array_type.ce7: type = array_type %int_2, f64 [template]
 // CHECK:STDOUT:   %float.6e4: f64 = float_literal 11.100000000000001 [template]
@@ -63,11 +66,43 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type.0cb = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %array_type.0cb = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type.0cb = var a
+// CHECK:STDOUT:   %.loc11_15: type = splice_block %array_type.loc11 [template = constants.%array_type.0cb] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
+// CHECK:STDOUT:     %array_type.loc11: type = array_type %int_1, %i32 [template = constants.%array_type.0cb]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type.0cb = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %array_type.ce7 = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %array_type.ce7 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %array_type.ce7 = var b
+// CHECK:STDOUT:   %.loc12_15: type = splice_block %array_type.loc12 [template = constants.%array_type.ce7] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2]
+// CHECK:STDOUT:     %.loc12_9.1: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc12_9.2: type = converted %float.make_type, %.loc12_9.1 [template = f64]
+// CHECK:STDOUT:     %array_type.loc12: type = array_type %int_2, f64 [template = constants.%array_type.ce7]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %array_type.ce7 = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %array_type.c13 = binding_pattern c
+// CHECK:STDOUT:     %.loc13_1: %array_type.c13 = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %array_type.c13 = var c
+// CHECK:STDOUT:   %.loc13_14: type = splice_block %array_type.loc13 [template = constants.%array_type.c13] {
+// CHECK:STDOUT:     %.loc13_10.1: %empty_tuple.type = tuple_literal ()
+// CHECK:STDOUT:     %int_5: Core.IntLiteral = int_value 5 [template = constants.%int_5]
+// CHECK:STDOUT:     %.loc13_10.2: type = converted %.loc13_10.1, constants.%empty_tuple.type [template = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %array_type.loc13: type = array_type %int_5, %empty_tuple.type [template = constants.%array_type.c13]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %array_type.c13 = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -84,8 +119,8 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc11_22.3: ref %i32 = array_index file.%a.var, %int_0.loc11
 // CHECK:STDOUT:   %.loc11_22.4: init %i32 = initialize_from %.loc11_22.2 to %.loc11_22.3 [template = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc11_22.5: init %array_type.0cb = array_init (%.loc11_22.4) to file.%a.var [template = constants.%array.237]
-// CHECK:STDOUT:   %.loc11_23: init %array_type.0cb = converted %.loc11_22.1, %.loc11_22.5 [template = constants.%array.237]
-// CHECK:STDOUT:   assign file.%a.var, %.loc11_23
+// CHECK:STDOUT:   %.loc11_1: init %array_type.0cb = converted %.loc11_22.1, %.loc11_22.5 [template = constants.%array.237]
+// CHECK:STDOUT:   assign file.%a.var, %.loc11_1
 // CHECK:STDOUT:   %float.loc12_20: f64 = float_literal 11.100000000000001 [template = constants.%float.6e4]
 // CHECK:STDOUT:   %float.loc12_26: f64 = float_literal 2.2000000000000002 [template = constants.%float.9f7]
 // CHECK:STDOUT:   %.loc12_30.1: %tuple.type.bdb = tuple_literal (%float.loc12_20, %float.loc12_26)
@@ -96,8 +131,8 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc12_30.4: ref f64 = array_index file.%b.var, %int_1.loc12
 // CHECK:STDOUT:   %.loc12_30.5: init f64 = initialize_from %float.loc12_26 to %.loc12_30.4 [template = constants.%float.9f7]
 // CHECK:STDOUT:   %.loc12_30.6: init %array_type.ce7 = array_init (%.loc12_30.3, %.loc12_30.5) to file.%b.var [template = constants.%array.6a2]
-// CHECK:STDOUT:   %.loc12_31: init %array_type.ce7 = converted %.loc12_30.1, %.loc12_30.6 [template = constants.%array.6a2]
-// CHECK:STDOUT:   assign file.%b.var, %.loc12_31
+// CHECK:STDOUT:   %.loc12_1: init %array_type.ce7 = converted %.loc12_30.1, %.loc12_30.6 [template = constants.%array.6a2]
+// CHECK:STDOUT:   assign file.%b.var, %.loc12_1
 // CHECK:STDOUT:   %.loc13_20.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc13_24.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:   %.loc13_28.1: %empty_tuple.type = tuple_literal ()
@@ -125,8 +160,8 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc13_36.2: init %empty_tuple.type = tuple_init () to %.loc13_38.10 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.11: init %empty_tuple.type = converted %.loc13_36.1, %.loc13_36.2 [template = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc13_38.12: init %array_type.c13 = array_init (%.loc13_38.3, %.loc13_38.5, %.loc13_38.7, %.loc13_38.9, %.loc13_38.11) to file.%c.var [template = constants.%array.1cb]
-// CHECK:STDOUT:   %.loc13_39: init %array_type.c13 = converted %.loc13_38.1, %.loc13_38.12 [template = constants.%array.1cb]
-// CHECK:STDOUT:   assign file.%c.var, %.loc13_39
+// CHECK:STDOUT:   %.loc13_1: init %array_type.c13 = converted %.loc13_38.1, %.loc13_38.12 [template = constants.%array.1cb]
+// CHECK:STDOUT:   assign file.%c.var, %.loc13_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 87 - 6
toolchain/check/testdata/array/canonicalize_index.carbon

@@ -28,6 +28,7 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [template]
 // CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [template]
 // CHECK:STDOUT:   %Convert.type.1b6: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
+// CHECK:STDOUT:   %Convert.type.71e: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
 // CHECK:STDOUT:   %impl_witness.d39: <witness> = impl_witness (imports.%import_ref.a5b), @impl.1(%int_32) [template]
 // CHECK:STDOUT:   %Convert.type.035: type = fn_type @Convert.2, @impl.1(%int_32) [template]
 // CHECK:STDOUT:   %Convert.956: %Convert.type.035 = struct_value () [template]
@@ -38,6 +39,11 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:   %Convert.specific_fn.787: <specific function> = specific_function %Convert.bound.ef9, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [template]
 // CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [template]
+// CHECK:STDOUT:   %impl_witness.023: <witness> = impl_witness (imports.%import_ref.85c), @impl.2(%int_32) [template]
+// CHECK:STDOUT:   %Convert.type.4ad: type = fn_type @Convert.3, @impl.2(%int_32) [template]
+// CHECK:STDOUT:   %Convert.960: %Convert.type.4ad = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound.2d6: <bound method> = bound_method %int_3.822, %Convert.960 [template]
+// CHECK:STDOUT:   %Convert.specific_fn.377: <specific function> = specific_function %Convert.bound.2d6, @Convert.3(%int_32) [template]
 // CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [template]
 // CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [template]
 // CHECK:STDOUT:   %ptr: type = ptr_type %array_type [template]
@@ -46,6 +52,12 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:   %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [template]
 // CHECK:STDOUT:   %Convert.specific_fn.b42: <specific function> = specific_function %Convert.bound.b30, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [template]
+// CHECK:STDOUT:   %int_3.d14: %u32 = int_value 3 [template]
+// CHECK:STDOUT:   %impl_witness.8da2: <witness> = impl_witness (imports.%import_ref.823), @impl.45(%int_32) [template]
+// CHECK:STDOUT:   %Convert.type.e06: type = fn_type @Convert.9, @impl.45(%int_32) [template]
+// CHECK:STDOUT:   %Convert.47f: %Convert.type.e06 = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound.258: <bound method> = bound_method %int_3.d14, %Convert.47f [template]
+// CHECK:STDOUT:   %Convert.specific_fn.d14: <specific function> = specific_function %Convert.bound.258, @Convert.9(%int_32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -64,8 +76,8 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:     .Add = %Add.decl
 // CHECK:STDOUT:     .ConvertToU32 = %ConvertToU32.decl
 // CHECK:STDOUT:     .a = %a
-// CHECK:STDOUT:     .b = @__global_init.%b
-// CHECK:STDOUT:     .c = @__global_init.%c
+// CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Add.decl: %Add.type.b1f = fn_decl @Add.1 [template = constants.%Add] {
@@ -110,8 +122,79 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:     %return.param: ref %u32 = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref %u32 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc14_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc14_23: type = splice_block %array_type.loc14 [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc14: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc14: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %Add.ref: %Add.type.b1f = name_ref Add, %Add.decl [template = constants.%Add]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
+// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
+// CHECK:STDOUT:     %impl.elem0.loc14_18: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:     %Convert.bound.loc14_18: <bound method> = bound_method %int_1, %impl.elem0.loc14_18 [template = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:     %Convert.specific_fn.loc14_18: <specific function> = specific_function %Convert.bound.loc14_18, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
+// CHECK:STDOUT:     %int.convert_checked.loc14_18: init %i32 = call %Convert.specific_fn.loc14_18(%int_1) [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %.loc14_18.1: %i32 = value_of_initializer %int.convert_checked.loc14_18 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %.loc14_18.2: %i32 = converted %int_1, %.loc14_18.1 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %impl.elem0.loc14_21: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:     %Convert.bound.loc14_21: <bound method> = bound_method %int_2, %impl.elem0.loc14_21 [template = constants.%Convert.bound.ef9]
+// CHECK:STDOUT:     %Convert.specific_fn.loc14_21: <specific function> = specific_function %Convert.bound.loc14_21, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.787]
+// CHECK:STDOUT:     %int.convert_checked.loc14_21: init %i32 = call %Convert.specific_fn.loc14_21(%int_2) [template = constants.%int_2.ef8]
+// CHECK:STDOUT:     %.loc14_21.1: %i32 = value_of_initializer %int.convert_checked.loc14_21 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:     %.loc14_21.2: %i32 = converted %int_2, %.loc14_21.1 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:     %int.sadd: init %i32 = call %Add.ref(%.loc14_18.2, %.loc14_21.2) [template = constants.%int_3.822]
+// CHECK:STDOUT:     %impl.elem0.loc14_22: %Convert.type.71e = impl_witness_access constants.%impl_witness.023, element0 [template = constants.%Convert.960]
+// CHECK:STDOUT:     %Convert.bound.loc14_22: <bound method> = bound_method %int.sadd, %impl.elem0.loc14_22 [template = constants.%Convert.bound.2d6]
+// CHECK:STDOUT:     %Convert.specific_fn.loc14_22: <specific function> = specific_function %Convert.bound.loc14_22, @Convert.3(constants.%int_32) [template = constants.%Convert.specific_fn.377]
+// CHECK:STDOUT:     %.loc14_22.1: %i32 = value_of_initializer %int.sadd [template = constants.%int_3.822]
+// CHECK:STDOUT:     %.loc14_22.2: %i32 = converted %int.sadd, %.loc14_22.1 [template = constants.%int_3.822]
+// CHECK:STDOUT:     %int.convert_checked.loc14_22: init Core.IntLiteral = call %Convert.specific_fn.loc14_22(%.loc14_22.2) [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %.loc14_22.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc14_22 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %.loc14_22.4: Core.IntLiteral = converted %int.sadd, %.loc14_22.3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type.loc14: type = array_type %.loc14_22.4, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %ptr = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15: type = splice_block %ptr.loc15 [template = constants.%ptr] {
+// CHECK:STDOUT:     %int_32.loc15: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc15: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc15: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type.loc15: type = array_type %int_3.loc15, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:     %ptr.loc15: type = ptr_type %array_type [template = constants.%ptr]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: %ptr = bind_name b, @__global_init.%addr.loc15
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %ptr = binding_pattern c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_30: type = splice_block %ptr.loc16 [template = constants.%ptr] {
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %ConvertToU32.ref: %ConvertToU32.type = name_ref ConvertToU32, %ConvertToU32.decl [template = constants.%ConvertToU32]
+// CHECK:STDOUT:     %int_3.loc16: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %impl.elem0.loc16_27: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:     %Convert.bound.loc16_27: <bound method> = bound_method %int_3.loc16, %impl.elem0.loc16_27 [template = constants.%Convert.bound.b30]
+// CHECK:STDOUT:     %Convert.specific_fn.loc16_27: <specific function> = specific_function %Convert.bound.loc16_27, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.b42]
+// CHECK:STDOUT:     %int.convert_checked.loc16_27: init %i32 = call %Convert.specific_fn.loc16_27(%int_3.loc16) [template = constants.%int_3.822]
+// CHECK:STDOUT:     %.loc16_27.1: %i32 = value_of_initializer %int.convert_checked.loc16_27 [template = constants.%int_3.822]
+// CHECK:STDOUT:     %.loc16_27.2: %i32 = converted %int_3.loc16, %.loc16_27.1 [template = constants.%int_3.822]
+// CHECK:STDOUT:     %int.convert_checked.loc16_28.1: init %u32 = call %ConvertToU32.ref(%.loc16_27.2) [template = constants.%int_3.d14]
+// CHECK:STDOUT:     %impl.elem0.loc16_28: %Convert.type.71e = impl_witness_access constants.%impl_witness.8da2, element0 [template = constants.%Convert.47f]
+// CHECK:STDOUT:     %Convert.bound.loc16_28: <bound method> = bound_method %int.convert_checked.loc16_28.1, %impl.elem0.loc16_28 [template = constants.%Convert.bound.258]
+// CHECK:STDOUT:     %Convert.specific_fn.loc16_28: <specific function> = specific_function %Convert.bound.loc16_28, @Convert.9(constants.%int_32) [template = constants.%Convert.specific_fn.d14]
+// CHECK:STDOUT:     %.loc16_28.1: %u32 = value_of_initializer %int.convert_checked.loc16_28.1 [template = constants.%int_3.d14]
+// CHECK:STDOUT:     %.loc16_28.2: %u32 = converted %int.convert_checked.loc16_28.1, %.loc16_28.1 [template = constants.%int_3.d14]
+// CHECK:STDOUT:     %int.convert_checked.loc16_28.2: init Core.IntLiteral = call %Convert.specific_fn.loc16_28(%.loc16_28.2) [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %.loc16_28.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc16_28.2 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %.loc16_28.4: Core.IntLiteral = converted %int.convert_checked.loc16_28.1, %.loc16_28.3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type.loc16: type = array_type %.loc16_28.4, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:     %ptr.loc16: type = ptr_type %array_type [template = constants.%ptr]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %c: %ptr = bind_name c, @__global_init.%addr.loc16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Add.1(%a.param_patt: %i32, %b.param_patt: %i32) -> %i32 = "int.sadd";
@@ -149,14 +232,12 @@ let c: [i32; ConvertToU32(3)]* = &a;
 // CHECK:STDOUT:   %.loc14_35.9: ref %i32 = array_index file.%a.var, %int_2.loc14_35
 // CHECK:STDOUT:   %.loc14_35.10: init %i32 = initialize_from %.loc14_35.8 to %.loc14_35.9 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc14_35.11: init %array_type = array_init (%.loc14_35.4, %.loc14_35.7, %.loc14_35.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc14_36: init %array_type = converted %.loc14_35.1, %.loc14_35.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%a.var, %.loc14_36
+// CHECK:STDOUT:   %.loc14_1: init %array_type = converted %.loc14_35.1, %.loc14_35.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%a.var, %.loc14_1
 // CHECK:STDOUT:   %a.ref.loc15: ref %array_type = name_ref a, file.%a
 // CHECK:STDOUT:   %addr.loc15: %ptr = addr_of %a.ref.loc15
-// CHECK:STDOUT:   %b: %ptr = bind_name b, %addr.loc15
 // CHECK:STDOUT:   %a.ref.loc16: ref %array_type = name_ref a, file.%a
 // CHECK:STDOUT:   %addr.loc16: %ptr = addr_of %a.ref.loc16
-// CHECK:STDOUT:   %c: %ptr = bind_name c, %addr.loc16
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 43 - 1
toolchain/check/testdata/array/fail_bound_negative.carbon

@@ -23,6 +23,22 @@ var a: [i32; Negate(1)];
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [template]
 // CHECK:STDOUT:   %Negate.type.15b: type = fn_type @Negate.1 [template]
 // CHECK:STDOUT:   %Negate: %Negate.type.15b = struct_value () [template]
+// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %Convert.type.1b6: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
+// CHECK:STDOUT:   %Convert.type.71e: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %impl_witness.d39: <witness> = impl_witness (imports.%import_ref.a5b), @impl.1(%int_32) [template]
+// CHECK:STDOUT:   %Convert.type.035: type = fn_type @Convert.2, @impl.1(%int_32) [template]
+// CHECK:STDOUT:   %Convert.956: %Convert.type.035 = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [template]
+// CHECK:STDOUT:   %Convert.specific_fn.70c: <specific function> = specific_function %Convert.bound.ab5, @Convert.2(%int_32) [template]
+// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [template]
+// CHECK:STDOUT:   %int_-1.251: %i32 = int_value -1 [template]
+// CHECK:STDOUT:   %impl_witness.023: <witness> = impl_witness (imports.%import_ref.85c), @impl.2(%int_32) [template]
+// CHECK:STDOUT:   %Convert.type.4ad: type = fn_type @Convert.3, @impl.2(%int_32) [template]
+// CHECK:STDOUT:   %Convert.960: %Convert.type.4ad = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound.75d: <bound method> = bound_method %int_-1.251, %Convert.960 [template]
+// CHECK:STDOUT:   %Convert.specific_fn.4af: <specific function> = specific_function %Convert.bound.75d, @Convert.3(%int_32) [template]
+// CHECK:STDOUT:   %int_-1.638: Core.IntLiteral = int_value -1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -58,8 +74,34 @@ var a: [i32; Negate(1)];
 // CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
+// CHECK:STDOUT:     %.loc17_1: <error> = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref <error> = var a
-// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc17_23: type = splice_block %array_type [template = <error>] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %Negate.ref: %Negate.type.15b = name_ref Negate, %Negate.decl [template = constants.%Negate]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
+// CHECK:STDOUT:     %impl.elem0.loc17_21: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:     %Convert.bound.loc17_21: <bound method> = bound_method %int_1, %impl.elem0.loc17_21 [template = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:     %Convert.specific_fn.loc17_21: <specific function> = specific_function %Convert.bound.loc17_21, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
+// CHECK:STDOUT:     %int.convert_checked.loc17_21: init %i32 = call %Convert.specific_fn.loc17_21(%int_1) [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %.loc17_21.1: %i32 = value_of_initializer %int.convert_checked.loc17_21 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %.loc17_21.2: %i32 = converted %int_1, %.loc17_21.1 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:     %int.snegate: init %i32 = call %Negate.ref(%.loc17_21.2) [template = constants.%int_-1.251]
+// CHECK:STDOUT:     %impl.elem0.loc17_22: %Convert.type.71e = impl_witness_access constants.%impl_witness.023, element0 [template = constants.%Convert.960]
+// CHECK:STDOUT:     %Convert.bound.loc17_22: <bound method> = bound_method %int.snegate, %impl.elem0.loc17_22 [template = constants.%Convert.bound.75d]
+// CHECK:STDOUT:     %Convert.specific_fn.loc17_22: <specific function> = specific_function %Convert.bound.loc17_22, @Convert.3(constants.%int_32) [template = constants.%Convert.specific_fn.4af]
+// CHECK:STDOUT:     %.loc17_22.1: %i32 = value_of_initializer %int.snegate [template = constants.%int_-1.251]
+// CHECK:STDOUT:     %.loc17_22.2: %i32 = converted %int.snegate, %.loc17_22.1 [template = constants.%int_-1.251]
+// CHECK:STDOUT:     %int.convert_checked.loc17_22: init Core.IntLiteral = call %Convert.specific_fn.loc17_22(%.loc17_22.2) [template = constants.%int_-1.638]
+// CHECK:STDOUT:     %.loc17_22.3: Core.IntLiteral = value_of_initializer %int.convert_checked.loc17_22 [template = constants.%int_-1.638]
+// CHECK:STDOUT:     %.loc17_22.4: Core.IntLiteral = converted %int.snegate, %.loc17_22.3 [template = constants.%int_-1.638]
+// CHECK:STDOUT:     %array_type: type = array_type %.loc17_22.4, %i32 [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: <error> = bind_name a, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Negate.1(%n.param_patt: %i32) -> %i32 = "int.snegate";

+ 26 - 2
toolchain/check/testdata/array/fail_bound_overflow.carbon

@@ -26,6 +26,10 @@ var b: [1; 39999999999999999993];
 // CHECK:STDOUT: --- fail_bound_overflow.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template]
+// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [template]
+// CHECK:STDOUT:   %int_39999999999999999993: Core.IntLiteral = int_value 39999999999999999993 [template]
+// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -44,9 +48,29 @@ var b: [1; 39999999999999999993];
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
+// CHECK:STDOUT:     %.loc15_1: <error> = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref <error> = var a
-// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc15_34: type = splice_block %array_type.loc15 [template = <error>] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_39999999999999999993.loc15: Core.IntLiteral = int_value 39999999999999999993 [template = constants.%int_39999999999999999993]
+// CHECK:STDOUT:     %array_type.loc15: type = array_type %int_39999999999999999993.loc15, %i32 [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: <error> = bind_name a, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: <error> = binding_pattern b
+// CHECK:STDOUT:     %.loc24_1: <error> = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref <error> = var b
-// CHECK:STDOUT:   %b: ref <error> = bind_name b, %b.var
+// CHECK:STDOUT:   %.loc24_32: type = splice_block %array_type.loc24 [template = <error>] {
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %int_39999999999999999993.loc24: Core.IntLiteral = int_value 39999999999999999993 [template = constants.%int_39999999999999999993]
+// CHECK:STDOUT:     %.loc24_9: type = converted %int_1, <error> [template = <error>]
+// CHECK:STDOUT:     %array_type.loc24: type = array_type %int_39999999999999999993.loc24, <error> [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: <error> = bind_name b, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 2
toolchain/check/testdata/array/fail_incomplete_element.carbon

@@ -25,6 +25,8 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [template]
+// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template]
+// CHECK:STDOUT:   %array_type: type = array_type %int_1, %Incomplete [template]
 // CHECK:STDOUT:   %ptr: type = ptr_type %Incomplete [template]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [template]
 // CHECK:STDOUT: }
@@ -45,9 +47,26 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
+// CHECK:STDOUT:     %.loc20_1: <error> = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref <error> = var a
-// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc20_22: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %Incomplete.ref.loc20: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %array_type: type = array_type %int_1, %Incomplete [template = constants.%array_type]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: <error> = bind_name a, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %p.patt: %ptr = binding_pattern p
+// CHECK:STDOUT:     %.loc22_1: %ptr = var_pattern %p.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %p.var: ref %ptr = var p
+// CHECK:STDOUT:   %.loc22_18: type = splice_block %ptr [template = constants.%ptr] {
+// CHECK:STDOUT:     %Incomplete.ref.loc22: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
+// CHECK:STDOUT:     %ptr: type = ptr_type %Incomplete [template = constants.%ptr]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %p: ref %ptr = bind_name p, %p.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -55,7 +74,7 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %a.ref: ref <error> = name_ref a, file.%a
+// CHECK:STDOUT:   %a.ref: <error> = name_ref a, file.%a
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0]
 // CHECK:STDOUT:   %addr: <error> = addr_of <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%p.var, <error>

+ 12 - 1
toolchain/check/testdata/array/fail_invalid_type.carbon

@@ -20,6 +20,7 @@ var a: [1; 1];
 // CHECK:STDOUT: --- fail_invalid_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -36,7 +37,17 @@ var a: [1; 1];
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
+// CHECK:STDOUT:     %.loc18_1: <error> = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref <error> = var a
-// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc18_13: type = splice_block %array_type [template = <error>] {
+// CHECK:STDOUT:     %int_1.loc18_9: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %int_1.loc18_12: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %.loc18_9: type = converted %int_1.loc18_9, <error> [template = <error>]
+// CHECK:STDOUT:     %array_type: type = array_type %int_1.loc18_12, <error> [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: <error> = bind_name a, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 0
toolchain/check/testdata/array/fail_out_of_bound.carbon

@@ -40,7 +40,17 @@ var a: [i32; 1] = (1, 2, 3);
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc15_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc15_15: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
+// CHECK:STDOUT:     %array_type: type = array_type %int_1, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 20 - 2
toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon

@@ -60,9 +60,27 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc11_15: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type: type = array_type %int_3, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %i32 = binding_pattern b
+// CHECK:STDOUT:     %.loc16_1: %i32 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %i32 = var b
+// CHECK:STDOUT:   %.loc16_8: type = splice_block %i32.loc16 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %i32 = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -97,8 +115,8 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:   %.loc11_27.9: ref %i32 = array_index file.%a.var, %int_2.loc11_27
 // CHECK:STDOUT:   %.loc11_27.10: init %i32 = initialize_from %.loc11_27.8 to %.loc11_27.9 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc11_27.11: init %array_type = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_28: init %array_type = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%a.var, %.loc11_28
+// CHECK:STDOUT:   %.loc11_1: init %array_type = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%a.var, %.loc11_1
 // CHECK:STDOUT:   %a.ref: ref %array_type = name_ref a, file.%a
 // CHECK:STDOUT:   %int_3.loc16: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
 // CHECK:STDOUT:   %.loc16_27.1: %struct_type.index = struct_literal (%int_3.loc16)

+ 64 - 0
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -59,9 +59,11 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %int_1.5b8, %Convert.956 [template]
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [template]
+// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [template]
 // CHECK:STDOUT:   %tuple.type.9e7: type = tuple_type (%i32, String, String) [template]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template]
 // CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [template]
+// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [template]
 // CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -85,17 +87,79 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc18_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc18_15: type = splice_block %array_type.loc18 [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc18: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc18: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc18: Core.IntLiteral = int_value 3 [template = constants.%int_3]
+// CHECK:STDOUT:     %array_type.loc18: type = array_type %int_3.loc18, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %t1.patt: %tuple.type.9e7 = binding_pattern t1
+// CHECK:STDOUT:     %.loc20_1: %tuple.type.9e7 = var_pattern %t1.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %t1.var: ref %tuple.type.9e7 = var t1
+// CHECK:STDOUT:   %.loc20_29.1: type = splice_block %.loc20_29.3 [template = constants.%tuple.type.9e7] {
+// CHECK:STDOUT:     %int_32.loc20: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc20: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc20_29.2: %tuple.type.ff9 = tuple_literal (%i32.loc20, String, String)
+// CHECK:STDOUT:     %.loc20_29.3: type = converted %.loc20_29.2, constants.%tuple.type.9e7 [template = constants.%tuple.type.9e7]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %t1: ref %tuple.type.9e7 = bind_name t1, %t1.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %array_type = binding_pattern b
+// CHECK:STDOUT:     %.loc28_1: %array_type = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %array_type = var b
+// CHECK:STDOUT:   %.loc28_15: type = splice_block %array_type.loc28 [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc28: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc28: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc28: Core.IntLiteral = int_value 3 [template = constants.%int_3]
+// CHECK:STDOUT:     %array_type.loc28: type = array_type %int_3.loc28, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %array_type = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %array_type = binding_pattern c
+// CHECK:STDOUT:     %.loc34_1: %array_type = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %array_type = var c
+// CHECK:STDOUT:   %.loc34_15: type = splice_block %array_type.loc34 [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc34: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc34: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc34: Core.IntLiteral = int_value 3 [template = constants.%int_3]
+// CHECK:STDOUT:     %array_type.loc34: type = array_type %int_3.loc34, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %array_type = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %t2.patt: %tuple.type.d07 = binding_pattern t2
+// CHECK:STDOUT:     %.loc36_1: %tuple.type.d07 = var_pattern %t2.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %t2.var: ref %tuple.type.d07 = var t2
+// CHECK:STDOUT:   %.loc36_18.1: type = splice_block %.loc36_18.3 [template = constants.%tuple.type.d07] {
+// CHECK:STDOUT:     %int_32.loc36_10: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc36_10: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc36_15: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc36_15: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc36_18.2: %tuple.type.24b = tuple_literal (%i32.loc36_10, %i32.loc36_15)
+// CHECK:STDOUT:     %.loc36_18.3: type = converted %.loc36_18.2, constants.%tuple.type.d07 [template = constants.%tuple.type.d07]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %t2: ref %tuple.type.d07 = bind_name t2, %t2.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %array_type = binding_pattern d
+// CHECK:STDOUT:     %.loc41_1: %array_type = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %array_type = var d
+// CHECK:STDOUT:   %.loc41_15: type = splice_block %array_type.loc41 [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc41: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc41: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3.loc41: Core.IntLiteral = int_value 3 [template = constants.%int_3]
+// CHECK:STDOUT:     %array_type.loc41: type = array_type %int_3.loc41, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %array_type = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 17 - 8
toolchain/check/testdata/array/generic_empty.carbon

@@ -54,18 +54,27 @@ fn G(T:! type) {
 // CHECK:STDOUT:   %T.patt.loc11_6.2: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_6.2 (constants.%T.patt)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %array_type: type = array_type constants.%int_0, @G.%T.loc11_6.2 (%T) [symbolic = %array_type (constants.%array_type)]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @G.%array_type (%array_type) [symbolic = %require_complete (constants.%require_complete)]
-// CHECK:STDOUT:   %array: @G.%array_type (%array_type) = tuple_value () [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:   %array_type.loc13_17.2: type = array_type constants.%int_0, @G.%T.loc11_6.2 (%T) [symbolic = %array_type.loc13_17.2 (constants.%array_type)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @G.%array_type.loc13_17.2 (%array_type) [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %array: @G.%array_type.loc13_17.2 (%array_type) = tuple_value () [symbolic = %array (constants.%array)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%T.param_patt: type) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %arr.var: ref @G.%array_type (%array_type) = var arr
-// CHECK:STDOUT:     %arr: ref @G.%array_type (%array_type) = bind_name arr, %arr.var
+// CHECK:STDOUT:     name_binding_decl {
+// CHECK:STDOUT:       %arr.patt: @G.%array_type.loc13_17.2 (%array_type) = binding_pattern arr
+// CHECK:STDOUT:       %.loc13_3.1: @G.%array_type.loc13_17.2 (%array_type) = var_pattern %arr.patt
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %arr.var: ref @G.%array_type.loc13_17.2 (%array_type) = var arr
 // CHECK:STDOUT:     %.loc13_22.1: %empty_tuple.type = tuple_literal ()
-// CHECK:STDOUT:     %.loc13_22.2: init @G.%array_type (%array_type) = array_init () to %arr.var [symbolic = %array (constants.%array)]
-// CHECK:STDOUT:     %.loc13_23: init @G.%array_type (%array_type) = converted %.loc13_22.1, %.loc13_22.2 [symbolic = %array (constants.%array)]
-// CHECK:STDOUT:     assign %arr.var, %.loc13_23
+// CHECK:STDOUT:     %.loc13_22.2: init @G.%array_type.loc13_17.2 (%array_type) = array_init () to %arr.var [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:     %.loc13_3.2: init @G.%array_type.loc13_17.2 (%array_type) = converted %.loc13_22.1, %.loc13_22.2 [symbolic = %array (constants.%array)]
+// CHECK:STDOUT:     assign %arr.var, %.loc13_3.2
+// CHECK:STDOUT:     %.loc13_17: type = splice_block %array_type.loc13_17.1 [symbolic = %array_type.loc13_17.2 (constants.%array_type)] {
+// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc11_6.1 [symbolic = %T.loc11_6.2 (constants.%T)]
+// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0]
+// CHECK:STDOUT:       %array_type.loc13_17.1: type = array_type %int_0, %T [symbolic = %array_type.loc13_17.2 (constants.%array_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %arr: ref @G.%array_type.loc13_17.2 (%array_type) = bind_name arr, %arr.var
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 20 - 2
toolchain/check/testdata/array/index_not_literal.carbon

@@ -56,9 +56,27 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc11_15: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32.loc11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [template = constants.%int_3.1ba]
+// CHECK:STDOUT:     %array_type: type = array_type %int_3, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %i32 = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %i32 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %i32 = var b
+// CHECK:STDOUT:   %.loc12_8: type = splice_block %i32.loc12 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc12: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc12: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %i32 = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -93,8 +111,8 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:   %.loc11_27.9: ref %i32 = array_index file.%a.var, %int_2.loc11_27
 // CHECK:STDOUT:   %.loc11_27.10: init %i32 = initialize_from %.loc11_27.8 to %.loc11_27.9 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc11_27.11: init %array_type = array_init (%.loc11_27.4, %.loc11_27.7, %.loc11_27.10) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_28: init %array_type = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%a.var, %.loc11_28
+// CHECK:STDOUT:   %.loc11_1: init %array_type = converted %.loc11_27.1, %.loc11_27.11 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%a.var, %.loc11_1
 // CHECK:STDOUT:   %a.ref: ref %array_type = name_ref a, file.%a
 // CHECK:STDOUT:   %int_2.loc12: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
 // CHECK:STDOUT:   %.loc12_27.1: %struct_type.index = struct_literal (%int_2.loc12)

+ 29 - 11
toolchain/check/testdata/array/init_dependent_bound.carbon

@@ -44,6 +44,8 @@ fn H() { G(3); }
 // CHECK:STDOUT:   %N.patt.8e2: %i32 = symbolic_binding_pattern N, 0 [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %Convert.type.71e: type = fn_type @Convert.1, @ImplicitAs(Core.IntLiteral) [template]
+// CHECK:STDOUT:   %impl_witness.023: <witness> = impl_witness (imports.%import_ref.85c), @impl.2(%int_32) [template]
 // CHECK:STDOUT:   %Convert.type.4ad: type = fn_type @Convert.3, @impl.2(%int_32) [template]
 // CHECK:STDOUT:   %Convert.960: %Convert.type.4ad = struct_value () [template]
 // CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %N.51e, %Convert.960 [symbolic]
@@ -77,9 +79,9 @@ fn H() { G(3); }
 // CHECK:STDOUT:     %N.param_patt: %i32 = value_param_pattern %N.patt.loc4_6.1, runtime_param<invalid> [symbolic = %N.patt.loc4_6.2 (constants.%N.patt.8e2)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %N.param: %i32 = value_param runtime_param<invalid>
-// CHECK:STDOUT:     %.loc4: type = splice_block %i32 [template = constants.%i32] {
-// CHECK:STDOUT:       %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
-// CHECK:STDOUT:       %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc4: type = splice_block %i32.loc4 [template = constants.%i32] {
+// CHECK:STDOUT:       %int_32.loc4: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:       %i32.loc4: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %N.loc4_6.1: %i32 = bind_symbolic_name N, 0, %N.param [symbolic = %N.loc4_6.2 (constants.%N.51e)]
 // CHECK:STDOUT:   }
@@ -90,21 +92,37 @@ fn H() { G(3); }
 // CHECK:STDOUT:   %N.patt.loc4_6.2: %i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc4_6.2 (constants.%N.patt.8e2)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %N.loc4_6.2, constants.%Convert.960 [symbolic = %Convert.bound (constants.%Convert.bound)]
-// CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.3(constants.%int_32) [symbolic = %Convert.specific_fn (constants.%Convert.specific_fn)]
-// CHECK:STDOUT:   %int.convert_checked: init Core.IntLiteral = call %Convert.specific_fn(%N.loc4_6.2) [symbolic = %int.convert_checked (constants.%int.convert_checked)]
-// CHECK:STDOUT:   %array_type: type = array_type %int.convert_checked, %i32 [symbolic = %array_type (constants.%array_type)]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @F.%array_type (%array_type) [symbolic = %require_complete (constants.%require_complete.9dc)]
+// CHECK:STDOUT:   %Convert.bound.loc9_18.2: <bound method> = bound_method %N.loc4_6.2, constants.%Convert.960 [symbolic = %Convert.bound.loc9_18.2 (constants.%Convert.bound)]
+// CHECK:STDOUT:   %Convert.specific_fn.loc9_18.2: <specific function> = specific_function %Convert.bound.loc9_18.2, @Convert.3(constants.%int_32) [symbolic = %Convert.specific_fn.loc9_18.2 (constants.%Convert.specific_fn)]
+// CHECK:STDOUT:   %int.convert_checked.loc9_18.2: init Core.IntLiteral = call %Convert.specific_fn.loc9_18.2(%N.loc4_6.2) [symbolic = %int.convert_checked.loc9_18.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:   %array_type.loc9_19.2: type = array_type %int.convert_checked.loc9_18.2, %i32 [symbolic = %array_type.loc9_19.2 (constants.%array_type)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @F.%array_type.loc9_19.2 (%array_type) [symbolic = %require_complete (constants.%require_complete.9dc)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%N.param_patt: %i32) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %arr.var: ref @F.%array_type (%array_type) = var arr
-// CHECK:STDOUT:     %arr: ref @F.%array_type (%array_type) = bind_name arr, %arr.var
+// CHECK:STDOUT:     name_binding_decl {
+// CHECK:STDOUT:       %arr.patt: @F.%array_type.loc9_19.2 (%array_type) = binding_pattern arr
+// CHECK:STDOUT:       %.loc9_3: @F.%array_type.loc9_19.2 (%array_type) = var_pattern %arr.patt
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %arr.var: ref @F.%array_type.loc9_19.2 (%array_type) = var arr
 // CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
 // CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2]
 // CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [template = constants.%int_3]
-// CHECK:STDOUT:     %.loc9: %tuple.type = tuple_literal (%int_1, %int_2, %int_3)
+// CHECK:STDOUT:     %.loc9_31: %tuple.type = tuple_literal (%int_1, %int_2, %int_3)
 // CHECK:STDOUT:     assign %arr.var, <error>
+// CHECK:STDOUT:     %.loc9_19: type = splice_block %array_type.loc9_19.1 [symbolic = %array_type.loc9_19.2 (constants.%array_type)] {
+// CHECK:STDOUT:       %int_32.loc9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:       %i32.loc9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:       %N.ref: %i32 = name_ref N, %N.loc4_6.1 [symbolic = %N.loc4_6.2 (constants.%N.51e)]
+// CHECK:STDOUT:       %impl.elem0: %Convert.type.71e = impl_witness_access constants.%impl_witness.023, element0 [template = constants.%Convert.960]
+// CHECK:STDOUT:       %Convert.bound.loc9_18.1: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Convert.bound.loc9_18.2 (constants.%Convert.bound)]
+// CHECK:STDOUT:       %Convert.specific_fn.loc9_18.1: <specific function> = specific_function %Convert.bound.loc9_18.1, @Convert.3(constants.%int_32) [symbolic = %Convert.specific_fn.loc9_18.2 (constants.%Convert.specific_fn)]
+// CHECK:STDOUT:       %int.convert_checked.loc9_18.1: init Core.IntLiteral = call %Convert.specific_fn.loc9_18.1(%N.ref) [symbolic = %int.convert_checked.loc9_18.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:       %.loc9_18.1: Core.IntLiteral = value_of_initializer %int.convert_checked.loc9_18.1 [symbolic = %int.convert_checked.loc9_18.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:       %.loc9_18.2: Core.IntLiteral = converted %N.ref, %.loc9_18.1 [symbolic = %int.convert_checked.loc9_18.2 (constants.%int.convert_checked)]
+// CHECK:STDOUT:       %array_type.loc9_19.1: type = array_type %.loc9_18.2, %i32 [symbolic = %array_type.loc9_19.2 (constants.%array_type)]
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %arr: ref @F.%array_type.loc9_19.2 (%array_type) = bind_name arr, %arr.var
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 12 - 2
toolchain/check/testdata/array/nine_elements.carbon

@@ -76,7 +76,17 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %array_type = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %array_type = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %array_type = var a
+// CHECK:STDOUT:   %.loc11_15: type = splice_block %array_type [template = constants.%array_type] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_9: Core.IntLiteral = int_value 9 [template = constants.%int_9.988]
+// CHECK:STDOUT:     %array_type: type = array_type %int_9, %i32 [template = constants.%array_type]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %array_type = bind_name a, %a.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -165,8 +175,8 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %.loc11_45.27: ref %i32 = array_index file.%a.var, %int_8.loc11_45
 // CHECK:STDOUT:   %.loc11_45.28: init %i32 = initialize_from %.loc11_45.26 to %.loc11_45.27 [template = constants.%int_9.f88]
 // CHECK:STDOUT:   %.loc11_45.29: init %array_type = array_init (%.loc11_45.4, %.loc11_45.7, %.loc11_45.10, %.loc11_45.13, %.loc11_45.16, %.loc11_45.19, %.loc11_45.22, %.loc11_45.25, %.loc11_45.28) to file.%a.var [template = constants.%array]
-// CHECK:STDOUT:   %.loc11_46: init %array_type = converted %.loc11_45.1, %.loc11_45.29 [template = constants.%array]
-// CHECK:STDOUT:   assign file.%a.var, %.loc11_46
+// CHECK:STDOUT:   %.loc11_1: init %array_type = converted %.loc11_45.1, %.loc11_45.29 [template = constants.%array]
+// CHECK:STDOUT:   assign file.%a.var, %.loc11_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 130 - 41
toolchain/check/testdata/as/adapter_conversion.carbon

@@ -131,7 +131,7 @@ fn F(a: A) {
 
   // CHECK:STDERR: fail_init_tuple_variable.carbon:[[@LINE+7]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
   // CHECK:STDERR:   var a_init: A = (a as (i32, Noncopyable)) as A;
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:   ^~~~~~~~~~~~~
   // CHECK:STDERR: fail_init_tuple_variable.carbon:[[@LINE+4]]:19: note: in copy of `A` [InCopy]
   // CHECK:STDERR:   var a_init: A = (a as (i32, Noncopyable)) as A;
   // CHECK:STDERR:                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -207,23 +207,59 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:     .A = %A.decl
 // CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:     .a_ref = %a_ref
-// CHECK:STDOUT:     .a_val = @__global_init.%a_val
-// CHECK:STDOUT:     .b_val = @__global_init.%b_val
-// CHECK:STDOUT:     .b_ptr = @__global_init.%b_ptr
+// CHECK:STDOUT:     .a_val = %a_val
+// CHECK:STDOUT:     .b_val = %b_val
+// CHECK:STDOUT:     .b_ptr = %b_ptr
 // CHECK:STDOUT:     .b_factory = %b_factory
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_ref.patt: %A = binding_pattern a_ref
+// CHECK:STDOUT:     %.loc17: %A = var_pattern %a_ref.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a_ref.var: ref %A = var a_ref
+// CHECK:STDOUT:   %A.ref.loc17: type = name_ref A, %A.decl [template = constants.%A]
 // CHECK:STDOUT:   %a_ref: ref %A = bind_name a_ref, %a_ref.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_val.patt: %A = binding_pattern a_val
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %A.ref.loc18: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:   %a_val: ref %A = bind_name a_val, @__global_init.%a_ref.ref.loc18
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_val.patt: %B = binding_pattern b_val
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.ref.loc21: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:   %b_val: ref %B = bind_name b_val, @__global_init.%.loc21_22.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_ptr.patt: %ptr.e79 = binding_pattern b_ptr
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc22: type = splice_block %ptr [template = constants.%ptr.e79] {
+// CHECK:STDOUT:     %B.ref.loc22: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:     %ptr: type = ptr_type %B [template = constants.%ptr.e79]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b_ptr: %ptr.e79 = bind_name b_ptr, @__global_init.%addr
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_factory.patt: %B = binding_pattern b_factory
+// CHECK:STDOUT:     %.loc24: %B = var_pattern %b_factory.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b_factory.var: ref %B = var b_factory
+// CHECK:STDOUT:   %B.ref.loc24: type = name_ref B, %B.decl [template = constants.%B]
 // CHECK:STDOUT:   %b_factory: ref %B = bind_name b_factory, %b_factory.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [template]
-// CHECK:STDOUT:   %.loc6: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [template = constants.%Make] {
 // CHECK:STDOUT:     %return.patt: %A = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %A = out_param_pattern %return.patt, runtime_param0
@@ -287,26 +323,22 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %.loc17_31.6: ref %i32 = class_element_access file.%a_ref.var, element1
 // CHECK:STDOUT:   %.loc17_31.7: init %i32 = initialize_from %.loc17_31.5 to %.loc17_31.6 [template = constants.%int_2.ef8]
 // CHECK:STDOUT:   %.loc17_31.8: init %A = class_init (%.loc17_31.4, %.loc17_31.7), file.%a_ref.var [template = constants.%A.val]
-// CHECK:STDOUT:   %.loc17_32: init %A = converted %.loc17_31.1, %.loc17_31.8 [template = constants.%A.val]
-// CHECK:STDOUT:   assign file.%a_ref.var, %.loc17_32
+// CHECK:STDOUT:   %.loc17_1: init %A = converted %.loc17_31.1, %.loc17_31.8 [template = constants.%A.val]
+// CHECK:STDOUT:   assign file.%a_ref.var, %.loc17_1
 // CHECK:STDOUT:   %a_ref.ref.loc18: ref %A = name_ref a_ref, file.%a_ref
-// CHECK:STDOUT:   %.loc18: %A = bind_value %a_ref.ref.loc18
-// CHECK:STDOUT:   %a_val: %A = bind_name a_val, %.loc18
-// CHECK:STDOUT:   %a_val.ref: %A = name_ref a_val, %a_val
+// CHECK:STDOUT:   %a_val.ref: ref %A = name_ref a_val, file.%a_val
 // CHECK:STDOUT:   %B.ref.loc21: type = name_ref B, file.%B.decl [template = constants.%B]
-// CHECK:STDOUT:   %.loc21_22.1: %B = as_compatible %a_val.ref
-// CHECK:STDOUT:   %.loc21_22.2: %B = converted %a_val.ref, %.loc21_22.1
-// CHECK:STDOUT:   %b_val: %B = bind_name b_val, %.loc21_22.2
+// CHECK:STDOUT:   %.loc21_22.1: ref %B = as_compatible %a_val.ref
+// CHECK:STDOUT:   %.loc21_22.2: ref %B = converted %a_val.ref, %.loc21_22.1
 // CHECK:STDOUT:   %a_ref.ref.loc22: ref %A = name_ref a_ref, file.%a_ref
 // CHECK:STDOUT:   %B.ref.loc22: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %.loc22_25.1: ref %B = as_compatible %a_ref.ref.loc22
 // CHECK:STDOUT:   %.loc22_25.2: ref %B = converted %a_ref.ref.loc22, %.loc22_25.1
 // CHECK:STDOUT:   %addr: %ptr.e79 = addr_of %.loc22_25.2
-// CHECK:STDOUT:   %b_ptr: %ptr.e79 = bind_name b_ptr, %addr
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, @A.%Make.decl [template = constants.%Make]
-// CHECK:STDOUT:   %.loc24_5: ref %B = splice_block file.%b_factory.var {}
-// CHECK:STDOUT:   %Make.call: init %A = call %Make.ref() to %.loc24_5
+// CHECK:STDOUT:   %.loc24_1: ref %B = splice_block file.%b_factory.var {}
+// CHECK:STDOUT:   %Make.call: init %A = call %Make.ref() to %.loc24_1
 // CHECK:STDOUT:   %B.ref.loc24: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %.loc24_29.1: init %B = as_compatible %Make.call
 // CHECK:STDOUT:   %.loc24_29.2: init %B = converted %Make.call, %.loc24_29.1
@@ -345,11 +377,24 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .A = %A.decl
-// CHECK:STDOUT:     .a = @__global_init.%a
-// CHECK:STDOUT:     .n = @__global_init.%n
+// CHECK:STDOUT:     .a = %a
+// CHECK:STDOUT:     .n = %n
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %A = binding_pattern a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %A.ref: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:   %a: %A = bind_name a, @__global_init.%.loc8_23.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc9: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %n: %i32 = bind_name n, @__global_init.%.loc9_16.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
@@ -374,13 +419,11 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc8_23.1: %A = as_compatible %.loc8_15.2 [template = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc8_23.2: %A = converted %.loc8_15.2, %.loc8_23.1 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %a: %A = bind_name a, %.loc8_23.2
-// CHECK:STDOUT:   %a.ref: %A = name_ref a, %a
+// CHECK:STDOUT:   %a.ref: %A = name_ref a, file.%a
 // CHECK:STDOUT:   %int_32.loc9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32.loc9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   %.loc9_16.1: %i32 = as_compatible %a.ref
 // CHECK:STDOUT:   %.loc9_16.2: %i32 = converted %a.ref, %.loc9_16.1
-// CHECK:STDOUT:   %n: %i32 = bind_name n, %.loc9_16.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -410,13 +453,18 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:     .D = %D.decl
-// CHECK:STDOUT:     .d = @__global_init.%d
+// CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %D.decl: type = class_decl @D [template = constants.%D] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %D = binding_pattern d
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %D.ref: type = name_ref D, %D.decl [template = constants.%D]
+// CHECK:STDOUT:   %d: %D = bind_name d, @__global_init.%.loc9_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
@@ -455,7 +503,6 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [template = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc9_15.1: %D = as_compatible %empty_struct [template = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc9_15.2: %D = converted %.loc9_13, %.loc9_15.1 [template = constants.%empty_struct]
-// CHECK:STDOUT:   %d: %D = bind_name d, %.loc9_15.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -499,16 +546,29 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .A = %A.decl
 // CHECK:STDOUT:     .B = %B.decl
-// CHECK:STDOUT:     .b_value = @__global_init.%b_value
+// CHECK:STDOUT:     .b_value = %b_value
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_value.patt: %B = binding_pattern b_value
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:   %b_value: ref %B = bind_name b_value, @__global_init.%.loc13_42.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [template]
-// CHECK:STDOUT:   %.loc6: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.y.871 [template = constants.%complete_type.70a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -547,8 +607,6 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %.loc13_42.1: ref %B = as_compatible %.loc13_36
 // CHECK:STDOUT:   %.loc13_42.2: ref %B = converted %.loc13_36, %.loc13_42.1
-// CHECK:STDOUT:   %.loc13_42.3: %B = bind_value %.loc13_42.2
-// CHECK:STDOUT:   %b_value: %B = bind_name b_value, %.loc13_42.3
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -597,13 +655,26 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b_init.patt: %B = binding_pattern b_init
+// CHECK:STDOUT:     %.loc22: %B = var_pattern %b_init.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b_init.var: ref %B = var b_init
+// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
 // CHECK:STDOUT:   %b_init: ref %B = bind_name b_init, %b_init.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [template]
-// CHECK:STDOUT:   %.loc6: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %A.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %A.elem = field_decl y, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %A.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.y.871 [template = constants.%complete_type.70a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -709,6 +780,9 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%a.param_patt: %A) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_value.patt: %A = binding_pattern a_value
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.ref: %A = name_ref a, %a
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
@@ -717,9 +791,10 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %.loc13_43.2: type = converted %.loc13_43.1, constants.%tuple.type.560 [template = constants.%tuple.type.560]
 // CHECK:STDOUT:   %.loc13_23.1: %tuple.type.560 = as_compatible %a.ref
 // CHECK:STDOUT:   %.loc13_23.2: %tuple.type.560 = converted %a.ref, %.loc13_23.1
-// CHECK:STDOUT:   %A.ref.loc13: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:   %A.ref.loc13_49: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc13_46.1: %A = as_compatible %.loc13_23.2
 // CHECK:STDOUT:   %.loc13_46.2: %A = converted %.loc13_23.2, %.loc13_46.1
+// CHECK:STDOUT:   %A.ref.loc13_16: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %a_value: %A = bind_name a_value, %.loc13_46.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -786,8 +861,11 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%a.param_patt: %A) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a_init.patt: %A = binding_pattern a_init
+// CHECK:STDOUT:     %.loc25_3.1: %A = var_pattern %a_init.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a_init.var: ref %A = var a_init
-// CHECK:STDOUT:   %a_init: ref %A = bind_name a_init, %a_init.var
 // CHECK:STDOUT:   %a.ref: %A = name_ref a, %a
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
@@ -796,16 +874,18 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %.loc25_42.2: type = converted %.loc25_42.1, constants.%tuple.type.560 [template = constants.%tuple.type.560]
 // CHECK:STDOUT:   %.loc25_22.1: %tuple.type.560 = as_compatible %a.ref
 // CHECK:STDOUT:   %.loc25_22.2: %tuple.type.560 = converted %a.ref, %.loc25_22.1
-// CHECK:STDOUT:   %A.ref.loc25: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:   %A.ref.loc25_48: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc25_45.1: %A = as_compatible %.loc25_22.2
 // CHECK:STDOUT:   %.loc25_45.2: %A = converted %.loc25_22.2, %.loc25_45.1
-// CHECK:STDOUT:   %.loc25_49.1: %tuple.type.560 = as_compatible %.loc25_45.2
-// CHECK:STDOUT:   %tuple.elem0.loc25_49.1: %i32 = tuple_access %.loc25_49.1, element0
-// CHECK:STDOUT:   %.loc25_49.2: ref %tuple.type.560 = as_compatible %a_init.var
-// CHECK:STDOUT:   %tuple.elem0.loc25_49.2: ref %i32 = tuple_access %.loc25_49.2, element0
-// CHECK:STDOUT:   %.loc25_49.3: init %i32 = initialize_from %tuple.elem0.loc25_49.1 to %tuple.elem0.loc25_49.2
-// CHECK:STDOUT:   %tuple.elem1: %Noncopyable = tuple_access %.loc25_49.1, element1
+// CHECK:STDOUT:   %.loc25_3.2: %tuple.type.560 = as_compatible %.loc25_45.2
+// CHECK:STDOUT:   %tuple.elem0.loc25_3.1: %i32 = tuple_access %.loc25_3.2, element0
+// CHECK:STDOUT:   %.loc25_3.3: ref %tuple.type.560 = as_compatible %a_init.var
+// CHECK:STDOUT:   %tuple.elem0.loc25_3.2: ref %i32 = tuple_access %.loc25_3.3, element0
+// CHECK:STDOUT:   %.loc25_3.4: init %i32 = initialize_from %tuple.elem0.loc25_3.1 to %tuple.elem0.loc25_3.2
+// CHECK:STDOUT:   %tuple.elem1: %Noncopyable = tuple_access %.loc25_3.2, element1
 // CHECK:STDOUT:   assign %a_init.var, <error>
+// CHECK:STDOUT:   %A.ref.loc25_15: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:   %a_init: ref %A = bind_name a_init, %a_init.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -842,12 +922,21 @@ var b: B = {.x = 1} as B;
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %B = binding_pattern b
+// CHECK:STDOUT:     %.loc22: %B = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %B = var b
+// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
 // CHECK:STDOUT:   %b: ref %B = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   %.loc5_8: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %A.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x.ed6 [template = constants.%complete_type.1ec]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 5 - 2
toolchain/check/testdata/as/as_type.carbon

@@ -30,9 +30,13 @@ let t: type = (i32, i32) as type;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
-// CHECK:STDOUT:     .t = @__global_init.%t
+// CHECK:STDOUT:     .t = %t
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %t.patt: type = binding_pattern t
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %t: type = bind_name t, @__global_init.%.loc11_26
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -43,7 +47,6 @@ let t: type = (i32, i32) as type;
 // CHECK:STDOUT:   %i32.loc11_21: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   %.loc11_24: %tuple.type.24b = tuple_literal (%i32.loc11_16, %i32.loc11_21)
 // CHECK:STDOUT:   %.loc11_26: type = converted %.loc11_24, constants.%tuple.type.d07 [template = constants.%tuple.type.d07]
-// CHECK:STDOUT:   %t: type = bind_name t, %.loc11_26
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 14 - 3
toolchain/check/testdata/as/fail_no_conversion.carbon

@@ -39,9 +39,22 @@ let n: (i32, i32) = 1 as (i32, i32);
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
-// CHECK:STDOUT:     .n = @__global_init.%n
+// CHECK:STDOUT:     .n = %n
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %n.patt: %tuple.type.d07 = binding_pattern n
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc18_17.1: type = splice_block %.loc18_17.3 [template = constants.%tuple.type.d07] {
+// CHECK:STDOUT:     %int_32.loc18_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc18_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_32.loc18_14: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc18_14: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %.loc18_17.2: %tuple.type.24b = tuple_literal (%i32.loc18_9, %i32.loc18_14)
+// CHECK:STDOUT:     %.loc18_17.3: type = converted %.loc18_17.2, constants.%tuple.type.d07 [template = constants.%tuple.type.d07]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %tuple.elem0: %i32 = tuple_access @__global_init.%.loc18_23, element0 [template = <error>]
+// CHECK:STDOUT:   %n: %tuple.type.d07 = bind_name n, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -54,8 +67,6 @@ let n: (i32, i32) = 1 as (i32, i32);
 // CHECK:STDOUT:   %.loc18_35.1: %tuple.type.24b = tuple_literal (%i32.loc18_27, %i32.loc18_32)
 // CHECK:STDOUT:   %.loc18_35.2: type = converted %.loc18_35.1, constants.%tuple.type.d07 [template = constants.%tuple.type.d07]
 // CHECK:STDOUT:   %.loc18_23: %tuple.type.d07 = converted %int_1, <error> [template = <error>]
-// CHECK:STDOUT:   %tuple.elem0: %i32 = tuple_access %.loc18_23, element0 [template = <error>]
-// CHECK:STDOUT:   %n: %tuple.type.d07 = bind_name n, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 9 - 2
toolchain/check/testdata/as/fail_not_type.carbon

@@ -38,9 +38,17 @@ let n: i32 = 1 as 2;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
-// CHECK:STDOUT:     .n = @__global_init.%n
+// CHECK:STDOUT:     .n = %n
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc18: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %n: %i32 = bind_name n, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -48,7 +56,6 @@ let n: i32 = 1 as 2;
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2]
 // CHECK:STDOUT:   %.loc18: type = converted %int_2, <error> [template = <error>]
-// CHECK:STDOUT:   %n: %i32 = bind_name n, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 26 - 10
toolchain/check/testdata/as/identity.carbon

@@ -76,9 +76,9 @@ fn Initializing() {
 // CHECK:STDOUT:     %p.param_patt: %ptr.d17 = value_param_pattern %p.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %p.param: %ptr.d17 = value_param runtime_param0
-// CHECK:STDOUT:     %.loc21: type = splice_block %ptr [template = constants.%ptr.d17] {
+// CHECK:STDOUT:     %.loc21: type = splice_block %ptr.loc21 [template = constants.%ptr.d17] {
 // CHECK:STDOUT:       %X.ref.loc21: type = name_ref X, file.%X.decl [template = constants.%X]
-// CHECK:STDOUT:       %ptr: type = ptr_type %X [template = constants.%ptr.d17]
+// CHECK:STDOUT:       %ptr.loc21: type = ptr_type %X [template = constants.%ptr.d17]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %p: %ptr.d17 = bind_name p, %p.param
 // CHECK:STDOUT:   }
@@ -100,18 +100,29 @@ fn Initializing() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Value(%n.param_patt: %X) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %m.patt: %X = binding_pattern m
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %n.ref: %X = name_ref n, %n
-// CHECK:STDOUT:   %X.ref.loc18: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc18_19: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:   %X.ref.loc18_10: type = name_ref X, file.%X.decl [template = constants.%X]
 // CHECK:STDOUT:   %m: %X = bind_name m, %n.ref
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Reference(%p.param_patt: %ptr.d17) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %q.patt: %ptr.d17 = binding_pattern q
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %p.ref: %ptr.d17 = name_ref p, %p
-// CHECK:STDOUT:   %.loc22: ref %X = deref %p.ref
-// CHECK:STDOUT:   %X.ref.loc22: type = name_ref X, file.%X.decl [template = constants.%X]
-// CHECK:STDOUT:   %addr: %ptr.d17 = addr_of %.loc22
+// CHECK:STDOUT:   %.loc22_17: ref %X = deref %p.ref
+// CHECK:STDOUT:   %X.ref.loc22_23: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:   %addr: %ptr.d17 = addr_of %.loc22_17
+// CHECK:STDOUT:   %.loc22_11: type = splice_block %ptr.loc22 [template = constants.%ptr.d17] {
+// CHECK:STDOUT:     %X.ref.loc22_10: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:     %ptr.loc22: type = ptr_type %X [template = constants.%ptr.d17]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %q: %ptr.d17 = bind_name q, %addr
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -120,13 +131,18 @@ fn Initializing() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Initializing() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %X = binding_pattern x
+// CHECK:STDOUT:     %.loc28_3.1: %X = var_pattern %x.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref %X = var x
-// CHECK:STDOUT:   %x: ref %X = bind_name x, %x.var
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [template = constants.%Make]
-// CHECK:STDOUT:   %.loc28: ref %X = splice_block %x.var {}
-// CHECK:STDOUT:   %Make.call: init %X = call %Make.ref() to %.loc28
-// CHECK:STDOUT:   %X.ref: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:   %.loc28_3.2: ref %X = splice_block %x.var {}
+// CHECK:STDOUT:   %Make.call: init %X = call %Make.ref() to %.loc28_3.2
+// CHECK:STDOUT:   %X.ref.loc28_25: type = name_ref X, file.%X.decl [template = constants.%X]
 // CHECK:STDOUT:   assign %x.var, %Make.call
+// CHECK:STDOUT:   %X.ref.loc28_10: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:   %x: ref %X = bind_name x, %x.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 25 - 6
toolchain/check/testdata/as/no_prelude/tuple.carbon

@@ -69,31 +69,43 @@ fn Var() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Let() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %tuple.type.b67 = binding_pattern a
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Make.ref.loc19_20: %Make.type = name_ref Make, file.%Make.decl [template = constants.%Make]
 // CHECK:STDOUT:   %.loc19_25.1: ref %X = temporary_storage
 // CHECK:STDOUT:   %Make.call.loc19_25: init %X = call %Make.ref.loc19_20() to %.loc19_25.1
 // CHECK:STDOUT:   %Make.ref.loc19_28: %Make.type = name_ref Make, file.%Make.decl [template = constants.%Make]
 // CHECK:STDOUT:   %.loc19_33.1: ref %X = temporary_storage
 // CHECK:STDOUT:   %Make.call.loc19_33: init %X = call %Make.ref.loc19_28() to %.loc19_33.1
-// CHECK:STDOUT:   %.loc19_34: %tuple.type.b67 = tuple_literal (%Make.call.loc19_25, %Make.call.loc19_33)
+// CHECK:STDOUT:   %.loc19_34.1: %tuple.type.b67 = tuple_literal (%Make.call.loc19_25, %Make.call.loc19_33)
 // CHECK:STDOUT:   %X.ref.loc19_40: type = name_ref X, file.%X.decl [template = constants.%X]
 // CHECK:STDOUT:   %X.ref.loc19_43: type = name_ref X, file.%X.decl [template = constants.%X]
 // CHECK:STDOUT:   %.loc19_44.1: %tuple.type.24b = tuple_literal (%X.ref.loc19_40, %X.ref.loc19_43)
 // CHECK:STDOUT:   %.loc19_44.2: type = converted %.loc19_44.1, constants.%tuple.type.b67 [template = constants.%tuple.type.b67]
+// CHECK:STDOUT:   %.loc19_15.1: type = splice_block %.loc19_15.3 [template = constants.%tuple.type.b67] {
+// CHECK:STDOUT:     %X.ref.loc19_11: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:     %X.ref.loc19_14: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:     %.loc19_15.2: %tuple.type.24b = tuple_literal (%X.ref.loc19_11, %X.ref.loc19_14)
+// CHECK:STDOUT:     %.loc19_15.3: type = converted %.loc19_15.2, constants.%tuple.type.b67 [template = constants.%tuple.type.b67]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc19_25.2: ref %X = temporary %.loc19_25.1, %Make.call.loc19_25
 // CHECK:STDOUT:   %.loc19_25.3: %X = bind_value %.loc19_25.2
 // CHECK:STDOUT:   %.loc19_33.2: ref %X = temporary %.loc19_33.1, %Make.call.loc19_33
 // CHECK:STDOUT:   %.loc19_33.3: %X = bind_value %.loc19_33.2
 // CHECK:STDOUT:   %tuple: %tuple.type.b67 = tuple_value (%.loc19_25.3, %.loc19_33.3)
-// CHECK:STDOUT:   %.loc19_45: %tuple.type.b67 = converted %.loc19_34, %tuple
-// CHECK:STDOUT:   %a: %tuple.type.b67 = bind_name a, %.loc19_45
+// CHECK:STDOUT:   %.loc19_34.2: %tuple.type.b67 = converted %.loc19_34.1, %tuple
+// CHECK:STDOUT:   %a: %tuple.type.b67 = bind_name a, %.loc19_34.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Var() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %tuple.type.b67 = binding_pattern b
+// CHECK:STDOUT:     %.loc24_3.1: %tuple.type.b67 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %tuple.type.b67 = var b
-// CHECK:STDOUT:   %b: ref %tuple.type.b67 = bind_name b, %b.var
 // CHECK:STDOUT:   %Make.ref.loc24_20: %Make.type = name_ref Make, file.%Make.decl [template = constants.%Make]
 // CHECK:STDOUT:   %tuple.elem0: ref %X = tuple_access %b.var, element0
 // CHECK:STDOUT:   %Make.call.loc24_25: init %X = call %Make.ref.loc24_20() to %tuple.elem0
@@ -106,8 +118,15 @@ fn Var() {
 // CHECK:STDOUT:   %.loc24_44.1: %tuple.type.24b = tuple_literal (%X.ref.loc24_40, %X.ref.loc24_43)
 // CHECK:STDOUT:   %.loc24_44.2: type = converted %.loc24_44.1, constants.%tuple.type.b67 [template = constants.%tuple.type.b67]
 // CHECK:STDOUT:   %.loc24_34.2: init %tuple.type.b67 = tuple_init (%Make.call.loc24_25, %Make.call.loc24_33) to %b.var
-// CHECK:STDOUT:   %.loc24_45: init %tuple.type.b67 = converted %.loc24_34.1, %.loc24_34.2
-// CHECK:STDOUT:   assign %b.var, %.loc24_45
+// CHECK:STDOUT:   %.loc24_3.2: init %tuple.type.b67 = converted %.loc24_34.1, %.loc24_34.2
+// CHECK:STDOUT:   assign %b.var, %.loc24_3.2
+// CHECK:STDOUT:   %.loc24_15.1: type = splice_block %.loc24_15.3 [template = constants.%tuple.type.b67] {
+// CHECK:STDOUT:     %X.ref.loc24_11: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:     %X.ref.loc24_14: type = name_ref X, file.%X.decl [template = constants.%X]
+// CHECK:STDOUT:     %.loc24_15.2: %tuple.type.24b = tuple_literal (%X.ref.loc24_11, %X.ref.loc24_14)
+// CHECK:STDOUT:     %.loc24_15.3: type = converted %.loc24_15.2, constants.%tuple.type.b67 [template = constants.%tuple.type.b67]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: ref %tuple.type.b67 = bind_name b, %b.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 15 - 4
toolchain/check/testdata/as/overloaded.carbon

@@ -67,7 +67,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .X = %X.decl
-// CHECK:STDOUT:     .n = @__global_init.%n
+// CHECK:STDOUT:     .n = %n
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %X.decl: type = class_decl @X [template = constants.%X] {} {}
@@ -89,6 +89,14 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:     %As.type: type = facet_type <@As, @As(constants.%i32)> [template = constants.%As.type.fd4]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl_witness.loc19: <witness> = impl_witness (@impl.2.%Convert.decl) [template = constants.%impl_witness.662]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc23: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %n: %i32 = bind_name n, @__global_init.%.loc23_32.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: impl @impl.1: %i32 as %As.type {
@@ -136,7 +144,11 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @X {
-// CHECK:STDOUT:   %.loc12: %X.elem = field_decl n, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: %X.elem = field_decl n, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %X.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %X.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.n [template = constants.%complete_type.54b]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -155,7 +167,7 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT: fn @Convert.3[%self.param_patt: %X]() -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %self.ref: %X = name_ref self, %self
-// CHECK:STDOUT:   %n.ref: %X.elem = name_ref n, @X.%.loc12 [template = @X.%.loc12]
+// CHECK:STDOUT:   %n.ref: %X.elem = name_ref n, @X.%.loc12_8 [template = @X.%.loc12_8]
 // CHECK:STDOUT:   %.loc20_45.1: ref %i32 = class_element_access %self.ref, element0
 // CHECK:STDOUT:   %.loc20_45.2: %i32 = bind_value %.loc20_45.1
 // CHECK:STDOUT:   return %.loc20_45.2
@@ -187,7 +199,6 @@ let n: i32 = ((4 as i32) as X) as i32;
 // CHECK:STDOUT:   %Convert.call.loc23_32: init %i32 = call %Convert.bound.loc23_32(%.loc23_26.4)
 // CHECK:STDOUT:   %.loc23_32.1: %i32 = value_of_initializer %Convert.call.loc23_32
 // CHECK:STDOUT:   %.loc23_32.2: %i32 = converted %.loc23_26.2, %.loc23_32.1
-// CHECK:STDOUT:   %n: %i32 = bind_name n, %.loc23_32.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 30 - 2
toolchain/check/testdata/basics/builtin_types.carbon

@@ -26,6 +26,9 @@ var test_type: type = i32;
 // CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %int_0.5c6, %Convert.956 [template]
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [template]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
+// CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
 // CHECK:STDOUT:   %float: f64 = float_literal 0.10000000000000001 [template]
 // CHECK:STDOUT:   %str: String = string_literal "Test" [template]
 // CHECK:STDOUT: }
@@ -45,14 +48,40 @@ var test_type: type = i32;
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .test_i32 = %test_i32
 // CHECK:STDOUT:     .test_f64 = %test_f64
-// CHECK:STDOUT:     .test_str = @__global_init.%test_str
+// CHECK:STDOUT:     .test_str = %test_str
 // CHECK:STDOUT:     .test_type = %test_type
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_i32.patt: %i32 = binding_pattern test_i32
+// CHECK:STDOUT:     %.loc11_1: %i32 = var_pattern %test_i32.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i32.var: ref %i32 = var test_i32
+// CHECK:STDOUT:   %.loc11_15: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i32: ref %i32 = bind_name test_i32, %test_i32.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_f64.patt: f64 = binding_pattern test_f64
+// CHECK:STDOUT:     %.loc12_1: f64 = var_pattern %test_f64.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_f64.var: ref f64 = var test_f64
+// CHECK:STDOUT:   %.loc12_15.1: type = splice_block %.loc12_15.3 [template = f64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %.loc12_15.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc12_15.3: type = converted %float.make_type, %.loc12_15.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_f64: ref f64 = bind_name test_f64, %test_f64.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_str.patt: String = binding_pattern test_str
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %test_str: String = bind_name test_str, @__global_init.%str
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_type.patt: type = binding_pattern test_type
+// CHECK:STDOUT:     %.loc14: type = var_pattern %test_type.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_type.var: ref type = var test_type
 // CHECK:STDOUT:   %test_type: ref type = bind_name test_type, %test_type.var
 // CHECK:STDOUT: }
@@ -69,7 +98,6 @@ var test_type: type = i32;
 // CHECK:STDOUT:   %float: f64 = float_literal 0.10000000000000001 [template = constants.%float]
 // CHECK:STDOUT:   assign file.%test_f64.var, %float
 // CHECK:STDOUT:   %str: String = string_literal "Test" [template = constants.%str]
-// CHECK:STDOUT:   %test_str: String = bind_name test_str, %str
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   assign file.%test_type.var, %i32

+ 6 - 2
toolchain/check/testdata/basics/fail_non_type_as_type.carbon

@@ -10,10 +10,10 @@
 
 // CHECK:STDERR: fail_non_type_as_type.carbon:[[@LINE+7]]:1: error: cannot implicitly convert from `Core.IntLiteral` to `type` [ImplicitAsConversionFailure]
 // CHECK:STDERR: var x: type = 42;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~~~~
 // CHECK:STDERR: fail_non_type_as_type.carbon:[[@LINE+4]]:1: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: var x: type = 42;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~~~~
 // CHECK:STDERR:
 var x: type = 42;
 
@@ -37,6 +37,10 @@ var x: type = 42;
 // CHECK:STDOUT:     .x = %x
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: type = binding_pattern x
+// CHECK:STDOUT:     %.loc18: type = var_pattern %x.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref type = var x
 // CHECK:STDOUT:   %x: ref type = bind_name x, %x.var
 // CHECK:STDOUT: }

+ 75 - 33
toolchain/check/testdata/basics/fail_numeric_literal_overflow.carbon

@@ -8,21 +8,21 @@
 // TIP: To dump output, run:
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/fail_numeric_literal_overflow.carbon
 
-// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:1: error: integer value 39999999999999999993 too large for type `i32` [IntTooLargeForType]
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:14: error: integer value 39999999999999999993 too large for type `i32` [IntTooLargeForType]
 // CHECK:STDERR: let a: i32 = 39999999999999999993;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
 let a: i32 = 39999999999999999993;
 
-// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:1: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:14: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
 // CHECK:STDERR: let b: i32 = 2_147_483_648;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:              ^~~~~~~~~~~~~
 // CHECK:STDERR:
 let b: i32 = 2_147_483_648;
 
-// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:1: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:14: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
 // CHECK:STDERR: let c: i32 = 0x8000_0000;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:              ^~~~~~~~~~~
 // CHECK:STDERR:
 let c: i32 = 0x8000_0000;
 
@@ -55,6 +55,9 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT:   %Convert.bound.85f: <bound method> = bound_method %int_2147483648.1db, %Convert.956 [template]
 // CHECK:STDOUT:   %Convert.specific_fn.387: <specific function> = specific_function %Convert.bound.85f, @Convert.2(%int_32) [template]
 // CHECK:STDOUT:   %int_2147483648.8df: %i32 = int_value 2147483648 [template]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
+// CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -70,43 +73,82 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
-// CHECK:STDOUT:     .a = @__global_init.%a
-// CHECK:STDOUT:     .b = @__global_init.%b
-// CHECK:STDOUT:     .c = @__global_init.%c
-// CHECK:STDOUT:     .d = @__global_init.%d
-// CHECK:STDOUT:     .e = @__global_init.%e
+// CHECK:STDOUT:     .a = %a
+// CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
+// CHECK:STDOUT:     .d = %d
+// CHECK:STDOUT:     .e = %e
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT: }
-// CHECK:STDOUT:
-// CHECK:STDOUT: fn @__global_init() {
-// CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %int_39999999999999999993: Core.IntLiteral = int_value 39999999999999999993 [template = constants.%int_39999999999999999993.af6]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %i32 = binding_pattern a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc15_8: type = splice_block %i32.loc15 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc15: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc15: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc15: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc15: <bound method> = bound_method %int_39999999999999999993, %impl.elem0.loc15 [template = constants.%Convert.bound.7ef]
+// CHECK:STDOUT:   %Convert.bound.loc15: <bound method> = bound_method @__global_init.%int_39999999999999999993, %impl.elem0.loc15 [template = constants.%Convert.bound.7ef]
 // CHECK:STDOUT:   %Convert.specific_fn.loc15: <specific function> = specific_function %Convert.bound.loc15, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.2ed]
-// CHECK:STDOUT:   %int.convert_checked.loc15: init %i32 = call %Convert.specific_fn.loc15(%int_39999999999999999993) [template = constants.%int_39999999999999999993.dee]
-// CHECK:STDOUT:   %.loc15_34.1: %i32 = value_of_initializer %int.convert_checked.loc15 [template = constants.%int_39999999999999999993.dee]
-// CHECK:STDOUT:   %.loc15_34.2: %i32 = converted %int_39999999999999999993, %.loc15_34.1 [template = constants.%int_39999999999999999993.dee]
-// CHECK:STDOUT:   %a: %i32 = bind_name a, %.loc15_34.2
-// CHECK:STDOUT:   %int_2147483648.loc21: Core.IntLiteral = int_value 2147483648 [template = constants.%int_2147483648.1db]
+// CHECK:STDOUT:   %int.convert_checked.loc15: init %i32 = call %Convert.specific_fn.loc15(@__global_init.%int_39999999999999999993) [template = constants.%int_39999999999999999993.dee]
+// CHECK:STDOUT:   %.loc15_14.1: %i32 = value_of_initializer %int.convert_checked.loc15 [template = constants.%int_39999999999999999993.dee]
+// CHECK:STDOUT:   %.loc15_14.2: %i32 = converted @__global_init.%int_39999999999999999993, %.loc15_14.1 [template = constants.%int_39999999999999999993.dee]
+// CHECK:STDOUT:   %a: %i32 = bind_name a, %.loc15_14.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %i32 = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc21_8: type = splice_block %i32.loc21 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc21: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc21: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc21: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc21: <bound method> = bound_method %int_2147483648.loc21, %impl.elem0.loc21 [template = constants.%Convert.bound.85f]
+// CHECK:STDOUT:   %Convert.bound.loc21: <bound method> = bound_method @__global_init.%int_2147483648.loc21, %impl.elem0.loc21 [template = constants.%Convert.bound.85f]
 // CHECK:STDOUT:   %Convert.specific_fn.loc21: <specific function> = specific_function %Convert.bound.loc21, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.387]
-// CHECK:STDOUT:   %int.convert_checked.loc21: init %i32 = call %Convert.specific_fn.loc21(%int_2147483648.loc21) [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %.loc21_27.1: %i32 = value_of_initializer %int.convert_checked.loc21 [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %.loc21_27.2: %i32 = converted %int_2147483648.loc21, %.loc21_27.1 [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %b: %i32 = bind_name b, %.loc21_27.2
-// CHECK:STDOUT:   %int_2147483648.loc27: Core.IntLiteral = int_value 2147483648 [template = constants.%int_2147483648.1db]
+// CHECK:STDOUT:   %int.convert_checked.loc21: init %i32 = call %Convert.specific_fn.loc21(@__global_init.%int_2147483648.loc21) [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %.loc21_14.1: %i32 = value_of_initializer %int.convert_checked.loc21 [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %.loc21_14.2: %i32 = converted @__global_init.%int_2147483648.loc21, %.loc21_14.1 [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %b: %i32 = bind_name b, %.loc21_14.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %i32 = binding_pattern c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc27_8: type = splice_block %i32.loc27 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc27: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc27: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc27: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc27: <bound method> = bound_method %int_2147483648.loc27, %impl.elem0.loc27 [template = constants.%Convert.bound.85f]
+// CHECK:STDOUT:   %Convert.bound.loc27: <bound method> = bound_method @__global_init.%int_2147483648.loc27, %impl.elem0.loc27 [template = constants.%Convert.bound.85f]
 // CHECK:STDOUT:   %Convert.specific_fn.loc27: <specific function> = specific_function %Convert.bound.loc27, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.387]
-// CHECK:STDOUT:   %int.convert_checked.loc27: init %i32 = call %Convert.specific_fn.loc27(%int_2147483648.loc27) [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %.loc27_25.1: %i32 = value_of_initializer %int.convert_checked.loc27 [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %.loc27_25.2: %i32 = converted %int_2147483648.loc27, %.loc27_25.1 [template = constants.%int_2147483648.8df]
-// CHECK:STDOUT:   %c: %i32 = bind_name c, %.loc27_25.2
+// CHECK:STDOUT:   %int.convert_checked.loc27: init %i32 = call %Convert.specific_fn.loc27(@__global_init.%int_2147483648.loc27) [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %.loc27_14.1: %i32 = value_of_initializer %int.convert_checked.loc27 [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %.loc27_14.2: %i32 = converted @__global_init.%int_2147483648.loc27, %.loc27_14.1 [template = constants.%int_2147483648.8df]
+// CHECK:STDOUT:   %c: %i32 = bind_name c, %.loc27_14.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: f64 = binding_pattern d
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc33_8.1: type = splice_block %.loc33_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64.loc33: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type.loc33: init type = call constants.%Float(%int_64.loc33) [template = f64]
+// CHECK:STDOUT:     %.loc33_8.2: type = value_of_initializer %float.make_type.loc33 [template = f64]
+// CHECK:STDOUT:     %.loc33_8.3: type = converted %float.make_type.loc33, %.loc33_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: f64 = bind_name d, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %e.patt: f64 = binding_pattern e
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc39_8.1: type = splice_block %.loc39_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64.loc39: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type.loc39: init type = call constants.%Float(%int_64.loc39) [template = f64]
+// CHECK:STDOUT:     %.loc39_8.2: type = value_of_initializer %float.make_type.loc39 [template = f64]
+// CHECK:STDOUT:     %.loc39_8.3: type = converted %float.make_type.loc39, %.loc39_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %e: f64 = bind_name e, <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %int_39999999999999999993: Core.IntLiteral = int_value 39999999999999999993 [template = constants.%int_39999999999999999993.af6]
+// CHECK:STDOUT:   %int_2147483648.loc21: Core.IntLiteral = int_value 2147483648 [template = constants.%int_2147483648.1db]
+// CHECK:STDOUT:   %int_2147483648.loc27: Core.IntLiteral = int_value 2147483648 [template = constants.%int_2147483648.1db]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 31 - 6
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -62,6 +62,9 @@ fn F() {
 // CHECK:STDOUT:   %int_2147483647.a74: %i32 = int_value 2147483647 [template]
 // CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [template]
 // CHECK:STDOUT:   %array.ae2: %array_type.d49 = tuple_value (%int_8.98c, %int_9.f88, %int_8.98c, %int_8.98c, %int_2147483647.a74, %int_2147483647.a74) [template]
+// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %Float.type: type = fn_type @Float [template]
+// CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
 // CHECK:STDOUT:   %array_type.72b: type = array_type %int_6, f64 [template]
 // CHECK:STDOUT:   %float.952: f64 = float_literal 0.90000000000000002 [template]
 // CHECK:STDOUT:   %float.298: f64 = float_literal 8 [template]
@@ -94,8 +97,11 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %ints.patt: %array_type.d49 = binding_pattern ints
+// CHECK:STDOUT:     %.loc14_3.1: %array_type.d49 = var_pattern %ints.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %ints.var: ref %array_type.d49 = var ints
-// CHECK:STDOUT:   %ints: ref %array_type.d49 = bind_name ints, %ints.var
 // CHECK:STDOUT:   %int_8.loc15: Core.IntLiteral = int_value 8 [template = constants.%int_8.b85]
 // CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [template = constants.%int_9.988]
 // CHECK:STDOUT:   %int_8.loc17: Core.IntLiteral = int_value 8 [template = constants.%int_8.b85]
@@ -152,10 +158,20 @@ fn F() {
 // CHECK:STDOUT:   %.loc21_3.18: ref %i32 = array_index %ints.var, %int_5.loc21
 // CHECK:STDOUT:   %.loc21_3.19: init %i32 = initialize_from %.loc21_3.17 to %.loc21_3.18 [template = constants.%int_2147483647.a74]
 // CHECK:STDOUT:   %.loc21_3.20: init %array_type.d49 = array_init (%.loc21_3.4, %.loc21_3.7, %.loc21_3.10, %.loc21_3.13, %.loc21_3.16, %.loc21_3.19) to %ints.var [template = constants.%array.ae2]
-// CHECK:STDOUT:   %.loc21_4: init %array_type.d49 = converted %.loc21_3.1, %.loc21_3.20 [template = constants.%array.ae2]
-// CHECK:STDOUT:   assign %ints.var, %.loc21_4
+// CHECK:STDOUT:   %.loc14_3.2: init %array_type.d49 = converted %.loc21_3.1, %.loc21_3.20 [template = constants.%array.ae2]
+// CHECK:STDOUT:   assign %ints.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_20: type = splice_block %array_type.loc14 [template = constants.%array_type.d49] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:     %int_6.loc14: Core.IntLiteral = int_value 6 [template = constants.%int_6]
+// CHECK:STDOUT:     %array_type.loc14: type = array_type %int_6.loc14, %i32 [template = constants.%array_type.d49]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %ints: ref %array_type.d49 = bind_name ints, %ints.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %floats.patt: %array_type.72b = binding_pattern floats
+// CHECK:STDOUT:     %.loc22_3.1: %array_type.72b = var_pattern %floats.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %floats.var: ref %array_type.72b = var floats
-// CHECK:STDOUT:   %floats: ref %array_type.72b = bind_name floats, %floats.var
 // CHECK:STDOUT:   %float.loc23: f64 = float_literal 0.90000000000000002 [template = constants.%float.952]
 // CHECK:STDOUT:   %float.loc24: f64 = float_literal 8 [template = constants.%float.298]
 // CHECK:STDOUT:   %float.loc25: f64 = float_literal 80 [template = constants.%float.dcb]
@@ -182,8 +198,17 @@ fn F() {
 // CHECK:STDOUT:   %.loc29_3.12: ref f64 = array_index %floats.var, %int_5.loc29
 // CHECK:STDOUT:   %.loc29_3.13: init f64 = initialize_from %float.loc28 to %.loc29_3.12 [template = constants.%float.401]
 // CHECK:STDOUT:   %.loc29_3.14: init %array_type.72b = array_init (%.loc29_3.3, %.loc29_3.5, %.loc29_3.7, %.loc29_3.9, %.loc29_3.11, %.loc29_3.13) to %floats.var [template = constants.%array.a2f]
-// CHECK:STDOUT:   %.loc29_4: init %array_type.72b = converted %.loc29_3.1, %.loc29_3.14 [template = constants.%array.a2f]
-// CHECK:STDOUT:   assign %floats.var, %.loc29_4
+// CHECK:STDOUT:   %.loc22_3.2: init %array_type.72b = converted %.loc29_3.1, %.loc29_3.14 [template = constants.%array.a2f]
+// CHECK:STDOUT:   assign %floats.var, %.loc22_3.2
+// CHECK:STDOUT:   %.loc22_22: type = splice_block %array_type.loc22 [template = constants.%array_type.72b] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %int_6.loc22: Core.IntLiteral = int_value 6 [template = constants.%int_6]
+// CHECK:STDOUT:     %.loc22_16.1: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc22_16.2: type = converted %float.make_type, %.loc22_16.1 [template = f64]
+// CHECK:STDOUT:     %array_type.loc22: type = array_type %int_6.loc22, f64 [template = constants.%array_type.72b]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %floats: ref %array_type.72b = bind_name floats, %floats.var
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 16 - 0
toolchain/check/testdata/basics/parens.carbon

@@ -46,9 +46,25 @@ var b: i32 = ((2));
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %i32 = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %i32 = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %i32 = var a
+// CHECK:STDOUT:   %.loc11_8: type = splice_block %i32.loc11 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc11: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %i32 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %i32 = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %i32 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %i32 = var b
+// CHECK:STDOUT:   %.loc12_8: type = splice_block %i32.loc12 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc12: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc12: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %i32 = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 48 - 0
toolchain/check/testdata/basics/type_literals.carbon

@@ -153,11 +153,35 @@ var test_f128: f128;
 // CHECK:STDOUT:     .test_i64 = %test_i64
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_i8.patt: %i8 = binding_pattern test_i8
+// CHECK:STDOUT:     %.loc3_1: %i8 = var_pattern %test_i8.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i8.var: ref %i8 = var test_i8
+// CHECK:STDOUT:   %.loc3_14: type = splice_block %i8 [template = constants.%i8] {
+// CHECK:STDOUT:     %int_8: Core.IntLiteral = int_value 8 [template = constants.%int_8]
+// CHECK:STDOUT:     %i8: type = class_type @Int, @Int(constants.%int_8) [template = constants.%i8]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i8: ref %i8 = bind_name test_i8, %test_i8.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_i16.patt: %i16 = binding_pattern test_i16
+// CHECK:STDOUT:     %.loc4_1: %i16 = var_pattern %test_i16.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i16.var: ref %i16 = var test_i16
+// CHECK:STDOUT:   %.loc4_15: type = splice_block %i16 [template = constants.%i16] {
+// CHECK:STDOUT:     %int_16: Core.IntLiteral = int_value 16 [template = constants.%int_16]
+// CHECK:STDOUT:     %i16: type = class_type @Int, @Int(constants.%int_16) [template = constants.%i16]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i16: ref %i16 = bind_name test_i16, %test_i16.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_i64.patt: %i64 = binding_pattern test_i64
+// CHECK:STDOUT:     %.loc5_1: %i64 = var_pattern %test_i64.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i64.var: ref %i64 = var test_i64
+// CHECK:STDOUT:   %.loc5_15: type = splice_block %i64 [template = constants.%i64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %i64: type = class_type @Int, @Int(constants.%int_64) [template = constants.%i64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_i64: ref %i64 = bind_name test_i64, %test_i64.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -195,11 +219,35 @@ var test_f128: f128;
 // CHECK:STDOUT:     .test_u64 = %test_u64
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_u8.patt: %u8 = binding_pattern test_u8
+// CHECK:STDOUT:     %.loc3_1: %u8 = var_pattern %test_u8.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u8.var: ref %u8 = var test_u8
+// CHECK:STDOUT:   %.loc3_14: type = splice_block %u8 [template = constants.%u8] {
+// CHECK:STDOUT:     %int_8: Core.IntLiteral = int_value 8 [template = constants.%int_8]
+// CHECK:STDOUT:     %u8: type = class_type @UInt, @UInt(constants.%int_8) [template = constants.%u8]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u8: ref %u8 = bind_name test_u8, %test_u8.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_u16.patt: %u16 = binding_pattern test_u16
+// CHECK:STDOUT:     %.loc4_1: %u16 = var_pattern %test_u16.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u16.var: ref %u16 = var test_u16
+// CHECK:STDOUT:   %.loc4_15: type = splice_block %u16 [template = constants.%u16] {
+// CHECK:STDOUT:     %int_16: Core.IntLiteral = int_value 16 [template = constants.%int_16]
+// CHECK:STDOUT:     %u16: type = class_type @UInt, @UInt(constants.%int_16) [template = constants.%u16]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u16: ref %u16 = bind_name test_u16, %test_u16.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %test_u64.patt: %u64 = binding_pattern test_u64
+// CHECK:STDOUT:     %.loc5_1: %u64 = var_pattern %test_u64.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u64.var: ref %u64 = var test_u64
+// CHECK:STDOUT:   %.loc5_15: type = splice_block %u64 [template = constants.%u64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %u64: type = class_type @UInt, @UInt(constants.%int_64) [template = constants.%u64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %test_u64: ref %u64 = bind_name test_u64, %test_u64.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 122 - 0
toolchain/check/testdata/builtins/bool/eq.carbon

@@ -142,13 +142,69 @@ var d: C(false == false) = True();
 // CHECK:STDOUT:     %return.param: ref %C.2ba = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %C.2ba = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C.a14 = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %C.a14 = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %C.a14 = var a
+// CHECK:STDOUT:   %.loc11_24.1: type = splice_block %C.loc11 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc11: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Eq.ref.loc11: %Eq.type = name_ref Eq, %Eq.decl [template = constants.%Eq]
+// CHECK:STDOUT:     %true.loc11_13: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %true.loc11_19: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %bool.eq.loc11: init bool = call %Eq.ref.loc11(%true.loc11_13, %true.loc11_19) [template = constants.%true]
+// CHECK:STDOUT:     %.loc11_24.2: bool = value_of_initializer %bool.eq.loc11 [template = constants.%true]
+// CHECK:STDOUT:     %.loc11_24.3: bool = converted %bool.eq.loc11, %.loc11_24.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc11: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %C.a14 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C.2ba = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %C.2ba = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %C.2ba = var b
+// CHECK:STDOUT:   %.loc12_25.1: type = splice_block %C.loc12 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Eq.ref.loc12: %Eq.type = name_ref Eq, %Eq.decl [template = constants.%Eq]
+// CHECK:STDOUT:     %true.loc12: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %false.loc12: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %bool.eq.loc12: init bool = call %Eq.ref.loc12(%true.loc12, %false.loc12) [template = constants.%false]
+// CHECK:STDOUT:     %.loc12_25.2: bool = value_of_initializer %bool.eq.loc12 [template = constants.%false]
+// CHECK:STDOUT:     %.loc12_25.3: bool = converted %bool.eq.loc12, %.loc12_25.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %C.2ba = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C.2ba = binding_pattern c
+// CHECK:STDOUT:     %.loc13_1: %C.2ba = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C.2ba = var c
+// CHECK:STDOUT:   %.loc13_25.1: type = splice_block %C.loc13 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc13: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Eq.ref.loc13: %Eq.type = name_ref Eq, %Eq.decl [template = constants.%Eq]
+// CHECK:STDOUT:     %false.loc13: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %true.loc13: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %bool.eq.loc13: init bool = call %Eq.ref.loc13(%false.loc13, %true.loc13) [template = constants.%false]
+// CHECK:STDOUT:     %.loc13_25.2: bool = value_of_initializer %bool.eq.loc13 [template = constants.%false]
+// CHECK:STDOUT:     %.loc13_25.3: bool = converted %bool.eq.loc13, %.loc13_25.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc13: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C.2ba = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C.a14 = binding_pattern d
+// CHECK:STDOUT:     %.loc14_1: %C.a14 = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %C.a14 = var d
+// CHECK:STDOUT:   %.loc14_26.1: type = splice_block %C.loc14 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc14: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Eq.ref.loc14: %Eq.type = name_ref Eq, %Eq.decl [template = constants.%Eq]
+// CHECK:STDOUT:     %false.loc14_13: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %false.loc14_20: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %bool.eq.loc14: init bool = call %Eq.ref.loc14(%false.loc14_13, %false.loc14_20) [template = constants.%true]
+// CHECK:STDOUT:     %.loc14_26.2: bool = value_of_initializer %bool.eq.loc14 [template = constants.%true]
+// CHECK:STDOUT:     %.loc14_26.3: bool = converted %bool.eq.loc14, %.loc14_26.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc14: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %C.a14 = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -229,6 +285,12 @@ var d: C(false == false) = True();
 // CHECK:STDOUT:   %C.2ba: type = class_type @C, @C(%false) [template]
 // CHECK:STDOUT:   %False.type: type = fn_type @False [template]
 // CHECK:STDOUT:   %False: %False.type = struct_value () [template]
+// CHECK:STDOUT:   %Equal.type.79c: type = fn_type @Equal.1 [template]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (imports.%import_ref.998, imports.%import_ref.fb6) [template]
+// CHECK:STDOUT:   %Equal.type.aa3: type = fn_type @Equal.2 [template]
+// CHECK:STDOUT:   %Equal.6e2: %Equal.type.aa3 = struct_value () [template]
+// CHECK:STDOUT:   %Equal.bound.fe0: <bound method> = bound_method %true, %Equal.6e2 [template]
+// CHECK:STDOUT:   %Equal.bound.d3c: <bound method> = bound_method %false, %Equal.6e2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -284,13 +346,73 @@ var d: C(false == false) = True();
 // CHECK:STDOUT:     %return.param: ref %C.2ba = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %C.2ba = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C.a14 = binding_pattern a
+// CHECK:STDOUT:     %.loc9_1: %C.a14 = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %C.a14 = var a
+// CHECK:STDOUT:   %.loc9_22.1: type = splice_block %C.loc9 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc9: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %true.loc9_10: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %true.loc9_18: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %impl.elem0.loc9: %Equal.type.79c = impl_witness_access constants.%impl_witness, element0 [template = constants.%Equal.6e2]
+// CHECK:STDOUT:     %Equal.bound.loc9: <bound method> = bound_method %true.loc9_10, %impl.elem0.loc9 [template = constants.%Equal.bound.fe0]
+// CHECK:STDOUT:     %bool.eq.loc9: init bool = call %Equal.bound.loc9(%true.loc9_10, %true.loc9_18) [template = constants.%true]
+// CHECK:STDOUT:     %.loc9_22.2: bool = value_of_initializer %bool.eq.loc9 [template = constants.%true]
+// CHECK:STDOUT:     %.loc9_22.3: bool = converted %bool.eq.loc9, %.loc9_22.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc9: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %C.a14 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C.2ba = binding_pattern b
+// CHECK:STDOUT:     %.loc10_1: %C.2ba = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %C.2ba = var b
+// CHECK:STDOUT:   %.loc10_23.1: type = splice_block %C.loc10 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc10: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %true.loc10: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %false.loc10: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %impl.elem0.loc10: %Equal.type.79c = impl_witness_access constants.%impl_witness, element0 [template = constants.%Equal.6e2]
+// CHECK:STDOUT:     %Equal.bound.loc10: <bound method> = bound_method %true.loc10, %impl.elem0.loc10 [template = constants.%Equal.bound.fe0]
+// CHECK:STDOUT:     %bool.eq.loc10: init bool = call %Equal.bound.loc10(%true.loc10, %false.loc10) [template = constants.%false]
+// CHECK:STDOUT:     %.loc10_23.2: bool = value_of_initializer %bool.eq.loc10 [template = constants.%false]
+// CHECK:STDOUT:     %.loc10_23.3: bool = converted %bool.eq.loc10, %.loc10_23.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc10: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %C.2ba = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C.2ba = binding_pattern c
+// CHECK:STDOUT:     %.loc11_1: %C.2ba = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C.2ba = var c
+// CHECK:STDOUT:   %.loc11_23.1: type = splice_block %C.loc11 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc11: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %false.loc11: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %true.loc11: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %impl.elem0.loc11: %Equal.type.79c = impl_witness_access constants.%impl_witness, element0 [template = constants.%Equal.6e2]
+// CHECK:STDOUT:     %Equal.bound.loc11: <bound method> = bound_method %false.loc11, %impl.elem0.loc11 [template = constants.%Equal.bound.d3c]
+// CHECK:STDOUT:     %bool.eq.loc11: init bool = call %Equal.bound.loc11(%false.loc11, %true.loc11) [template = constants.%false]
+// CHECK:STDOUT:     %.loc11_23.2: bool = value_of_initializer %bool.eq.loc11 [template = constants.%false]
+// CHECK:STDOUT:     %.loc11_23.3: bool = converted %bool.eq.loc11, %.loc11_23.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc11: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C.2ba = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C.a14 = binding_pattern d
+// CHECK:STDOUT:     %.loc12_1: %C.a14 = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %C.a14 = var d
+// CHECK:STDOUT:   %.loc12_24.1: type = splice_block %C.loc12 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %false.loc12_10: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %false.loc12_19: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %impl.elem0.loc12: %Equal.type.79c = impl_witness_access constants.%impl_witness, element0 [template = constants.%Equal.6e2]
+// CHECK:STDOUT:     %Equal.bound.loc12: <bound method> = bound_method %false.loc12_10, %impl.elem0.loc12 [template = constants.%Equal.bound.d3c]
+// CHECK:STDOUT:     %bool.eq.loc12: init bool = call %Equal.bound.loc12(%false.loc12_10, %false.loc12_19) [template = constants.%true]
+// CHECK:STDOUT:     %.loc12_24.2: bool = value_of_initializer %bool.eq.loc12 [template = constants.%true]
+// CHECK:STDOUT:     %.loc12_24.3: bool = converted %bool.eq.loc12, %.loc12_24.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %C.a14 = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 0
toolchain/check/testdata/builtins/bool/make_type.carbon

@@ -77,7 +77,17 @@ var b: Bool() = false;
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: bool = binding_pattern b
+// CHECK:STDOUT:     %.loc6_1: bool = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref bool = var b
+// CHECK:STDOUT:   %.loc6_13.1: type = splice_block %.loc6_13.3 [template = bool] {
+// CHECK:STDOUT:     %Bool.ref: %Bool.type = name_ref Bool, imports.%import_ref [template = constants.%Bool]
+// CHECK:STDOUT:     %bool.make_type: init type = call %Bool.ref() [template = bool]
+// CHECK:STDOUT:     %.loc6_13.2: type = value_of_initializer %bool.make_type [template = bool]
+// CHECK:STDOUT:     %.loc6_13.3: type = converted %bool.make_type, %.loc6_13.2 [template = bool]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref bool = bind_name b, %b.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 122 - 0
toolchain/check/testdata/builtins/bool/neq.carbon

@@ -142,13 +142,69 @@ var d: C(false != false) = False();
 // CHECK:STDOUT:     %return.param: ref %C.2ba = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %C.2ba = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C.2ba = binding_pattern a
+// CHECK:STDOUT:     %.loc11_1: %C.2ba = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %C.2ba = var a
+// CHECK:STDOUT:   %.loc11_25.1: type = splice_block %C.loc11 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc11: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Neq.ref.loc11: %Neq.type = name_ref Neq, %Neq.decl [template = constants.%Neq]
+// CHECK:STDOUT:     %true.loc11_14: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %true.loc11_20: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %bool.neq.loc11: init bool = call %Neq.ref.loc11(%true.loc11_14, %true.loc11_20) [template = constants.%false]
+// CHECK:STDOUT:     %.loc11_25.2: bool = value_of_initializer %bool.neq.loc11 [template = constants.%false]
+// CHECK:STDOUT:     %.loc11_25.3: bool = converted %bool.neq.loc11, %.loc11_25.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc11: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %C.2ba = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C.a14 = binding_pattern b
+// CHECK:STDOUT:     %.loc12_1: %C.a14 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %C.a14 = var b
+// CHECK:STDOUT:   %.loc12_26.1: type = splice_block %C.loc12 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Neq.ref.loc12: %Neq.type = name_ref Neq, %Neq.decl [template = constants.%Neq]
+// CHECK:STDOUT:     %true.loc12: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %false.loc12: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %bool.neq.loc12: init bool = call %Neq.ref.loc12(%true.loc12, %false.loc12) [template = constants.%true]
+// CHECK:STDOUT:     %.loc12_26.2: bool = value_of_initializer %bool.neq.loc12 [template = constants.%true]
+// CHECK:STDOUT:     %.loc12_26.3: bool = converted %bool.neq.loc12, %.loc12_26.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %C.a14 = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C.a14 = binding_pattern c
+// CHECK:STDOUT:     %.loc13_1: %C.a14 = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C.a14 = var c
+// CHECK:STDOUT:   %.loc13_26.1: type = splice_block %C.loc13 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc13: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Neq.ref.loc13: %Neq.type = name_ref Neq, %Neq.decl [template = constants.%Neq]
+// CHECK:STDOUT:     %false.loc13: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %true.loc13: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %bool.neq.loc13: init bool = call %Neq.ref.loc13(%false.loc13, %true.loc13) [template = constants.%true]
+// CHECK:STDOUT:     %.loc13_26.2: bool = value_of_initializer %bool.neq.loc13 [template = constants.%true]
+// CHECK:STDOUT:     %.loc13_26.3: bool = converted %bool.neq.loc13, %.loc13_26.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc13: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C.a14 = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C.2ba = binding_pattern d
+// CHECK:STDOUT:     %.loc14_1: %C.2ba = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %C.2ba = var d
+// CHECK:STDOUT:   %.loc14_27.1: type = splice_block %C.loc14 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc14: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %Neq.ref.loc14: %Neq.type = name_ref Neq, %Neq.decl [template = constants.%Neq]
+// CHECK:STDOUT:     %false.loc14_14: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %false.loc14_21: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %bool.neq.loc14: init bool = call %Neq.ref.loc14(%false.loc14_14, %false.loc14_21) [template = constants.%false]
+// CHECK:STDOUT:     %.loc14_27.2: bool = value_of_initializer %bool.neq.loc14 [template = constants.%false]
+// CHECK:STDOUT:     %.loc14_27.3: bool = converted %bool.neq.loc14, %.loc14_27.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc14: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %C.2ba = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -229,6 +285,12 @@ var d: C(false != false) = False();
 // CHECK:STDOUT:   %C.2ba: type = class_type @C, @C(%false) [template]
 // CHECK:STDOUT:   %False.type: type = fn_type @False [template]
 // CHECK:STDOUT:   %False: %False.type = struct_value () [template]
+// CHECK:STDOUT:   %NotEqual.type.e6c: type = fn_type @NotEqual.1 [template]
+// CHECK:STDOUT:   %impl_witness: <witness> = impl_witness (imports.%import_ref.85b, imports.%import_ref.67a) [template]
+// CHECK:STDOUT:   %NotEqual.type.c0e: type = fn_type @NotEqual.2 [template]
+// CHECK:STDOUT:   %NotEqual.bf4: %NotEqual.type.c0e = struct_value () [template]
+// CHECK:STDOUT:   %NotEqual.bound.542: <bound method> = bound_method %true, %NotEqual.bf4 [template]
+// CHECK:STDOUT:   %NotEqual.bound.5a9: <bound method> = bound_method %false, %NotEqual.bf4 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -284,13 +346,73 @@ var d: C(false != false) = False();
 // CHECK:STDOUT:     %return.param: ref %C.2ba = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %C.2ba = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C.2ba = binding_pattern a
+// CHECK:STDOUT:     %.loc9_1: %C.2ba = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref %C.2ba = var a
+// CHECK:STDOUT:   %.loc9_22.1: type = splice_block %C.loc9 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc9: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %true.loc9_10: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %true.loc9_18: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %impl.elem1.loc9: %NotEqual.type.e6c = impl_witness_access constants.%impl_witness, element1 [template = constants.%NotEqual.bf4]
+// CHECK:STDOUT:     %NotEqual.bound.loc9: <bound method> = bound_method %true.loc9_10, %impl.elem1.loc9 [template = constants.%NotEqual.bound.542]
+// CHECK:STDOUT:     %bool.neq.loc9: init bool = call %NotEqual.bound.loc9(%true.loc9_10, %true.loc9_18) [template = constants.%false]
+// CHECK:STDOUT:     %.loc9_22.2: bool = value_of_initializer %bool.neq.loc9 [template = constants.%false]
+// CHECK:STDOUT:     %.loc9_22.3: bool = converted %bool.neq.loc9, %.loc9_22.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc9: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %C.2ba = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %C.a14 = binding_pattern b
+// CHECK:STDOUT:     %.loc10_1: %C.a14 = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %C.a14 = var b
+// CHECK:STDOUT:   %.loc10_23.1: type = splice_block %C.loc10 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc10: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %true.loc10: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %false.loc10: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %impl.elem1.loc10: %NotEqual.type.e6c = impl_witness_access constants.%impl_witness, element1 [template = constants.%NotEqual.bf4]
+// CHECK:STDOUT:     %NotEqual.bound.loc10: <bound method> = bound_method %true.loc10, %impl.elem1.loc10 [template = constants.%NotEqual.bound.542]
+// CHECK:STDOUT:     %bool.neq.loc10: init bool = call %NotEqual.bound.loc10(%true.loc10, %false.loc10) [template = constants.%true]
+// CHECK:STDOUT:     %.loc10_23.2: bool = value_of_initializer %bool.neq.loc10 [template = constants.%true]
+// CHECK:STDOUT:     %.loc10_23.3: bool = converted %bool.neq.loc10, %.loc10_23.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc10: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b: ref %C.a14 = bind_name b, %b.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C.a14 = binding_pattern c
+// CHECK:STDOUT:     %.loc11_1: %C.a14 = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C.a14 = var c
+// CHECK:STDOUT:   %.loc11_23.1: type = splice_block %C.loc11 [template = constants.%C.a14] {
+// CHECK:STDOUT:     %C.ref.loc11: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %false.loc11: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %true.loc11: bool = bool_literal true [template = constants.%true]
+// CHECK:STDOUT:     %impl.elem1.loc11: %NotEqual.type.e6c = impl_witness_access constants.%impl_witness, element1 [template = constants.%NotEqual.bf4]
+// CHECK:STDOUT:     %NotEqual.bound.loc11: <bound method> = bound_method %false.loc11, %impl.elem1.loc11 [template = constants.%NotEqual.bound.5a9]
+// CHECK:STDOUT:     %bool.neq.loc11: init bool = call %NotEqual.bound.loc11(%false.loc11, %true.loc11) [template = constants.%true]
+// CHECK:STDOUT:     %.loc11_23.2: bool = value_of_initializer %bool.neq.loc11 [template = constants.%true]
+// CHECK:STDOUT:     %.loc11_23.3: bool = converted %bool.neq.loc11, %.loc11_23.2 [template = constants.%true]
+// CHECK:STDOUT:     %C.loc11: type = class_type @C, @C(constants.%true) [template = constants.%C.a14]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C.a14 = bind_name c, %c.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %C.2ba = binding_pattern d
+// CHECK:STDOUT:     %.loc12_1: %C.2ba = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %C.2ba = var d
+// CHECK:STDOUT:   %.loc12_24.1: type = splice_block %C.loc12 [template = constants.%C.2ba] {
+// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [template = constants.%C.generic]
+// CHECK:STDOUT:     %false.loc12_10: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %false.loc12_19: bool = bool_literal false [template = constants.%false]
+// CHECK:STDOUT:     %impl.elem1.loc12: %NotEqual.type.e6c = impl_witness_access constants.%impl_witness, element1 [template = constants.%NotEqual.bf4]
+// CHECK:STDOUT:     %NotEqual.bound.loc12: <bound method> = bound_method %false.loc12_10, %impl.elem1.loc12 [template = constants.%NotEqual.bound.5a9]
+// CHECK:STDOUT:     %bool.neq.loc12: init bool = call %NotEqual.bound.loc12(%false.loc12_10, %false.loc12_19) [template = constants.%false]
+// CHECK:STDOUT:     %.loc12_24.2: bool = value_of_initializer %bool.neq.loc12 [template = constants.%false]
+// CHECK:STDOUT:     %.loc12_24.3: bool = converted %bool.neq.loc12, %.loc12_24.2 [template = constants.%false]
+// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%false) [template = constants.%C.2ba]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d: ref %C.2ba = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 0
toolchain/check/testdata/builtins/float/add.carbon

@@ -144,7 +144,17 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     %return.param: ref f64 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: f64 = binding_pattern x
+// CHECK:STDOUT:     %.loc8_1: f64 = var_pattern %x.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref f64 = var x
+// CHECK:STDOUT:   %.loc8_8.1: type = splice_block %.loc8_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %.loc8_8.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc8_8.3: type = converted %float.make_type, %.loc8_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x: ref f64 = bind_name x, %x.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 36 - 8
toolchain/check/testdata/builtins/float/div.carbon

@@ -86,8 +86,8 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     .Div = %Div.decl
 // CHECK:STDOUT:     .RuntimeCallIsValid = %RuntimeCallIsValid.decl
 // CHECK:STDOUT:     .a = %a
-// CHECK:STDOUT:     .b = @__global_init.%b
-// CHECK:STDOUT:     .c = @__global_init.%c
+// CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Div.decl: %Div.type = fn_decl @Div [template = constants.%Div] {
@@ -152,8 +152,42 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     %return.param: ref f64 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: f64 = binding_pattern a
+// CHECK:STDOUT:     %.loc8_1: f64 = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref f64 = var a
+// CHECK:STDOUT:   %.loc8_8.1: type = splice_block %.loc8_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64.loc8: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type.loc8: init type = call constants.%Float(%int_64.loc8) [template = f64]
+// CHECK:STDOUT:     %.loc8_8.2: type = value_of_initializer %float.make_type.loc8 [template = f64]
+// CHECK:STDOUT:     %.loc8_8.3: type = converted %float.make_type.loc8, %.loc8_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref f64 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: f64 = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc9_8.1: type = splice_block %.loc9_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64.loc9: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type.loc9: init type = call constants.%Float(%int_64.loc9) [template = f64]
+// CHECK:STDOUT:     %.loc9_8.2: type = value_of_initializer %float.make_type.loc9 [template = f64]
+// CHECK:STDOUT:     %.loc9_8.3: type = converted %float.make_type.loc9, %.loc9_8.2 [template = f64]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc9_26.1: ref f64 = temporary_storage
+// CHECK:STDOUT:   %.loc9_26.2: ref f64 = temporary %.loc9_26.1, @__global_init.%float.div.loc9
+// CHECK:STDOUT:   %b: ref f64 = bind_name b, %.loc9_26.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: f64 = binding_pattern c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc10_8.1: type = splice_block %.loc10_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64.loc10: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type.loc10: init type = call constants.%Float(%int_64.loc10) [template = f64]
+// CHECK:STDOUT:     %.loc10_8.2: type = value_of_initializer %float.make_type.loc10 [template = f64]
+// CHECK:STDOUT:     %.loc10_8.3: type = converted %float.make_type.loc10, %.loc10_8.2 [template = f64]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc10_26.1: ref f64 = temporary_storage
+// CHECK:STDOUT:   %.loc10_26.2: ref f64 = temporary %.loc10_26.1, @__global_init.%float.div.loc10
+// CHECK:STDOUT:   %c: ref f64 = bind_name c, %.loc10_26.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Div(%a.param_patt: f64, %b.param_patt: f64) -> f64 = "float.div";
@@ -180,16 +214,10 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:   %float.loc9_18: f64 = float_literal 1 [template = constants.%float.f4e]
 // CHECK:STDOUT:   %float.loc9_23: f64 = float_literal 0 [template = constants.%float.555]
 // CHECK:STDOUT:   %float.div.loc9: init f64 = call %Div.ref.loc9(%float.loc9_18, %float.loc9_23) [template = constants.%float.bd4]
-// CHECK:STDOUT:   %.loc9_27.1: f64 = value_of_initializer %float.div.loc9 [template = constants.%float.bd4]
-// CHECK:STDOUT:   %.loc9_27.2: f64 = converted %float.div.loc9, %.loc9_27.1 [template = constants.%float.bd4]
-// CHECK:STDOUT:   %b: f64 = bind_name b, %.loc9_27.2
 // CHECK:STDOUT:   %Div.ref.loc10: %Div.type = name_ref Div, file.%Div.decl [template = constants.%Div]
 // CHECK:STDOUT:   %float.loc10_18: f64 = float_literal 0 [template = constants.%float.555]
 // CHECK:STDOUT:   %float.loc10_23: f64 = float_literal 0 [template = constants.%float.555]
 // CHECK:STDOUT:   %float.div.loc10: init f64 = call %Div.ref.loc10(%float.loc10_18, %float.loc10_23) [template = constants.%float.8b7]
-// CHECK:STDOUT:   %.loc10_27.1: f64 = value_of_initializer %float.div.loc10 [template = constants.%float.8b7]
-// CHECK:STDOUT:   %.loc10_27.2: f64 = converted %float.div.loc10, %.loc10_27.1 [template = constants.%float.8b7]
-// CHECK:STDOUT:   %c: f64 = bind_name c, %.loc10_27.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 67 - 2
toolchain/check/testdata/builtins/float/make_type.carbon

@@ -94,6 +94,14 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:   %Float: %Float.type = struct_value () [template]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [template]
+// CHECK:STDOUT:   %int_64.fab: Core.IntLiteral = int_value 64 [template]
+// CHECK:STDOUT:   %Convert.type.6da: type = fn_type @Convert.1, @ImplicitAs(%i32) [template]
+// CHECK:STDOUT:   %impl_witness.b97: <witness> = impl_witness (imports.%import_ref.a86), @impl.1(%int_32) [template]
+// CHECK:STDOUT:   %Convert.type.ed5: type = fn_type @Convert.2, @impl.1(%int_32) [template]
+// CHECK:STDOUT:   %Convert.16d: %Convert.type.ed5 = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %int_64.fab, %Convert.16d [template]
+// CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [template]
+// CHECK:STDOUT:   %int_64.198: %i32 = int_value 64 [template]
 // CHECK:STDOUT:   %float: f64 = float_literal 0 [template]
 // CHECK:STDOUT:   %GetFloat.type: type = fn_type @GetFloat [template]
 // CHECK:STDOUT:   %GetFloat: %GetFloat.type = struct_value () [template]
@@ -118,7 +126,24 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %f.patt: f64 = binding_pattern f
+// CHECK:STDOUT:     %.loc6_1: f64 = var_pattern %f.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %f.var: ref f64 = var f
+// CHECK:STDOUT:   %.loc6_16.1: type = splice_block %.loc6_16.3 [template = f64] {
+// CHECK:STDOUT:     %Float.ref: %Float.type = name_ref Float, imports.%import_ref.fb8 [template = constants.%Float]
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64.fab]
+// CHECK:STDOUT:     %impl.elem0: %Convert.type.6da = impl_witness_access constants.%impl_witness.b97, element0 [template = constants.%Convert.16d]
+// CHECK:STDOUT:     %Convert.bound: <bound method> = bound_method %int_64, %impl.elem0 [template = constants.%Convert.bound]
+// CHECK:STDOUT:     %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn]
+// CHECK:STDOUT:     %int.convert_checked: init %i32 = call %Convert.specific_fn(%int_64) [template = constants.%int_64.198]
+// CHECK:STDOUT:     %.loc6_14.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_64.198]
+// CHECK:STDOUT:     %.loc6_14.2: %i32 = converted %int_64, %.loc6_14.1 [template = constants.%int_64.198]
+// CHECK:STDOUT:     %float.make_type: init type = call %Float.ref(%.loc6_14.2) [template = f64]
+// CHECK:STDOUT:     %.loc6_16.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc6_16.3: type = converted %float.make_type, %.loc6_16.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %f: ref f64 = bind_name f, %f.var
 // CHECK:STDOUT:   %GetFloat.decl: %GetFloat.type = fn_decl @GetFloat [template = constants.%GetFloat] {
 // CHECK:STDOUT:     %dyn_size.patt: %i32 = binding_pattern dyn_size
@@ -167,6 +192,9 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:   %impl_witness.b97: <witness> = impl_witness (imports.%import_ref.a86), @impl.1(%int_32.be0) [template]
 // CHECK:STDOUT:   %Convert.type.ed5: type = fn_type @Convert.2, @impl.1(%int_32.be0) [template]
 // CHECK:STDOUT:   %Convert.16d: %Convert.type.ed5 = struct_value () [template]
+// CHECK:STDOUT:   %Convert.bound.cce: <bound method> = bound_method %int_32.be0, %Convert.16d [template]
+// CHECK:STDOUT:   %Convert.specific_fn.23b: <specific function> = specific_function %Convert.bound.cce, @Convert.2(%int_32.be0) [template]
+// CHECK:STDOUT:   %int_32.4de: %i32 = int_value 32 [template]
 // CHECK:STDOUT:   %int_64.fab: Core.IntLiteral = int_value 64 [template]
 // CHECK:STDOUT:   %Convert.bound.575: <bound method> = bound_method %int_64.fab, %Convert.16d [template]
 // CHECK:STDOUT:   %Convert.specific_fn.bd8: <specific function> = specific_function %Convert.bound.575, @Convert.2(%int_32.be0) [template]
@@ -193,12 +221,49 @@ var dyn: Float(dyn_size);
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %invalid_float.patt: <error> = binding_pattern invalid_float
+// CHECK:STDOUT:     %.loc10_1: <error> = var_pattern %invalid_float.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %invalid_float.var: ref <error> = var invalid_float
-// CHECK:STDOUT:   %invalid_float: ref <error> = bind_name invalid_float, %invalid_float.var
+// CHECK:STDOUT:   %.loc10_28.1: type = splice_block %.loc10_28.3 [template = <error>] {
+// CHECK:STDOUT:     %Float.ref.loc10: %Float.type = name_ref Float, imports.%import_ref.fb8 [template = constants.%Float]
+// CHECK:STDOUT:     %int_32.loc10: Core.IntLiteral = int_value 32 [template = constants.%int_32.be0]
+// CHECK:STDOUT:     %impl.elem0: %Convert.type.6da = impl_witness_access constants.%impl_witness.b97, element0 [template = constants.%Convert.16d]
+// CHECK:STDOUT:     %Convert.bound: <bound method> = bound_method %int_32.loc10, %impl.elem0 [template = constants.%Convert.bound.cce]
+// CHECK:STDOUT:     %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(constants.%int_32.be0) [template = constants.%Convert.specific_fn.23b]
+// CHECK:STDOUT:     %int.convert_checked: init %i32 = call %Convert.specific_fn(%int_32.loc10) [template = constants.%int_32.4de]
+// CHECK:STDOUT:     %.loc10_26.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_32.4de]
+// CHECK:STDOUT:     %.loc10_26.2: %i32 = converted %int_32.loc10, %.loc10_26.1 [template = constants.%int_32.4de]
+// CHECK:STDOUT:     %float.make_type.loc10: init type = call %Float.ref.loc10(%.loc10_26.2) [template = <error>]
+// CHECK:STDOUT:     %.loc10_28.2: type = value_of_initializer %float.make_type.loc10 [template = <error>]
+// CHECK:STDOUT:     %.loc10_28.3: type = converted %float.make_type.loc10, %.loc10_28.2 [template = <error>]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %invalid_float: <error> = bind_name invalid_float, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %dyn_size.patt: %i32 = binding_pattern dyn_size
+// CHECK:STDOUT:     %.loc12_1: %i32 = var_pattern %dyn_size.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %dyn_size.var: ref %i32 = var dyn_size
+// CHECK:STDOUT:   %.loc12_15: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc12: Core.IntLiteral = int_value 32 [template = constants.%int_32.be0]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32.be0) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %dyn_size: ref %i32 = bind_name dyn_size, %dyn_size.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %dyn.patt: <error> = binding_pattern dyn
+// CHECK:STDOUT:     %.loc17_1: <error> = var_pattern %dyn.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %dyn.var: ref <error> = var dyn
-// CHECK:STDOUT:   %dyn: ref <error> = bind_name dyn, %dyn.var
+// CHECK:STDOUT:   %.1: <error> = splice_block <error> [template = <error>] {
+// CHECK:STDOUT:     %Float.ref.loc17: %Float.type = name_ref Float, imports.%import_ref.fb8 [template = constants.%Float]
+// CHECK:STDOUT:     %dyn_size.ref: ref %i32 = name_ref dyn_size, %dyn_size
+// CHECK:STDOUT:     %.loc17_16: %i32 = bind_value %dyn_size.ref
+// CHECK:STDOUT:     %float.make_type.loc17: init type = call %Float.ref.loc17(%.loc17_16)
+// CHECK:STDOUT:     %.loc17_24.1: type = value_of_initializer %float.make_type.loc17
+// CHECK:STDOUT:     %.loc17_24.2: type = converted %float.make_type.loc17, %.loc17_24.1
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %dyn: <error> = bind_name dyn, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Float(%size.param_patt: %i32) -> type = "float.make_type" [from "types.carbon"];

+ 10 - 0
toolchain/check/testdata/builtins/float/mul.carbon

@@ -144,7 +144,17 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     %return.param: ref f64 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: f64 = binding_pattern x
+// CHECK:STDOUT:     %.loc8_1: f64 = var_pattern %x.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref f64 = var x
+// CHECK:STDOUT:   %.loc8_8.1: type = splice_block %.loc8_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %.loc8_8.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc8_8.3: type = converted %float.make_type, %.loc8_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x: ref f64 = bind_name x, %x.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 13 - 4
toolchain/check/testdata/builtins/float/negate.carbon

@@ -99,7 +99,7 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .Negate = %Negate.decl
 // CHECK:STDOUT:     .RuntimeCallIsValid = %RuntimeCallIsValid.decl
-// CHECK:STDOUT:     .a = @__global_init.%a
+// CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Negate.decl: %Negate.type = fn_decl @Negate [template = constants.%Negate] {
@@ -154,6 +154,18 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     %return.param: ref f64 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: f64 = binding_pattern a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_8.1: type = splice_block %.loc8_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %.loc8_8.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc8_8.3: type = converted %float.make_type, %.loc8_8.2 [template = f64]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8_24.1: ref f64 = temporary_storage
+// CHECK:STDOUT:   %.loc8_24.2: ref f64 = temporary %.loc8_24.1, @__global_init.%float.negate
+// CHECK:STDOUT:   %a: ref f64 = bind_name a, %.loc8_24.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Negate(%a.param_patt: f64) -> f64 = "float.negate";
@@ -173,9 +185,6 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [template = constants.%Negate]
 // CHECK:STDOUT:   %float: f64 = float_literal 1.5 [template = constants.%float.e93]
 // CHECK:STDOUT:   %float.negate: init f64 = call %Negate.ref(%float) [template = constants.%float.928]
-// CHECK:STDOUT:   %.loc8_25.1: f64 = value_of_initializer %float.negate [template = constants.%float.928]
-// CHECK:STDOUT:   %.loc8_25.2: f64 = converted %float.negate, %.loc8_25.1 [template = constants.%float.928]
-// CHECK:STDOUT:   %a: f64 = bind_name a, %.loc8_25.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 0
toolchain/check/testdata/builtins/float/sub.carbon

@@ -144,7 +144,17 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
 // CHECK:STDOUT:     %return.param: ref f64 = out_param runtime_param2
 // CHECK:STDOUT:     %return: ref f64 = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: f64 = binding_pattern x
+// CHECK:STDOUT:     %.loc8_1: f64 = var_pattern %x.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x.var: ref f64 = var x
+// CHECK:STDOUT:   %.loc8_8.1: type = splice_block %.loc8_8.3 [template = f64] {
+// CHECK:STDOUT:     %int_64: Core.IntLiteral = int_value 64 [template = constants.%int_64]
+// CHECK:STDOUT:     %float.make_type: init type = call constants.%Float(%int_64) [template = f64]
+// CHECK:STDOUT:     %.loc8_8.2: type = value_of_initializer %float.make_type [template = f64]
+// CHECK:STDOUT:     %.loc8_8.3: type = converted %float.make_type, %.loc8_8.2 [template = f64]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x: ref f64 = bind_name x, %x.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 20 - 6
toolchain/check/testdata/builtins/read/int.carbon

@@ -64,17 +64,31 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %ReadChar.ref.loc16: %ReadChar.type.fa8 = name_ref ReadChar, file.%ReadChar.decl [template = constants.%ReadChar.7f4]
 // CHECK:STDOUT:   %read.char.loc16: init %i32 = call %ReadChar.ref.loc16()
-// CHECK:STDOUT:   %.loc16_26.1: %i32 = value_of_initializer %read.char.loc16
-// CHECK:STDOUT:   %.loc16_26.2: %i32 = converted %read.char.loc16, %.loc16_26.1
-// CHECK:STDOUT:   %n: %i32 = bind_name n, %.loc16_26.2
+// CHECK:STDOUT:   %.loc16_10: type = splice_block %i32.loc16 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16_25.1: ref %i32 = temporary_storage
+// CHECK:STDOUT:   %.loc16_25.2: ref %i32 = temporary %.loc16_25.1, %read.char.loc16
+// CHECK:STDOUT:   %n: ref %i32 = bind_name n, %.loc16_25.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.ref: <namespace> = name_ref Core, imports.%Core [template = imports.%Core]
 // CHECK:STDOUT:   %ReadChar.ref.loc17: %ReadChar.type.9f3 = name_ref ReadChar, imports.%import_ref.ecd [template = constants.%ReadChar.01f]
 // CHECK:STDOUT:   %read.char.loc17: init %i32 = call %ReadChar.ref.loc17()
-// CHECK:STDOUT:   %.loc17_31.1: %i32 = value_of_initializer %read.char.loc17
-// CHECK:STDOUT:   %.loc17_31.2: %i32 = converted %read.char.loc17, %.loc17_31.1
-// CHECK:STDOUT:   %m: %i32 = bind_name m, %.loc17_31.2
+// CHECK:STDOUT:   %.loc17_10: type = splice_block %i32.loc17 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc17_30.1: ref %i32 = temporary_storage
+// CHECK:STDOUT:   %.loc17_30.2: ref %i32 = temporary %.loc17_30.1, %read.char.loc17
+// CHECK:STDOUT:   %m: ref %i32 = bind_name m, %.loc17_30.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 107 - 29
toolchain/check/testdata/class/access_modifers.carbon

@@ -198,15 +198,26 @@ class A {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Circle {
-// CHECK:STDOUT:   %.loc5: %Circle.elem = field_decl radius, element0 [template]
+// CHECK:STDOUT:   %.loc5_21: %Circle.elem = field_decl radius, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_11: %Circle.elem = var_pattern %.loc5_21
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Circle.elem = var <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %SOME_INTERNAL_CONSTANT.patt: %i32 = binding_pattern SOME_INTERNAL_CONSTANT
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [template = constants.%int_5.64b]
+// CHECK:STDOUT:   %.loc6_39: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %int_5, %impl.elem0 [template = constants.%Convert.bound.4e6]
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.ba9]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %Convert.specific_fn(%int_5) [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc6_46.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc6_46.2: %i32 = converted %int_5, %.loc6_46.1 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %SOME_INTERNAL_CONSTANT: %i32 = bind_name SOME_INTERNAL_CONSTANT, %.loc6_46.2
+// CHECK:STDOUT:   %.loc6_45.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %.loc6_45.2: %i32 = converted %int_5, %.loc6_45.1 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %SOME_INTERNAL_CONSTANT: %i32 = bind_name SOME_INTERNAL_CONSTANT, %.loc6_45.2
 // CHECK:STDOUT:   %SomeInternalFunction.decl: %SomeInternalFunction.type = fn_decl @SomeInternalFunction [template = constants.%SomeInternalFunction] {
 // CHECK:STDOUT:     %return.patt: %i32 = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %i32 = out_param_pattern %return.patt, runtime_param0
@@ -258,23 +269,33 @@ class A {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Circle.ref: type = name_ref Circle, file.%Circle.decl [template = constants.%Circle]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %circle.patt: %Circle = binding_pattern circle
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Circle.ref.loc18_24: type = name_ref Circle, file.%Circle.decl [template = constants.%Circle]
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, @Circle.%Make.decl [template = constants.%Make]
 // CHECK:STDOUT:   %.loc18_36.1: ref %Circle = temporary_storage
 // CHECK:STDOUT:   %Make.call: init %Circle = call %Make.ref() to %.loc18_36.1
+// CHECK:STDOUT:   %Circle.ref.loc18_15: type = name_ref Circle, file.%Circle.decl [template = constants.%Circle]
 // CHECK:STDOUT:   %.loc18_36.2: ref %Circle = temporary %.loc18_36.1, %Make.call
-// CHECK:STDOUT:   %.loc18_36.3: %Circle = bind_value %.loc18_36.2
-// CHECK:STDOUT:   %circle: %Circle = bind_name circle, %.loc18_36.3
-// CHECK:STDOUT:   %circle.ref.loc26: %Circle = name_ref circle, %circle
+// CHECK:STDOUT:   %circle: ref %Circle = bind_name circle, %.loc18_36.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %radius.patt: %i32 = binding_pattern radius
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %circle.ref.loc26: ref %Circle = name_ref circle, %circle
 // CHECK:STDOUT:   %radius.ref.loc26: <error> = name_ref radius, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc26: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %radius: %i32 = bind_name radius, <error>
-// CHECK:STDOUT:   %circle.ref.loc34: %Circle = name_ref circle, %circle
+// CHECK:STDOUT:   %circle.ref.loc34: ref %Circle = name_ref circle, %circle
 // CHECK:STDOUT:   %radius.ref.loc34: <error> = name_ref radius, <error> [template = <error>]
 // CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [template = constants.%int_5.64b]
 // CHECK:STDOUT:   assign %radius.ref.loc34, <error>
-// CHECK:STDOUT:   %circle.ref.loc42: %Circle = name_ref circle, %circle
+// CHECK:STDOUT:   %circle.ref.loc42: ref %Circle = name_ref circle, %circle
 // CHECK:STDOUT:   %SOME_INTERNAL_CONSTANT.ref: <error> = name_ref SOME_INTERNAL_CONSTANT, <error> [template = <error>]
-// CHECK:STDOUT:   %circle.ref.loc51: %Circle = name_ref circle, %circle
+// CHECK:STDOUT:   %circle.ref.loc51: ref %Circle = name_ref circle, %circle
 // CHECK:STDOUT:   %SomeInternalFunction.ref: <error> = name_ref SomeInternalFunction, <error> [template = <error>]
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -312,15 +333,26 @@ class A {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   %.loc5_18: %A.elem = field_decl x, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_13: %A.elem = var_pattern %.loc5_18
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x [template = constants.%complete_type.1ec]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %i32 = binding_pattern x
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc16: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x: %i32 = bind_name x, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -369,7 +401,11 @@ class A {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Circle {
-// CHECK:STDOUT:   %.loc5: %Circle.elem = field_decl radius, element0 [template]
+// CHECK:STDOUT:   %.loc5_21: %Circle.elem = field_decl radius, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_11: %Circle.elem = var_pattern %.loc5_21
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Circle.elem = var <invalid>
 // CHECK:STDOUT:   %GetRadius.decl: %GetRadius.type = fn_decl @GetRadius [template = constants.%GetRadius] {
 // CHECK:STDOUT:     %self.patt: %Circle = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %Circle = value_param_pattern %self.patt, runtime_param0
@@ -414,7 +450,7 @@ class A {
 // CHECK:STDOUT: fn @GetRadius[%self.param_patt: %Circle]() -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %self.ref: %Circle = name_ref self, %self
-// CHECK:STDOUT:   %radius.ref: %Circle.elem = name_ref radius, @Circle.%.loc5 [template = @Circle.%.loc5]
+// CHECK:STDOUT:   %radius.ref: %Circle.elem = name_ref radius, @Circle.%.loc5_21 [template = @Circle.%.loc5_21]
 // CHECK:STDOUT:   %.loc8_16.1: ref %i32 = class_element_access %self.ref, element0
 // CHECK:STDOUT:   %.loc8_16.2: %i32 = bind_value %.loc8_16.1
 // CHECK:STDOUT:   return %.loc8_16.2
@@ -473,21 +509,36 @@ class A {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .A = %A.decl
-// CHECK:STDOUT:     .x = @__global_init.%x
+// CHECK:STDOUT:     .x = %x
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %i32 = binding_pattern x
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc8: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %x: %i32 = bind_name x, @__global_init.%x.ref
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %i32 = binding_pattern x
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [template = constants.%int_5.64b]
+// CHECK:STDOUT:   %.loc5_10: type = splice_block %i32 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound: <bound method> = bound_method %int_5, %impl.elem0 [template = constants.%Convert.bound]
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %Convert.specific_fn(%int_5) [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc5_17.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc5_17.2: %i32 = converted %int_5, %.loc5_17.1 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %x: %i32 = bind_name x, %.loc5_17.2
+// CHECK:STDOUT:   %.loc5_16.1: %i32 = value_of_initializer %int.convert_checked [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %.loc5_16.2: %i32 = converted %int_5, %.loc5_16.1 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %x: %i32 = bind_name x, %.loc5_16.2
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [template = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -496,7 +547,6 @@ class A {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %x.ref: %i32 = name_ref x, @A.%x
-// CHECK:STDOUT:   %x: %i32 = bind_name x, %x.ref
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -531,30 +581,60 @@ class A {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .A = %A.decl
-// CHECK:STDOUT:     .x = @__global_init.%x
-// CHECK:STDOUT:     .y = @__global_init.%y
+// CHECK:STDOUT:     .x = %x
+// CHECK:STDOUT:     .y = %y
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %A.decl: type = class_decl @A [template = constants.%A] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %i32 = binding_pattern x
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc16: type = splice_block %i32.loc16 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %x: %i32 = bind_name x, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %y.patt: %i32 = binding_pattern y
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc24: type = splice_block %i32.loc24 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc24: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc24: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %y: %i32 = bind_name y, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %x.patt: %i32 = binding_pattern x
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_5.loc5: Core.IntLiteral = int_value 5 [template = constants.%int_5.64b]
+// CHECK:STDOUT:   %.loc5_20: type = splice_block %i32.loc5 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc5: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc5: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc5: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc5: <bound method> = bound_method %int_5.loc5, %impl.elem0.loc5 [template = constants.%Convert.bound]
 // CHECK:STDOUT:   %Convert.specific_fn.loc5: <specific function> = specific_function %Convert.bound.loc5, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn]
 // CHECK:STDOUT:   %int.convert_checked.loc5: init %i32 = call %Convert.specific_fn.loc5(%int_5.loc5) [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc5_27.1: %i32 = value_of_initializer %int.convert_checked.loc5 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc5_27.2: %i32 = converted %int_5.loc5, %.loc5_27.1 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %x: %i32 = bind_name x, %.loc5_27.2
+// CHECK:STDOUT:   %.loc5_26.1: %i32 = value_of_initializer %int.convert_checked.loc5 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %.loc5_26.2: %i32 = converted %int_5.loc5, %.loc5_26.1 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %x: %i32 = bind_name x, %.loc5_26.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %y.patt: %i32 = binding_pattern y
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_5.loc6: Core.IntLiteral = int_value 5 [template = constants.%int_5.64b]
+// CHECK:STDOUT:   %.loc6_18: type = splice_block %i32.loc6 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc6: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc6: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc6: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc6: <bound method> = bound_method %int_5.loc6, %impl.elem0.loc6 [template = constants.%Convert.bound]
 // CHECK:STDOUT:   %Convert.specific_fn.loc6: <specific function> = specific_function %Convert.bound.loc6, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn]
 // CHECK:STDOUT:   %int.convert_checked.loc6: init %i32 = call %Convert.specific_fn.loc6(%int_5.loc6) [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc6_25.1: %i32 = value_of_initializer %int.convert_checked.loc6 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %.loc6_25.2: %i32 = converted %int_5.loc6, %.loc6_25.1 [template = constants.%int_5.0f6]
-// CHECK:STDOUT:   %y: %i32 = bind_name y, %.loc6_25.2
+// CHECK:STDOUT:   %.loc6_24.1: %i32 = value_of_initializer %int.convert_checked.loc6 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %.loc6_24.2: %i32 = converted %int_5.loc6, %.loc6_24.1 [template = constants.%int_5.0f6]
+// CHECK:STDOUT:   %y: %i32 = bind_name y, %.loc6_24.2
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [template = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -563,10 +643,8 @@ class A {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %A.ref.loc16: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [template = <error>]
-// CHECK:STDOUT:   %x: %i32 = bind_name x, <error>
 // CHECK:STDOUT:   %A.ref.loc24: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %y.ref: <error> = name_ref y, <error> [template = <error>]
-// CHECK:STDOUT:   %y: %i32 = bind_name y, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 10 - 2
toolchain/check/testdata/class/adapter/adapt.carbon

@@ -99,8 +99,16 @@ interface I {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @SomeClass {
-// CHECK:STDOUT:   %.loc5: %SomeClass.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc6: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %SomeClass.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %SomeClass.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %SomeClass.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 103 - 45
toolchain/check/testdata/class/adapter/adapt_copy.carbon

@@ -86,7 +86,7 @@ class AdaptNoncopyableIndirect {
 fn H(a: AdaptNoncopyableIndirect) -> AdaptNoncopyableIndirect {
   // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+7]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]
   // CHECK:STDERR:   var b: AdaptNoncopyableIndirect = a;
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+4]]:37: note: in copy of `AdaptNoncopyableIndirect` [InCopy]
   // CHECK:STDERR:   var b: AdaptNoncopyableIndirect = a;
   // CHECK:STDERR:                                     ^
@@ -203,10 +203,15 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%c.param_patt: %AdaptCopyable) -> %AdaptCopyable {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %AdaptCopyable = binding_pattern d
+// CHECK:STDOUT:     %.loc11: %AdaptCopyable = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %AdaptCopyable = var d
-// CHECK:STDOUT:   %d: ref %AdaptCopyable = bind_name d, %d.var
 // CHECK:STDOUT:   %c.ref: %AdaptCopyable = name_ref c, %c
 // CHECK:STDOUT:   assign %d.var, %c.ref
+// CHECK:STDOUT:   %AdaptCopyable.ref.loc11: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [template = constants.%AdaptCopyable]
+// CHECK:STDOUT:   %d: ref %AdaptCopyable = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %AdaptCopyable = name_ref d, %d
 // CHECK:STDOUT:   %.loc12: %AdaptCopyable = bind_value %d.ref
 // CHECK:STDOUT:   return %.loc12
@@ -214,8 +219,11 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @InTuple(%c.param_patt: %tuple.type.2a3) -> %return.param_patt: %tuple.type.2a3 {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %tuple.type.2a3 = binding_pattern d
+// CHECK:STDOUT:     %.loc16_3.1: %tuple.type.2a3 = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %tuple.type.2a3 = var d
-// CHECK:STDOUT:   %d: ref %tuple.type.2a3 = bind_name d, %d.var
 // CHECK:STDOUT:   %c.ref: %tuple.type.2a3 = name_ref c, %c
 // CHECK:STDOUT:   %tuple.elem0.loc16_33.1: %AdaptCopyable = tuple_access %c.ref, element0
 // CHECK:STDOUT:   %tuple.elem0.loc16_33.2: ref %AdaptCopyable = tuple_access %d.var, element0
@@ -224,8 +232,16 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %tuple.elem1.loc16_33.2: ref %u32 = tuple_access %d.var, element1
 // CHECK:STDOUT:   %.loc16_33.2: init %u32 = initialize_from %tuple.elem1.loc16_33.1 to %tuple.elem1.loc16_33.2
 // CHECK:STDOUT:   %.loc16_33.3: init %tuple.type.2a3 = tuple_init (%.loc16_33.1, %.loc16_33.2) to %d.var
-// CHECK:STDOUT:   %.loc16_34: init %tuple.type.2a3 = converted %c.ref, %.loc16_33.3
-// CHECK:STDOUT:   assign %d.var, %.loc16_34
+// CHECK:STDOUT:   %.loc16_3.2: init %tuple.type.2a3 = converted %c.ref, %.loc16_33.3
+// CHECK:STDOUT:   assign %d.var, %.loc16_3.2
+// CHECK:STDOUT:   %.loc16_29.1: type = splice_block %.loc16_29.3 [template = constants.%tuple.type.2a3] {
+// CHECK:STDOUT:     %AdaptCopyable.ref.loc16: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [template = constants.%AdaptCopyable]
+// CHECK:STDOUT:     %int_32.loc16: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %u32.loc16: type = class_type @UInt, @UInt(constants.%int_32) [template = constants.%u32]
+// CHECK:STDOUT:     %.loc16_29.2: %tuple.type.24b = tuple_literal (%AdaptCopyable.ref.loc16, %u32.loc16)
+// CHECK:STDOUT:     %.loc16_29.3: type = converted %.loc16_29.2, constants.%tuple.type.2a3 [template = constants.%tuple.type.2a3]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %d: ref %tuple.type.2a3 = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %tuple.type.2a3 = name_ref d, %d
 // CHECK:STDOUT:   %tuple.elem0.loc17_10.1: ref %AdaptCopyable = tuple_access %d.ref, element0
 // CHECK:STDOUT:   %.loc17_10.1: %AdaptCopyable = bind_value %tuple.elem0.loc17_10.1
@@ -327,21 +343,26 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%c.param_patt: %AdaptTuple) -> %return.param_patt: %AdaptTuple {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %AdaptTuple = binding_pattern d
+// CHECK:STDOUT:     %.loc9_3.1: %AdaptTuple = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %AdaptTuple = var d
-// CHECK:STDOUT:   %d: ref %AdaptTuple = bind_name d, %d.var
 // CHECK:STDOUT:   %c.ref: %AdaptTuple = name_ref c, %c
-// CHECK:STDOUT:   %.loc9_24.1: %tuple.type.d07 = as_compatible %c.ref
-// CHECK:STDOUT:   %tuple.elem0.loc9_24.1: %i32 = tuple_access %.loc9_24.1, element0
-// CHECK:STDOUT:   %.loc9_24.2: ref %tuple.type.d07 = as_compatible %d.var
-// CHECK:STDOUT:   %tuple.elem0.loc9_24.2: ref %i32 = tuple_access %.loc9_24.2, element0
-// CHECK:STDOUT:   %.loc9_24.3: init %i32 = initialize_from %tuple.elem0.loc9_24.1 to %tuple.elem0.loc9_24.2
-// CHECK:STDOUT:   %tuple.elem1.loc9_24.1: %i32 = tuple_access %.loc9_24.1, element1
-// CHECK:STDOUT:   %tuple.elem1.loc9_24.2: ref %i32 = tuple_access %.loc9_24.2, element1
-// CHECK:STDOUT:   %.loc9_24.4: init %i32 = initialize_from %tuple.elem1.loc9_24.1 to %tuple.elem1.loc9_24.2
-// CHECK:STDOUT:   %.loc9_24.5: init %tuple.type.d07 = tuple_init (%.loc9_24.3, %.loc9_24.4) to %.loc9_24.2
-// CHECK:STDOUT:   %.loc9_24.6: init %AdaptTuple = as_compatible %.loc9_24.5
-// CHECK:STDOUT:   %.loc9_24.7: init %AdaptTuple = converted %c.ref, %.loc9_24.6
-// CHECK:STDOUT:   assign %d.var, %.loc9_24.7
+// CHECK:STDOUT:   %.loc9_3.2: %tuple.type.d07 = as_compatible %c.ref
+// CHECK:STDOUT:   %tuple.elem0.loc9_3.1: %i32 = tuple_access %.loc9_3.2, element0
+// CHECK:STDOUT:   %.loc9_3.3: ref %tuple.type.d07 = as_compatible %d.var
+// CHECK:STDOUT:   %tuple.elem0.loc9_3.2: ref %i32 = tuple_access %.loc9_3.3, element0
+// CHECK:STDOUT:   %.loc9_3.4: init %i32 = initialize_from %tuple.elem0.loc9_3.1 to %tuple.elem0.loc9_3.2
+// CHECK:STDOUT:   %tuple.elem1.loc9_3.1: %i32 = tuple_access %.loc9_3.2, element1
+// CHECK:STDOUT:   %tuple.elem1.loc9_3.2: ref %i32 = tuple_access %.loc9_3.3, element1
+// CHECK:STDOUT:   %.loc9_3.5: init %i32 = initialize_from %tuple.elem1.loc9_3.1 to %tuple.elem1.loc9_3.2
+// CHECK:STDOUT:   %.loc9_3.6: init %tuple.type.d07 = tuple_init (%.loc9_3.4, %.loc9_3.5) to %.loc9_3.3
+// CHECK:STDOUT:   %.loc9_3.7: init %AdaptTuple = as_compatible %.loc9_3.6
+// CHECK:STDOUT:   %.loc9_3.8: init %AdaptTuple = converted %c.ref, %.loc9_3.7
+// CHECK:STDOUT:   assign %d.var, %.loc9_3.8
+// CHECK:STDOUT:   %AdaptTuple.ref.loc9: type = name_ref AdaptTuple, file.%AdaptTuple.decl [template = constants.%AdaptTuple]
+// CHECK:STDOUT:   %d: ref %AdaptTuple = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %AdaptTuple = name_ref d, %d
 // CHECK:STDOUT:   %.loc10_11.1: ref %tuple.type.d07 = as_compatible %d.ref
 // CHECK:STDOUT:   %tuple.elem0.loc10_11.1: ref %i32 = tuple_access %.loc10_11.1, element0
@@ -361,8 +382,11 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @InTuple(%c.param_patt: %tuple.type.f69) -> %return.param_patt: %tuple.type.f69 {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %tuple.type.f69 = binding_pattern d
+// CHECK:STDOUT:     %.loc14_3.1: %tuple.type.f69 = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %tuple.type.f69 = var d
-// CHECK:STDOUT:   %d: ref %tuple.type.f69 = bind_name d, %d.var
 // CHECK:STDOUT:   %c.ref: %tuple.type.f69 = name_ref c, %c
 // CHECK:STDOUT:   %tuple.elem0.loc14_30.1: %AdaptTuple = tuple_access %c.ref, element0
 // CHECK:STDOUT:   %.loc14_30.1: %tuple.type.d07 = as_compatible %tuple.elem0.loc14_30.1
@@ -381,8 +405,16 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %tuple.elem1.loc14_30.4: ref %u32 = tuple_access %d.var, element1
 // CHECK:STDOUT:   %.loc14_30.8: init %u32 = initialize_from %tuple.elem1.loc14_30.3 to %tuple.elem1.loc14_30.4
 // CHECK:STDOUT:   %.loc14_30.9: init %tuple.type.f69 = tuple_init (%.loc14_30.7, %.loc14_30.8) to %d.var
-// CHECK:STDOUT:   %.loc14_31: init %tuple.type.f69 = converted %c.ref, %.loc14_30.9
-// CHECK:STDOUT:   assign %d.var, %.loc14_31
+// CHECK:STDOUT:   %.loc14_3.2: init %tuple.type.f69 = converted %c.ref, %.loc14_30.9
+// CHECK:STDOUT:   assign %d.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_26.1: type = splice_block %.loc14_26.3 [template = constants.%tuple.type.f69] {
+// CHECK:STDOUT:     %AdaptTuple.ref.loc14: type = name_ref AdaptTuple, file.%AdaptTuple.decl [template = constants.%AdaptTuple]
+// CHECK:STDOUT:     %int_32.loc14: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %u32.loc14: type = class_type @UInt, @UInt(constants.%int_32) [template = constants.%u32]
+// CHECK:STDOUT:     %.loc14_26.2: %tuple.type.24b = tuple_literal (%AdaptTuple.ref.loc14, %u32.loc14)
+// CHECK:STDOUT:     %.loc14_26.3: type = converted %.loc14_26.2, constants.%tuple.type.f69 [template = constants.%tuple.type.f69]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %d: ref %tuple.type.f69 = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %tuple.type.f69 = name_ref d, %d
 // CHECK:STDOUT:   %tuple.elem0.loc15_10.1: ref %AdaptTuple = tuple_access %d.ref, element0
 // CHECK:STDOUT:   %.loc15_10.1: ref %tuple.type.d07 = as_compatible %tuple.elem0.loc15_10.1
@@ -465,10 +497,15 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G(%a.param_patt: %AdaptNoncopyable) -> %return.param_patt: %AdaptNoncopyable {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %AdaptNoncopyable = binding_pattern b
+// CHECK:STDOUT:     %.loc17: %AdaptNoncopyable = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %AdaptNoncopyable = var b
-// CHECK:STDOUT:   %b: ref %AdaptNoncopyable = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: %AdaptNoncopyable = name_ref a, %a
 // CHECK:STDOUT:   assign %b.var, <error>
+// CHECK:STDOUT:   %AdaptNoncopyable.ref.loc17: type = name_ref AdaptNoncopyable, file.%AdaptNoncopyable.decl [template = constants.%AdaptNoncopyable]
+// CHECK:STDOUT:   %b: ref %AdaptNoncopyable = bind_name b, %b.var
 // CHECK:STDOUT:   %b.ref: ref %AdaptNoncopyable = name_ref b, %b
 // CHECK:STDOUT:   %.loc22: %AdaptNoncopyable = bind_value %b.ref
 // CHECK:STDOUT:   return <error> to %return
@@ -543,16 +580,21 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @H(%a.param_patt: %AdaptNoncopyableIndirect) -> %return.param_patt: %AdaptNoncopyableIndirect {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %AdaptNoncopyableIndirect = binding_pattern b
+// CHECK:STDOUT:     %.loc20_3.1: %AdaptNoncopyableIndirect = var_pattern %b.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %AdaptNoncopyableIndirect = var b
-// CHECK:STDOUT:   %b: ref %AdaptNoncopyableIndirect = bind_name b, %b.var
 // CHECK:STDOUT:   %a.ref: %AdaptNoncopyableIndirect = name_ref a, %a
-// CHECK:STDOUT:   %.loc20_38.1: %tuple.type.c9a = as_compatible %a.ref
-// CHECK:STDOUT:   %tuple.elem0.loc20_38.1: %i32 = tuple_access %.loc20_38.1, element0
-// CHECK:STDOUT:   %.loc20_38.2: ref %tuple.type.c9a = as_compatible %b.var
-// CHECK:STDOUT:   %tuple.elem0.loc20_38.2: ref %i32 = tuple_access %.loc20_38.2, element0
-// CHECK:STDOUT:   %.loc20_38.3: init %i32 = initialize_from %tuple.elem0.loc20_38.1 to %tuple.elem0.loc20_38.2
-// CHECK:STDOUT:   %tuple.elem1.loc20: %Noncopyable = tuple_access %.loc20_38.1, element1
+// CHECK:STDOUT:   %.loc20_3.2: %tuple.type.c9a = as_compatible %a.ref
+// CHECK:STDOUT:   %tuple.elem0.loc20_3.1: %i32 = tuple_access %.loc20_3.2, element0
+// CHECK:STDOUT:   %.loc20_3.3: ref %tuple.type.c9a = as_compatible %b.var
+// CHECK:STDOUT:   %tuple.elem0.loc20_3.2: ref %i32 = tuple_access %.loc20_3.3, element0
+// CHECK:STDOUT:   %.loc20_3.4: init %i32 = initialize_from %tuple.elem0.loc20_3.1 to %tuple.elem0.loc20_3.2
+// CHECK:STDOUT:   %tuple.elem1.loc20: %Noncopyable = tuple_access %.loc20_3.2, element1
 // CHECK:STDOUT:   assign %b.var, <error>
+// CHECK:STDOUT:   %AdaptNoncopyableIndirect.ref.loc20: type = name_ref AdaptNoncopyableIndirect, file.%AdaptNoncopyableIndirect.decl [template = constants.%AdaptNoncopyableIndirect]
+// CHECK:STDOUT:   %b: ref %AdaptNoncopyableIndirect = bind_name b, %b.var
 // CHECK:STDOUT:   %b.ref: ref %AdaptNoncopyableIndirect = name_ref b, %b
 // CHECK:STDOUT:   %.loc28_11.1: ref %tuple.type.c9a = as_compatible %b.ref
 // CHECK:STDOUT:   %tuple.elem0.loc28_11.1: ref %i32 = tuple_access %.loc28_11.1, element0
@@ -651,21 +693,26 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @I(%g.param_patt: %AdaptStruct) -> %return.param_patt: %AdaptStruct {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %h.patt: %AdaptStruct = binding_pattern h
+// CHECK:STDOUT:     %.loc9_3.1: %AdaptStruct = var_pattern %h.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %h.var: ref %AdaptStruct = var h
-// CHECK:STDOUT:   %h: ref %AdaptStruct = bind_name h, %h.var
 // CHECK:STDOUT:   %g.ref: %AdaptStruct = name_ref g, %g
-// CHECK:STDOUT:   %.loc9_25.1: %struct_type.e.f = as_compatible %g.ref
-// CHECK:STDOUT:   %.loc9_25.2: %i32 = struct_access %.loc9_25.1, element0
-// CHECK:STDOUT:   %.loc9_25.3: ref %struct_type.e.f = as_compatible %h.var
-// CHECK:STDOUT:   %.loc9_25.4: ref %i32 = struct_access %.loc9_25.3, element0
-// CHECK:STDOUT:   %.loc9_25.5: init %i32 = initialize_from %.loc9_25.2 to %.loc9_25.4
-// CHECK:STDOUT:   %.loc9_25.6: %i32 = struct_access %.loc9_25.1, element1
-// CHECK:STDOUT:   %.loc9_25.7: ref %i32 = struct_access %.loc9_25.3, element1
-// CHECK:STDOUT:   %.loc9_25.8: init %i32 = initialize_from %.loc9_25.6 to %.loc9_25.7
-// CHECK:STDOUT:   %.loc9_25.9: init %struct_type.e.f = struct_init (%.loc9_25.5, %.loc9_25.8) to %.loc9_25.3
-// CHECK:STDOUT:   %.loc9_25.10: init %AdaptStruct = as_compatible %.loc9_25.9
-// CHECK:STDOUT:   %.loc9_25.11: init %AdaptStruct = converted %g.ref, %.loc9_25.10
-// CHECK:STDOUT:   assign %h.var, %.loc9_25.11
+// CHECK:STDOUT:   %.loc9_3.2: %struct_type.e.f = as_compatible %g.ref
+// CHECK:STDOUT:   %.loc9_3.3: %i32 = struct_access %.loc9_3.2, element0
+// CHECK:STDOUT:   %.loc9_3.4: ref %struct_type.e.f = as_compatible %h.var
+// CHECK:STDOUT:   %.loc9_3.5: ref %i32 = struct_access %.loc9_3.4, element0
+// CHECK:STDOUT:   %.loc9_3.6: init %i32 = initialize_from %.loc9_3.3 to %.loc9_3.5
+// CHECK:STDOUT:   %.loc9_3.7: %i32 = struct_access %.loc9_3.2, element1
+// CHECK:STDOUT:   %.loc9_3.8: ref %i32 = struct_access %.loc9_3.4, element1
+// CHECK:STDOUT:   %.loc9_3.9: init %i32 = initialize_from %.loc9_3.7 to %.loc9_3.8
+// CHECK:STDOUT:   %.loc9_3.10: init %struct_type.e.f = struct_init (%.loc9_3.6, %.loc9_3.9) to %.loc9_3.4
+// CHECK:STDOUT:   %.loc9_3.11: init %AdaptStruct = as_compatible %.loc9_3.10
+// CHECK:STDOUT:   %.loc9_3.12: init %AdaptStruct = converted %g.ref, %.loc9_3.11
+// CHECK:STDOUT:   assign %h.var, %.loc9_3.12
+// CHECK:STDOUT:   %AdaptStruct.ref.loc9: type = name_ref AdaptStruct, file.%AdaptStruct.decl [template = constants.%AdaptStruct]
+// CHECK:STDOUT:   %h: ref %AdaptStruct = bind_name h, %h.var
 // CHECK:STDOUT:   %h.ref: ref %AdaptStruct = name_ref h, %h
 // CHECK:STDOUT:   %.loc10_11.1: ref %struct_type.e.f = as_compatible %h.ref
 // CHECK:STDOUT:   %.loc10_11.2: ref %i32 = struct_access %.loc10_11.1, element0
@@ -685,8 +732,11 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @InTuple(%c.param_patt: %tuple.type.80b) -> %return.param_patt: %tuple.type.80b {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %tuple.type.80b = binding_pattern d
+// CHECK:STDOUT:     %.loc14_3.1: %tuple.type.80b = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %tuple.type.80b = var d
-// CHECK:STDOUT:   %d: ref %tuple.type.80b = bind_name d, %d.var
 // CHECK:STDOUT:   %c.ref: %tuple.type.80b = name_ref c, %c
 // CHECK:STDOUT:   %tuple.elem0.loc14_31.1: %AdaptStruct = tuple_access %c.ref, element0
 // CHECK:STDOUT:   %.loc14_31.1: %struct_type.e.f = as_compatible %tuple.elem0.loc14_31.1
@@ -705,8 +755,16 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %tuple.elem1.loc14_31.2: ref %u32 = tuple_access %d.var, element1
 // CHECK:STDOUT:   %.loc14_31.12: init %u32 = initialize_from %tuple.elem1.loc14_31.1 to %tuple.elem1.loc14_31.2
 // CHECK:STDOUT:   %.loc14_31.13: init %tuple.type.80b = tuple_init (%.loc14_31.11, %.loc14_31.12) to %d.var
-// CHECK:STDOUT:   %.loc14_32: init %tuple.type.80b = converted %c.ref, %.loc14_31.13
-// CHECK:STDOUT:   assign %d.var, %.loc14_32
+// CHECK:STDOUT:   %.loc14_3.2: init %tuple.type.80b = converted %c.ref, %.loc14_31.13
+// CHECK:STDOUT:   assign %d.var, %.loc14_3.2
+// CHECK:STDOUT:   %.loc14_27.1: type = splice_block %.loc14_27.3 [template = constants.%tuple.type.80b] {
+// CHECK:STDOUT:     %AdaptStruct.ref.loc14: type = name_ref AdaptStruct, file.%AdaptStruct.decl [template = constants.%AdaptStruct]
+// CHECK:STDOUT:     %int_32.loc14: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %u32.loc14: type = class_type @UInt, @UInt(constants.%int_32) [template = constants.%u32]
+// CHECK:STDOUT:     %.loc14_27.2: %tuple.type.24b = tuple_literal (%AdaptStruct.ref.loc14, %u32.loc14)
+// CHECK:STDOUT:     %.loc14_27.3: type = converted %.loc14_27.2, constants.%tuple.type.80b [template = constants.%tuple.type.80b]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %d: ref %tuple.type.80b = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %tuple.type.80b = name_ref d, %d
 // CHECK:STDOUT:   %tuple.elem0.loc15_10.1: ref %AdaptStruct = tuple_access %d.ref, element0
 // CHECK:STDOUT:   %.loc15_10.1: ref %struct_type.e.f = as_compatible %tuple.elem0.loc15_10.1

+ 21 - 5
toolchain/check/testdata/class/adapter/extend_adapt.carbon

@@ -205,8 +205,16 @@ fn F(a: IntAdapter) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @SomeClass {
-// CHECK:STDOUT:   %.loc7: %SomeClass.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc8: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc7_8: %SomeClass.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc7_3: %SomeClass.elem = var_pattern %.loc7_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc7: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.loc8_8: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc8_3: %SomeClass.elem = var_pattern %.loc8_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc8: ref %SomeClass.elem = var <invalid>
 // CHECK:STDOUT:   %StaticMemberFunction.decl: %StaticMemberFunction.type = fn_decl @StaticMemberFunction [template = constants.%StaticMemberFunction] {} {}
 // CHECK:STDOUT:   %AdapterMethod.decl: %AdapterMethod.type = fn_decl @AdapterMethod [template = constants.%AdapterMethod] {
 // CHECK:STDOUT:     %self.patt: %SomeClassAdapter = binding_pattern self
@@ -365,8 +373,16 @@ fn F(a: IntAdapter) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @SomeClass {
-// CHECK:STDOUT:   %.loc5: %SomeClass.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc6: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %SomeClass.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %SomeClass.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %SomeClass.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %SomeClass.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %SomeClass.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %SomeClass.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -381,7 +397,7 @@ fn F(a: IntAdapter) -> i32 {
 // CHECK:STDOUT: fn @F(%a.param_patt: %SomeClassAdapter) -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: %SomeClassAdapter = name_ref a, %a
-// CHECK:STDOUT:   %b.ref: %SomeClass.elem = name_ref b, @SomeClass.%.loc6 [template = @SomeClass.%.loc6]
+// CHECK:STDOUT:   %b.ref: %SomeClass.elem = name_ref b, @SomeClass.%.loc6_8 [template = @SomeClass.%.loc6_8]
 // CHECK:STDOUT:   %.loc21_11.1: %SomeClass = converted %a.ref, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc21_11.2: %i32 = class_element_access <error>, element1 [template = <error>]
 // CHECK:STDOUT:   return <error>

+ 25 - 5
toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon

@@ -154,7 +154,11 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   adapt_decl %i32 [template]
-// CHECK:STDOUT:   %.loc13: %AdaptWithField.elem = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   %.loc13_8: %AdaptWithField.elem = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc13_3: %AdaptWithField.elem = var_pattern %.loc13_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %AdaptWithField.elem = var <invalid>
 // CHECK:STDOUT:   complete_type_witness = <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -162,9 +166,21 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:   adapt_decl %i32 [template]
-// CHECK:STDOUT:   %.loc25: %AdaptWithFields.elem = field_decl a, element<invalid> [template]
-// CHECK:STDOUT:   %.loc26: %AdaptWithFields.elem = field_decl b, element<invalid> [template]
-// CHECK:STDOUT:   %.loc27: %AdaptWithFields.elem = field_decl c, element<invalid> [template]
+// CHECK:STDOUT:   %.loc25_8: %AdaptWithFields.elem = field_decl a, element<invalid> [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc25_3: %AdaptWithFields.elem = var_pattern %.loc25_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc25: ref %AdaptWithFields.elem = var <invalid>
+// CHECK:STDOUT:   %.loc26_8: %AdaptWithFields.elem = field_decl b, element<invalid> [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc26_3: %AdaptWithFields.elem = var_pattern %.loc26_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc26: ref %AdaptWithFields.elem = var <invalid>
+// CHECK:STDOUT:   %.loc27_8: %AdaptWithFields.elem = field_decl c, element<invalid> [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc27_3: %AdaptWithFields.elem = var_pattern %.loc27_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc27: ref %AdaptWithFields.elem = var <invalid>
 // CHECK:STDOUT:   complete_type_witness = <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -208,7 +224,11 @@ class AdaptWithBaseAndFields {
 // CHECK:STDOUT: class @AdaptWithBaseAndFields {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc7: %AdaptWithBaseAndFields.elem.767 = base_decl %Base.ref, element<invalid> [template]
-// CHECK:STDOUT:   %.loc8: %AdaptWithBaseAndFields.elem.ddf = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   %.loc8_8: %AdaptWithBaseAndFields.elem.ddf = field_decl n, element<invalid> [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc8_3: %AdaptWithBaseAndFields.elem.ddf = var_pattern %.loc8_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %AdaptWithBaseAndFields.elem.ddf = var <invalid>
 // CHECK:STDOUT:   %.loc16_10: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc16_11: type = converted %.loc16_10, constants.%empty_struct_type [template = constants.%empty_struct_type]
 // CHECK:STDOUT:   adapt_decl %.loc16_11 [template]

+ 142 - 84
toolchain/check/testdata/class/adapter/init_adapt.carbon

@@ -52,21 +52,21 @@ let a: C = {.a = 1, .b = 2};
 
 // Cannot implicitly convert between a type and an adapter for the type.
 
-// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert from `C` to `AdaptC` [ImplicitAsConversionFailure]
+// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:17: error: cannot implicitly convert from `C` to `AdaptC` [ImplicitAsConversionFailure]
 // CHECK:STDERR: let b: AdaptC = a;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `C` does not implement interface `Core.ImplicitAs(AdaptC)` [MissingImplInMemberAccessNote]
+// CHECK:STDERR:                 ^
+// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:17: note: type `C` does not implement interface `Core.ImplicitAs(AdaptC)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: let b: AdaptC = a;
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:                 ^
 // CHECK:STDERR:
 let b: AdaptC = a;
 
-// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert from `AdaptC` to `C` [ImplicitAsConversionFailure]
+// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:12: error: cannot implicitly convert from `AdaptC` to `C` [ImplicitAsConversionFailure]
 // CHECK:STDERR: let c: C = b;
-// CHECK:STDERR: ^~~~~~~~~~~~~
-// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `AdaptC` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessNote]
+// CHECK:STDERR:            ^
+// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:12: note: type `AdaptC` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: let c: C = b;
-// CHECK:STDERR: ^~~~~~~~~~~~~
+// CHECK:STDERR:            ^
 // CHECK:STDERR:
 let c: C = b;
 
@@ -76,19 +76,19 @@ fn MakeAdaptC() -> AdaptC;
 
 // CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert from `C` to `AdaptC` [ImplicitAsConversionFailure]
 // CHECK:STDERR: var d: AdaptC = MakeC();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~~~~~~
 // CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `C` does not implement interface `Core.ImplicitAs(AdaptC)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: var d: AdaptC = MakeC();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~~~~~~
 // CHECK:STDERR:
 var d: AdaptC = MakeC();
 
 // CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert from `AdaptC` to `C` [ImplicitAsConversionFailure]
 // CHECK:STDERR: var e: C = MakeAdaptC();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `AdaptC` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessNote]
 // CHECK:STDERR: var e: C = MakeAdaptC();
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR:
 var e: C = MakeAdaptC();
 
@@ -136,9 +136,9 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:     .AdaptC = %AdaptC.decl
-// CHECK:STDOUT:     .a = @__global_init.%a
-// CHECK:STDOUT:     .b = @__global_init.%b
-// CHECK:STDOUT:     .c = @__global_init.%c
+// CHECK:STDOUT:     .a = %a
+// CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:     .MakeC = %MakeC.decl
 // CHECK:STDOUT:     .MakeAdaptC = %MakeAdaptC.decl
 // CHECK:STDOUT:     .d = %d
@@ -147,6 +147,39 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %AdaptC.decl: type = class_decl @AdaptC [template = constants.%AdaptC] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C = binding_pattern a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:   %Convert.bound.loc13_27.1: <bound method> = bound_method @__global_init.%int_1, %impl.elem0.loc13_27.1 [template = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.1: <specific function> = specific_function %Convert.bound.loc13_27.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
+// CHECK:STDOUT:   %int.convert_checked.loc13_27.1: init %i32 = call %Convert.specific_fn.loc13_27.1(@__global_init.%int_1) [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc13_27.1: init %i32 = converted @__global_init.%int_1, %int.convert_checked.loc13_27.1 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc13_27.2: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc13_27.3: ref %i32 = class_element_access %.loc13_27.2, element0
+// CHECK:STDOUT:   %.loc13_27.4: init %i32 = initialize_from %.loc13_27.1 to %.loc13_27.3 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:   %Convert.bound.loc13_27.2: <bound method> = bound_method @__global_init.%int_2, %impl.elem0.loc13_27.2 [template = constants.%Convert.bound.ef9]
+// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.2: <specific function> = specific_function %Convert.bound.loc13_27.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.787]
+// CHECK:STDOUT:   %int.convert_checked.loc13_27.2: init %i32 = call %Convert.specific_fn.loc13_27.2(@__global_init.%int_2) [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.5: init %i32 = converted @__global_init.%int_2, %int.convert_checked.loc13_27.2 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.6: ref %i32 = class_element_access %.loc13_27.2, element1
+// CHECK:STDOUT:   %.loc13_27.7: init %i32 = initialize_from %.loc13_27.5 to %.loc13_27.6 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.8: init %C = class_init (%.loc13_27.4, %.loc13_27.7), %.loc13_27.2 [template = constants.%C.val]
+// CHECK:STDOUT:   %.loc13_27.9: ref %C = temporary %.loc13_27.2, %.loc13_27.8
+// CHECK:STDOUT:   %.loc13_27.10: ref %C = converted @__global_init.%.loc13, %.loc13_27.9
+// CHECK:STDOUT:   %a: ref %C = bind_name a, %.loc13_27.10
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %AdaptC = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %AdaptC.ref.loc15: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
+// CHECK:STDOUT:   %b: ref %AdaptC = bind_name b, @__global_init.%.loc15_19.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.ref.loc17: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %c: ref %C = bind_name c, @__global_init.%.loc17_14.2
 // CHECK:STDOUT:   %MakeC.decl: %MakeC.type = fn_decl @MakeC [template = constants.%MakeC] {
 // CHECK:STDOUT:     %return.patt: %C = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %C = out_param_pattern %return.patt, runtime_param0
@@ -163,15 +196,33 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:     %return.param: ref %AdaptC = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %AdaptC = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %AdaptC = binding_pattern d
+// CHECK:STDOUT:     %.loc23: %AdaptC = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %AdaptC = var d
+// CHECK:STDOUT:   %AdaptC.ref.loc23: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
 // CHECK:STDOUT:   %d: ref %AdaptC = bind_name d, %d.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %e.patt: %C = binding_pattern e
+// CHECK:STDOUT:     %.loc25: %C = var_pattern %e.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %e.var: ref %C = var e
+// CHECK:STDOUT:   %C.ref.loc25: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %e: ref %C = bind_name e, %e.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc5: %C.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc6: %C.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %C.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %C.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %C.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %C.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.501 [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -191,47 +242,25 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
-// CHECK:STDOUT:   %.loc13_27.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
-// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc13_27.1: <bound method> = bound_method %int_1, %impl.elem0.loc13_27.1 [template = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.1: <specific function> = specific_function %Convert.bound.loc13_27.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
-// CHECK:STDOUT:   %int.convert_checked.loc13_27.1: init %i32 = call %Convert.specific_fn.loc13_27.1(%int_1) [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc13_27.2: init %i32 = converted %int_1, %int.convert_checked.loc13_27.1 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc13_27.3: ref %C = temporary_storage
-// CHECK:STDOUT:   %.loc13_27.4: ref %i32 = class_element_access %.loc13_27.3, element0
-// CHECK:STDOUT:   %.loc13_27.5: init %i32 = initialize_from %.loc13_27.2 to %.loc13_27.4 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc13_27.2: <bound method> = bound_method %int_2, %impl.elem0.loc13_27.2 [template = constants.%Convert.bound.ef9]
-// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.2: <specific function> = specific_function %Convert.bound.loc13_27.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.787]
-// CHECK:STDOUT:   %int.convert_checked.loc13_27.2: init %i32 = call %Convert.specific_fn.loc13_27.2(%int_2) [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.6: init %i32 = converted %int_2, %int.convert_checked.loc13_27.2 [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.7: ref %i32 = class_element_access %.loc13_27.3, element1
-// CHECK:STDOUT:   %.loc13_27.8: init %i32 = initialize_from %.loc13_27.6 to %.loc13_27.7 [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.9: init %C = class_init (%.loc13_27.5, %.loc13_27.8), %.loc13_27.3 [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc13_27.10: ref %C = temporary %.loc13_27.3, %.loc13_27.9
-// CHECK:STDOUT:   %.loc13_28.1: ref %C = converted %.loc13_27.1, %.loc13_27.10
-// CHECK:STDOUT:   %.loc13_28.2: %C = bind_value %.loc13_28.1
-// CHECK:STDOUT:   %a: %C = bind_name a, %.loc13_28.2
-// CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
+// CHECK:STDOUT:   %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
+// CHECK:STDOUT:   %a.ref: ref %C = name_ref a, file.%a
 // CHECK:STDOUT:   %AdaptC.ref.loc15: type = name_ref AdaptC, file.%AdaptC.decl [template = constants.%AdaptC]
-// CHECK:STDOUT:   %.loc15_19.1: %AdaptC = as_compatible %a.ref
-// CHECK:STDOUT:   %.loc15_19.2: %AdaptC = converted %a.ref, %.loc15_19.1
-// CHECK:STDOUT:   %b: %AdaptC = bind_name b, %.loc15_19.2
-// CHECK:STDOUT:   %b.ref: %AdaptC = name_ref b, %b
+// CHECK:STDOUT:   %.loc15_19.1: ref %AdaptC = as_compatible %a.ref
+// CHECK:STDOUT:   %.loc15_19.2: ref %AdaptC = converted %a.ref, %.loc15_19.1
+// CHECK:STDOUT:   %b.ref: ref %AdaptC = name_ref b, file.%b
 // CHECK:STDOUT:   %C.ref.loc17: type = name_ref C, file.%C.decl [template = constants.%C]
-// CHECK:STDOUT:   %.loc17_14.1: %C = as_compatible %b.ref
-// CHECK:STDOUT:   %.loc17_14.2: %C = converted %b.ref, %.loc17_14.1
-// CHECK:STDOUT:   %c: %C = bind_name c, %.loc17_14.2
+// CHECK:STDOUT:   %.loc17_14.1: ref %C = as_compatible %b.ref
+// CHECK:STDOUT:   %.loc17_14.2: ref %C = converted %b.ref, %.loc17_14.1
 // CHECK:STDOUT:   %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [template = constants.%MakeC]
-// CHECK:STDOUT:   %.loc23_5: ref %AdaptC = splice_block file.%d.var {}
-// CHECK:STDOUT:   %MakeC.call: init %C = call %MakeC.ref() to %.loc23_5
+// CHECK:STDOUT:   %.loc23_1: ref %AdaptC = splice_block file.%d.var {}
+// CHECK:STDOUT:   %MakeC.call: init %C = call %MakeC.ref() to %.loc23_1
 // CHECK:STDOUT:   %AdaptC.ref.loc23: type = name_ref AdaptC, file.%AdaptC.decl [template = constants.%AdaptC]
 // CHECK:STDOUT:   %.loc23_25.1: init %AdaptC = as_compatible %MakeC.call
 // CHECK:STDOUT:   %.loc23_25.2: init %AdaptC = converted %MakeC.call, %.loc23_25.1
 // CHECK:STDOUT:   assign file.%d.var, %.loc23_25.2
 // CHECK:STDOUT:   %MakeAdaptC.ref: %MakeAdaptC.type = name_ref MakeAdaptC, file.%MakeAdaptC.decl [template = constants.%MakeAdaptC]
-// CHECK:STDOUT:   %.loc25_5: ref %C = splice_block file.%e.var {}
-// CHECK:STDOUT:   %MakeAdaptC.call: init %AdaptC = call %MakeAdaptC.ref() to %.loc25_5
+// CHECK:STDOUT:   %.loc25_1: ref %C = splice_block file.%e.var {}
+// CHECK:STDOUT:   %MakeAdaptC.call: init %AdaptC = call %MakeAdaptC.ref() to %.loc25_1
 // CHECK:STDOUT:   %C.ref.loc25: type = name_ref C, file.%C.decl [template = constants.%C]
 // CHECK:STDOUT:   %.loc25_25.1: init %C = as_compatible %MakeAdaptC.call
 // CHECK:STDOUT:   %.loc25_25.2: init %C = converted %MakeAdaptC.call, %.loc25_25.1
@@ -283,9 +312,9 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:     .AdaptC = %AdaptC.decl
-// CHECK:STDOUT:     .a = @__global_init.%a
-// CHECK:STDOUT:     .b = @__global_init.%b
-// CHECK:STDOUT:     .c = @__global_init.%c
+// CHECK:STDOUT:     .a = %a
+// CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:     .MakeC = %MakeC.decl
 // CHECK:STDOUT:     .MakeAdaptC = %MakeAdaptC.decl
 // CHECK:STDOUT:     .d = %d
@@ -294,6 +323,41 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
 // CHECK:STDOUT:   %AdaptC.decl: type = class_decl @AdaptC [template = constants.%AdaptC] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %C = binding_pattern a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:   %Convert.bound.loc13_27.1: <bound method> = bound_method @__global_init.%int_1, %impl.elem0.loc13_27.1 [template = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.1: <specific function> = specific_function %Convert.bound.loc13_27.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
+// CHECK:STDOUT:   %int.convert_checked.loc13_27.1: init %i32 = call %Convert.specific_fn.loc13_27.1(@__global_init.%int_1) [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc13_27.1: init %i32 = converted @__global_init.%int_1, %int.convert_checked.loc13_27.1 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc13_27.2: ref %C = temporary_storage
+// CHECK:STDOUT:   %.loc13_27.3: ref %i32 = class_element_access %.loc13_27.2, element0
+// CHECK:STDOUT:   %.loc13_27.4: init %i32 = initialize_from %.loc13_27.1 to %.loc13_27.3 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
+// CHECK:STDOUT:   %Convert.bound.loc13_27.2: <bound method> = bound_method @__global_init.%int_2, %impl.elem0.loc13_27.2 [template = constants.%Convert.bound.ef9]
+// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.2: <specific function> = specific_function %Convert.bound.loc13_27.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.787]
+// CHECK:STDOUT:   %int.convert_checked.loc13_27.2: init %i32 = call %Convert.specific_fn.loc13_27.2(@__global_init.%int_2) [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.5: init %i32 = converted @__global_init.%int_2, %int.convert_checked.loc13_27.2 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.6: ref %i32 = class_element_access %.loc13_27.2, element1
+// CHECK:STDOUT:   %.loc13_27.7: init %i32 = initialize_from %.loc13_27.5 to %.loc13_27.6 [template = constants.%int_2.ef8]
+// CHECK:STDOUT:   %.loc13_27.8: init %C = class_init (%.loc13_27.4, %.loc13_27.7), %.loc13_27.2 [template = constants.%C.val]
+// CHECK:STDOUT:   %.loc13_27.9: ref %C = temporary %.loc13_27.2, %.loc13_27.8
+// CHECK:STDOUT:   %.loc13_27.10: ref %C = converted @__global_init.%.loc13, %.loc13_27.9
+// CHECK:STDOUT:   %a: ref %C = bind_name a, %.loc13_27.10
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %AdaptC = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %AdaptC.ref.loc24: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
+// CHECK:STDOUT:   %.loc24: %AdaptC = converted @__global_init.%a.ref, <error> [template = <error>]
+// CHECK:STDOUT:   %b: %AdaptC = bind_name b, <error>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %C.ref.loc33: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:   %.loc33: %C = converted @__global_init.%b.ref, <error> [template = <error>]
+// CHECK:STDOUT:   %c: %C = bind_name c, <error>
 // CHECK:STDOUT:   %MakeC.decl: %MakeC.type = fn_decl @MakeC [template = constants.%MakeC] {
 // CHECK:STDOUT:     %return.patt: %C = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %C = out_param_pattern %return.patt, runtime_param0
@@ -310,15 +374,33 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT:     %return.param: ref %AdaptC = out_param runtime_param0
 // CHECK:STDOUT:     %return: ref %AdaptC = return_slot %return.param
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %d.patt: %AdaptC = binding_pattern d
+// CHECK:STDOUT:     %.loc46: %AdaptC = var_pattern %d.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %d.var: ref %AdaptC = var d
+// CHECK:STDOUT:   %AdaptC.ref.loc46: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
 // CHECK:STDOUT:   %d: ref %AdaptC = bind_name d, %d.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %e.patt: %C = binding_pattern e
+// CHECK:STDOUT:     %.loc55: %C = var_pattern %e.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %e.var: ref %C = var e
+// CHECK:STDOUT:   %C.ref.loc55: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %e: ref %C = bind_name e, %e.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc5: %C.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc6: %C.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc5_8: %C.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %C.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc5: ref %C.elem = var <invalid>
+// CHECK:STDOUT:   %.loc6_8: %C.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc6_3: %C.elem = var_pattern %.loc6_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc6: ref %C.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.501 [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -338,42 +420,18 @@ var e: C = MakeAdaptC();
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
-// CHECK:STDOUT:   %.loc13_27.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
-// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc13_27.1: <bound method> = bound_method %int_1, %impl.elem0.loc13_27.1 [template = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.1: <specific function> = specific_function %Convert.bound.loc13_27.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
-// CHECK:STDOUT:   %int.convert_checked.loc13_27.1: init %i32 = call %Convert.specific_fn.loc13_27.1(%int_1) [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc13_27.2: init %i32 = converted %int_1, %int.convert_checked.loc13_27.1 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc13_27.3: ref %C = temporary_storage
-// CHECK:STDOUT:   %.loc13_27.4: ref %i32 = class_element_access %.loc13_27.3, element0
-// CHECK:STDOUT:   %.loc13_27.5: init %i32 = initialize_from %.loc13_27.2 to %.loc13_27.4 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
-// CHECK:STDOUT:   %Convert.bound.loc13_27.2: <bound method> = bound_method %int_2, %impl.elem0.loc13_27.2 [template = constants.%Convert.bound.ef9]
-// CHECK:STDOUT:   %Convert.specific_fn.loc13_27.2: <specific function> = specific_function %Convert.bound.loc13_27.2, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.787]
-// CHECK:STDOUT:   %int.convert_checked.loc13_27.2: init %i32 = call %Convert.specific_fn.loc13_27.2(%int_2) [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.6: init %i32 = converted %int_2, %int.convert_checked.loc13_27.2 [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.7: ref %i32 = class_element_access %.loc13_27.3, element1
-// CHECK:STDOUT:   %.loc13_27.8: init %i32 = initialize_from %.loc13_27.6 to %.loc13_27.7 [template = constants.%int_2.ef8]
-// CHECK:STDOUT:   %.loc13_27.9: init %C = class_init (%.loc13_27.5, %.loc13_27.8), %.loc13_27.3 [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc13_27.10: ref %C = temporary %.loc13_27.3, %.loc13_27.9
-// CHECK:STDOUT:   %.loc13_28.1: ref %C = converted %.loc13_27.1, %.loc13_27.10
-// CHECK:STDOUT:   %.loc13_28.2: %C = bind_value %.loc13_28.1
-// CHECK:STDOUT:   %a: %C = bind_name a, %.loc13_28.2
-// CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
-// CHECK:STDOUT:   %.loc24: %AdaptC = converted %a.ref, <error> [template = <error>]
-// CHECK:STDOUT:   %b: %AdaptC = bind_name b, <error>
-// CHECK:STDOUT:   %b.ref: %AdaptC = name_ref b, %b
-// CHECK:STDOUT:   %.loc33: %C = converted %b.ref, <error> [template = <error>]
-// CHECK:STDOUT:   %c: %C = bind_name c, <error>
+// CHECK:STDOUT:   %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
+// CHECK:STDOUT:   %a.ref: ref %C = name_ref a, file.%a
+// CHECK:STDOUT:   %b.ref: %AdaptC = name_ref b, file.%b
 // CHECK:STDOUT:   %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [template = constants.%MakeC]
 // CHECK:STDOUT:   %.loc46_23: ref %C = temporary_storage
 // CHECK:STDOUT:   %MakeC.call: init %C = call %MakeC.ref() to %.loc46_23
-// CHECK:STDOUT:   %.loc46_24: %AdaptC = converted %MakeC.call, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc46_1: %AdaptC = converted %MakeC.call, <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%d.var, <error>
 // CHECK:STDOUT:   %MakeAdaptC.ref: %MakeAdaptC.type = name_ref MakeAdaptC, file.%MakeAdaptC.decl [template = constants.%MakeAdaptC]
 // CHECK:STDOUT:   %.loc55_23: ref %AdaptC = temporary_storage
 // CHECK:STDOUT:   %MakeAdaptC.call: init %AdaptC = call %MakeAdaptC.ref() to %.loc55_23
-// CHECK:STDOUT:   %.loc55_24: %C = converted %MakeAdaptC.call, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc55_1: %C = converted %MakeAdaptC.call, <error> [template = <error>]
 // CHECK:STDOUT:   assign file.%e.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 17 - 5
toolchain/check/testdata/class/base.carbon

@@ -132,7 +132,11 @@ class Derived {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc4: %Base.elem = field_decl b, element0 [template]
+// CHECK:STDOUT:   %.loc4_8: %Base.elem = field_decl b, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc4_3: %Base.elem = var_pattern %.loc4_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Base.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.b.0a3 [template = constants.%complete_type.ba8]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -140,7 +144,11 @@ class Derived {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc8: %Derived.elem.69e = base_decl %Base.ref, element0 [template]
-// CHECK:STDOUT:   %.loc10: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   %.loc10_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.f8f [template = constants.%complete_type.da6]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -176,14 +184,14 @@ class Derived {
 // CHECK:STDOUT: fn @Access(%d.param_patt: %Derived) -> %return.param_patt: %tuple.type.d07 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %d.ref.loc18_11: %Derived = name_ref d, %d
-// CHECK:STDOUT:   %d.ref.loc18_12: %Derived.elem.344 = name_ref d, @Derived.%.loc10 [template = @Derived.%.loc10]
+// CHECK:STDOUT:   %d.ref.loc18_12: %Derived.elem.344 = name_ref d, @Derived.%.loc10_8 [template = @Derived.%.loc10_8]
 // CHECK:STDOUT:   %.loc18_12.1: ref %i32 = class_element_access %d.ref.loc18_11, element1
 // CHECK:STDOUT:   %.loc18_12.2: %i32 = bind_value %.loc18_12.1
 // CHECK:STDOUT:   %d.ref.loc18_16: %Derived = name_ref d, %d
 // CHECK:STDOUT:   %base.ref: %Derived.elem.69e = name_ref base, @Derived.%.loc8 [template = @Derived.%.loc8]
 // CHECK:STDOUT:   %.loc18_17.1: ref %Base = class_element_access %d.ref.loc18_16, element0
 // CHECK:STDOUT:   %.loc18_17.2: %Base = bind_value %.loc18_17.1
-// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc4 [template = @Base.%.loc4]
+// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc4_8 [template = @Base.%.loc4_8]
 // CHECK:STDOUT:   %.loc18_22.1: ref %i32 = class_element_access %.loc18_17.2, element0
 // CHECK:STDOUT:   %.loc18_22.2: %i32 = bind_value %.loc18_22.1
 // CHECK:STDOUT:   %.loc18_24.1: %tuple.type.d07 = tuple_literal (%.loc18_12.2, %.loc18_22.2)
@@ -235,7 +243,11 @@ class Derived {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %.loc7: %Derived.elem = field_decl d, element0 [template]
+// CHECK:STDOUT:   %.loc7_8: %Derived.elem = field_decl d, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc7_3: %Derived.elem = var_pattern %.loc7_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Derived.elem = var <invalid>
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.d [template = constants.%complete_type.860]
 // CHECK:STDOUT:   complete_type_witness = %complete_type

+ 26 - 6
toolchain/check/testdata/class/base_field.carbon

@@ -84,9 +84,21 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc12: %Base.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc13: %Base.elem = field_decl b, element1 [template]
-// CHECK:STDOUT:   %.loc14: %Base.elem = field_decl c, element2 [template]
+// CHECK:STDOUT:   %.loc12_8: %Base.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.loc13_8: %Base.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc13_3: %Base.elem = var_pattern %.loc13_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.loc14_8: %Base.elem = field_decl c, element2 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc14_3: %Base.elem = var_pattern %.loc14_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.c [template = constants.%complete_type.ebc]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -94,8 +106,16 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc18: %Derived.elem.69e = base_decl %Base.ref, element0 [template]
-// CHECK:STDOUT:   %.loc20: %Derived.elem.344 = field_decl d, element1 [template]
-// CHECK:STDOUT:   %.loc21: %Derived.elem.344 = field_decl e, element2 [template]
+// CHECK:STDOUT:   %.loc20_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc20_3: %Derived.elem.344 = var_pattern %.loc20_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.loc21_8: %Derived.elem.344 = field_decl e, element2 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc21_3: %Derived.elem.344 = var_pattern %.loc21_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.e.6a7 [template = constants.%complete_type.401]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -104,7 +124,7 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: %ptr.404 = name_ref p, %p
 // CHECK:STDOUT:   %.loc25_12: ref %Derived = deref %p.ref
-// CHECK:STDOUT:   %c.ref: %Base.elem = name_ref c, @Base.%.loc14 [template = @Base.%.loc14]
+// CHECK:STDOUT:   %c.ref: %Base.elem = name_ref c, @Base.%.loc14_8 [template = @Base.%.loc14_8]
 // CHECK:STDOUT:   %.loc25_15.1: ref %Base = class_element_access %.loc25_12, element0
 // CHECK:STDOUT:   %.loc25_15.2: ref %Base = converted %.loc25_12, %.loc25_15.1
 // CHECK:STDOUT:   %.loc25_15.3: ref %i32 = class_element_access %.loc25_15.2, element2

+ 6 - 2
toolchain/check/testdata/class/base_method.carbon

@@ -101,7 +101,11 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc12: %Base.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: %Base.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Base.elem = var <invalid>
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {
 // CHECK:STDOUT:     %self.patt: %ptr.11f = binding_pattern self
 // CHECK:STDOUT:     %self.param_patt: %ptr.11f = value_param_pattern %self.patt, runtime_param0
@@ -129,7 +133,7 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %self.ref: %ptr.11f = name_ref self, %self.loc17
 // CHECK:STDOUT:   %.loc18_4: ref %Base = deref %self.ref
-// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc12 [template = @Base.%.loc12]
+// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc12_8 [template = @Base.%.loc12_8]
 // CHECK:STDOUT:   %.loc18_10: ref %i32 = class_element_access %.loc18_4, element0
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %impl.elem0: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]

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

@@ -133,7 +133,11 @@ fn Run() -> i32 {
 // CHECK:STDOUT:     %return.param.loc16: ref %i32 = out_param runtime_param1
 // CHECK:STDOUT:     %return.loc16: ref %i32 = return_slot %return.param.loc16
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc18: %Class.elem = field_decl k, element0 [template]
+// CHECK:STDOUT:   %.loc18_8: %Class.elem = field_decl k, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc18_3: %Class.elem = var_pattern %.loc18_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Class.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.k [template = constants.%complete_type.954]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 6 - 2
toolchain/check/testdata/class/complete_in_member_fn.carbon

@@ -59,7 +59,11 @@ class C {
 // CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param1
 // CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc14: %C.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc14_8: %C.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc14_3: %C.elem = var_pattern %.loc14_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %C.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -67,7 +71,7 @@ class C {
 // CHECK:STDOUT: fn @F(%c.param_patt: %C) -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %c.ref: %C = name_ref c, %c
-// CHECK:STDOUT:   %a.ref: %C.elem = name_ref a, @C.%.loc14 [template = @C.%.loc14]
+// CHECK:STDOUT:   %a.ref: %C.elem = name_ref a, @C.%.loc14_8 [template = @C.%.loc14_8]
 // CHECK:STDOUT:   %.loc12_31.1: ref %i32 = class_element_access %c.ref, element0
 // CHECK:STDOUT:   %.loc12_31.2: %i32 = bind_value %.loc12_31.1
 // CHECK:STDOUT:   return %.loc12_31.2

+ 29 - 9
toolchain/check/testdata/class/compound_field.carbon

@@ -151,9 +151,21 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %.loc12: %Base.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc13: %Base.elem = field_decl b, element1 [template]
-// CHECK:STDOUT:   %.loc14: %Base.elem = field_decl c, element2 [template]
+// CHECK:STDOUT:   %.loc12_8: %Base.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %Base.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc12: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.loc13_8: %Base.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc13_3: %Base.elem = var_pattern %.loc13_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc13: ref %Base.elem = var <invalid>
+// CHECK:STDOUT:   %.loc14_8: %Base.elem = field_decl c, element2 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc14_3: %Base.elem = var_pattern %.loc14_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc14: ref %Base.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.c [template = constants.%complete_type.ebc]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -161,8 +173,16 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc18: %Derived.elem.69e = base_decl %Base.ref, element0 [template]
-// CHECK:STDOUT:   %.loc20: %Derived.elem.344 = field_decl d, element1 [template]
-// CHECK:STDOUT:   %.loc21: %Derived.elem.344 = field_decl e, element2 [template]
+// CHECK:STDOUT:   %.loc20_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc20_3: %Derived.elem.344 = var_pattern %.loc20_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc20: ref %Derived.elem.344 = var <invalid>
+// CHECK:STDOUT:   %.loc21_8: %Derived.elem.344 = field_decl e, element2 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc21_3: %Derived.elem.344 = var_pattern %.loc21_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc21: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.e.6a7 [template = constants.%complete_type.401]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -171,7 +191,7 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %d.ref.loc25_10: %Derived = name_ref d, %d
 // CHECK:STDOUT:   %Derived.ref.loc25: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived]
-// CHECK:STDOUT:   %d.ref.loc25_20: %Derived.elem.344 = name_ref d, @Derived.%.loc20 [template = @Derived.%.loc20]
+// CHECK:STDOUT:   %d.ref.loc25_20: %Derived.elem.344 = name_ref d, @Derived.%.loc20_8 [template = @Derived.%.loc20_8]
 // CHECK:STDOUT:   %.loc25_11.1: ref %i32 = class_element_access %d.ref.loc25_10, element1
 // CHECK:STDOUT:   %.loc25_11.2: %i32 = bind_value %.loc25_11.1
 // CHECK:STDOUT:   return %.loc25_11.2
@@ -181,7 +201,7 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %d.ref: %Derived = name_ref d, %d
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
-// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc13 [template = @Base.%.loc13]
+// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc13_8 [template = @Base.%.loc13_8]
 // CHECK:STDOUT:   %.loc29_11.1: ref %Base = class_element_access %d.ref, element0
 // CHECK:STDOUT:   %.loc29_11.2: ref %Base = converted %d.ref, %.loc29_11.1
 // CHECK:STDOUT:   %.loc29_11.3: ref %i32 = class_element_access %.loc29_11.2, element1
@@ -193,7 +213,7 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: %ptr.404 = name_ref p, %p
 // CHECK:STDOUT:   %Derived.ref.loc33: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived]
-// CHECK:STDOUT:   %d.ref: %Derived.elem.344 = name_ref d, @Derived.%.loc20 [template = @Derived.%.loc20]
+// CHECK:STDOUT:   %d.ref: %Derived.elem.344 = name_ref d, @Derived.%.loc20_8 [template = @Derived.%.loc20_8]
 // CHECK:STDOUT:   %.loc33_12.1: ref %Derived = deref %p.ref
 // CHECK:STDOUT:   %.loc33_12.2: ref %i32 = class_element_access %.loc33_12.1, element1
 // CHECK:STDOUT:   %addr: %ptr.235 = addr_of %.loc33_12.2
@@ -204,7 +224,7 @@ fn AccessBaseIndirect(p: Derived*) -> i32* {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: %ptr.404 = name_ref p, %p
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
-// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc13 [template = @Base.%.loc13]
+// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc13_8 [template = @Base.%.loc13_8]
 // CHECK:STDOUT:   %.loc37_12.1: ref %Derived = deref %p.ref
 // CHECK:STDOUT:   %.loc37_12.2: ref %Base = class_element_access %.loc37_12.1, element0
 // CHECK:STDOUT:   %.loc37_12.3: ref %Base = converted %.loc37_12.1, %.loc37_12.2

+ 44 - 7
toolchain/check/testdata/class/cross_package_import.carbon

@@ -199,6 +199,7 @@ var c: Other.C = {};
 // CHECK:STDOUT:     .C = %import_ref.3b0
 // CHECK:STDOUT:     import Other//other_define
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.3b0: type = import_ref Other//other_define, C, loaded [template = constants.%C]
 // CHECK:STDOUT:   %import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [template = constants.%complete_type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -210,7 +211,15 @@ var c: Other.C = {};
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Other.import = import Other
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:     %.loc6_1: %C = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C = var c
+// CHECK:STDOUT:   %.loc6_13: type = splice_block %C.ref [template = constants.%C] {
+// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [template = imports.%Other]
+// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%import_ref.3b0 [template = constants.%C]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -222,14 +231,15 @@ var c: Other.C = {};
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc6_19.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc6_19.2: init %C = class_init (), file.%c.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc6_20: init %C = converted %.loc6_19.1, %.loc6_19.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%c.var, %.loc6_20
+// CHECK:STDOUT:   %.loc6_1: init %C = converted %.loc6_19.1, %.loc6_19.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%c.var, %.loc6_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_extern.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %C: type = class_type @C [template]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -242,6 +252,7 @@ var c: Other.C = {};
 // CHECK:STDOUT:     .C = %import_ref
 // CHECK:STDOUT:     import Other//other_extern
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref: type = import_ref Other//other_extern, C, loaded [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -252,8 +263,16 @@ var c: Other.C = {};
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Other.import = import Other
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: <error> = binding_pattern c
+// CHECK:STDOUT:     %.loc14_1: <error> = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref <error> = var c
-// CHECK:STDOUT:   %c: ref <error> = bind_name c, %c.var
+// CHECK:STDOUT:   %.loc14_13: type = splice_block %C.ref [template = constants.%C] {
+// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [template = imports.%Other]
+// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%import_ref [template = constants.%C]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %c: <error> = bind_name c, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C [from "other_extern.carbon"];
@@ -284,6 +303,7 @@ var c: Other.C = {};
 // CHECK:STDOUT:     import Other//other_define
 // CHECK:STDOUT:     import Other//other_extern
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.3b0: type = import_ref Other//other_define, C, loaded [template = constants.%C]
 // CHECK:STDOUT:   %import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [template = constants.%complete_type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -295,7 +315,15 @@ var c: Other.C = {};
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Other.import = import Other
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:     %.loc19_1: %C = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C = var c
+// CHECK:STDOUT:   %.loc19_13: type = splice_block %C.ref [template = constants.%C] {
+// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [template = imports.%Other]
+// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%import_ref.3b0 [template = constants.%C]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -307,8 +335,8 @@ var c: Other.C = {};
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc19_19.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc19_19.2: init %C = class_init (), file.%c.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc19_20: init %C = converted %.loc19_19.1, %.loc19_19.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%c.var, %.loc19_20
+// CHECK:STDOUT:   %.loc19_1: init %C = converted %.loc19_19.1, %.loc19_19.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%c.var, %.loc19_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -331,6 +359,7 @@ var c: Other.C = {};
 // CHECK:STDOUT:     import Other//other_define
 // CHECK:STDOUT:     import Other//other_conflict
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %import_ref.3b0: type = import_ref Other//other_define, C, loaded [template = constants.%C]
 // CHECK:STDOUT:   %import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [template = constants.%complete_type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -342,7 +371,15 @@ var c: Other.C = {};
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Other.import = import Other
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %C = binding_pattern c
+// CHECK:STDOUT:     %.loc19_1: %C = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %C = var c
+// CHECK:STDOUT:   %.loc19_13: type = splice_block %C.ref [template = constants.%C] {
+// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [template = imports.%Other]
+// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%import_ref.3b0 [template = constants.%C]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -354,8 +391,8 @@ var c: Other.C = {};
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc19_19.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %.loc19_19.2: init %C = class_init (), file.%c.var [template = constants.%C.val]
-// CHECK:STDOUT:   %.loc19_20: init %C = converted %.loc19_19.1, %.loc19_19.2 [template = constants.%C.val]
-// CHECK:STDOUT:   assign file.%c.var, %.loc19_20
+// CHECK:STDOUT:   %.loc19_1: init %C = converted %.loc19_19.1, %.loc19_19.2 [template = constants.%C.val]
+// CHECK:STDOUT:   assign file.%c.var, %.loc19_1
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 32 - 14
toolchain/check/testdata/class/derived_to_base.carbon

@@ -202,7 +202,11 @@ fn ConvertInit() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc12: %A.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: %A.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %A.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.ba9 [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -210,7 +214,11 @@ fn ConvertInit() {
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc16: %B.elem.e38 = base_decl %A.ref, element0 [template]
-// CHECK:STDOUT:   %.loc17: %B.elem.5c3 = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc17_8: %B.elem.5c3 = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc17_3: %B.elem.5c3 = var_pattern %.loc17_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %B.elem.5c3 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.b.b44 [template = constants.%complete_type.725]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -218,7 +226,11 @@ fn ConvertInit() {
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %.loc21: %C.elem.f0c = base_decl %B.ref, element0 [template]
-// CHECK:STDOUT:   %.loc22: %C.elem.646 = field_decl c, element1 [template]
+// CHECK:STDOUT:   %.loc22_8: %C.elem.646 = field_decl c, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc22_3: %C.elem.646 = var_pattern %.loc22_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %C.elem.646 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.c.8e2 [template = constants.%complete_type.58a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -256,12 +268,15 @@ fn ConvertInit() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @ConvertValue(%c.param_patt: %C) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %A = binding_pattern a
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.ref: %C = name_ref c, %c
-// CHECK:STDOUT:   %.loc30_15.1: ref %B = class_element_access %c.ref, element0
-// CHECK:STDOUT:   %.loc30_15.2: ref %A = class_element_access %.loc30_15.1, element0
-// CHECK:STDOUT:   %.loc30_15.3: ref %A = converted %c.ref, %.loc30_15.2
-// CHECK:STDOUT:   %.loc30_15.4: %A = bind_value %.loc30_15.3
-// CHECK:STDOUT:   %a: %A = bind_name a, %.loc30_15.4
+// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:   %.loc30_14.1: ref %B = class_element_access %c.ref, element0
+// CHECK:STDOUT:   %.loc30_14.2: ref %A = class_element_access %.loc30_14.1, element0
+// CHECK:STDOUT:   %.loc30_14.3: ref %A = converted %c.ref, %.loc30_14.2
+// CHECK:STDOUT:   %a: ref %A = bind_name a, %.loc30_14.3
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -279,6 +294,9 @@ fn ConvertInit() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @ConvertInit() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %A = binding_pattern a
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %.loc38_39.1: %struct_type.a.a6c = struct_literal (%int_1)
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
@@ -316,12 +334,12 @@ fn ConvertInit() {
 // CHECK:STDOUT:   %.loc38_57.7: init %i32 = initialize_from %.loc38_57.5 to %.loc38_57.6 [template = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc38_57.8: init %C = class_init (%.loc38_57.4, %.loc38_57.7), %.loc38_57.2 [template = constants.%C.val]
 // CHECK:STDOUT:   %.loc38_57.9: ref %C = temporary %.loc38_57.2, %.loc38_57.8
-// CHECK:STDOUT:   %.loc38_59: ref %C = converted %.loc38_57.1, %.loc38_57.9
-// CHECK:STDOUT:   %.loc38_63.1: ref %B = class_element_access %.loc38_59, element0
-// CHECK:STDOUT:   %.loc38_63.2: ref %A = class_element_access %.loc38_63.1, element0
-// CHECK:STDOUT:   %.loc38_63.3: ref %A = converted %.loc38_59, %.loc38_63.2
-// CHECK:STDOUT:   %.loc38_63.4: %A = bind_value %.loc38_63.3
-// CHECK:STDOUT:   %a: %A = bind_name a, %.loc38_63.4
+// CHECK:STDOUT:   %.loc38_59.1: ref %C = converted %.loc38_57.1, %.loc38_57.9
+// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:   %.loc38_59.2: ref %B = class_element_access %.loc38_59.1, element0
+// CHECK:STDOUT:   %.loc38_59.3: ref %A = class_element_access %.loc38_59.2, element0
+// CHECK:STDOUT:   %.loc38_59.4: ref %A = converted %.loc38_59.1, %.loc38_59.3
+// CHECK:STDOUT:   %a: ref %A = bind_name a, %.loc38_59.4
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 41 - 8
toolchain/check/testdata/class/fail_abstract.carbon

@@ -16,7 +16,7 @@ abstract class Abstract {
 }
 
 class Contains {
-  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE+7]]:10: error: field has abstract type `Abstract` [AbstractTypeInVarDecl]
+  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE+7]]:10: error: field has abstract type `Abstract` [AbstractTypeInFieldDecl]
   // CHECK:STDERR:   var a: Abstract;
   // CHECK:STDERR:          ^~~~~~~~
   // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE-7]]:1: note: class was declared abstract here [ClassAbstractHere]
@@ -222,7 +222,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Contains {
-// CHECK:STDOUT:   %.loc15: <error> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc15_8: <error> = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc15_3: <error> = var_pattern %.loc15_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -262,8 +266,13 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Var() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %v.patt: <error> = binding_pattern v
+// CHECK:STDOUT:     %.loc15: <error> = var_pattern %v.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref <error> = var v
-// CHECK:STDOUT:   %v: ref <error> = bind_name v, %v.var
+// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
+// CHECK:STDOUT:   %v: <error> = bind_name v, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -297,7 +306,7 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:     %a.param_patt: %Abstract = value_param_pattern %a.patt, runtime_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %a.param: %Abstract = value_param runtime_param0
-// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
+// CHECK:STDOUT:     %Abstract.ref.loc7: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:     %a: %Abstract = bind_name a, %a.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -309,7 +318,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%a.param_patt: %Abstract) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %l.patt: %Abstract = binding_pattern l
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.ref: %Abstract = name_ref a, %a
+// CHECK:STDOUT:   %Abstract.ref.loc8: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:   %l: %Abstract = bind_name l, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -472,7 +485,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:   %.loc8: %Derived.elem.513 = base_decl %Abstract.ref, element0 [template]
-// CHECK:STDOUT:   %.loc10: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   %.loc10_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.c44 [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -544,7 +561,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:   %.loc8: %Derived.elem.513 = base_decl %Abstract.ref, element0 [template]
-// CHECK:STDOUT:   %.loc10: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   %.loc10_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc10_3: %Derived.elem.344 = var_pattern %.loc10_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -608,7 +629,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Abstract {
-// CHECK:STDOUT:   %.loc5: %Abstract.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc5_8: %Abstract.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %Abstract.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Abstract.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -616,7 +641,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:   %.loc9: %Derived.elem.513 = base_decl %Abstract.ref, element0 [template]
-// CHECK:STDOUT:   %.loc11: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   %.loc11_8: %Derived.elem.344 = field_decl d, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc11_3: %Derived.elem.344 = var_pattern %.loc11_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Derived.elem.344 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.d.c44 [template = constants.%complete_type.32a]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -665,7 +694,11 @@ fn CallReturnAbstract() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %l.patt: %Abstract = binding_pattern l
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc8: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [template = constants.%Abstract]
 // CHECK:STDOUT:   %l: %Abstract = bind_name l, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 6 - 2
toolchain/check/testdata/class/fail_base_bad_type.carbon

@@ -796,7 +796,11 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Final {
-// CHECK:STDOUT:   %.loc5: %Final.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc5_8: %Final.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc5_3: %Final.elem = var_pattern %.loc5_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %Final.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -822,7 +826,7 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %p.ref: %ptr.160 = name_ref p, %p
 // CHECK:STDOUT:   %.loc22_11: ref %DeriveFromFinal = deref %p.ref
-// CHECK:STDOUT:   %a.ref: %Final.elem = name_ref a, @Final.%.loc5 [template = @Final.%.loc5]
+// CHECK:STDOUT:   %a.ref: %Final.elem = name_ref a, @Final.%.loc5_8 [template = @Final.%.loc5_8]
 // CHECK:STDOUT:   %.loc22_14.1: ref %Final = class_element_access %.loc22_11, element0
 // CHECK:STDOUT:   %.loc22_14.2: ref %Final = converted %.loc22_11, %.loc22_14.1
 // CHECK:STDOUT:   %.loc22_14.3: ref %i32 = class_element_access %.loc22_14.2, element0

+ 6 - 2
toolchain/check/testdata/class/fail_base_unbound.carbon

@@ -44,11 +44,16 @@ let b: B = C.base;
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:     .C = %C.decl
-// CHECK:STDOUT:     .b = @__global_init.%b
+// CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %B.decl: type = class_decl @B [template = constants.%B] {} {}
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [template = constants.%C] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %B = binding_pattern b
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:   %b: %B = bind_name b, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
@@ -67,7 +72,6 @@ let b: B = C.base;
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
 // CHECK:STDOUT:   %base.ref: %C.elem = name_ref base, @C.%.loc14 [template = @C.%.loc14]
-// CHECK:STDOUT:   %b: %B = bind_name b, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 11 - 3
toolchain/check/testdata/class/fail_compound_type_mismatch.carbon

@@ -80,13 +80,21 @@ fn AccessBInA(a: A) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %.loc12: %A.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: %A.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %A.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %.loc16: %B.elem = field_decl b, element0 [template]
+// CHECK:STDOUT:   %.loc16_8: %B.elem = field_decl b, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc16_3: %B.elem = var_pattern %.loc16_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %B.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.b [template = constants.%complete_type.ba8]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -95,7 +103,7 @@ fn AccessBInA(a: A) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: %A = name_ref a, %a
 // CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
-// CHECK:STDOUT:   %b.ref: %B.elem = name_ref b, @B.%.loc16 [template = @B.%.loc16]
+// CHECK:STDOUT:   %b.ref: %B.elem = name_ref b, @B.%.loc16_8 [template = @B.%.loc16_8]
 // CHECK:STDOUT:   %.loc27_11.1: %B = converted %a.ref, <error> [template = <error>]
 // CHECK:STDOUT:   %.loc27_11.2: %i32 = class_element_access <error>, element0 [template = <error>]
 // CHECK:STDOUT:   return <error>

+ 5 - 1
toolchain/check/testdata/class/fail_convert_to_invalid.carbon

@@ -56,7 +56,11 @@ fn Make() -> C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc16: <error> = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc16_8: <error> = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc16_3: <error> = var_pattern %.loc16_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 15 - 3
toolchain/check/testdata/class/fail_derived_to_base.carbon

@@ -129,13 +129,21 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A1 {
-// CHECK:STDOUT:   %.loc12: %A1.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: %A1.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %A1.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A1.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A2 {
-// CHECK:STDOUT:   %.loc16: %A2.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc16_8: %A2.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc16_3: %A2.elem = var_pattern %.loc16_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %A2.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [template = constants.%complete_type.fd7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -143,7 +151,11 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT: class @B2 {
 // CHECK:STDOUT:   %A2.ref: type = name_ref A2, file.%A2.decl [template = constants.%A2]
 // CHECK:STDOUT:   %.loc20: %B2.elem.a92 = base_decl %A2.ref, element0 [template]
-// CHECK:STDOUT:   %.loc21: %B2.elem.4b2 = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc21_8: %B2.elem.4b2 = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc21_3: %B2.elem.4b2 = var_pattern %.loc21_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %B2.elem.4b2 = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base.b.618 [template = constants.%complete_type.92f]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 5 - 1
toolchain/check/testdata/class/fail_extend_cycle.carbon

@@ -80,7 +80,11 @@ base class A {
 // CHECK:STDOUT: class @.1 {
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc27: %.elem = base_decl %A.ref, element0 [template]
-// CHECK:STDOUT:   %.loc32: <error> = field_decl c, element1 [template]
+// CHECK:STDOUT:   %.loc32_8: <error> = field_decl c, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc32_3: <error> = var_pattern %.loc32_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 30 - 8
toolchain/check/testdata/class/fail_field_modifiers.carbon

@@ -77,24 +77,46 @@ class Class {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc17: %Class.elem = field_decl j, element0 [template]
-// CHECK:STDOUT:   %.loc23: %Class.elem = field_decl k, element1 [template]
+// CHECK:STDOUT:   %.loc17_16: %Class.elem = field_decl j, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc17_11: %Class.elem = var_pattern %.loc17_16
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc17: ref %Class.elem = var <invalid>
+// CHECK:STDOUT:   %.loc23_14: %Class.elem = field_decl k, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc23_9: %Class.elem = var_pattern %.loc23_14
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc23: ref %Class.elem = var <invalid>
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %l.patt: %i32 = binding_pattern l
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [template = constants.%int_0.5c6]
+// CHECK:STDOUT:   %.loc29_18: type = splice_block %i32.loc29 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc29: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc29: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc29: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc29: <bound method> = bound_method %int_0, %impl.elem0.loc29 [template = constants.%Convert.bound.d04]
 // CHECK:STDOUT:   %Convert.specific_fn.loc29: <specific function> = specific_function %Convert.bound.loc29, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.d62]
 // CHECK:STDOUT:   %int.convert_checked.loc29: init %i32 = call %Convert.specific_fn.loc29(%int_0) [template = constants.%int_0.6a9]
-// CHECK:STDOUT:   %.loc29_25.1: %i32 = value_of_initializer %int.convert_checked.loc29 [template = constants.%int_0.6a9]
-// CHECK:STDOUT:   %.loc29_25.2: %i32 = converted %int_0, %.loc29_25.1 [template = constants.%int_0.6a9]
-// CHECK:STDOUT:   %l: %i32 = bind_name l, %.loc29_25.2
+// CHECK:STDOUT:   %.loc29_24.1: %i32 = value_of_initializer %int.convert_checked.loc29 [template = constants.%int_0.6a9]
+// CHECK:STDOUT:   %.loc29_24.2: %i32 = converted %int_0, %.loc29_24.1 [template = constants.%int_0.6a9]
+// CHECK:STDOUT:   %l: %i32 = bind_name l, %.loc29_24.2
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
+// CHECK:STDOUT:   %.loc35_16: type = splice_block %i32.loc35 [template = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc35: Core.IntLiteral = int_value 32 [template = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc35: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %impl.elem0.loc35: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc35: <bound method> = bound_method %int_1, %impl.elem0.loc35 [template = constants.%Convert.bound.ab5]
 // CHECK:STDOUT:   %Convert.specific_fn.loc35: <specific function> = specific_function %Convert.bound.loc35, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
 // CHECK:STDOUT:   %int.convert_checked.loc35: init %i32 = call %Convert.specific_fn.loc35(%int_1) [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc35_23.1: %i32 = value_of_initializer %int.convert_checked.loc35 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc35_23.2: %i32 = converted %int_1, %.loc35_23.1 [template = constants.%int_1.5d2]
-// CHECK:STDOUT:   %m: %i32 = bind_name m, %.loc35_23.2
+// CHECK:STDOUT:   %.loc35_22.1: %i32 = value_of_initializer %int.convert_checked.loc35 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc35_22.2: %i32 = converted %int_1, %.loc35_22.1 [template = constants.%int_1.5d2]
+// CHECK:STDOUT:   %m: %i32 = bind_name m, %.loc35_22.2
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.j.k [template = constants.%complete_type.cf7]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 5 - 1
toolchain/check/testdata/class/fail_generic_method.carbon

@@ -110,7 +110,11 @@ fn Class(N:! i32).F[self: Self](n: T) {}
 // CHECK:STDOUT:   %complete_type.loc14_1.2: <witness> = complete_type_witness @Class.%struct_type.a (%struct_type.a) [symbolic = %complete_type.loc14_1.2 (constants.%complete_type.f1b)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
-// CHECK:STDOUT:     %.loc12: @Class.%Class.elem (%Class.elem) = field_decl a, element0 [template]
+// CHECK:STDOUT:     %.loc12_8: @Class.%Class.elem (%Class.elem) = field_decl a, element0 [template]
+// CHECK:STDOUT:     name_binding_decl {
+// CHECK:STDOUT:       %.loc12_3: @Class.%Class.elem (%Class.elem) = var_pattern %.loc12_8
+// CHECK:STDOUT:     }
+// CHECK:STDOUT:     %.var: ref @Class.%Class.elem (%Class.elem) = var <invalid>
 // CHECK:STDOUT:     %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = @Class.%F (constants.%F)] {
 // CHECK:STDOUT:       %self.patt: @F.%Class (%Class) = binding_pattern self
 // CHECK:STDOUT:       %self.param_patt: @F.%Class (%Class) = value_param_pattern %self.patt, runtime_param0

+ 6 - 1
toolchain/check/testdata/class/fail_import_misuses.carbon

@@ -108,8 +108,13 @@ var a: Incomplete;
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
 // CHECK:STDOUT:   %.decl: type = class_decl @.1 [template = constants.%.a95] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: <error> = binding_pattern a
+// CHECK:STDOUT:     %.loc25: <error> = var_pattern %a.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a.var: ref <error> = var a
-// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, imports.%import_ref.9b0 [template = constants.%Incomplete]
+// CHECK:STDOUT:   %a: <error> = bind_name a, <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Empty [from "a.carbon"] {

+ 17 - 4
toolchain/check/testdata/class/fail_incomplete.carbon

@@ -164,7 +164,7 @@ fn CallIncompleteAddrSelf(p: Class*) {
 library "[[@TEST_NAME]]";
 
 class C {
-  // CHECK:STDERR: fail_in_definition.carbon:[[@LINE+7]]:10: error: field has incomplete type `C` [IncompleteTypeInVarDecl]
+  // CHECK:STDERR: fail_in_definition.carbon:[[@LINE+7]]:10: error: field has incomplete type `C` [IncompleteTypeInFieldDecl]
   // CHECK:STDERR:   var c: C;
   // CHECK:STDERR:          ^
   // CHECK:STDERR: fail_in_definition.carbon:[[@LINE-4]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition]
@@ -243,8 +243,13 @@ class C {
 // CHECK:STDOUT:   %Class.decl: type = class_decl @Class [template = constants.%Class] {} {}
 // CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {} {}
 // CHECK:STDOUT:   %CallClassFunction.decl: %CallClassFunction.type = fn_decl @CallClassFunction [template = constants.%CallClassFunction] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %global_var.patt: <error> = binding_pattern global_var
+// CHECK:STDOUT:     %.loc33: <error> = var_pattern %global_var.patt
+// CHECK:STDOUT:   }
 // 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:   %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:   %global_var: <error> = bind_name global_var, <error>
 // CHECK:STDOUT:   %ConvertFromStruct.decl: %ConvertFromStruct.type = fn_decl @ConvertFromStruct [template = constants.%ConvertFromStruct] {
 // CHECK:STDOUT:     %return.patt: %Class = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %Class = out_param_pattern %return.patt, runtime_param0
@@ -309,7 +314,7 @@ class C {
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %p.param: %ptr.e71 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc77: type = splice_block %ptr [template = constants.%ptr.e71] {
-// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:       %Class.ref.loc77: type = name_ref Class, file.%Class.decl [template = constants.%Class]
 // CHECK:STDOUT:       %ptr: type = ptr_type %Class [template = constants.%ptr.e71]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %p: %ptr.e71 = bind_name p, %p.param
@@ -416,8 +421,12 @@ class C {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Let(%p.param_patt: %ptr.e71) {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: <error> = binding_pattern c
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %p.ref: %ptr.e71 = name_ref p, %p
 // CHECK:STDOUT:   %.loc85: ref %Class = deref %p.ref
+// CHECK:STDOUT:   %Class.ref.loc85: type = name_ref Class, file.%Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %c: <error> = bind_name c, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -482,7 +491,11 @@ class C {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %.loc12: <error> = field_decl c, element0 [template]
+// CHECK:STDOUT:   %.loc12_8: <error> = field_decl c, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: <error> = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref <error> = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [template = <error>]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 10 - 2
toolchain/check/testdata/class/fail_init.carbon

@@ -78,8 +78,16 @@ fn F() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc12: %Class.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc13: %Class.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc12_8: %Class.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %Class.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc12: ref %Class.elem = var <invalid>
+// CHECK:STDOUT:   %.loc13_8: %Class.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc13_3: %Class.elem = var_pattern %.loc13_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc13: ref %Class.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }

+ 17 - 4
toolchain/check/testdata/class/fail_init_as_inplace.carbon

@@ -91,8 +91,16 @@ fn F() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %.loc12: %Class.elem = field_decl a, element0 [template]
-// CHECK:STDOUT:   %.loc13: %Class.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   %.loc12_8: %Class.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc12_3: %Class.elem = var_pattern %.loc12_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc12: ref %Class.elem = var <invalid>
+// CHECK:STDOUT:   %.loc13_8: %Class.elem = field_decl b, element1 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc13_3: %Class.elem = var_pattern %.loc13_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var.loc13: ref %Class.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.b.501 [template = constants.%complete_type.705]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -101,12 +109,15 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %c.patt: %Class = binding_pattern c
+// CHECK:STDOUT:     %.loc26_3: %Class = var_pattern %c.patt
+// CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c.var: ref %Class = var c
-// CHECK:STDOUT:   %c: ref %Class = bind_name c, %c.var
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [template = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [template = constants.%int_2.ecc]
 // CHECK:STDOUT:   %.loc26_33.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc26_38: type = name_ref Class, file.%Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %impl.elem0.loc26_33.1: %Convert.type.1b6 = impl_witness_access constants.%impl_witness.d39, element0 [template = constants.%Convert.956]
 // CHECK:STDOUT:   %Convert.bound.loc26_33.1: <bound method> = bound_method %int_1, %impl.elem0.loc26_33.1 [template = constants.%Convert.bound.ab5]
 // CHECK:STDOUT:   %Convert.specific_fn.loc26_33.1: <specific function> = specific_function %Convert.bound.loc26_33.1, @Convert.2(constants.%int_32) [template = constants.%Convert.specific_fn.70c]
@@ -127,6 +138,8 @@ fn F() {
 // CHECK:STDOUT:   %.loc26_35.1: ref %Class = converted %.loc26_33.1, %.loc26_33.10
 // CHECK:STDOUT:   %.loc26_35.2: %Class = bind_value %.loc26_35.1
 // CHECK:STDOUT:   assign %c.var, <error>
+// CHECK:STDOUT:   %Class.ref.loc26_10: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:   %c: ref %Class = bind_name c, %c.var
 // CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [template = constants.%G]
 // CHECK:STDOUT:   %c.ref: ref %Class = name_ref c, %c
 // CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %c.ref

+ 6 - 2
toolchain/check/testdata/class/fail_memaccess_category.carbon

@@ -110,7 +110,11 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %.loc16: %B.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   %.loc16_8: %B.elem = field_decl a, element0 [template]
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %.loc16_3: %B.elem = var_pattern %.loc16_8
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.var: ref %B.elem = var <invalid>
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a.72c [template = constants.%complete_type.2b9]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
@@ -125,7 +129,7 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT:   %F.bound.loc28: <bound method> = bound_method %.loc28, %F.ref.loc28
 // CHECK:STDOUT:   %F.call.loc28: init %empty_tuple.type = call %F.bound.loc28(<error>)
 // CHECK:STDOUT:   %b.ref: %B = name_ref b, %b
-// CHECK:STDOUT:   %a.ref: %B.elem = name_ref a, @B.%.loc16 [template = @B.%.loc16]
+// CHECK:STDOUT:   %a.ref: %B.elem = name_ref a, @B.%.loc16_8 [template = @B.%.loc16_8]
 // CHECK:STDOUT:   %.loc39_4.1: ref %A = class_element_access %b.ref, element0
 // CHECK:STDOUT:   %.loc39_4.2: %A = bind_value %.loc39_4.1
 // CHECK:STDOUT:   %F.ref.loc39: %F.type.649 = name_ref F, @A.%F.decl [template = constants.%F.485]

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

@@ -52,10 +52,14 @@ fn T.F() {}
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
 // CHECK:STDOUT:     .Class = %Class.decl
-// CHECK:STDOUT:     .T = @__global_init.%T
+// CHECK:STDOUT:     .T = %T
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Class.decl: type = class_decl @Class [template = constants.%Class] {} {}
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %T.patt: type = binding_pattern T
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %T: type = bind_name T, @__global_init.%Class.ref
 // CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -83,7 +87,6 @@ fn T.F() {}
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
-// CHECK:STDOUT:   %T: type = bind_name T, %Class.ref
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini