Przeglądaj źródła

Refactor CheckIsAllowedRedecl and stop function definition merging (#4800)

Rename `CheckIsAllowedRedecl` to `DiagnoseIfInvalidRedecl` to try to
better document behavior, and clean up comments.

This extends the no-merge-if-defined behavior to functions. It was
already the case for class/interface, and just added for impl, so if
anything functions were now inconsistent. I was kind of tempted to make
a helper for it, but I didn't think of a great structure/name to get
there: `DiagnoseRedef` isn't always called when it's a redefinition, for
example due to `extern` diagnostics, it's hard to combine.

Cleans up `is_defined` calls to rely more on `has_definition_started`,
removing some code paths that are unused since definitions aren't
merged.
Jon Ross-Perkins 1 rok temu
rodzic
commit
d958caaff3

+ 7 - 8
toolchain/check/handle_class.cpp

@@ -65,13 +65,13 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc,
     return false;
   }
 
-  CheckIsAllowedRedecl(
+  DiagnoseIfInvalidRedecl(
       context, Lex::TokenKind::Class, prev_class.name_id,
       RedeclInfo(new_class, new_loc, new_is_definition),
-      RedeclInfo(prev_class, prev_loc, prev_class.is_defined()),
+      RedeclInfo(prev_class, prev_loc, prev_class.has_definition_started()),
       prev_import_ir_id);
 
-  if (new_is_definition && prev_class.is_defined()) {
+  if (new_is_definition && prev_class.has_definition_started()) {
     // Don't attempt to merge multiple definitions.
     return false;
   }
@@ -280,11 +280,10 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)
   auto& class_info = context.classes().Get(class_id);
 
   // Track that this declaration is the definition.
-  if (!class_info.is_defined()) {
-    class_info.definition_id = class_decl_id;
-    class_info.scope_id = context.name_scopes().Add(
-        class_decl_id, SemIR::NameId::Invalid, class_info.parent_scope_id);
-  }
+  CARBON_CHECK(!class_info.has_definition_started());
+  class_info.definition_id = class_decl_id;
+  class_info.scope_id = context.name_scopes().Add(
+      class_decl_id, SemIR::NameId::Invalid, class_info.parent_scope_id);
 
   // Enter the class scope.
   context.scope_stack().Push(

+ 9 - 5
toolchain/check/handle_function.cpp

@@ -88,11 +88,15 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc,
     return false;
   }
 
-  CheckIsAllowedRedecl(context, Lex::TokenKind::Fn, prev_function.name_id,
-                       RedeclInfo(new_function, new_loc, new_is_definition),
-                       RedeclInfo(prev_function, prev_function.latest_decl_id(),
-                                  prev_function.has_definition_started()),
-                       prev_import_ir_id);
+  DiagnoseIfInvalidRedecl(
+      context, Lex::TokenKind::Fn, prev_function.name_id,
+      RedeclInfo(new_function, new_loc, new_is_definition),
+      RedeclInfo(prev_function, prev_function.latest_decl_id(),
+                 prev_function.has_definition_started()),
+      prev_import_ir_id);
+  if (new_is_definition && prev_function.has_definition_started()) {
+    return false;
+  }
 
   if (!prev_function.first_owning_decl_id.is_valid()) {
     prev_function.first_owning_decl_id = new_function.first_owning_decl_id;

+ 4 - 9
toolchain/check/handle_impl.cpp

@@ -453,10 +453,7 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionStartId node_id)
       impl_decl_id, impl_info.scope_id,
       context.generics().GetSelfSpecific(impl_info.generic_id));
   StartGenericDefinition(context);
-
-  if (!impl_info.is_defined()) {
-    ImplWitnessStartDefinition(context, impl_info);
-  }
+  ImplWitnessStartDefinition(context, impl_info);
   context.inst_block_stack().Push();
   context.node_stack().Push(node_id, impl_id);
 
@@ -479,11 +476,9 @@ auto HandleParseNode(Context& context, Parse::ImplDefinitionId /*node_id*/)
       context.node_stack().Pop<Parse::NodeKind::ImplDefinitionStart>();
 
   auto& impl_info = context.impls().Get(impl_id);
-  if (!impl_info.is_defined()) {
-    FinishImplWitness(context, impl_info);
-    impl_info.defined = true;
-  }
-
+  CARBON_CHECK(!impl_info.is_defined());
+  FinishImplWitness(context, impl_info);
+  impl_info.defined = true;
   FinishGenericDefinition(context, impl_info.generic_id);
 
   context.inst_block_stack().Pop();

+ 25 - 28
toolchain/check/handle_interface.cpp

@@ -79,16 +79,15 @@ static auto BuildInterfaceDecl(Context& context,
         // TODO: This should be refactored a little, particularly for
         // prev_import_ir_id. See similar logic for classes and functions, which
         // might also be refactored to merge.
-        CheckIsAllowedRedecl(
+        DiagnoseIfInvalidRedecl(
             context, Lex::TokenKind::Interface, existing_interface.name_id,
             RedeclInfo(interface_info, node_id, is_definition),
             RedeclInfo(existing_interface, existing_interface.latest_decl_id(),
-                       existing_interface.is_defined()),
+                       existing_interface.has_definition_started()),
             /*prev_import_ir_id=*/SemIR::ImportIRId::Invalid);
 
         // Can't merge interface definitions due to the generic requirements.
-        // TODO: Should this also be mirrored to classes/functions for generics?
-        if (!is_definition || !existing_interface.is_defined()) {
+        if (!is_definition || !existing_interface.has_definition_started()) {
           // This is a redeclaration of an existing interface.
           interface_decl.interface_id = existing_interface_decl->interface_id;
           interface_decl.type_id = existing_interface_decl->type_id;
@@ -140,7 +139,7 @@ auto HandleParseNode(Context& context,
   auto& interface_info = context.interfaces().Get(interface_id);
 
   // Track that this declaration is the definition.
-  CARBON_CHECK(!interface_info.is_defined(),
+  CARBON_CHECK(!interface_info.has_definition_started(),
                "Can't merge with defined interfaces.");
   interface_info.definition_id = interface_decl_id;
   interface_info.scope_id =
@@ -159,29 +158,27 @@ auto HandleParseNode(Context& context,
   context.args_type_info_stack().Push();
 
   // Declare and introduce `Self`.
-  if (!interface_info.is_defined()) {
-    SemIR::FacetType facet_type =
-        context.FacetTypeFromInterface(interface_id, self_specific_id);
-    SemIR::TypeId self_type_id = context.GetTypeIdForTypeConstant(
-        TryEvalInst(context, SemIR::InstId::Invalid, facet_type));
-
-    // We model `Self` as a symbolic binding whose type is the interface.
-    // Because there is no equivalent non-symbolic value, we use `Invalid` as
-    // the `value_id` on the `BindSymbolicName`.
-    auto entity_name_id = context.entity_names().Add(
-        {.name_id = SemIR::NameId::SelfType,
-         .parent_scope_id = interface_info.scope_id,
-         .bind_index = context.scope_stack().AddCompileTimeBinding()});
-    interface_info.self_param_id =
-        context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
-            {.type_id = self_type_id,
-             .entity_name_id = entity_name_id,
-             .value_id = SemIR::InstId::Invalid}));
-    context.scope_stack().PushCompileTimeBinding(interface_info.self_param_id);
-    context.name_scopes().AddRequiredName(interface_info.scope_id,
-                                          SemIR::NameId::SelfType,
-                                          interface_info.self_param_id);
-  }
+  SemIR::FacetType facet_type =
+      context.FacetTypeFromInterface(interface_id, self_specific_id);
+  SemIR::TypeId self_type_id = context.GetTypeIdForTypeConstant(
+      TryEvalInst(context, SemIR::InstId::Invalid, facet_type));
+
+  // We model `Self` as a symbolic binding whose type is the interface.
+  // Because there is no equivalent non-symbolic value, we use `Invalid` as
+  // the `value_id` on the `BindSymbolicName`.
+  auto entity_name_id = context.entity_names().Add(
+      {.name_id = SemIR::NameId::SelfType,
+       .parent_scope_id = interface_info.scope_id,
+       .bind_index = context.scope_stack().AddCompileTimeBinding()});
+  interface_info.self_param_id =
+      context.AddInst(SemIR::LocIdAndInst::NoLoc<SemIR::BindSymbolicName>(
+          {.type_id = self_type_id,
+           .entity_name_id = entity_name_id,
+           .value_id = SemIR::InstId::Invalid}));
+  context.scope_stack().PushCompileTimeBinding(interface_info.self_param_id);
+  context.name_scopes().AddRequiredName(interface_info.scope_id,
+                                        SemIR::NameId::SelfType,
+                                        interface_info.self_param_id);
 
   // Enter the interface scope.
   context.scope_stack().Push(interface_decl_id, interface_info.scope_id,

+ 4 - 6
toolchain/check/merge.cpp

@@ -91,12 +91,10 @@ auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIRLoc loc)
   context.emitter().Build(loc, ExternRequiresDeclInApiFile).Emit();
 }
 
-// Checks to see if a structurally valid redeclaration is allowed in context.
-// These all still merge.
-auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind,
-                          SemIR::NameId name_id, RedeclInfo new_decl,
-                          RedeclInfo prev_decl, SemIR::ImportIRId import_ir_id)
-    -> void {
+auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
+                             SemIR::NameId name_id, RedeclInfo new_decl,
+                             RedeclInfo prev_decl,
+                             SemIR::ImportIRId import_ir_id) -> void {
   if (!import_ir_id.is_valid()) {
     // Check for disallowed redeclarations in the same file.
     if (!new_decl.is_definition) {

+ 8 - 7
toolchain/check/merge.h

@@ -16,7 +16,7 @@ namespace Carbon::Check {
 auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIRLoc loc)
     -> void;
 
-// Information on new and previous declarations for CheckIsAllowedRedecl.
+// Information on new and previous declarations for DiagnoseIfInvalidRedecl.
 struct RedeclInfo {
   explicit RedeclInfo(SemIR::EntityWithParamsBase params, SemIRLoc loc,
                       bool is_definition)
@@ -35,18 +35,19 @@ struct RedeclInfo {
   SemIR::LibraryNameId extern_library_id;
 };
 
-// Checks if a redeclaration is allowed prior to merging. This may emit a
-// diagnostic, but diagnostics do not prevent merging.
+// Checks for various invalid redeclarations. This can emit diagnostics.
+// However, merging is still often appropriate for error recovery, so this
+// doesn't return whether a diagnostic occurred.
 //
 // The kinds of things this verifies are:
 // - A declaration is not redundant.
 // - A definition doesn't redefine a prior definition.
 // - The use of `extern` is consistent within a library.
 // - Multiple libraries do not declare non-`extern`.
-auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind,
-                          SemIR::NameId name_id, RedeclInfo new_decl,
-                          RedeclInfo prev_decl,
-                          SemIR::ImportIRId prev_import_ir_id) -> void;
+auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
+                             SemIR::NameId name_id, RedeclInfo new_decl,
+                             RedeclInfo prev_decl,
+                             SemIR::ImportIRId prev_import_ir_id) -> void;
 
 // When the prior name lookup result is an import and we are successfully
 // merging, replace the name lookup result with the reference in the current

+ 10 - 3
toolchain/check/testdata/class/fail_method_redefinition.carbon

@@ -25,6 +25,8 @@ class Class {
 // CHECK:STDOUT:   %Class: type = class_type @Class [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d22: %.type = struct_value () [template]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [template]
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [template]
 // CHECK:STDOUT: }
@@ -46,13 +48,13 @@ class Class {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [template = constants.%F] {} {}
-// CHECK:STDOUT:   %F.decl.loc19: %F.type = fn_decl @F [template = constants.%F] {} {}
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d22] {} {}
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [template = constants.%complete_type]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = constants.%Class
-// CHECK:STDOUT:   .F = %F.decl.loc12
+// CHECK:STDOUT:   .F = %F.decl
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -61,3 +63,8 @@ class Class {
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 11 - 4
toolchain/check/testdata/class/fail_redefinition.carbon

@@ -54,7 +54,7 @@ fn Class.I() {}
 // CHECK:STDOUT:   %I.c9a: %I.type.2b6 = struct_value () [template]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [template]
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [template]
-// CHECK:STDOUT:   %.a95: type = class_type @.1 [template]
+// CHECK:STDOUT:   %.a95: type = class_type @.2 [template]
 // CHECK:STDOUT:   %G.type.bf6: type = fn_type @G.1 [template]
 // CHECK:STDOUT:   %G.e39: %G.type.bf6 = struct_value () [template]
 // CHECK:STDOUT:   %H.type.e2f: type = fn_type @H.2 [template]
@@ -63,6 +63,8 @@ fn Class.I() {}
 // CHECK:STDOUT:   %I.a7f: %I.type.b27 = struct_value () [template]
 // CHECK:STDOUT:   %G.type.621: type = fn_type @G.2 [template]
 // CHECK:STDOUT:   %G.f0c: %G.type.621 = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d22: %.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -79,11 +81,11 @@ fn Class.I() {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Class.decl: type = class_decl @Class [template = constants.%Class] {} {}
-// CHECK:STDOUT:   %.decl: type = class_decl @.1 [template = constants.%.a95] {} {}
+// CHECK:STDOUT:   %.decl.loc24: type = class_decl @.2 [template = constants.%.a95] {} {}
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
 // CHECK:STDOUT:   %G.decl: %G.type.621 = fn_decl @G.2 [template = constants.%G.f0c] {} {}
 // CHECK:STDOUT:   %H.decl: %H.type.91d = fn_decl @H.1 [template = constants.%H.d38] {} {}
-// CHECK:STDOUT:   %I.decl: %I.type.2b6 = fn_decl @I.1 [template = constants.%I.c9a] {} {}
+// CHECK:STDOUT:   %.decl.loc43: %.type = fn_decl @.1 [template = constants.%.d22] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
@@ -101,7 +103,7 @@ fn Class.I() {}
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: class @.1 {
+// CHECK:STDOUT: class @.2 {
 // CHECK:STDOUT:   %G.decl: %G.type.bf6 = fn_decl @G.1 [template = constants.%G.e39] {} {}
 // CHECK:STDOUT:   %H.decl: %H.type.e2f = fn_decl @H.2 [template = constants.%H.382] {} {}
 // CHECK:STDOUT:   %I.decl: %I.type.b27 = fn_decl @I.2 [template = constants.%I.a7f] {} {}
@@ -144,3 +146,8 @@ fn Class.I() {}
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 61 - 49
toolchain/check/testdata/function/builtin/fail_redefined.carbon

@@ -44,10 +44,16 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [template]
 // CHECK:STDOUT:   %A.type: type = fn_type @A [template]
 // CHECK:STDOUT:   %A: %A.type = struct_value () [template]
+// CHECK:STDOUT:   %.type.b6a92a.1: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d852be.1: %.type.b6a92a.1 = struct_value () [template]
 // CHECK:STDOUT:   %B.type: type = fn_type @B [template]
 // CHECK:STDOUT:   %B: %B.type = struct_value () [template]
+// CHECK:STDOUT:   %.type.b6a92a.2: type = fn_type @.2 [template]
+// CHECK:STDOUT:   %.d852be.2: %.type.b6a92a.2 = struct_value () [template]
 // CHECK:STDOUT:   %C.type: type = fn_type @C [template]
 // CHECK:STDOUT:   %C: %C.type = struct_value () [template]
+// CHECK:STDOUT:   %.type.b6a92a.3: type = fn_type @.3 [template]
+// CHECK:STDOUT:   %.d852be.3: %.type.b6a92a.3 = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -61,12 +67,12 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .Core = imports.%Core
-// CHECK:STDOUT:     .A = %A.decl.loc11
-// CHECK:STDOUT:     .B = %B.decl.loc21
-// CHECK:STDOUT:     .C = %C.decl.loc31
+// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .B = %B.decl
+// CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %A.decl.loc11: %A.type = fn_decl @A [template = constants.%A] {
+// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [template = constants.%A] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -76,22 +82,22 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc11_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc11_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc11: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc11_9: type = splice_block %i32.loc11_9 [template = constants.%i32] {
 // 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:     }
-// CHECK:STDOUT:     %n.loc11: %i32 = bind_name n, %n.param.loc11
-// CHECK:STDOUT:     %m.param.loc11: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc11_17: type = splice_block %i32.loc11_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc11_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc11_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc11: %i32 = bind_name m, %m.param.loc11
-// CHECK:STDOUT:     %return.param.loc11: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc11: ref %i32 = return_slot %return.param.loc11
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %A.decl.loc19: %A.type = fn_decl @A [template = constants.%A] {
+// CHECK:STDOUT:   %.decl.loc19: %.type.b6a92a.1 = fn_decl @.1 [template = constants.%.d852be.1] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -101,22 +107,22 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc19_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc19_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc19: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc19_9: type = splice_block %i32.loc19_9 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc19_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc19_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n.loc19: %i32 = bind_name n, %n.param.loc19
-// CHECK:STDOUT:     %m.param.loc19: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc19_17: type = splice_block %i32.loc19_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc19_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc19_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc19: %i32 = bind_name m, %m.param.loc19
-// CHECK:STDOUT:     %return.param.loc19: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc19: ref %i32 = return_slot %return.param.loc19
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %B.decl.loc21: %B.type = fn_decl @B [template = constants.%B] {
+// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [template = constants.%B] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -126,22 +132,22 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc21_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc21_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc21: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc21_9: type = splice_block %i32.loc21_9 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc21_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc21_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n.loc21: %i32 = bind_name n, %n.param.loc21
-// CHECK:STDOUT:     %m.param.loc21: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc21_17: type = splice_block %i32.loc21_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc21_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc21_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc21: %i32 = bind_name m, %m.param.loc21
-// CHECK:STDOUT:     %return.param.loc21: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc21: ref %i32 = return_slot %return.param.loc21
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %B.decl.loc29: %B.type = fn_decl @B [template = constants.%B] {
+// CHECK:STDOUT:   %.decl.loc29: %.type.b6a92a.2 = fn_decl @.2 [template = constants.%.d852be.2] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -151,22 +157,22 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc29_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc29_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc29: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc29_9: type = splice_block %i32.loc29_9 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc29_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc29_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n.loc29: %i32 = bind_name n, %n.param.loc29
-// CHECK:STDOUT:     %m.param.loc29: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc29_17: type = splice_block %i32.loc29_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc29_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc29_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc29: %i32 = bind_name m, %m.param.loc29
-// CHECK:STDOUT:     %return.param.loc29: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc29: ref %i32 = return_slot %return.param.loc29
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %C.decl.loc31: %C.type = fn_decl @C [template = constants.%C] {
+// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [template = constants.%C] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -176,22 +182,22 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc31_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc31_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc31: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc31_9: type = splice_block %i32.loc31_9 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc31_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc31_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n.loc31: %i32 = bind_name n, %n.param.loc31
-// CHECK:STDOUT:     %m.param.loc31: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc31_17: type = splice_block %i32.loc31_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc31_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc31_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc31: %i32 = bind_name m, %m.param.loc31
-// CHECK:STDOUT:     %return.param.loc31: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc31: ref %i32 = return_slot %return.param.loc31
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %C.decl.loc38: %C.type = fn_decl @C [template = constants.%C] {
+// CHECK:STDOUT:   %.decl.loc38: %.type.b6a92a.3 = fn_decl @.3 [template = constants.%.d852be.3] {
 // CHECK:STDOUT:     %n.patt: %i32 = binding_pattern n
 // CHECK:STDOUT:     %n.param_patt: %i32 = value_param_pattern %n.patt, runtime_param0
 // CHECK:STDOUT:     %m.patt: %i32 = binding_pattern m
@@ -201,34 +207,40 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %int_32.loc38_25: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc38_25: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
-// CHECK:STDOUT:     %n.param.loc38: %i32 = value_param runtime_param0
+// CHECK:STDOUT:     %n.param: %i32 = value_param runtime_param0
 // CHECK:STDOUT:     %.loc38_9: type = splice_block %i32.loc38_9 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc38_9: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc38_9: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %n.loc38: %i32 = bind_name n, %n.param.loc38
-// CHECK:STDOUT:     %m.param.loc38: %i32 = value_param runtime_param1
+// CHECK:STDOUT:     %n: %i32 = bind_name n, %n.param
+// CHECK:STDOUT:     %m.param: %i32 = value_param runtime_param1
 // CHECK:STDOUT:     %.loc38_17: type = splice_block %i32.loc38_17 [template = constants.%i32] {
 // CHECK:STDOUT:       %int_32.loc38_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:       %i32.loc38_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %m.loc38: %i32 = bind_name m, %m.param.loc38
-// CHECK:STDOUT:     %return.param.loc38: ref %i32 = out_param runtime_param2
-// CHECK:STDOUT:     %return.loc38: ref %i32 = return_slot %return.param.loc38
+// CHECK:STDOUT:     %m: %i32 = bind_name m, %m.param
+// CHECK:STDOUT:     %return.param: ref %i32 = out_param runtime_param2
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @A(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd" {
+// CHECK:STDOUT: fn @A(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd";
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n.loc19
+// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n
 // CHECK:STDOUT:   return %n.ref
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @B(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd" {
+// CHECK:STDOUT: fn @B(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n.loc21
+// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n
 // CHECK:STDOUT:   return %n.ref
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.2(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd";
+// CHECK:STDOUT:
 // CHECK:STDOUT: fn @C(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd";
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.3(%n.param_patt: %i32, %m.param_patt: %i32) -> %i32 = "int.sadd";
+// CHECK:STDOUT:

+ 13 - 6
toolchain/check/testdata/function/declaration/no_prelude/fail_redecl.carbon

@@ -67,12 +67,14 @@ fn E() {}
 // CHECK:STDOUT:   %B: %B.type = struct_value () [template]
 // CHECK:STDOUT:   %C.type: type = fn_type @C [template]
 // CHECK:STDOUT:   %C: %C.type = struct_value () [template]
-// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
-// CHECK:STDOUT:   %.d85: %.type = struct_value () [template]
+// CHECK:STDOUT:   %.type.b6a92a.1: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d852be.1: %.type.b6a92a.1 = struct_value () [template]
 // CHECK:STDOUT:   %D.type: type = fn_type @D [template]
 // CHECK:STDOUT:   %D: %D.type = struct_value () [template]
 // CHECK:STDOUT:   %E.type: type = fn_type @E [template]
 // CHECK:STDOUT:   %E: %E.type = struct_value () [template]
+// CHECK:STDOUT:   %.type.b6a92a.2: type = fn_type @.2 [template]
+// CHECK:STDOUT:   %.d852be.2: %.type.b6a92a.2 = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -81,7 +83,7 @@ fn E() {}
 // CHECK:STDOUT:     .B = %B.decl.loc21
 // CHECK:STDOUT:     .C = %C.decl
 // CHECK:STDOUT:     .D = %D.decl.loc41
-// CHECK:STDOUT:     .E = %E.decl.loc51
+// CHECK:STDOUT:     .E = %E.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %A.decl.loc11: %A.type = fn_decl @A [template = constants.%A] {} {}
 // CHECK:STDOUT:   %A.decl.loc19: %A.type = fn_decl @A [template = constants.%A] {} {}
@@ -108,7 +110,7 @@ fn E() {}
 // CHECK:STDOUT:     %x.loc29: %empty_tuple.type = bind_name x, %x.param.loc29
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [template = constants.%C] {} {}
-// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {
+// CHECK:STDOUT:   %.decl.loc39: %.type.b6a92a.1 = fn_decl @.1 [template = constants.%.d852be.1] {
 // CHECK:STDOUT:     %x.patt: %empty_tuple.type = binding_pattern x
 // CHECK:STDOUT:     %x.param_patt: %empty_tuple.type = value_param_pattern %x.patt, runtime_param0
 // CHECK:STDOUT:   } {
@@ -121,8 +123,8 @@ fn E() {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %D.decl.loc41: %D.type = fn_decl @D [template = constants.%D] {} {}
 // CHECK:STDOUT:   %D.decl.loc49: %D.type = fn_decl @D [template = constants.%D] {} {}
-// CHECK:STDOUT:   %E.decl.loc51: %E.type = fn_decl @E [template = constants.%E] {} {}
-// CHECK:STDOUT:   %E.decl.loc58: %E.type = fn_decl @E [template = constants.%E] {} {}
+// CHECK:STDOUT:   %E.decl: %E.type = fn_decl @E [template = constants.%E] {} {}
+// CHECK:STDOUT:   %.decl.loc58: %.type.b6a92a.2 = fn_decl @.2 [template = constants.%.d852be.2] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A();
@@ -143,3 +145,8 @@ fn E() {}
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.2() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 8 - 3
toolchain/check/testdata/function/definition/import.carbon

@@ -337,6 +337,8 @@ fn D() {}
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %A.type: type = fn_type @A [template]
 // CHECK:STDOUT:   %A: %A.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d85: %.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:   %B.type: type = fn_type @B [template]
@@ -344,6 +346,7 @@ fn D() {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %import_ref.a6e: %A.type = import_ref Main//fns, A, loaded [template = constants.%A]
 // CHECK:STDOUT:   %import_ref.b05 = import_ref Main//fns, C, unloaded
 // CHECK:STDOUT:   %import_ref.caf = import_ref Main//fns, D, unloaded
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [template] {
@@ -355,7 +358,7 @@ fn D() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .A = imports.%import_ref.a6e
 // CHECK:STDOUT:     .B = %B.decl
 // CHECK:STDOUT:     .C = imports.%import_ref.b05
 // CHECK:STDOUT:     .D = imports.%import_ref.caf
@@ -363,7 +366,7 @@ fn D() {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <invalid>
-// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {} {}
 // CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [template = constants.%B] {} {
 // CHECK:STDOUT:     %int_32.loc23_17: Core.IntLiteral = int_value 32 [template = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc23_17: type = class_type @Int, @Int(constants.%int_32) [template = constants.%i32]
@@ -378,7 +381,9 @@ fn D() {}
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @A() [from "fns.carbon"] {
+// CHECK:STDOUT: fn @A() [from "fns.carbon"];
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 10 - 3
toolchain/check/testdata/function/definition/no_prelude/fail_redef.carbon

@@ -22,14 +22,16 @@ fn F() {}
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %F.type: type = fn_type @F [template]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d85: %.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .F = %F.decl.loc11
+// CHECK:STDOUT:     .F = %F.decl
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %F.decl.loc11: %F.type = fn_decl @F [template = constants.%F] {} {}
-// CHECK:STDOUT:   %F.decl.loc18: %F.type = fn_decl @F [template = constants.%F] {} {}
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
@@ -37,3 +39,8 @@ fn F() {}
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 8 - 3
toolchain/check/testdata/function/definition/no_prelude/implicit_import.carbon

@@ -304,21 +304,26 @@ fn B() {}
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %A.type: type = fn_type @A [template]
 // CHECK:STDOUT:   %A: %A.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.d85: %.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %import_ref: %A.type = import_ref Main//redef_after_def, A, loaded [template = constants.%A]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .A = %A.decl
+// CHECK:STDOUT:     .A = imports.%import_ref
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import.loc2_6.1 = import <invalid>
 // CHECK:STDOUT:   %default.import.loc2_6.2 = import <invalid>
-// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.d85] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @A() [from "redef_after_def.carbon"] {
+// CHECK:STDOUT: fn @A() [from "redef_after_def.carbon"];
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 10 - 3
toolchain/check/testdata/namespace/fail_duplicate.carbon

@@ -27,6 +27,8 @@ fn Foo.Baz() {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Baz.type: type = fn_type @Baz [template]
 // CHECK:STDOUT:   %Baz: %Baz.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.700: %.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -43,10 +45,10 @@ fn Foo.Baz() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %Foo: <namespace> = namespace [template] {
-// CHECK:STDOUT:     .Baz = %Baz.decl.loc13
+// CHECK:STDOUT:     .Baz = %Baz.decl
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Baz.decl.loc13: %Baz.type = fn_decl @Baz [template = constants.%Baz] {} {}
-// CHECK:STDOUT:   %Baz.decl.loc22: %Baz.type = fn_decl @Baz [template = constants.%Baz] {} {}
+// CHECK:STDOUT:   %Baz.decl: %Baz.type = fn_decl @Baz [template = constants.%Baz] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.700] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Baz() {
@@ -54,3 +56,8 @@ fn Foo.Baz() {
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 7 - 5
toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon

@@ -473,14 +473,14 @@ fn UseF() { Other.F(); }
 // CHECK:STDOUT: --- fail_main_namespace_conflict.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %F.type: type = fn_type @F [template]
-// CHECK:STDOUT:   %F: %F.type = struct_value () [template]
+// CHECK:STDOUT:   %.type: type = fn_type @.1 [template]
+// CHECK:STDOUT:   %.b19: %.type = struct_value () [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %import_ref.b6b: <namespace> = import_ref Main//main_other_ns, Other, loaded
 // CHECK:STDOUT:   %Other: <namespace> = namespace %import_ref.b6b, [template] {
-// CHECK:STDOUT:     .F = file.%F.decl
+// CHECK:STDOUT:     .F = %import_ref.db9
 // CHECK:STDOUT:     import Other//other_fn
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -491,10 +491,12 @@ fn UseF() { Other.F(); }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %default.import = import <invalid>
 // CHECK:STDOUT:   %Other.import = import Other
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
+// CHECK:STDOUT:   %.decl: %.type = fn_decl @.1 [template = constants.%.b19] {} {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F() [from "other_fn.carbon"] {
+// CHECK:STDOUT: fn @F() [from "other_fn.carbon"];
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @.1() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }