Explorar o código

Rewrite symbolic constants in generic redeclarations (#5154)

When a generic function declaration was encountered for the second or
more time, we would FinishGenericRedecl() for the function decl, but
this just popped the generic region stack and moved on.

The issue with that is when the stack entry is gone, we lose the
symbolic constants from that declaration, and are unable to rewrite them
to point to the actual generic. This left us with a function declaration
with abstract symbolic values that were not useful, and in a function
call we use the declaration attached to the definition, which would be a
declaration with broken symbolic values. Then the function would be
uncallable since deduce would be unable to determine argument types
without the generic bindings.

This resolves the issue for functions, as well as ensuring the correct
generic id from a previous declaration is used for other generic entity
types that have redeclarations.

When a function declaration is qualified, such as defining a class
method outside the class body, we need only the function declaration to
contribute to its generic region stack. The code was collecting constant
values from all qualifier segments together incorrectly.

So when we PushNameQualifierScope(), we also drop the current generic
region stack and rewrite its constant values by calling
FinishGenericRedecl(), and open a new stack entry for the next part of
the qualified declaration.

If a generic declaration somehow has more dependent instruction than a
previous declaration, it would add new instructions to its eval block
with indices beyond the elements in the actual declaration eval block,
since we only store the block from the first declaration found. To avoid
this we plumb through that we are in a redeclaration, and terminate with
an ICE instead of adding new instructions to crash on later.

Fixes #5136.
Dana Jansens hai 1 ano
pai
achega
6dbcc78e6c
Modificáronse 23 ficheiros con 317 adicións e 242 borrados
  1. 25 15
      toolchain/check/decl_name_stack.cpp
  2. 1 1
      toolchain/check/decl_name_stack.h
  3. 69 30
      toolchain/check/generic.cpp
  4. 1 2
      toolchain/check/generic.h
  5. 3 1
      toolchain/check/handle_class.cpp
  6. 3 1
      toolchain/check/handle_function.cpp
  7. 3 2
      toolchain/check/handle_impl.cpp
  8. 3 3
      toolchain/check/handle_interface.cpp
  9. 2 2
      toolchain/check/testdata/class/generic/import.carbon
  10. 54 54
      toolchain/check/testdata/class/generic/member_out_of_line.carbon
  11. 3 3
      toolchain/check/testdata/class/generic/redeclare.carbon
  12. 18 18
      toolchain/check/testdata/class/generic_method.carbon
  13. 18 18
      toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon
  14. 3 3
      toolchain/check/testdata/class/syntactic_merge_literal.carbon
  15. 1 1
      toolchain/check/testdata/function/call/prefer_unqualified_lookup.carbon
  16. 12 12
      toolchain/check/testdata/function/generic/redeclare.carbon
  17. 18 18
      toolchain/check/testdata/function/generic/undefined.carbon
  18. 24 0
      toolchain/check/testdata/generic/forward_decl.carbon
  19. 16 16
      toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon
  20. 3 3
      toolchain/check/testdata/impl/no_prelude/import_generic.carbon
  21. 27 27
      toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon
  22. 6 8
      toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon
  23. 4 4
      toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon

+ 25 - 15
toolchain/check/decl_name_stack.cpp

@@ -209,18 +209,30 @@ auto DeclNameStack::LookupOrAddName(NameContext name_context,
 static auto PushNameQualifierScope(Context& context, SemIRLoc loc,
                                    SemIR::InstId scope_inst_id,
                                    SemIR::NameScopeId scope_id,
-                                   SemIR::SpecificId specific_id,
+                                   SemIR::GenericId generic_id,
                                    bool has_error = false) -> void {
   // If the qualifier has no parameters, we don't need to keep around a
   // parameter scope.
   context.scope_stack().PopIfEmpty();
 
-  // When declaring a member of a generic, resolve the self specific.
-  if (specific_id.has_value()) {
-    ResolveSpecificDefinition(context, loc, specific_id);
+  auto self_specific_id = SemIR::SpecificId::None;
+  if (generic_id.has_value()) {
+    self_specific_id = context.generics().GetSelfSpecific(generic_id);
+    // When declaring a member of a generic, resolve the self specific.
+    ResolveSpecificDefinition(context, loc, self_specific_id);
   }
 
-  context.scope_stack().Push(scope_inst_id, scope_id, specific_id, has_error);
+  // Close the generic stack scope and open a new one for whatever comes after
+  // the qualifier. As this is a qualifier it must not be the initial
+  // declaration of the entity, so we treat it as a redeclaration.
+  FinishGenericRedecl(context, generic_id);
+  // What follows the qualifier will be a declaration. The signature of an
+  // entity is also a declaration even if it is followed by curly braces
+  // providing the definition.
+  StartGenericDecl(context);
+
+  context.scope_stack().Push(scope_inst_id, scope_id, self_specific_id,
+                             has_error);
 
   // An interface also introduces its 'Self' parameter into scope, despite it
   // not being redeclared as part of the qualifier.
@@ -241,10 +253,10 @@ auto DeclNameStack::ApplyNameQualifier(const NameComponent& name) -> void {
   name_context.has_qualifiers = true;
 
   // Resolve the qualifier as a scope and enter the new scope.
-  auto [scope_id, specific_id] = ResolveAsScope(name_context, name);
+  auto [scope_id, generic_id] = ResolveAsScope(name_context, name);
   if (scope_id.has_value()) {
     PushNameQualifierScope(*context_, name_context.loc_id,
-                           name_context.resolved_inst_id, scope_id, specific_id,
+                           name_context.resolved_inst_id, scope_id, generic_id,
                            context_->name_scopes().Get(scope_id).has_error());
     name_context.parent_scope_id = scope_id;
   } else {
@@ -374,9 +386,9 @@ static auto DiagnoseQualifiedDeclInNonScope(Context& context, SemIRLoc use_loc,
 
 auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
                                    const NameComponent& name) const
-    -> std::pair<SemIR::NameScopeId, SemIR::SpecificId> {
-  constexpr std::pair<SemIR::NameScopeId, SemIR::SpecificId> InvalidResult = {
-      SemIR::NameScopeId::None, SemIR::SpecificId::None};
+    -> std::pair<SemIR::NameScopeId, SemIR::GenericId> {
+  constexpr std::pair<SemIR::NameScopeId, SemIR::GenericId> InvalidResult = {
+      SemIR::NameScopeId::None, SemIR::GenericId::None};
 
   if (!CheckQualifierIsResolved(*context_, name_context)) {
     return InvalidResult;
@@ -406,8 +418,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
             *context_, name_context.loc_id, class_decl.class_id);
         return InvalidResult;
       }
-      return {class_info.scope_id,
-              context_->generics().GetSelfSpecific(class_info.generic_id)};
+      return {class_info.scope_id, class_info.generic_id};
     }
     case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
       const auto& interface_info =
@@ -422,8 +433,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
             name_context.resolved_inst_id);
         return InvalidResult;
       }
-      return {interface_info.scope_id,
-              context_->generics().GetSelfSpecific(interface_info.generic_id)};
+      return {interface_info.scope_id, interface_info.generic_id};
     }
     case CARBON_KIND(SemIR::Namespace resolved_inst): {
       auto scope_id = resolved_inst.name_scope_id;
@@ -443,7 +453,7 @@ auto DeclNameStack::ResolveAsScope(const NameContext& name_context,
         // be used as a name qualifier.
         scope.set_is_closed_import(false);
       }
-      return {scope_id, SemIR::SpecificId::None};
+      return {scope_id, SemIR::GenericId::None};
     }
     default: {
       DiagnoseQualifiedDeclInNonScope(*context_, name_context.loc_id,

+ 1 - 1
toolchain/check/decl_name_stack.h

@@ -273,7 +273,7 @@ class DeclNameStack {
   // the name doesn't resolve to a scope.
   auto ResolveAsScope(const NameContext& name_context,
                       const NameComponent& name) const
-      -> std::pair<SemIR::NameScopeId, SemIR::SpecificId>;
+      -> std::pair<SemIR::NameScopeId, SemIR::GenericId>;
 
   // The linked context.
   Context* context_;

+ 69 - 30
toolchain/check/generic.cpp

@@ -6,12 +6,14 @@
 
 #include "common/map.h"
 #include "toolchain/base/kind_switch.h"
+#include "toolchain/check/diagnostic_helpers.h"
 #include "toolchain/check/eval.h"
 #include "toolchain/check/generic_region_stack.h"
 #include "toolchain/check/inst.h"
 #include "toolchain/check/subst.h"
 #include "toolchain/check/type.h"
 #include "toolchain/check/type_completion.h"
+#include "toolchain/diagnostics/diagnostic.h"
 #include "toolchain/sem_ir/constant.h"
 #include "toolchain/sem_ir/generic.h"
 #include "toolchain/sem_ir/ids.h"
@@ -74,12 +76,13 @@ class RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {
   RebuildGenericConstantInEvalBlockCallbacks(
       Context& context, SemIR::GenericId generic_id,
       SemIR::GenericInstIndex::Region region, SemIR::LocId loc_id,
-      ConstantsInGenericMap& constants_in_generic)
+      ConstantsInGenericMap& constants_in_generic, bool inside_redeclaration)
       : context_(context),
         generic_id_(generic_id),
         region_(region),
         loc_id_(loc_id),
-        constants_in_generic_(constants_in_generic) {}
+        constants_in_generic_(constants_in_generic),
+        inside_redeclaration_(inside_redeclaration) {}
 
   auto context() const -> Context& { return context_; }
 
@@ -149,6 +152,16 @@ class RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {
     // We might already have an instruction in the eval block if a transitive
     // operand of this instruction has the same constant value.
     auto result = constants_in_generic_.Insert(const_inst_id, [&] {
+      if (inside_redeclaration_) {
+        // Adding instructions to a redeclaration causes crashes later since it
+        // causes us to produce invalid indices into the original declaration's
+        // set of instructions. So we terminate now and avoid adding a new
+        // instruction and new index. It should not be possible to create this
+        // situation where a generic redeclaration introduces new instructions
+        // to the eval block.
+        CARBON_FATAL("generic redeclaration differs from previous declaration");
+      }
+
       // TODO: Add a function on `Context` to add the instruction without
       // inserting it into the dependent instructions list or computing a
       // constant value for it.
@@ -170,6 +183,7 @@ class RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {
   SemIR::GenericInstIndex::Region region_;
   SemIR::LocId loc_id_;
   ConstantsInGenericMap& constants_in_generic_;
+  bool inside_redeclaration_;
 };
 
 // Substitution callbacks to rebuild a template action. This rebuilds the action
@@ -180,9 +194,11 @@ class RebuildTemplateActionInEvalBlockCallbacks final
   RebuildTemplateActionInEvalBlockCallbacks(
       Context& context, SemIR::GenericId generic_id,
       SemIR::GenericInstIndex::Region region, SemIR::LocId loc_id,
-      ConstantsInGenericMap& constants_in_generic, SemIR::InstId action_inst_id)
-      : RebuildGenericConstantInEvalBlockCallbacks(
-            context, generic_id, region, loc_id, constants_in_generic),
+      ConstantsInGenericMap& constants_in_generic, bool inside_redeclaration,
+      SemIR::InstId action_inst_id)
+      : RebuildGenericConstantInEvalBlockCallbacks(context, generic_id, region,
+                                                   loc_id, constants_in_generic,
+                                                   inside_redeclaration),
         action_inst_id_(action_inst_id) {}
 
   auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst) const
@@ -209,14 +225,15 @@ class RebuildTemplateActionInEvalBlockCallbacks final
 static auto AddGenericTypeToEvalBlock(
     Context& context, SemIR::GenericId generic_id,
     SemIR::GenericInstIndex::Region region, SemIR::LocId loc_id,
-    ConstantsInGenericMap& constants_in_generic, SemIR::TypeId type_id)
-    -> SemIR::TypeId {
+    ConstantsInGenericMap& constants_in_generic, bool inside_redeclaration,
+    SemIR::TypeId type_id) -> SemIR::TypeId {
   // Substitute into the type's constant instruction and rebuild it in the eval
   // block.
   auto type_inst_id =
       SubstInst(context, context.types().GetInstId(type_id),
                 RebuildGenericConstantInEvalBlockCallbacks(
-                    context, generic_id, region, loc_id, constants_in_generic));
+                    context, generic_id, region, loc_id, constants_in_generic,
+                    inside_redeclaration));
   return context.types().GetTypeIdForTypeInstId(type_inst_id);
 }
 
@@ -227,14 +244,14 @@ static auto AddGenericTypeToEvalBlock(
 static auto AddGenericConstantToEvalBlock(
     Context& context, SemIR::GenericId generic_id,
     SemIR::GenericInstIndex::Region region,
-    ConstantsInGenericMap& constants_in_generic, SemIR::InstId inst_id)
-    -> SemIR::ConstantId {
+    ConstantsInGenericMap& constants_in_generic, bool inside_redeclaration,
+    SemIR::InstId inst_id) -> SemIR::ConstantId {
   // Substitute into the constant value and rebuild it in the eval block if
   // we've not encountered it before.
   auto const_inst_id = context.constant_values().GetConstantInstId(inst_id);
   auto callbacks = RebuildGenericConstantInEvalBlockCallbacks(
       context, generic_id, region, context.insts().GetLocId(inst_id),
-      constants_in_generic);
+      constants_in_generic, inside_redeclaration);
   auto new_inst_id = SubstInst(context, const_inst_id, callbacks);
   if (new_inst_id == const_inst_id) {
     // It's possible that no substitutions were necessary in this instruction.
@@ -255,14 +272,14 @@ static auto AddGenericConstantToEvalBlock(
 static auto AddTemplateActionToEvalBlock(
     Context& context, SemIR::GenericId generic_id,
     SemIR::GenericInstIndex::Region region,
-    ConstantsInGenericMap& constants_in_generic, SemIR::InstId inst_id)
-    -> void {
+    ConstantsInGenericMap& constants_in_generic, bool inside_redeclaration,
+    SemIR::InstId inst_id) -> void {
   // Substitute into the constant value and rebuild it in the eval block.
   auto new_inst_id = SubstInst(
       context, inst_id,
       RebuildTemplateActionInEvalBlockCallbacks(
           context, generic_id, region, context.insts().GetLocId(inst_id),
-          constants_in_generic, inst_id));
+          constants_in_generic, inside_redeclaration, inst_id));
   CARBON_CHECK(new_inst_id == inst_id,
                "Substitution changed InstId of template action");
   constants_in_generic.Insert(inst_id, inst_id);
@@ -298,14 +315,15 @@ static auto PopulateConstantsFromDeclaration(
 // Builds and returns a block of instructions whose constant values need to be
 // evaluated in order to resolve a generic to a specific.
 static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
-                                 SemIR::GenericInstIndex::Region region)
+                                 SemIR::GenericInstIndex::Region region,
+                                 bool inside_redeclaration)
     -> SemIR::InstBlockId {
   context.inst_block_stack().Push();
 
   ConstantsInGenericMap constants_in_generic;
 
-  // For the definition region, populate constants from the declaration.
-  if (region == SemIR::GenericInstIndex::Region::Definition) {
+  if (region == SemIR::GenericInstIndex::Region::Definition ||
+      inside_redeclaration) {
     PopulateConstantsFromDeclaration(context, generic_id, constants_in_generic);
   }
 
@@ -324,7 +342,11 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
       auto inst = context.insts().Get(inst_id);
       auto type_id = AddGenericTypeToEvalBlock(
           context, generic_id, region, context.insts().GetLocId(inst_id),
-          constants_in_generic, inst.type_id());
+          constants_in_generic, inside_redeclaration, inst.type_id());
+      // If the generic declaration is invalid, it can result in an error.
+      if (type_id == SemIR::ErrorInst::SingletonTypeId) {
+        break;
+      }
       // TODO: Eventually, completeness requirements should be modeled as
       // constraints on the generic rather than properties of the type. For now,
       // require the transformed type to be complete if the original was.
@@ -343,9 +365,9 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
         GenericRegionStack::DependencyKind::None) {
       // Update the constant value to refer to this generic.
       context.constant_values().Set(
-          inst_id,
-          AddGenericConstantToEvalBlock(context, generic_id, region,
-                                        constants_in_generic, inst_id));
+          inst_id, AddGenericConstantToEvalBlock(
+                       context, generic_id, region, constants_in_generic,
+                       inside_redeclaration, inst_id));
     }
 
     // If the instruction is a template action, add it directly to this position
@@ -353,7 +375,8 @@ static auto MakeGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
     if ((dep_kind & GenericRegionStack::DependencyKind::Template) !=
         GenericRegionStack::DependencyKind::None) {
       AddTemplateActionToEvalBlock(context, generic_id, region,
-                                   constants_in_generic, inst_id);
+                                   constants_in_generic, inside_redeclaration,
+                                   inst_id);
     }
   }
 
@@ -377,10 +400,15 @@ auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
     -> SemIR::InstBlockId {
   context.inst_block_stack().Push();
 
+  // We say we are not inside a redeclaration since this function is used for
+  // import and there's no redeclaration there.
+  bool inside_redeclaration = false;
+
   ConstantsInGenericMap constants_in_generic;
 
   // For the definition region, populate constants from the declaration.
-  if (region == SemIR::GenericInstIndex::Region::Definition) {
+  if (inside_redeclaration ||
+      region == SemIR::GenericInstIndex::Region::Definition) {
     PopulateConstantsFromDeclaration(context, generic_id, constants_in_generic);
   }
 
@@ -388,7 +416,8 @@ auto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,
   for (auto [i, inst_id] : llvm::enumerate(const_ids)) {
     // Build a constant in the inst block.
     AddGenericConstantToEvalBlock(context, generic_id, region,
-                                  constants_in_generic, inst_id);
+                                  constants_in_generic, inside_redeclaration,
+                                  inst_id);
     CARBON_CHECK(
         context.inst_block_stack().PeekCurrentBlockContents().size() == i + 1,
         "Produced {0} instructions when importing {1}",
@@ -443,7 +472,8 @@ auto FinishGenericDecl(Context& context, SemIRLoc loc,
     return;
   }
   auto decl_block_id = MakeGenericEvalBlock(
-      context, generic_id, SemIR::GenericInstIndex::Region::Declaration);
+      context, generic_id, SemIR::GenericInstIndex::Region::Declaration,
+      /*inside_redeclaration=*/false);
   context.generic_region_stack().Pop();
   context.generics().Get(generic_id).decl_block_id = decl_block_id;
 
@@ -460,10 +490,18 @@ auto BuildGenericDecl(Context& context, SemIR::InstId decl_id)
   return generic_id;
 }
 
-auto FinishGenericRedecl(Context& context, SemIR::InstId /*decl_id*/,
-                         SemIR::GenericId /*generic_id*/) -> void {
-  // TODO: Compare contents of this declaration with the existing one on the
-  // generic.
+auto FinishGenericRedecl(Context& context, SemIR::GenericId generic_id)
+    -> void {
+  if (!generic_id.has_value()) {
+    context.generic_region_stack().Pop();
+    return;
+  }
+
+  auto definition_block_id = MakeGenericEvalBlock(
+      context, generic_id, SemIR::GenericInstIndex::Region::Declaration,
+      /*inside_redeclaration=*/true);
+  CARBON_CHECK(definition_block_id == SemIR::InstBlockId::Empty);
+
   context.generic_region_stack().Pop();
 }
 
@@ -479,7 +517,8 @@ auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)
   }
 
   auto definition_block_id = MakeGenericEvalBlock(
-      context, generic_id, SemIR::GenericInstIndex::Region::Definition);
+      context, generic_id, SemIR::GenericInstIndex::Region::Definition,
+      /*inside_redeclaration=*/false);
   context.generics().Get(generic_id).definition_block_id = definition_block_id;
 
   context.generic_region_stack().Pop();

+ 1 - 2
toolchain/check/generic.h

@@ -38,8 +38,7 @@ auto BuildGenericDecl(Context& context, SemIR::InstId decl_id)
 
 // Merge a redeclaration of an entity that might be a generic into the original
 // declaration.
-auto FinishGenericRedecl(Context& context, SemIR::InstId decl_id,
-                         SemIR::GenericId generic_id) -> void;
+auto FinishGenericRedecl(Context& context, SemIR::GenericId generic_id) -> void;
 
 // Finish processing a potentially generic definition.
 auto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)

+ 3 - 1
toolchain/check/handle_class.cpp

@@ -251,7 +251,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
           context, class_decl.class_id, context.scope_stack().PeekSpecificId());
     }
   } else {
-    FinishGenericRedecl(context, class_decl_id, class_info.generic_id);
+    auto prev_decl_generic_id =
+        context.classes().Get(class_decl.class_id).generic_id;
+    FinishGenericRedecl(context, prev_decl_generic_id);
   }
 
   // Write the class ID into the ClassDecl.

+ 3 - 1
toolchain/check/handle_function.cpp

@@ -503,7 +503,9 @@ static auto BuildFunctionDecl(Context& context,
         GetFunctionType(context, function_decl.function_id,
                         context.scope_stack().PeekSpecificId());
   } else {
-    FinishGenericRedecl(context, decl_id, function_info.generic_id);
+    auto prev_decl_generic_id =
+        context.functions().Get(function_decl.function_id).generic_id;
+    FinishGenericRedecl(context, prev_decl_generic_id);
     // TODO: Validate that the redeclaration doesn't set an access modifier.
   }
 

+ 3 - 2
toolchain/check/handle_impl.cpp

@@ -429,8 +429,9 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
     impl_decl.impl_id = context.impls().Add(impl_info);
     lookup_bucket_ref.push_back(impl_decl.impl_id);
   } else {
-    const auto& first_impl = context.impls().Get(impl_decl.impl_id);
-    FinishGenericRedecl(context, impl_decl_id, first_impl.generic_id);
+    auto prev_decl_generic_id =
+        context.impls().Get(impl_decl.impl_id).generic_id;
+    FinishGenericRedecl(context, prev_decl_generic_id);
   }
 
   // Write the impl ID into the ImplDecl.

+ 3 - 3
toolchain/check/handle_interface.cpp

@@ -126,9 +126,9 @@ static auto BuildInterfaceDecl(Context& context,
                                   context.scope_stack().PeekSpecificId());
     }
   } else {
-    FinishGenericRedecl(
-        context, interface_decl_id,
-        context.interfaces().Get(interface_decl.interface_id).generic_id);
+    auto prev_decl_generic_id =
+        context.interfaces().Get(interface_decl.interface_id).generic_id;
+    FinishGenericRedecl(context, prev_decl_generic_id);
   }
 
   // Write the interface ID into the InterfaceDecl.

+ 2 - 2
toolchain/check/testdata/class/generic/import.carbon

@@ -317,9 +317,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %default.import.loc2_19.2 = import <none>
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {
-// CHECK:STDOUT:     %T.patt.loc4: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
+// CHECK:STDOUT:     %T.patt.loc4: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.1 (constants.%T.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc4: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
+// CHECK:STDOUT:     %T.loc4: type = bind_symbolic_name T, 0 [symbolic = %T.1 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl: %F.type.b25 = fn_decl @F.2 [concrete = constants.%F.c41] {
 // CHECK:STDOUT:     %return.patt: %CompleteClass.a06 = return_slot_pattern

+ 54 - 54
toolchain/check/testdata/class/generic/member_out_of_line.carbon

@@ -144,35 +144,35 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:     %T.loc4_13.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_13.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = constants.%F] {
-// CHECK:STDOUT:     %n.patt: %T = binding_pattern n
-// CHECK:STDOUT:     %n.param_patt: %T = value_param_pattern %n.patt, call_param0
-// CHECK:STDOUT:     %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     %n.patt: @F.%T.loc5 (%T) = binding_pattern n
+// CHECK:STDOUT:     %n.param_patt: @F.%T.loc5 (%T) = value_param_pattern %n.patt, call_param0
+// CHECK:STDOUT:     %return.patt: @F.%T.loc5 (%T) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.%T.loc5 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %T.ref.loc10_31: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %n.param.loc10: %T = value_param call_param0
-// CHECK:STDOUT:     %T.ref.loc10_25: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %n.loc10: %T = bind_name n, %n.param.loc10
-// CHECK:STDOUT:     %return.param.loc10: ref %T = out_param call_param1
-// CHECK:STDOUT:     %return.loc10: ref %T = return_slot %return.param.loc10
+// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = @Class.%T.loc4_13.2 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc10_31: type = name_ref T, %T.loc10 [symbolic = %T.loc5 (constants.%T)]
+// CHECK:STDOUT:     %n.param.loc10: @F.%T.loc5 (%T) = value_param call_param0
+// CHECK:STDOUT:     %T.ref.loc10_25: type = name_ref T, %T.loc10 [symbolic = %T.loc5 (constants.%T)]
+// CHECK:STDOUT:     %n.loc10: @F.%T.loc5 (%T) = bind_name n, %n.param.loc10
+// CHECK:STDOUT:     %return.param.loc10: ref @F.%T.loc5 (%T) = out_param call_param1
+// CHECK:STDOUT:     %return.loc10: ref @F.%T.loc5 (%T) = return_slot %return.param.loc10
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: @Class.%G.type (%G.type) = fn_decl @G [symbolic = constants.%G] {
-// CHECK:STDOUT:     %self.patt: %Class = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: %Class = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:     %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     %self.patt: @G.%Class (%Class) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @G.%Class (%Class) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:     %return.patt: @G.%T.loc6 (%T) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @G.%T.loc6 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc14: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %T.ref.loc14: type = name_ref T, %T.loc14 [symbolic = constants.%T]
-// CHECK:STDOUT:     %self.param.loc14: %Class = value_param call_param0
-// CHECK:STDOUT:     %.loc14_28.1: type = splice_block %Self.ref.loc14 [symbolic = constants.%Class] {
-// CHECK:STDOUT:       %.loc14_28.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = constants.%Class]
-// CHECK:STDOUT:       %Self.ref.loc14: type = name_ref Self, %.loc14_28.2 [symbolic = constants.%Class]
+// CHECK:STDOUT:     %T.loc14: type = bind_symbolic_name T, 0 [symbolic = @Class.%T.loc4_13.2 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc14: type = name_ref T, %T.loc14 [symbolic = %T.loc6 (constants.%T)]
+// CHECK:STDOUT:     %self.param.loc14: @G.%Class (%Class) = value_param call_param0
+// CHECK:STDOUT:     %.loc14_28.1: type = splice_block %Self.ref.loc14 [symbolic = %Class (constants.%Class)] {
+// CHECK:STDOUT:       %.loc14_28.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class (constants.%Class)]
+// CHECK:STDOUT:       %Self.ref.loc14: type = name_ref Self, %.loc14_28.2 [symbolic = %Class (constants.%Class)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %self.loc14: %Class = bind_name self, %self.param.loc14
-// CHECK:STDOUT:     %return.param.loc14: ref %T = out_param call_param1
-// CHECK:STDOUT:     %return.loc14: ref %T = return_slot %return.param.loc14
+// CHECK:STDOUT:     %self.loc14: @G.%Class (%Class) = bind_name self, %self.param.loc14
+// CHECK:STDOUT:     %return.param.loc14: ref @G.%T.loc6 (%T) = out_param call_param1
+// CHECK:STDOUT:     %return.loc14: ref @G.%T.loc6 (%T) = return_slot %return.param.loc14
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -193,10 +193,10 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
 // CHECK:STDOUT:     %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = @Class.%F (constants.%F)] {
-// CHECK:STDOUT:       %n.patt: %T = binding_pattern n
-// CHECK:STDOUT:       %n.param_patt: %T = value_param_pattern %n.patt, call_param0
-// CHECK:STDOUT:       %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:       %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:       %n.patt: @F.%T.loc5 (%T) = binding_pattern n
+// CHECK:STDOUT:       %n.param_patt: @F.%T.loc5 (%T) = value_param_pattern %n.patt, call_param0
+// CHECK:STDOUT:       %return.patt: @F.%T.loc5 (%T) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @F.%T.loc5 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %T.ref.loc5_17: type = name_ref T, @Class.%T.loc4_13.1 [symbolic = %T.loc5 (constants.%T)]
 // CHECK:STDOUT:       %n.param.loc5: @F.%T.loc5 (%T) = value_param call_param0
@@ -206,10 +206,10 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:       %return.loc5: ref @F.%T.loc5 (%T) = return_slot %return.param.loc5
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %G.decl: @Class.%G.type (%G.type) = fn_decl @G [symbolic = @Class.%G (constants.%G)] {
-// CHECK:STDOUT:       %self.patt: %Class = binding_pattern self
-// CHECK:STDOUT:       %self.param_patt: %Class = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:       %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:       %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:       %self.patt: @G.%Class (%Class) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @G.%Class (%Class) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %return.patt: @G.%T.loc6 (%T) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @G.%T.loc6 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %T.ref.loc6: type = name_ref T, @Class.%T.loc4_13.1 [symbolic = %T.loc6 (constants.%T)]
 // CHECK:STDOUT:       %self.param.loc6: @G.%Class (%Class) = value_param call_param0
@@ -244,7 +244,7 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @F.%T.loc5 (%T) [symbolic = %require_complete (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%n.param_patt: %T) -> %T {
+// CHECK:STDOUT:   fn(%n.param_patt: @F.%T.loc5 (%T)) -> @F.%T.loc5 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %n.ref: @F.%T.loc5 (%T) = name_ref n, %n.loc10
 // CHECK:STDOUT:     return %n.ref
@@ -260,7 +260,7 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:   %Class.elem: type = unbound_element_type @G.%Class (%Class), @G.%T.loc6 (%T) [symbolic = %Class.elem (constants.%Class.elem)]
 // CHECK:STDOUT:   %require_complete.loc15: <witness> = require_complete_type @G.%T.loc6 (%T) [symbolic = %require_complete.loc15 (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: %Class]() -> %T {
+// CHECK:STDOUT:   fn[%self.param_patt: @G.%Class (%Class)]() -> @G.%T.loc6 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @G.%Class (%Class) = name_ref self, %self.loc14
 // CHECK:STDOUT:     %n.ref: @G.%Class.elem (%Class.elem) = name_ref n, @Class.%.loc7_8 [concrete = @Class.%.loc7_8]
@@ -339,23 +339,23 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:     %T.loc4_9.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_9.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl: @B.%F.type (%F.type) = fn_decl @F [symbolic = constants.%F] {
-// CHECK:STDOUT:     %self.patt: %B = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: %B = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:     %a.patt: %T = binding_pattern a
-// CHECK:STDOUT:     %a.param_patt: %T = value_param_pattern %a.patt, call_param1
+// CHECK:STDOUT:     %self.patt: @F.%B (%B) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @F.%B (%B) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:     %a.patt: @F.%T.loc6 (%T) = binding_pattern a
+// CHECK:STDOUT:     %a.param_patt: @F.%T.loc6 (%T) = value_param_pattern %a.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %T.ref.loc10_22: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %N.loc10: %T = bind_symbolic_name N, 1 [symbolic = constants.%N]
-// CHECK:STDOUT:     %self.param.loc10: %B = value_param call_param0
-// CHECK:STDOUT:     %.loc10_33.1: type = splice_block %Self.ref.loc10 [symbolic = constants.%B] {
-// CHECK:STDOUT:       %.loc10_33.2: type = specific_constant constants.%B, @B(constants.%T, constants.%N) [symbolic = constants.%B]
-// CHECK:STDOUT:       %Self.ref.loc10: type = name_ref Self, %.loc10_33.2 [symbolic = constants.%B]
+// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = @A.%T.loc4_9.2 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc10_22: type = name_ref T, %T.loc10 [symbolic = @B.%T (constants.%T)]
+// CHECK:STDOUT:     %N.loc10: @B.%T (%T) = bind_symbolic_name N, 1 [symbolic = @B.%N.loc5_11.2 (constants.%N)]
+// CHECK:STDOUT:     %self.param.loc10: @F.%B (%B) = value_param call_param0
+// CHECK:STDOUT:     %.loc10_33.1: type = splice_block %Self.ref.loc10 [symbolic = %B (constants.%B)] {
+// CHECK:STDOUT:       %.loc10_33.2: type = specific_constant constants.%B, @B(constants.%T, constants.%N) [symbolic = %B (constants.%B)]
+// CHECK:STDOUT:       %Self.ref.loc10: type = name_ref Self, %.loc10_33.2 [symbolic = %B (constants.%B)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %self.loc10: %B = bind_name self, %self.param.loc10
-// CHECK:STDOUT:     %a.param.loc10: %T = value_param call_param1
-// CHECK:STDOUT:     %T.ref.loc10_42: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %a.loc10: %T = bind_name a, %a.param.loc10
+// CHECK:STDOUT:     %self.loc10: @F.%B (%B) = bind_name self, %self.param.loc10
+// CHECK:STDOUT:     %a.param.loc10: @F.%T.loc6 (%T) = value_param call_param1
+// CHECK:STDOUT:     %T.ref.loc10_42: type = name_ref T, %T.loc10 [symbolic = %T.loc6 (constants.%T)]
+// CHECK:STDOUT:     %a.loc10: @F.%T.loc6 (%T) = bind_name a, %a.param.loc10
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -395,10 +395,10 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
 // CHECK:STDOUT:     %F.decl: @B.%F.type (%F.type) = fn_decl @F [symbolic = @B.%F (constants.%F)] {
-// CHECK:STDOUT:       %self.patt: %B = binding_pattern self
-// CHECK:STDOUT:       %self.param_patt: %B = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:       %a.patt: %T = binding_pattern a
-// CHECK:STDOUT:       %a.param_patt: %T = value_param_pattern %a.patt, call_param1
+// CHECK:STDOUT:       %self.patt: @F.%B (%B) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @F.%B (%B) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %a.patt: @F.%T.loc6 (%T) = binding_pattern a
+// CHECK:STDOUT:       %a.param_patt: @F.%T.loc6 (%T) = value_param_pattern %a.patt, call_param1
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %self.param.loc6: @F.%B (%B) = value_param call_param0
 // CHECK:STDOUT:       %.loc6_16.1: type = splice_block %Self.ref.loc6 [symbolic = %B (constants.%B)] {
@@ -429,7 +429,7 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:   %require_complete.loc10_31: <witness> = require_complete_type @F.%B (%B) [symbolic = %require_complete.loc10_31 (constants.%require_complete.fca)]
 // CHECK:STDOUT:   %require_complete.loc10_40: <witness> = require_complete_type @F.%T.loc6 (%T) [symbolic = %require_complete.loc10_40 (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: %B](%a.param_patt: %T) {
+// CHECK:STDOUT:   fn[%self.param_patt: @F.%B (%B)](%a.param_patt: @F.%T.loc6 (%T)) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }

+ 3 - 3
toolchain/check/testdata/class/generic/redeclare.carbon

@@ -113,14 +113,14 @@ class E(U:! type) {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Generic.decl.loc4: %Generic.type = class_decl @Generic [concrete = constants.%Generic.generic] {
-// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
+// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.loc4_15.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_15.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Generic.decl.loc6: %Generic.type = class_decl @Generic [concrete = constants.%Generic.generic] {
-// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
+// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc6: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
+// CHECK:STDOUT:     %T.loc6: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_15.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 18 - 18
toolchain/check/testdata/class/generic_method.carbon

@@ -51,21 +51,21 @@ fn Class(T:! type).F[self: Self](n: T) {}
 // CHECK:STDOUT:     %T.loc11_13.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc11_13.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = constants.%F] {
-// CHECK:STDOUT:     %self.patt: %Class = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: %Class = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:     %n.patt: %T = binding_pattern n
-// CHECK:STDOUT:     %n.param_patt: %T = value_param_pattern %n.patt, call_param1
+// CHECK:STDOUT:     %self.patt: @F.%Class (%Class) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @F.%Class (%Class) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:     %n.patt: @F.%T.loc13 (%T) = binding_pattern n
+// CHECK:STDOUT:     %n.param_patt: @F.%T.loc13 (%T) = value_param_pattern %n.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc16: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %self.param.loc16: %Class = value_param call_param0
-// CHECK:STDOUT:     %.loc16_28.1: type = splice_block %Self.ref.loc16 [symbolic = constants.%Class] {
-// CHECK:STDOUT:       %.loc16_28.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = constants.%Class]
-// CHECK:STDOUT:       %Self.ref.loc16: type = name_ref Self, %.loc16_28.2 [symbolic = constants.%Class]
+// CHECK:STDOUT:     %T.loc16: type = bind_symbolic_name T, 0 [symbolic = @Class.%T.loc11_13.2 (constants.%T)]
+// CHECK:STDOUT:     %self.param.loc16: @F.%Class (%Class) = value_param call_param0
+// CHECK:STDOUT:     %.loc16_28.1: type = splice_block %Self.ref.loc16 [symbolic = %Class (constants.%Class)] {
+// CHECK:STDOUT:       %.loc16_28.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class (constants.%Class)]
+// CHECK:STDOUT:       %Self.ref.loc16: type = name_ref Self, %.loc16_28.2 [symbolic = %Class (constants.%Class)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %self.loc16: %Class = bind_name self, %self.param.loc16
-// CHECK:STDOUT:     %n.param.loc16: %T = value_param call_param1
-// CHECK:STDOUT:     %T.ref.loc16: type = name_ref T, %T.loc16 [symbolic = constants.%T]
-// CHECK:STDOUT:     %n.loc16: %T = bind_name n, %n.param.loc16
+// CHECK:STDOUT:     %self.loc16: @F.%Class (%Class) = bind_name self, %self.param.loc16
+// CHECK:STDOUT:     %n.param.loc16: @F.%T.loc13 (%T) = value_param call_param1
+// CHECK:STDOUT:     %T.ref.loc16: type = name_ref T, %T.loc16 [symbolic = %T.loc13 (constants.%T)]
+// CHECK:STDOUT:     %n.loc16: @F.%T.loc13 (%T) = bind_name n, %n.param.loc16
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -89,10 +89,10 @@ fn Class(T:! type).F[self: Self](n: T) {}
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %.var: ref @Class.%Class.elem (%Class.elem) = var <none>
 // CHECK:STDOUT:     %F.decl: @Class.%F.type (%F.type) = fn_decl @F [symbolic = @Class.%F (constants.%F)] {
-// CHECK:STDOUT:       %self.patt: %Class = binding_pattern self
-// CHECK:STDOUT:       %self.param_patt: %Class = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:       %n.patt: %T = binding_pattern n
-// CHECK:STDOUT:       %n.param_patt: %T = value_param_pattern %n.patt, call_param1
+// CHECK:STDOUT:       %self.patt: @F.%Class (%Class) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @F.%Class (%Class) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %n.patt: @F.%T.loc13 (%T) = binding_pattern n
+// CHECK:STDOUT:       %n.param_patt: @F.%T.loc13 (%T) = value_param_pattern %n.patt, call_param1
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %self.param.loc13: @F.%Class (%Class) = value_param call_param0
 // CHECK:STDOUT:       %.loc13_14.1: type = splice_block %Self.ref.loc13 [symbolic = %Class (constants.%Class)] {
@@ -123,7 +123,7 @@ fn Class(T:! type).F[self: Self](n: T) {}
 // CHECK:STDOUT:   %require_complete.loc16_26: <witness> = require_complete_type @F.%Class (%Class) [symbolic = %require_complete.loc16_26 (constants.%require_complete.4f8)]
 // CHECK:STDOUT:   %require_complete.loc16_35: <witness> = require_complete_type @F.%T.loc13 (%T) [symbolic = %require_complete.loc16_35 (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: %Class](%n.param_patt: %T) {
+// CHECK:STDOUT:   fn[%self.param_patt: @F.%Class (%Class)](%n.param_patt: @F.%T.loc13 (%T)) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }

+ 18 - 18
toolchain/check/testdata/class/no_prelude/syntactic_merge.carbon

@@ -207,28 +207,28 @@ fn Base.F[addr self: Base*]() {
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %D: type = bind_alias D, %C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc8: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc8: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc7 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:     %a.loc7_11.1: %C = bind_symbolic_name a, 0 [symbolic = %a.loc7_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Foo.decl.loc8: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc8: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc8: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc7 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc8: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc8: %C = bind_symbolic_name a, 0 [symbolic = %a.loc7_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Bar.decl.loc10: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {
-// CHECK:STDOUT:     %a.patt.loc11: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc11: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc10 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %D.ref.loc10: type = name_ref D, file.%D [concrete = constants.%C]
 // CHECK:STDOUT:     %a.loc10_11.1: %C = bind_symbolic_name a, 0 [symbolic = %a.loc10_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Bar.decl.loc11: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {
-// CHECK:STDOUT:     %a.patt.loc11: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc11: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc10 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %D.ref.loc11: type = name_ref D, file.%D [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc11: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc11: %C = bind_symbolic_name a, 0 [symbolic = %a.loc10_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -300,16 +300,16 @@ fn Base.F[addr self: Base*]() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:     %a.loc6_17.1: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_17.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_17.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -436,16 +436,16 @@ fn Base.F[addr self: Base*]() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:     %a.loc6_11.1: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc7: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_11.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -582,16 +582,16 @@ fn Base.F[addr self: Base*]() {
 // CHECK:STDOUT:   %default.import.loc2_24.1 = import <none>
 // CHECK:STDOUT:   %default.import.loc2_24.2 = import <none>
 // CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc4: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc4: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.1 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc4: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc4: %C = bind_symbolic_name a, 0 [symbolic = %a.1 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Bar.decl: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {
-// CHECK:STDOUT:     %a.patt.loc5: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc5: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.1 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc5: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc5: %C = bind_symbolic_name a, 0 [symbolic = %a.1 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -955,10 +955,10 @@ fn Base.F[addr self: Base*]() {
 // CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]
 // CHECK:STDOUT:   %D: type = bind_alias D, imports.%Main.C [concrete = constants.%C]
 // CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {
-// CHECK:STDOUT:     %a.patt.loc6: %C = symbolic_binding_pattern a, 0 [symbolic = constants.%a.patt]
+// CHECK:STDOUT:     %a.patt.loc6: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.1 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc6: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc6: %C = bind_symbolic_name a, 0 [symbolic = %a.1 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/class/syntactic_merge_literal.carbon

@@ -89,7 +89,7 @@ class D(b:! C(1_000)) {}
 // CHECK:STDOUT:     %a.loc4_9.1: %i32 = bind_symbolic_name a, 0 [symbolic = %a.loc4_9.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %D.decl.loc5: %D.type = class_decl @D [concrete = constants.%D.generic] {
-// CHECK:STDOUT:     %b.patt.loc6: %C.262 = symbolic_binding_pattern b, 0 [symbolic = constants.%b.patt]
+// CHECK:STDOUT:     %b.patt.loc6: %C.262 = symbolic_binding_pattern b, 0 [symbolic = %b.patt.loc5 (constants.%b.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %.loc5_20.1: type = splice_block %C.loc5 [concrete = constants.%C.262] {
 // CHECK:STDOUT:       %C.ref.loc5: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
@@ -106,7 +106,7 @@ class D(b:! C(1_000)) {}
 // CHECK:STDOUT:     %b.loc5_9.1: %C.262 = bind_symbolic_name b, 0 [symbolic = %b.loc5_9.2 (constants.%b)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %D.decl.loc6: %D.type = class_decl @D [concrete = constants.%D.generic] {
-// CHECK:STDOUT:     %b.patt.loc6: %C.262 = symbolic_binding_pattern b, 0 [symbolic = constants.%b.patt]
+// CHECK:STDOUT:     %b.patt.loc6: %C.262 = symbolic_binding_pattern b, 0 [symbolic = %b.patt.loc5 (constants.%b.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %.loc6_20.1: type = splice_block %C.loc6 [concrete = constants.%C.262] {
 // CHECK:STDOUT:       %C.ref.loc6: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
@@ -120,7 +120,7 @@ class D(b:! C(1_000)) {}
 // CHECK:STDOUT:       %.loc6_20.3: %i32 = converted %int_1000.loc6, %.loc6_20.2 [concrete = constants.%int_1000.1b6]
 // CHECK:STDOUT:       %C.loc6: type = class_type @C, @C(constants.%int_1000.1b6) [concrete = constants.%C.262]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %b.loc6: %C.262 = bind_symbolic_name b, 0 [symbolic = constants.%b]
+// CHECK:STDOUT:     %b.loc6: %C.262 = bind_symbolic_name b, 0 [symbolic = %b.loc5_9.2 (constants.%b)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/function/call/prefer_unqualified_lookup.carbon

@@ -80,7 +80,7 @@ fn Class(F:! type).Inner.G() -> i32 { return F(); }
 // CHECK:STDOUT:     %return.patt: %i32 = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: %i32 = out_param_pattern %return.patt, call_param0
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %F.loc13_10: type = bind_symbolic_name F, 0 [symbolic = constants.%F.8b3]
+// CHECK:STDOUT:     %F.loc13_10: type = bind_symbolic_name F, 0 [symbolic = @Class.%F.loc5_13.2 (constants.%F.8b3)]
 // CHECK:STDOUT:     %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc13: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:     %return.param.loc13: ref %i32 = out_param call_param0

+ 12 - 12
toolchain/check/testdata/function/generic/redeclare.carbon

@@ -116,9 +116,9 @@ fn F(U:! type, T:! type) -> U* {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {
-// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
-// CHECK:STDOUT:     %return.patt: %ptr = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %ptr = out_param_pattern %return.patt, call_param0
+// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
+// CHECK:STDOUT:     %return.patt: @F.%ptr.loc4_20.2 (%ptr) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.%ptr.loc4_20.2 (%ptr) = out_param_pattern %return.patt, call_param0
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref.loc4: type = name_ref T, %T.loc4_6.1 [symbolic = %T.loc4_6.2 (constants.%T)]
 // CHECK:STDOUT:     %ptr.loc4_20.1: type = ptr_type %T [symbolic = %ptr.loc4_20.2 (constants.%ptr)]
@@ -127,15 +127,15 @@ fn F(U:! type, T:! type) -> U* {
 // CHECK:STDOUT:     %return.loc4: ref @F.%ptr.loc4_20.2 (%ptr) = return_slot %return.param.loc4
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %F.decl.loc6: %F.type = fn_decl @F [concrete = constants.%F] {
-// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
-// CHECK:STDOUT:     %return.patt: %ptr = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %ptr = out_param_pattern %return.patt, call_param0
+// CHECK:STDOUT:     %T.patt.loc6: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
+// CHECK:STDOUT:     %return.patt: @F.%ptr.loc4_20.2 (%ptr) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.%ptr.loc4_20.2 (%ptr) = out_param_pattern %return.patt, call_param0
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc6: type = name_ref T, %T.loc6 [symbolic = constants.%T]
-// CHECK:STDOUT:     %ptr.loc6: type = ptr_type %T [symbolic = constants.%ptr]
-// CHECK:STDOUT:     %T.loc6: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %return.param.loc6: ref %ptr = out_param call_param0
-// CHECK:STDOUT:     %return.loc6: ref %ptr = return_slot %return.param.loc6
+// CHECK:STDOUT:     %T.ref.loc6: type = name_ref T, %T.loc6 [symbolic = %T.loc4_6.2 (constants.%T)]
+// CHECK:STDOUT:     %ptr.loc6: type = ptr_type %T [symbolic = %ptr.loc4_20.2 (constants.%ptr)]
+// CHECK:STDOUT:     %T.loc6: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_6.2 (constants.%T)]
+// CHECK:STDOUT:     %return.param.loc6: ref @F.%ptr.loc4_20.2 (%ptr) = out_param call_param0
+// CHECK:STDOUT:     %return.loc6: ref @F.%ptr.loc4_20.2 (%ptr) = return_slot %return.param.loc6
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -148,7 +148,7 @@ fn F(U:! type, T:! type) -> U* {
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @F.%ptr.loc4_20.2 (%ptr) [symbolic = %require_complete (constants.%require_complete)]
 // CHECK:STDOUT:   %F.specific_fn.loc7_10.2: <specific function> = specific_function constants.%F, @F(%T.loc4_6.2) [symbolic = %F.specific_fn.loc7_10.2 (constants.%F.specific_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%T.patt.loc6: type) -> %ptr {
+// CHECK:STDOUT:   fn(%T.patt.loc6: type) -> @F.%ptr.loc4_20.2 (%ptr) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl.loc4 [concrete = constants.%F]
 // CHECK:STDOUT:     %T.ref.loc7: type = name_ref T, %T.loc6 [symbolic = %T.loc4_6.2 (constants.%T)]

+ 18 - 18
toolchain/check/testdata/function/generic/undefined.carbon

@@ -215,11 +215,11 @@ fn CallUndefined() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Defined.decl.loc4: %Defined.type = fn_decl @Defined [concrete = constants.%Defined] {
-// CHECK:STDOUT:     %T.patt.loc10: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
-// CHECK:STDOUT:     %x.patt: %T = binding_pattern x
-// CHECK:STDOUT:     %x.param_patt: %T = value_param_pattern %x.patt, call_param0
-// CHECK:STDOUT:     %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     %T.patt.loc10: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
+// CHECK:STDOUT:     %x.patt: @Defined.%T.loc4_12.2 (%T) = binding_pattern x
+// CHECK:STDOUT:     %x.param_patt: @Defined.%T.loc4_12.2 (%T) = value_param_pattern %x.patt, call_param0
+// CHECK:STDOUT:     %return.patt: @Defined.%T.loc4_12.2 (%T) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @Defined.%T.loc4_12.2 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref.loc4_31: type = name_ref T, %T.loc4_12.1 [symbolic = %T.loc4_12.2 (constants.%T)]
 // CHECK:STDOUT:     %T.loc4_12.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_12.2 (constants.%T)]
@@ -239,19 +239,19 @@ fn CallUndefined() -> i32 {
 // CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Defined.decl.loc10: %Defined.type = fn_decl @Defined [concrete = constants.%Defined] {
-// CHECK:STDOUT:     %T.patt.loc10: type = symbolic_binding_pattern T, 0 [symbolic = constants.%T.patt]
-// CHECK:STDOUT:     %x.patt: %T = binding_pattern x
-// CHECK:STDOUT:     %x.param_patt: %T = value_param_pattern %x.patt, call_param0
-// CHECK:STDOUT:     %return.patt: %T = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %T = out_param_pattern %return.patt, call_param1
+// CHECK:STDOUT:     %T.patt.loc10: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc4 (constants.%T.patt)]
+// CHECK:STDOUT:     %x.patt: @Defined.%T.loc4_12.2 (%T) = binding_pattern x
+// CHECK:STDOUT:     %x.param_patt: @Defined.%T.loc4_12.2 (%T) = value_param_pattern %x.patt, call_param0
+// CHECK:STDOUT:     %return.patt: @Defined.%T.loc4_12.2 (%T) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @Defined.%T.loc4_12.2 (%T) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc10_31: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
-// CHECK:STDOUT:     %x.param.loc10: %T = value_param call_param0
-// CHECK:STDOUT:     %T.ref.loc10_25: type = name_ref T, %T.loc10 [symbolic = constants.%T]
-// CHECK:STDOUT:     %x.loc10: %T = bind_name x, %x.param.loc10
-// CHECK:STDOUT:     %return.param.loc10: ref %T = out_param call_param1
-// CHECK:STDOUT:     %return.loc10: ref %T = return_slot %return.param.loc10
+// CHECK:STDOUT:     %T.ref.loc10_31: type = name_ref T, %T.loc10 [symbolic = %T.loc4_12.2 (constants.%T)]
+// CHECK:STDOUT:     %T.loc10: type = bind_symbolic_name T, 0 [symbolic = %T.loc4_12.2 (constants.%T)]
+// CHECK:STDOUT:     %x.param.loc10: @Defined.%T.loc4_12.2 (%T) = value_param call_param0
+// CHECK:STDOUT:     %T.ref.loc10_25: type = name_ref T, %T.loc10 [symbolic = %T.loc4_12.2 (constants.%T)]
+// CHECK:STDOUT:     %x.loc10: @Defined.%T.loc4_12.2 (%T) = bind_name x, %x.param.loc10
+// CHECK:STDOUT:     %return.param.loc10: ref @Defined.%T.loc4_12.2 (%T) = out_param call_param1
+// CHECK:STDOUT:     %return.loc10: ref @Defined.%T.loc4_12.2 (%T) = return_slot %return.param.loc10
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -262,7 +262,7 @@ fn CallUndefined() -> i32 {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type @Defined.%T.loc4_12.2 (%T) [symbolic = %require_complete (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%T.patt.loc10: type](%x.param_patt: %T) -> %T {
+// CHECK:STDOUT:   fn[%T.patt.loc10: type](%x.param_patt: @Defined.%T.loc4_12.2 (%T)) -> @Defined.%T.loc4_12.2 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @Defined.%T.loc4_12.2 (%T) = name_ref x, %x.loc10
 // CHECK:STDOUT:     return %x.ref

+ 24 - 0
toolchain/check/testdata/generic/forward_decl.carbon

@@ -0,0 +1,24 @@
+// 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
+//
+// EXTRA-ARGS: --no-dump-sem-ir
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/forward_decl.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/forward_decl.carbon
+
+interface Z {}
+
+class C {}
+impl C as Z {}
+
+fn G[T:! Z](p: T);
+
+fn F() {
+    G({} as C);
+}
+
+fn G[T:! Z](p: T) {}

+ 16 - 16
toolchain/check/testdata/impl/no_prelude/generic_redeclaration.carbon

@@ -180,42 +180,42 @@ impl forall [T:! type] T as I {
 // CHECK:STDOUT:   impl_decl @impl.c3d [concrete] {
 // CHECK:STDOUT:     %T.patt.loc11_14.1: %I.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc11_14.2 (constants.%T.patt.3ad)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc18: %I.type = name_ref T, %T.loc18 [symbolic = constants.%T.826]
-// CHECK:STDOUT:     %T.as_type.loc18: type = facet_access_type %T.ref.loc18 [symbolic = constants.%T.as_type.b70]
-// CHECK:STDOUT:     %.loc18: type = converted %T.ref.loc18, %T.as_type.loc18 [symbolic = constants.%T.as_type.b70]
+// CHECK:STDOUT:     %T.ref.loc18: %I.type = name_ref T, %T.loc18 [symbolic = %T.loc11_14.2 (constants.%T.826)]
+// CHECK:STDOUT:     %T.as_type.loc18: type = facet_access_type %T.ref.loc18 [symbolic = %T.as_type.loc11_21.2 (constants.%T.as_type.b70)]
+// CHECK:STDOUT:     %.loc18: type = converted %T.ref.loc18, %T.as_type.loc18 [symbolic = %T.as_type.loc11_21.2 (constants.%T.as_type.b70)]
 // CHECK:STDOUT:     %Interface.ref.loc18: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]
 // CHECK:STDOUT:     %I.ref.loc18: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
-// CHECK:STDOUT:     %T.loc18: %I.type = bind_symbolic_name T, 0 [symbolic = constants.%T.826]
+// CHECK:STDOUT:     %T.loc18: %I.type = bind_symbolic_name T, 0 [symbolic = %T.loc11_14.2 (constants.%T.826)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   impl_decl @impl.793 [concrete] {
 // CHECK:STDOUT:     %T.patt.loc12_14.1: %J.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc12_14.2 (constants.%T.patt.371)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc19: %J.type = name_ref T, %T.loc19 [symbolic = constants.%T.ccd]
-// CHECK:STDOUT:     %T.as_type.loc19: type = facet_access_type %T.ref.loc19 [symbolic = constants.%T.as_type.3df]
-// CHECK:STDOUT:     %.loc19: type = converted %T.ref.loc19, %T.as_type.loc19 [symbolic = constants.%T.as_type.3df]
+// CHECK:STDOUT:     %T.ref.loc19: %J.type = name_ref T, %T.loc19 [symbolic = %T.loc12_14.2 (constants.%T.ccd)]
+// CHECK:STDOUT:     %T.as_type.loc19: type = facet_access_type %T.ref.loc19 [symbolic = %T.as_type.loc12_21.2 (constants.%T.as_type.3df)]
+// CHECK:STDOUT:     %.loc19: type = converted %T.ref.loc19, %T.as_type.loc19 [symbolic = %T.as_type.loc12_21.2 (constants.%T.as_type.3df)]
 // CHECK:STDOUT:     %Interface.ref.loc19: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]
 // CHECK:STDOUT:     %J.ref.loc19: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
-// CHECK:STDOUT:     %T.loc19: %J.type = bind_symbolic_name T, 0 [symbolic = constants.%T.ccd]
+// CHECK:STDOUT:     %T.loc19: %J.type = bind_symbolic_name T, 0 [symbolic = %T.loc12_14.2 (constants.%T.ccd)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   impl_decl @impl.c93 [concrete] {
 // CHECK:STDOUT:     %T.patt.loc13_14.1: %K.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc13_14.2 (constants.%T.patt.036)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc20: %K.type = name_ref T, %T.loc20 [symbolic = constants.%T.09f]
-// CHECK:STDOUT:     %T.as_type.loc20: type = facet_access_type %T.ref.loc20 [symbolic = constants.%T.as_type.037]
-// CHECK:STDOUT:     %.loc20: type = converted %T.ref.loc20, %T.as_type.loc20 [symbolic = constants.%T.as_type.037]
+// CHECK:STDOUT:     %T.ref.loc20: %K.type = name_ref T, %T.loc20 [symbolic = %T.loc13_14.2 (constants.%T.09f)]
+// CHECK:STDOUT:     %T.as_type.loc20: type = facet_access_type %T.ref.loc20 [symbolic = %T.as_type.loc13_21.2 (constants.%T.as_type.037)]
+// CHECK:STDOUT:     %.loc20: type = converted %T.ref.loc20, %T.as_type.loc20 [symbolic = %T.as_type.loc13_21.2 (constants.%T.as_type.037)]
 // CHECK:STDOUT:     %Interface.ref.loc20: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]
 // CHECK:STDOUT:     %K.ref.loc20: type = name_ref K, file.%K.decl [concrete = constants.%K.type]
-// CHECK:STDOUT:     %T.loc20: %K.type = bind_symbolic_name T, 0 [symbolic = constants.%T.09f]
+// CHECK:STDOUT:     %T.loc20: %K.type = bind_symbolic_name T, 0 [symbolic = %T.loc13_14.2 (constants.%T.09f)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   impl_decl @impl.9e6 [concrete] {
 // CHECK:STDOUT:     %T.patt.loc14_14.1: %L.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc14_14.2 (constants.%T.patt.29d)]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc21: %L.type = name_ref T, %T.loc21 [symbolic = constants.%T.1d2]
-// CHECK:STDOUT:     %T.as_type.loc21: type = facet_access_type %T.ref.loc21 [symbolic = constants.%T.as_type.0ed]
-// CHECK:STDOUT:     %.loc21: type = converted %T.ref.loc21, %T.as_type.loc21 [symbolic = constants.%T.as_type.0ed]
+// CHECK:STDOUT:     %T.ref.loc21: %L.type = name_ref T, %T.loc21 [symbolic = %T.loc14_14.2 (constants.%T.1d2)]
+// CHECK:STDOUT:     %T.as_type.loc21: type = facet_access_type %T.ref.loc21 [symbolic = %T.as_type.loc14_21.2 (constants.%T.as_type.0ed)]
+// CHECK:STDOUT:     %.loc21: type = converted %T.ref.loc21, %T.as_type.loc21 [symbolic = %T.as_type.loc14_21.2 (constants.%T.as_type.0ed)]
 // CHECK:STDOUT:     %Interface.ref.loc21: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]
 // CHECK:STDOUT:     %L.ref.loc21: type = name_ref L, file.%L.decl [concrete = constants.%L.type]
-// CHECK:STDOUT:     %T.loc21: %L.type = bind_symbolic_name T, 0 [symbolic = constants.%T.1d2]
+// CHECK:STDOUT:     %T.loc21: %L.type = bind_symbolic_name T, 0 [symbolic = %T.loc14_14.2 (constants.%T.1d2)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 3
toolchain/check/testdata/impl/no_prelude/import_generic.carbon

@@ -143,9 +143,9 @@ impl forall [T:! type] D as J(T*) {}
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc9: type = name_ref C, file.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:     %I.ref.loc9: %I.type.dac = name_ref I, file.%I.decl [concrete = constants.%I.generic]
-// CHECK:STDOUT:     %T.ref.loc9: type = name_ref T, %T.loc9 [symbolic = constants.%T]
-// CHECK:STDOUT:     %I.type.loc9: type = facet_type <@I, @I(constants.%T)> [symbolic = constants.%I.type.325]
-// CHECK:STDOUT:     %T.loc9: type = bind_symbolic_name T, 0 [symbolic = constants.%T]
+// CHECK:STDOUT:     %T.ref.loc9: type = name_ref T, %T.loc9 [symbolic = %T.loc8_14.2 (constants.%T)]
+// CHECK:STDOUT:     %I.type.loc9: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.325)]
+// CHECK:STDOUT:     %T.loc9: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   impl_decl @impl.cd2 [concrete] {
 // CHECK:STDOUT:     %T.patt.loc12_14.1: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc12_14.2 (constants.%T.patt)]

+ 27 - 27
toolchain/check/testdata/interface/fail_todo_define_default_fn_out_of_line.carbon

@@ -228,27 +228,27 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Interface.decl: type = interface_decl @Interface [concrete = constants.%Interface.type] {} {}
 // CHECK:STDOUT:   %F.decl: @C.%F.type (%F.type) = fn_decl @F [symbolic = constants.%F] {
-// CHECK:STDOUT:     %self.patt: %C.7e5 = binding_pattern self
-// CHECK:STDOUT:     %self.param_patt: %C.7e5 = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:     %U.patt.loc20: type = symbolic_binding_pattern U, 1 [symbolic = constants.%U.patt]
-// CHECK:STDOUT:     %u.patt: %U = binding_pattern u
-// CHECK:STDOUT:     %u.param_patt: %U = value_param_pattern %u.patt, call_param1
-// CHECK:STDOUT:     %return.patt: %U = return_slot_pattern
-// CHECK:STDOUT:     %return.param_patt: %U = out_param_pattern %return.patt, call_param2
+// CHECK:STDOUT:     %self.patt: @F.%C (%C.7e5) = binding_pattern self
+// CHECK:STDOUT:     %self.param_patt: @F.%C (%C.7e5) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:     %U.patt.loc20: type = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc14 (constants.%U.patt)]
+// CHECK:STDOUT:     %u.patt: @F.%U.loc14_22.1 (%U) = binding_pattern u
+// CHECK:STDOUT:     %u.param_patt: @F.%U.loc14_22.1 (%U) = value_param_pattern %u.patt, call_param1
+// CHECK:STDOUT:     %return.patt: @F.%U.loc14_22.1 (%U) = return_slot_pattern
+// CHECK:STDOUT:     %return.param_patt: @F.%U.loc14_22.1 (%U) = out_param_pattern %return.patt, call_param2
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %U.ref.loc20_49: type = name_ref U, %U.loc20 [symbolic = constants.%U]
-// CHECK:STDOUT:     %self.param.loc20: %C.7e5 = value_param call_param0
-// CHECK:STDOUT:     %.loc20_24.1: type = splice_block %Self.ref.loc20 [symbolic = constants.%C.7e5] {
-// CHECK:STDOUT:       %.loc20_24.2: type = specific_constant constants.%C.7e5, @C(constants.%Self) [symbolic = constants.%C.7e5]
-// CHECK:STDOUT:       %Self.ref.loc20: type = name_ref Self, %.loc20_24.2 [symbolic = constants.%C.7e5]
+// CHECK:STDOUT:     %U.ref.loc20_49: type = name_ref U, %U.loc20 [symbolic = %U.loc14_22.1 (constants.%U)]
+// CHECK:STDOUT:     %self.param.loc20: @F.%C (%C.7e5) = value_param call_param0
+// CHECK:STDOUT:     %.loc20_24.1: type = splice_block %Self.ref.loc20 [symbolic = %C (constants.%C.7e5)] {
+// CHECK:STDOUT:       %.loc20_24.2: type = specific_constant constants.%C.7e5, @C(constants.%Self) [symbolic = %C (constants.%C.7e5)]
+// CHECK:STDOUT:       %Self.ref.loc20: type = name_ref Self, %.loc20_24.2 [symbolic = %C (constants.%C.7e5)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %self.loc20: %C.7e5 = bind_name self, %self.param.loc20
-// CHECK:STDOUT:     %U.loc20: type = bind_symbolic_name U, 1 [symbolic = constants.%U]
-// CHECK:STDOUT:     %u.param.loc20: %U = value_param call_param1
-// CHECK:STDOUT:     %U.ref.loc20_43: type = name_ref U, %U.loc20 [symbolic = constants.%U]
-// CHECK:STDOUT:     %u.loc20: %U = bind_name u, %u.param.loc20
-// CHECK:STDOUT:     %return.param.loc20: ref %U = out_param call_param2
-// CHECK:STDOUT:     %return.loc20: ref %U = return_slot %return.param.loc20
+// CHECK:STDOUT:     %self.loc20: @F.%C (%C.7e5) = bind_name self, %self.param.loc20
+// CHECK:STDOUT:     %U.loc20: type = bind_symbolic_name U, 1 [symbolic = %U.loc14_22.1 (constants.%U)]
+// CHECK:STDOUT:     %u.param.loc20: @F.%U.loc14_22.1 (%U) = value_param call_param1
+// CHECK:STDOUT:     %U.ref.loc20_43: type = name_ref U, %U.loc20 [symbolic = %U.loc14_22.1 (constants.%U)]
+// CHECK:STDOUT:     %u.loc20: @F.%U.loc14_22.1 (%U) = bind_name u, %u.param.loc20
+// CHECK:STDOUT:     %return.param.loc20: ref @F.%U.loc14_22.1 (%U) = out_param call_param2
+// CHECK:STDOUT:     %return.loc20: ref @F.%U.loc14_22.1 (%U) = return_slot %return.param.loc20
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -270,13 +270,13 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; }
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
 // CHECK:STDOUT:     %F.decl: @C.%F.type (%F.type) = fn_decl @F [symbolic = @C.%F (constants.%F)] {
-// CHECK:STDOUT:       %self.patt: %C.7e5 = binding_pattern self
-// CHECK:STDOUT:       %self.param_patt: %C.7e5 = value_param_pattern %self.patt, call_param0
-// CHECK:STDOUT:       %U.patt.loc20: type = symbolic_binding_pattern U, 1 [symbolic = constants.%U.patt]
-// CHECK:STDOUT:       %u.patt: %U = binding_pattern u
-// CHECK:STDOUT:       %u.param_patt: %U = value_param_pattern %u.patt, call_param1
-// CHECK:STDOUT:       %return.patt: %U = return_slot_pattern
-// CHECK:STDOUT:       %return.param_patt: %U = out_param_pattern %return.patt, call_param2
+// CHECK:STDOUT:       %self.patt: @F.%C (%C.7e5) = binding_pattern self
+// CHECK:STDOUT:       %self.param_patt: @F.%C (%C.7e5) = value_param_pattern %self.patt, call_param0
+// CHECK:STDOUT:       %U.patt.loc20: type = symbolic_binding_pattern U, 1 [symbolic = %U.patt.loc14 (constants.%U.patt)]
+// CHECK:STDOUT:       %u.patt: @F.%U.loc14_22.1 (%U) = binding_pattern u
+// CHECK:STDOUT:       %u.param_patt: @F.%U.loc14_22.1 (%U) = value_param_pattern %u.patt, call_param1
+// CHECK:STDOUT:       %return.patt: @F.%U.loc14_22.1 (%U) = return_slot_pattern
+// CHECK:STDOUT:       %return.param_patt: @F.%U.loc14_22.1 (%U) = out_param_pattern %return.patt, call_param2
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %U.ref.loc14_41: type = name_ref U, %U.loc14_22.2 [symbolic = %U.loc14_22.1 (constants.%U)]
 // CHECK:STDOUT:       %self.param.loc14: @F.%C (%C.7e5) = value_param call_param0
@@ -311,7 +311,7 @@ fn Interface.C.F[self: Self](U:! type, u: U) -> U { return u; }
 // CHECK:STDOUT:   %require_complete.loc20_46: <witness> = require_complete_type @F.%U.loc14_22.1 (%U) [symbolic = %require_complete.loc20_46 (constants.%require_complete.b54)]
 // CHECK:STDOUT:   %require_complete.loc20_22: <witness> = require_complete_type @F.%C (%C.7e5) [symbolic = %require_complete.loc20_22 (constants.%require_complete.e44)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn[%self.param_patt: %C.7e5](%U.patt.loc20: type, %u.param_patt: %U) -> %U {
+// CHECK:STDOUT:   fn[%self.param_patt: @F.%C (%C.7e5)](%U.patt.loc20: type, %u.param_patt: @F.%U.loc14_22.1 (%U)) -> @F.%U.loc14_22.1 (%U) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %u.ref: @F.%U.loc14_22.1 (%U) = name_ref u, %u.loc20
 // CHECK:STDOUT:     return %u.ref

+ 6 - 8
toolchain/check/testdata/interface/no_prelude/fail_todo_generic_default_fn.carbon

@@ -56,7 +56,7 @@ fn I(T:! type).F[self: Self]() -> Self { return self; }
 // CHECK:STDOUT:     %return.patt: @F.2.%Self.as_type.loc23_24.2 (%Self.as_type) = return_slot_pattern
 // CHECK:STDOUT:     %return.param_patt: @F.2.%Self.as_type.loc23_24.2 (%Self.as_type) = out_param_pattern %return.patt, call_param1
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.loc23_6.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc23_6.2 (constants.%T)]
+// CHECK:STDOUT:     %T.loc23_6: type = bind_symbolic_name T, 0 [symbolic = @I.%T.loc11_13.2 (constants.%T)]
 // CHECK:STDOUT:     %.loc23_35.1: @F.2.%I.type (%I.type.325) = specific_constant @I.%Self.1, @I(constants.%T) [symbolic = %Self (constants.%Self)]
 // CHECK:STDOUT:     %Self.ref.loc23_35: @F.2.%I.type (%I.type.325) = name_ref Self, %.loc23_35.1 [symbolic = %Self (constants.%Self)]
 // CHECK:STDOUT:     %Self.as_type.loc23_35: type = facet_access_type %Self.ref.loc23_35 [symbolic = %Self.as_type.loc23_24.2 (constants.%Self.as_type)]
@@ -127,10 +127,9 @@ fn I(T:! type).F[self: Self]() -> Self { return self; }
 // CHECK:STDOUT:   fn[%self.param_patt: @F.1.%Self.as_type.loc13_14.1 (%Self.as_type)]() -> @F.1.%Self.as_type.loc13_14.1 (%Self.as_type);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F.2(%T.loc23_6.1: type, @I.%Self.1: @I.%I.type (%I.type.325)) {
-// CHECK:STDOUT:   %T.loc23_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc23_6.2 (constants.%T)]
-// CHECK:STDOUT:   %T.patt: type = symbolic_binding_pattern T, 0 [symbolic = %T.patt (constants.%T.patt)]
-// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc23_6.2)> [symbolic = %I.type (constants.%I.type.325)]
+// CHECK:STDOUT: generic fn @F.2(%T.loc23_6: type, @I.%Self.1: @I.%I.type (%I.type.325)) {
+// CHECK:STDOUT:   %T.loc23_24: type = bind_symbolic_name T, 0 [symbolic = %T.loc23_24 (constants.%T)]
+// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc23_24)> [symbolic = %I.type (constants.%I.type.325)]
 // CHECK:STDOUT:   %Self: %I.type.325 = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self)]
 // CHECK:STDOUT:   %Self.as_type.loc23_24.2: type = facet_access_type %Self [symbolic = %Self.as_type.loc23_24.2 (constants.%Self.as_type)]
 // CHECK:STDOUT:
@@ -169,12 +168,11 @@ fn I(T:! type).F[self: Self]() -> Self { return self; }
 // CHECK:STDOUT: specific @I(%T.loc11_13.2) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.2(constants.%T, constants.%Self) {
-// CHECK:STDOUT:   %T.loc23_6.2 => constants.%T
-// CHECK:STDOUT:   %T.patt => constants.%T
+// CHECK:STDOUT:   %T.loc23_24 => constants.%T
 // CHECK:STDOUT:   %I.type => constants.%I.type.325
 // CHECK:STDOUT:   %Self => constants.%Self
 // CHECK:STDOUT:   %Self.as_type.loc23_24.2 => constants.%Self.as_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @I(@F.2.%T.loc23_6.2) {}
+// CHECK:STDOUT: specific @I(@F.2.%T.loc23_24) {}
 // CHECK:STDOUT:

+ 4 - 4
toolchain/check/testdata/interface/no_prelude/syntactic_merge.carbon

@@ -224,7 +224,7 @@ interface Foo(a:! const (const C)) {}
 // CHECK:STDOUT:     %a.patt.loc7_15.1: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc7_15.2 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc8: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc8: %C = bind_symbolic_name a, 0 [symbolic = %a.loc7_15.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Bar.decl.loc10: %Bar.type.982 = interface_decl @Bar [concrete = constants.%Bar.generic] {
 // CHECK:STDOUT:     %a.patt.loc10_15.1: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc10_15.2 (constants.%a.patt)]
@@ -236,7 +236,7 @@ interface Foo(a:! const (const C)) {}
 // CHECK:STDOUT:     %a.patt.loc10_15.1: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc10_15.2 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %D.ref.loc11: type = name_ref D, file.%D [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc11: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc11: %C = bind_symbolic_name a, 0 [symbolic = %a.loc10_15.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -326,7 +326,7 @@ interface Foo(a:! const (const C)) {}
 // CHECK:STDOUT:     %a.patt.loc6_21.1: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6_21.2 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_21.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -472,7 +472,7 @@ interface Foo(a:! const (const C)) {}
 // CHECK:STDOUT:     %a.patt.loc6_15.1: %C = symbolic_binding_pattern a, 0 [symbolic = %a.patt.loc6_15.2 (constants.%a.patt)]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]
-// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = constants.%a]
+// CHECK:STDOUT:     %a.loc7: %C = bind_symbolic_name a, 0 [symbolic = %a.loc6_15.2 (constants.%a)]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: