Bladeren bron

Restructure return declaration handling (#7076)

- A function with a return declaration always has exactly one
`ReturnSlotPattern`, representing the whole return declaration (whereas
previously that was omitted for value and reference returns).
- The `ReturnSlotPattern` always has a subpattern with the same form.
`OutParamPattern` already plays that role for initializing forms, and
`TuplePattern` will play that role for tuple forms. This change
introduces `ValueReturnPattern` and `RefReturnPattern` to represent
value and reference return forms.
- As before, the `ReturnSlotPattern` has a corresponding `ReturnSlot`
that represents the output that is initialized by a `return` statement.
Its structure parallels the structure of the `ReturnSlotPattern`, so we
need `ValueReturn` and `RefReturn` insts that correspond to
`ValueReturnPattern` and `RefReturnPattern`.

This is a step toward supporting generic return forms, where the
`ReturnSlotPattern`'s subpattern may be an action: this change ensures
that evaluating the action for a specific form produces the same SemIR
as if the form were concrete to begin with. More speculatively, this
should simplify the implementation of `return` statements with compound
return forms.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Geoff Romer 1 week geleden
bovenliggende
commit
49c7288619
40 gewijzigde bestanden met toevoegingen van 593 en 385 verwijderingen
  1. 8 9
      toolchain/check/call.cpp
  2. 4 5
      toolchain/check/convert.cpp
  3. 1 2
      toolchain/check/convert.h
  4. 12 14
      toolchain/check/cpp/import.cpp
  5. 7 8
      toolchain/check/cpp/thunk.cpp
  6. 36 29
      toolchain/check/function.cpp
  7. 2 2
      toolchain/check/function.h
  8. 1 1
      toolchain/check/global_init.cpp
  9. 9 9
      toolchain/check/handle_function.cpp
  10. 1 1
      toolchain/check/handle_impl.cpp
  11. 27 5
      toolchain/check/import_ref.cpp
  12. 3 3
      toolchain/check/name_component.cpp
  13. 2 2
      toolchain/check/name_component.h
  14. 1 1
      toolchain/check/node_stack.h
  15. 37 14
      toolchain/check/pattern_match.cpp
  16. 5 5
      toolchain/check/pattern_match.h
  17. 202 214
      toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon
  18. 13 15
      toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon
  19. 2 0
      toolchain/check/testdata/class/self/self.carbon
  20. 1 1
      toolchain/check/testdata/eval/call.carbon
  21. 16 6
      toolchain/check/testdata/function/call/form.carbon
  22. 7 2
      toolchain/check/testdata/function/declaration/ref.carbon
  23. 8 2
      toolchain/check/testdata/impl/import_use_generic.carbon
  24. 4 1
      toolchain/check/testdata/impl/incomplete.carbon
  25. 12 1
      toolchain/check/testdata/impl/use_assoc_entity.carbon
  26. 4 1
      toolchain/check/testdata/interface/fail_lookup_undefined.carbon
  27. 2 0
      toolchain/check/testdata/interface/fail_member_lookup.carbon
  28. 8 2
      toolchain/check/testdata/let/compile_time_bindings.carbon
  29. 4 1
      toolchain/check/testdata/packages/export_import.carbon
  30. 4 1
      toolchain/check/testdata/return/fail_call_in_type.carbon
  31. 4 1
      toolchain/check/testdata/return/fail_error_in_type.carbon
  32. 12 3
      toolchain/check/testdata/return/fail_let_in_type.carbon
  33. 4 1
      toolchain/check/testdata/return/fail_var_in_type.carbon
  34. 4 1
      toolchain/check/testdata/struct/fail_duplicate_name.carbon
  35. 26 10
      toolchain/check/thunk.cpp
  36. 18 0
      toolchain/lower/handle.cpp
  37. 8 11
      toolchain/sem_ir/function.h
  38. 16 0
      toolchain/sem_ir/inst_categories.h
  39. 4 0
      toolchain/sem_ir/inst_kind.def
  40. 54 1
      toolchain/sem_ir/typed_insts.h

+ 8 - 9
toolchain/check/call.cpp

@@ -236,17 +236,16 @@ auto PerformCallToFunction(Context& context, SemIR::LocId loc_id,
     return_type_id = GetTupleType(context, {});
   }
 
-  llvm::SmallVector<SemIR::InstId, 1> return_arg_ids;
-  for (auto return_pattern_id :
-       context.inst_blocks().GetOrEmpty(callee.return_patterns_id)) {
+  auto return_arg_id = SemIR::InstId::None;
+  if (callee.return_pattern_id.has_value()) {
     Diagnostics::AnnotationScope annotate_diagnostics(
         &context.emitter(), [&](auto& builder) {
           CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,
                             "return type declared here");
-          builder.Note(return_pattern_id, IncompleteReturnTypeHere);
+          builder.Note(callee.return_pattern_id, IncompleteReturnTypeHere);
         });
     auto arg_type_id = CheckFunctionReturnPatternType(
-        context, loc_id, return_pattern_id, *callee_specific_id);
+        context, loc_id, callee.return_pattern_id, *callee_specific_id);
     if (arg_type_id == SemIR::ErrorInst::TypeId) {
       return_type_id = SemIR::ErrorInst::TypeId;
     }
@@ -255,20 +254,20 @@ auto PerformCallToFunction(Context& context, SemIR::LocId loc_id,
       case SemIR::InitRepr::Dependent:
         // Tentatively use storage for a temporary as the return argument.
         // This will be replaced if necessary when we perform initialization.
-        return_arg_ids.push_back(AddInst<SemIR::TemporaryStorage>(
-            context, loc_id, {.type_id = arg_type_id}));
+        return_arg_id = AddInst<SemIR::TemporaryStorage>(
+            context, loc_id, {.type_id = arg_type_id});
         break;
       case SemIR::InitRepr::None:
       case SemIR::InitRepr::ByCopy:
       case SemIR::InitRepr::Incomplete:
       case SemIR::InitRepr::Abstract:
-        return_arg_ids.push_back(SemIR::InstId::None);
+        return_arg_id = SemIR::InstId::None;
         break;
     }
   }
   // Convert the arguments to match the parameters.
   auto converted_args_id = ConvertCallArgs(
-      context, loc_id, callee_function.self_id, arg_ids, return_arg_ids, callee,
+      context, loc_id, callee_function.self_id, arg_ids, return_arg_id, callee,
       *callee_specific_id, is_operator_syntax);
   switch (callee.special_function_kind) {
     case SemIR::Function::SpecialFunctionKind::Thunk: {

+ 4 - 5
toolchain/check/convert.cpp

@@ -2130,13 +2130,12 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
 auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
                      SemIR::InstId self_id,
                      llvm::ArrayRef<SemIR::InstId> arg_refs,
-                     llvm::ArrayRef<SemIR::InstId> return_arg_ids,
-                     const SemIR::Function& callee,
+                     SemIR::InstId return_arg_id, const SemIR::Function& callee,
                      SemIR::SpecificId callee_specific_id,
                      bool is_operator_syntax) -> SemIR::InstBlockId {
   auto param_patterns =
       context.inst_blocks().GetOrEmpty(callee.param_patterns_id);
-  auto return_patterns_id = callee.return_patterns_id;
+  auto return_pattern_id = callee.return_pattern_id;
 
   // The caller should have ensured this callee has the right arity.
   CARBON_CHECK(arg_refs.size() == param_patterns.size());
@@ -2153,8 +2152,8 @@ auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
   }
 
   return CallerPatternMatch(context, callee_specific_id, callee.self_param_id,
-                            callee.param_patterns_id, return_patterns_id,
-                            self_id, arg_refs, return_arg_ids,
+                            callee.param_patterns_id, return_pattern_id,
+                            self_id, arg_refs, return_arg_id,
                             is_operator_syntax);
 }
 

+ 1 - 2
toolchain/check/convert.h

@@ -157,8 +157,7 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
 auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
                      SemIR::InstId self_id,
                      llvm::ArrayRef<SemIR::InstId> arg_refs,
-                     llvm::ArrayRef<SemIR::InstId> return_arg_ids,
-                     const SemIR::Function& callee,
+                     SemIR::InstId return_arg_id, const SemIR::Function& callee,
                      SemIR::SpecificId callee_specific_id,
                      bool is_operator_syntax) -> SemIR::InstBlockId;
 

+ 12 - 14
toolchain/check/cpp/import.cpp

@@ -1294,7 +1294,7 @@ static auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id,
 struct ReturnInfo {
   SemIR::TypeInstId return_type_inst_id;
   SemIR::InstId return_form_inst_id;
-  SemIR::InstBlockId return_patterns_id;
+  SemIR::InstId return_pattern_id;
 };
 
 // Returns information about the declared return type of the given function
@@ -1309,12 +1309,12 @@ static auto GetReturnInfo(Context& context, SemIR::LocId loc_id,
     // void.
     return {.return_type_inst_id = SemIR::TypeInstId::None,
             .return_form_inst_id = SemIR::InstId::None,
-            .return_patterns_id = SemIR::InstBlockId::None};
+            .return_pattern_id = SemIR::InstId::None};
   }
   if (form_inst_id == SemIR::ErrorInst::InstId) {
     return {.return_type_inst_id = SemIR::ErrorInst::TypeInstId,
             .return_form_inst_id = SemIR::ErrorInst::InstId,
-            .return_patterns_id = SemIR::InstBlockId::None};
+            .return_pattern_id = SemIR::InstId::None};
   }
   auto pattern_type_id = GetPatternType(context, type_id);
   clang::SourceLocation return_type_loc =
@@ -1328,7 +1328,7 @@ static auto GetReturnInfo(Context& context, SemIR::LocId loc_id,
   }
   SemIR::ImportIRInstId return_type_import_ir_inst_id =
       AddImportIRInst(context.sem_ir(), return_type_loc);
-  auto return_patterns_id = SemIR::InstBlockId::Empty;
+  auto return_pattern_id = SemIR::InstId::None;
   if (auto init_form =
           context.insts().TryGetAs<SemIR::InitForm>(form_inst_id)) {
     auto param_pattern_id = AddInst(
@@ -1337,18 +1337,17 @@ static auto GetReturnInfo(Context& context, SemIR::LocId loc_id,
                      SemIR::OutParamPattern(
                          {.type_id = pattern_type_id,
                           .pretty_name_id = SemIR::NameId::ReturnSlot})));
-    SemIR::InstId return_slot_pattern_id =
+    return_pattern_id =
         AddInst(context,
                 SemIR::LocIdAndInst::RuntimeVerified(
                     context.sem_ir(), return_type_import_ir_inst_id,
                     SemIR::ReturnSlotPattern({.type_id = pattern_type_id,
                                               .subpattern_id = param_pattern_id,
                                               .type_inst_id = type_inst_id})));
-    return_patterns_id = context.inst_blocks().Add({return_slot_pattern_id});
   }
   return {.return_type_inst_id = type_inst_id,
           .return_form_inst_id = form_inst_id,
-          .return_patterns_id = return_patterns_id};
+          .return_pattern_id = return_pattern_id};
 }
 
 namespace {
@@ -1360,7 +1359,7 @@ struct FunctionSignatureInsts {
   SemIR::InstBlockId param_patterns_id;
   SemIR::TypeInstId return_type_inst_id;
   SemIR::InstId return_form_inst_id;
-  SemIR::InstBlockId return_patterns_id;
+  SemIR::InstId return_pattern_id;
   SemIR::InstBlockId call_param_patterns_id;
   SemIR::InstBlockId call_params_id;
   SemIR::Function::CallParamIndexRanges param_ranges;
@@ -1392,21 +1391,20 @@ static auto CreateFunctionSignatureInsts(
     return std::nullopt;
   }
   context.full_pattern_stack().EndExplicitParamList();
-  auto [return_type_inst_id, return_form_inst_id, return_patterns_id] =
+  auto [return_type_inst_id, return_form_inst_id, return_pattern_id] =
       GetReturnInfo(context, loc_id, clang_decl);
   if (return_type_inst_id == SemIR::ErrorInst::TypeInstId) {
     return std::nullopt;
   }
 
-  auto match_results =
-      CalleePatternMatch(context, implicit_param_patterns_id, param_patterns_id,
-                         return_patterns_id);
+  auto match_results = CalleePatternMatch(context, implicit_param_patterns_id,
+                                          param_patterns_id, return_pattern_id);
 
   return {{.implicit_param_patterns_id = implicit_param_patterns_id,
            .param_patterns_id = param_patterns_id,
            .return_type_inst_id = return_type_inst_id,
            .return_form_inst_id = return_form_inst_id,
-           .return_patterns_id = return_patterns_id,
+           .return_pattern_id = return_pattern_id,
            .call_param_patterns_id = match_results.call_param_patterns_id,
            .call_params_id = match_results.call_params_id,
            .param_ranges = match_results.param_ranges}};
@@ -1518,7 +1516,7 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
               .call_param_ranges = function_params_insts->param_ranges,
               .return_type_inst_id = function_params_insts->return_type_inst_id,
               .return_form_inst_id = function_params_insts->return_form_inst_id,
-              .return_patterns_id = function_params_insts->return_patterns_id,
+              .return_pattern_id = function_params_insts->return_pattern_id,
               .virtual_modifier = virtual_modifier,
               .virtual_index = virtual_index,
               .evaluation_mode = evaluation_mode,

+ 7 - 8
toolchain/check/cpp/thunk.cpp

@@ -667,23 +667,22 @@ auto PerformCppThunkCall(Context& context, SemIR::LocId loc_id,
   auto& callee_function = context.functions().Get(callee_function_id);
   auto callee_function_params =
       context.inst_blocks().Get(callee_function.call_params_id);
-  auto callee_return_patterns =
-      context.inst_blocks().GetOrEmpty(callee_function.return_patterns_id);
+  auto num_callee_return_params =
+      callee_function.call_param_ranges.return_size();
 
   auto thunk_callee = GetCalleeAsFunction(context.sem_ir(), thunk_callee_id);
   auto& thunk_function = context.functions().Get(thunk_callee.function_id);
   auto thunk_function_params =
       context.inst_blocks().Get(thunk_function.call_params_id);
-  auto thunk_return_patterns =
-      context.inst_blocks().GetOrEmpty(thunk_function.return_patterns_id);
+  auto num_thunk_return_params = thunk_function.call_param_ranges.return_size();
 
   CARBON_CHECK(
-      callee_return_patterns.size() <= 1 && thunk_return_patterns.size() <= 1,
+      num_callee_return_params <= 1 && num_thunk_return_params <= 1,
       "TODO: generalize this logic to support multiple return patterns.");
 
   // Whether we need to pass a return address to the thunk as a final argument.
   bool thunk_takes_return_address =
-      !callee_return_patterns.empty() && thunk_return_patterns.empty();
+      num_callee_return_params > 0 && num_thunk_return_params == 0;
 
   // The number of arguments we should be acquiring in order to call the thunk.
   // This includes the return address parameters, if any.
@@ -704,9 +703,9 @@ auto PerformCppThunkCall(Context& context, SemIR::LocId loc_id,
   // TODO: The parameter should probably only be created if the return pattern
   // actually needs a return address to be passed in.
   thunk_function_params =
-      thunk_function_params.drop_back(thunk_return_patterns.size());
+      thunk_function_params.drop_back(num_thunk_return_params);
   callee_function_params =
-      callee_function_params.drop_back(callee_return_patterns.size());
+      callee_function_params.drop_back(num_callee_return_params);
 
   // We assume that the call parameters exactly match the parameter patterns for
   // both the thunk and the callee. This is guaranteed even when we generate a

+ 36 - 29
toolchain/check/function.cpp

@@ -32,42 +32,52 @@ auto FindSelfPattern(Context& context,
   });
 }
 
-auto AddReturnPatterns(Context& context, SemIR::LocId loc_id,
-                       Context::FormExpr form_expr) -> SemIR::InstBlockId {
-  llvm::SmallVector<SemIR::InstId, 1> return_patterns;
+auto AddReturnPattern(Context& context, SemIR::LocId loc_id,
+                      Context::FormExpr form_expr) -> SemIR::InstId {
+  auto result_id = SemIR::InstId::None;
+  auto result_type_id = SemIR::TypeId::None;
   auto form_inst = context.insts().Get(
       context.constant_values().GetConstantInstId(form_expr.form_inst_id));
   CARBON_KIND_SWITCH(form_inst) {
-    case SemIR::RefForm::Kind:
+    case SemIR::RefForm::Kind: {
+      result_type_id = GetPatternType(context, form_expr.type_component_id);
+      result_id = AddInst<SemIR::RefReturnPattern>(context, loc_id,
+                                                   {.type_id = result_type_id});
+      break;
+    }
     case SemIR::ValueForm::Kind: {
+      result_type_id = GetPatternType(context, form_expr.type_component_id);
+      result_id = AddInst<SemIR::ValueReturnPattern>(
+          context, loc_id, {.type_id = result_type_id});
       break;
     }
     case CARBON_KIND(SemIR::InitForm _): {
-      auto pattern_type_id =
-          GetPatternType(context, form_expr.type_component_id);
-      auto out_param_id = AddInst<SemIR::OutParamPattern>(
+      result_type_id = GetPatternType(context, form_expr.type_component_id);
+      result_id = AddInst<SemIR::OutParamPattern>(
           context, SemIR::LocId(form_expr.form_inst_id),
-          {.type_id = pattern_type_id,
+          {.type_id = result_type_id,
            .pretty_name_id = SemIR::NameId::ReturnSlot});
-      return_patterns.push_back(AddInst<SemIR::ReturnSlotPattern>(
-          context, SemIR::LocId(form_expr.form_inst_id),
-          {.type_id = pattern_type_id,
-           .subpattern_id = out_param_id,
-           .type_inst_id = form_expr.type_component_inst_id}));
-      break;
-    }
-    case SemIR::ErrorInst::Kind: {
       break;
     }
     case SemIR::SymbolicBinding::Kind:
       CARBON_CHECK(
           context.constant_values().Get(form_expr.form_inst_id).is_symbolic());
       context.TODO(loc_id, "Support symbolic return forms");
+      result_type_id = SemIR::ErrorInst::TypeId;
+      result_id = SemIR::ErrorInst::InstId;
+      break;
+    case SemIR::ErrorInst::Kind:
+      result_type_id = SemIR::ErrorInst::TypeId;
+      result_id = SemIR::ErrorInst::InstId;
       break;
     default:
       CARBON_FATAL("unexpected inst kind: {0}", form_inst);
   }
-  return context.inst_blocks().AddCanonical(return_patterns);
+  return AddInst<SemIR::ReturnSlotPattern>(
+      context, SemIR::LocId(form_expr.form_inst_id),
+      {.type_id = result_type_id,
+       .subpattern_id = result_id,
+       .type_inst_id = form_expr.type_component_inst_id});
 }
 
 auto IsValidBuiltinDeclaration(Context& context,
@@ -108,7 +118,7 @@ struct FunctionSignatureInsts {
       SemIR::Function::CallParamIndexRanges::Empty;
   SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None;
   SemIR::InstId return_form_inst_id = SemIR::InstId::None;
-  SemIR::InstBlockId return_patterns_id = SemIR::InstBlockId::None;
+  SemIR::InstId return_pattern_id = SemIR::InstId::None;
   SemIR::InstId self_param_id = SemIR::InstId::None;
 };
 }  // namespace
@@ -166,12 +176,12 @@ static auto MakeFunctionSignature(Context& context, SemIR::LocId loc_id,
         context, loc_id, context.types().GetTypeInstId(args.return_type_id));
     insts.return_type_inst_id = return_form.type_component_inst_id;
     insts.return_form_inst_id = return_form.form_inst_id;
-    insts.return_patterns_id = AddReturnPatterns(context, loc_id, return_form);
+    insts.return_pattern_id = AddReturnPattern(context, loc_id, return_form);
   }
 
   auto match_results =
       CalleePatternMatch(context, insts.implicit_param_patterns_id,
-                         insts.param_patterns_id, insts.return_patterns_id);
+                         insts.param_patterns_id, insts.return_pattern_id);
   insts.call_param_patterns_id = match_results.call_param_patterns_id;
   insts.call_params_id = match_results.call_params_id;
   insts.call_param_ranges = match_results.param_ranges;
@@ -215,7 +225,7 @@ auto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id,
               .call_param_ranges = insts.call_param_ranges,
               .return_type_inst_id = insts.return_type_inst_id,
               .return_form_inst_id = insts.return_form_inst_id,
-              .return_patterns_id = insts.return_patterns_id,
+              .return_pattern_id = insts.return_pattern_id,
               .self_param_id = insts.self_param_id,
           }});
   context.generated().push_back(decl_id);
@@ -386,7 +396,7 @@ auto CheckFunctionDefinitionSignature(Context& context,
   // The return parameter will be diagnosed after and differently from other
   // parameters.
   auto return_call_param = SemIR::InstId::None;
-  if (!params_to_complete.empty() && function.return_patterns_id.has_value()) {
+  if (!params_to_complete.empty() && function.return_pattern_id.has_value()) {
     return_call_param = params_to_complete.consume_back();
   }
 
@@ -410,13 +420,10 @@ auto CheckFunctionDefinitionSignature(Context& context,
   }
 
   // Check the return type is complete.
-  if (function.return_patterns_id.has_value()) {
-    for (auto return_pattern_id :
-         context.inst_blocks().Get(function.return_patterns_id)) {
-      CheckFunctionReturnPatternType(context, SemIR::LocId(return_pattern_id),
-                                     return_pattern_id,
-                                     SemIR::SpecificId::None);
-    }
+  if (function.return_pattern_id.has_value()) {
+    CheckFunctionReturnPatternType(
+        context, SemIR::LocId(function.return_pattern_id),
+        function.return_pattern_id, SemIR::SpecificId::None);
 
     // `CheckFunctionReturnPatternType` should have diagnosed incomplete types,
     // so don't `RequireCompleteType` on the return type.

+ 2 - 2
toolchain/check/function.h

@@ -22,8 +22,8 @@ auto FindSelfPattern(Context& context,
 
 // Creates suitable return patterns for the given return form, and adds them to
 // the current pattern block.
-auto AddReturnPatterns(Context& context, SemIR::LocId loc_id,
-                       Context::FormExpr form_expr) -> SemIR::InstBlockId;
+auto AddReturnPattern(Context& context, SemIR::LocId loc_id,
+                      Context::FormExpr form_expr) -> SemIR::InstId;
 
 // Returns whether `function` is a valid declaration of `builtin_kind`.
 auto IsValidBuiltinDeclaration(Context& context,

+ 1 - 1
toolchain/check/global_init.cpp

@@ -53,7 +53,7 @@ auto GlobalInit::Finalize() -> void {
         .call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty,
         .return_type_inst_id = SemIR::TypeInstId::None,
         .return_form_inst_id = SemIR::InstId::None,
-        .return_patterns_id = SemIR::InstBlockId::None,
+        .return_pattern_id = SemIR::InstId::None,
         .body_block_ids = {SemIR::InstBlockId::GlobalInit}}}));
 }
 

+ 9 - 9
toolchain/check/handle_function.cpp

@@ -61,8 +61,8 @@ static auto HandleReturnDecl(Context& context, Parse::AnyReturnDeclId node_id)
     }
   }();
   context.PushReturnForm(form_expr);
-  auto return_patterns_id = AddReturnPatterns(context, node_id, form_expr);
-  context.node_stack().Push(node_id, return_patterns_id);
+  context.node_stack().Push(node_id,
+                            AddReturnPattern(context, node_id, form_expr));
   return true;
 }
 
@@ -173,7 +173,7 @@ static auto MergeFunctionRedecl(Context& context,
     prev_function.call_params_id = new_function.call_params_id;
     prev_function.return_type_inst_id = new_function.return_type_inst_id;
     prev_function.return_form_inst_id = new_function.return_form_inst_id;
-    prev_function.return_patterns_id = new_function.return_patterns_id;
+    prev_function.return_pattern_id = new_function.return_pattern_id;
     prev_function.self_param_id = new_function.self_param_id;
   }
   if (prev_import_ir_id.has_value()) {
@@ -500,20 +500,20 @@ static auto BuildFunctionDecl(Context& context,
                               Parse::AnyFunctionDeclId node_id,
                               bool is_definition)
     -> std::pair<SemIR::FunctionId, SemIR::InstId> {
-  auto return_patterns_id = SemIR::InstBlockId::None;
+  auto return_pattern_id = SemIR::InstId::None;
   auto return_type_inst_id = SemIR::TypeInstId::None;
   auto return_form_inst_id = SemIR::InstId::None;
-  if (auto [return_node, maybe_return_patterns_id] =
+  if (auto [return_node, maybe_return_pattern_id] =
           context.node_stack()
               .PopWithNodeIdIf<Parse::NodeCategory::ReturnDecl>();
-      maybe_return_patterns_id) {
-    return_patterns_id = *maybe_return_patterns_id;
+      maybe_return_pattern_id) {
+    return_pattern_id = *maybe_return_pattern_id;
     auto return_form = context.PopReturnForm();
     return_type_inst_id = return_form.type_component_inst_id;
     return_form_inst_id = return_form.form_inst_id;
   }
 
-  auto name = PopNameComponent(context, return_patterns_id);
+  auto name = PopNameComponent(context, return_pattern_id);
   auto name_context = context.decl_name_stack().FinishName(name);
 
   context.node_stack()
@@ -550,7 +550,7 @@ static auto BuildFunctionDecl(Context& context,
                        .call_param_ranges = name.param_ranges,
                        .return_type_inst_id = return_type_inst_id,
                        .return_form_inst_id = return_form_inst_id,
-                       .return_patterns_id = return_patterns_id,
+                       .return_pattern_id = return_pattern_id,
                        .virtual_modifier = virtual_modifier,
                        .evaluation_mode = evaluation_mode,
                        .self_param_id = self_param_id}};

+ 1 - 1
toolchain/check/handle_impl.cpp

@@ -158,7 +158,7 @@ static auto PopImplIntroducerAndParamsAsNameComponent(
     // because `impl`s are never actually called at runtime.
     auto match_results =
         CalleePatternMatch(context, *implicit_param_patterns_id,
-                           SemIR::InstBlockId::None, SemIR::InstBlockId::None);
+                           SemIR::InstBlockId::None, SemIR::InstId::None);
     CARBON_CHECK(match_results.call_params_id == SemIR::InstBlockId::Empty);
     CARBON_CHECK(match_results.call_param_patterns_id ==
                  SemIR::InstBlockId::Empty);

+ 27 - 5
toolchain/check/import_ref.cpp

@@ -1568,6 +1568,23 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, ParamPatternT inst,
        .pretty_name_id = name_id});
 }
 
+template <typename ReturnPatternT>
+  requires SemIR::Internal::HasInstCategory<SemIR::AnyReturnPattern,
+                                            ReturnPatternT>
+static auto TryResolveTypedInst(ImportRefResolver& resolver,
+                                ReturnPatternT inst,
+                                SemIR::InstId import_inst_id) -> ResolveResult {
+  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);
+  if (resolver.HasNewWork()) {
+    return ResolveResult::Retry();
+  }
+
+  return ResolveResult::Unique<ReturnPatternT>(
+      resolver, import_inst_id,
+      {.type_id =
+           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id)});
+}
+
 static auto TryResolveTypedInst(ImportRefResolver& resolver,
                                 SemIR::ArrayType inst) -> ResolveResult {
   CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);
@@ -2227,7 +2244,7 @@ static auto ImportFunctionDecl(ImportContext& context,
         .call_param_ranges = import_function.call_param_ranges,
         .return_type_inst_id = SemIR::TypeInstId::None,
         .return_form_inst_id = SemIR::InstId::None,
-        .return_patterns_id = SemIR::InstBlockId::None,
+        .return_pattern_id = SemIR::InstId::None,
         .virtual_modifier = import_function.virtual_modifier,
         .virtual_index = import_function.virtual_index,
         .evaluation_mode = import_function.evaluation_mode}});
@@ -2304,8 +2321,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
   auto generic_data = GetLocalGenericData(resolver, import_function.generic_id);
   auto self_param_id =
       GetLocalConstantInstId(resolver, import_function.self_param_id);
-  auto return_patterns =
-      GetLocalInstBlockContents(resolver, import_function.return_patterns_id);
+  auto return_pattern_id =
+      GetLocalConstantInstId(resolver, import_function.return_pattern_id);
   auto& new_function = resolver.local_functions().Get(function_id);
   if (resolver.HasNewWork()) {
     return ResolveResult::Retry(function_const_id,
@@ -2333,8 +2350,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
         resolver, SemIR::FormType::TypeId, import_function.return_form_inst_id,
         return_form_const_id);
   }
-  new_function.return_patterns_id = GetLocalCanonicalInstBlockId(
-      resolver, import_function.return_patterns_id, return_patterns);
+  new_function.return_pattern_id = return_pattern_id;
   if (import_function.definition_id.has_value()) {
     new_function.definition_id = new_function.first_owning_decl_id;
   }
@@ -4266,6 +4282,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
     case CARBON_KIND(SemIR::RefParamPattern inst): {
       return TryResolveTypedInst(resolver, inst, constant_inst_id);
     }
+    case CARBON_KIND(SemIR::RefReturnPattern inst): {
+      return TryResolveTypedInst(resolver, inst, constant_inst_id);
+    }
     case CARBON_KIND(SemIR::RequireCompleteType inst): {
       return TryResolveTypedInst(resolver, inst);
     }
@@ -4320,6 +4339,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
     case CARBON_KIND(SemIR::ValueParamPattern inst): {
       return TryResolveTypedInst(resolver, inst, constant_inst_id);
     }
+    case CARBON_KIND(SemIR::ValueReturnPattern inst): {
+      return TryResolveTypedInst(resolver, inst, constant_inst_id);
+    }
     case CARBON_KIND(SemIR::VarParamPattern inst): {
       return TryResolveTypedInst(resolver, inst, constant_inst_id);
     }

+ 3 - 3
toolchain/check/name_component.cpp

@@ -9,7 +9,7 @@
 
 namespace Carbon::Check {
 
-auto PopNameComponent(Context& context, SemIR::InstBlockId return_patterns_id)
+auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
     -> NameComponent {
   Parse::NodeId first_param_node_id = Parse::NoneNodeId();
   Parse::NodeId last_param_node_id = Parse::NoneNodeId();
@@ -50,9 +50,9 @@ auto PopNameComponent(Context& context, SemIR::InstBlockId return_patterns_id)
   auto pattern_block_id = SemIR::InstBlockId::None;
   if (param_patterns_id->has_value() ||
       implicit_param_patterns_id->has_value() ||
-      (!context.inst_blocks().GetOrEmpty(return_patterns_id).empty())) {
+      return_pattern_id.has_value()) {
     auto results = CalleePatternMatch(context, *implicit_param_patterns_id,
-                                      *param_patterns_id, return_patterns_id);
+                                      *param_patterns_id, return_pattern_id);
     call_param_patterns_id = results.call_param_patterns_id;
     call_params_id = results.call_params_id;
     param_ranges = results.param_ranges;

+ 2 - 2
toolchain/check/name_component.h

@@ -48,8 +48,8 @@ struct NameComponent {
 
 // Pops a name component from the node stack (and pattern block stack, if it has
 // parameters).
-auto PopNameComponent(Context& context, SemIR::InstBlockId return_patterns_id =
-                                            SemIR::InstBlockId::None)
+auto PopNameComponent(Context& context,
+                      SemIR::InstId return_pattern_id = SemIR::InstId::None)
     -> NameComponent;
 
 // Equivalent to PopNameComponent, but also diagnoses if the name component has

+ 1 - 1
toolchain/check/node_stack.h

@@ -404,7 +404,7 @@ class NodeStack {
                               Parse::NodeCategory::Modifier,
                           Id::Kind::None);
     set_id_if_category_is(Parse::NodeCategory::ReturnDecl,
-                          Id::KindFor<SemIR::InstBlockId>());
+                          Id::KindFor<SemIR::InstId>());
     return result;
   }
 

+ 37 - 14
toolchain/check/pattern_match.cpp

@@ -148,6 +148,8 @@ class MatchContext {
                  SemIR::InstId scrutinee_id, WorkItem entry) -> void;
   auto DoPreWork(State state, SemIR::AnyParamPattern param_pattern,
                  SemIR::InstId scrutinee_id, WorkItem entry) -> void;
+  auto DoPreWork(State state, SemIR::AnyReturnPattern return_pattern,
+                 SemIR::InstId scrutinee_id, WorkItem entry) -> void;
   auto DoPreWork(State state, SemIR::ExprPattern expr_pattern,
                  SemIR::InstId scrutinee_id, WorkItem entry) -> void;
   auto DoPreWork(State state, SemIR::ReturnSlotPattern return_slot_pattern,
@@ -786,6 +788,26 @@ auto MatchContext::DoPostWork(State /*state*/,
   results_stack_.AppendToTop(tuple_value_id);
 }
 
+auto MatchContext::DoPreWork(State state,
+                             SemIR::AnyReturnPattern return_pattern,
+                             SemIR::InstId /*scrutinee_id*/, WorkItem entry)
+    -> void {
+  CARBON_CHECK(std::holds_alternative<CalleeState*>(state));
+  if (need_subpattern_results()) {
+    auto type_id =
+        ExtractScrutineeType(context_.sem_ir(), return_pattern.type_id);
+    SemIR::InstKind result_kind =
+        return_pattern.kind == SemIR::RefReturnPattern::Kind
+            ? SemIR::RefReturn::Kind
+            : SemIR::ValueReturn::Kind;
+    results_stack_.AppendToTop(AddInst(
+        context_,
+        SemIR::LocIdAndInst::RuntimeVerified(
+            context_.sem_ir(), SemIR::LocId(entry.pattern_id),
+            SemIR::AnyReturnPattern{.kind = result_kind, .type_id = type_id})));
+  }
+}
+
 auto MatchContext::Dispatch(State state, WorkItem entry) -> void {
   if (entry.pattern_id == SemIR::ErrorInst::InstId) {
     if (need_subpattern_results()) {
@@ -816,6 +838,10 @@ auto MatchContext::Dispatch(State state, WorkItem entry) -> void {
           DoPreWork(state, any_param_pattern, work.scrutinee_id, entry);
           break;
         }
+        case CARBON_KIND_ANY(SemIR::AnyReturnPattern, return_pattern): {
+          DoPreWork(state, return_pattern, work.scrutinee_id, entry);
+          break;
+        }
         case CARBON_KIND(SemIR::ExprPattern expr_pattern): {
           DoPreWork(state, expr_pattern, work.scrutinee_id, entry);
           break;
@@ -876,9 +902,9 @@ auto MatchContext::Dispatch(State state, WorkItem entry) -> void {
 auto CalleePatternMatch(Context& context,
                         SemIR::InstBlockId implicit_param_patterns_id,
                         SemIR::InstBlockId param_patterns_id,
-                        SemIR::InstBlockId return_patterns_id)
+                        SemIR::InstId return_pattern_id)
     -> CalleePatternMatchResults {
-  if (!return_patterns_id.has_value() && !param_patterns_id.has_value() &&
+  if (!return_pattern_id.has_value() && !param_patterns_id.has_value() &&
       !implicit_param_patterns_id.has_value()) {
     return {.call_param_patterns_id = SemIR::InstBlockId::None,
             .call_params_id = SemIR::InstBlockId::None,
@@ -911,8 +937,7 @@ auto CalleePatternMatch(Context& context,
   }
   auto explicit_end = SemIR::CallParamIndex(state.call_params.size());
 
-  for (auto return_pattern_id :
-       context.inst_blocks().GetOrEmpty(return_patterns_id)) {
+  if (return_pattern_id.has_value()) {
     match.Match(
         &state,
         {.pattern_id = return_pattern_id,
@@ -958,11 +983,11 @@ auto ThunkPatternMatch(Context& context, SemIR::InstId self_pattern_id,
 auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
                         SemIR::InstId self_pattern_id,
                         SemIR::InstBlockId param_patterns_id,
-                        SemIR::InstBlockId return_patterns_id,
+                        SemIR::InstId return_pattern_id,
                         SemIR::InstId self_arg_id,
                         llvm::ArrayRef<SemIR::InstId> arg_refs,
-                        llvm::ArrayRef<SemIR::InstId> return_arg_ids,
-                        bool is_operator_syntax) -> SemIR::InstBlockId {
+                        SemIR::InstId return_arg_id, bool is_operator_syntax)
+    -> SemIR::InstBlockId {
   CallerState state = {.callee_specific_id = specific_id};
   MatchContext match(context);
 
@@ -980,19 +1005,17 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
                          .allow_unmarked_ref = is_operator_syntax});
   }
 
-  auto return_patterns = context.inst_blocks().GetOrEmpty(return_patterns_id);
   // Track the return storage, if present.
-  for (auto [return_pattern_id, return_arg_id] :
-       llvm::zip_equal(return_patterns, return_arg_ids)) {
+  if (return_pattern_id.has_value()) {
+    // TODO: Do the match even if return_arg_id is None, so that subsequent
+    // args are at the right index in the arg block.
     if (return_arg_id.has_value()) {
       match.Match(&state, {.pattern_id = return_pattern_id,
                            .work = MatchContext::PreWork{.scrutinee_id =
                                                              return_arg_id}});
-    } else {
-      CARBON_CHECK(return_arg_ids.size() == 1,
-                   "TODO: do the match even if return_arg_id is None, so that "
-                   "subsequent args are at the right index in the arg block");
     }
+  } else {
+    CARBON_CHECK(!return_arg_id.has_value(), "No pattern to match return arg");
   }
 
   return context.inst_blocks().Add(state.call_args);

+ 5 - 5
toolchain/check/pattern_match.h

@@ -29,7 +29,7 @@ struct CalleePatternMatchResults {
 
 // Emits the pattern-match IR for the declaration of a parameterized entity with
 // the given implicit and explicit parameter patterns, and the given return
-// patterns (any of which may be `None` if not applicable). This IR performs the
+// pattern (any of which may be `None` if not applicable). This IR performs the
 // callee side of pattern matching, starting at the `ParamPattern` insts, and
 // matching them against the corresponding `Call` parameters (see
 // entity_with_params_base.h for the definition of that term).
@@ -39,7 +39,7 @@ struct CalleePatternMatchResults {
 auto CalleePatternMatch(Context& context,
                         SemIR::InstBlockId implicit_param_patterns_id,
                         SemIR::InstBlockId param_patterns_id,
-                        SemIR::InstBlockId return_patterns_id)
+                        SemIR::InstId return_pattern_id)
     -> CalleePatternMatchResults;
 
 // Return type for ThunkPatternMatch.
@@ -70,11 +70,11 @@ auto ThunkPatternMatch(Context& context, SemIR::InstId self_pattern_id,
 auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
                         SemIR::InstId self_pattern_id,
                         SemIR::InstBlockId param_patterns_id,
-                        SemIR::InstBlockId return_patterns_id,
+                        SemIR::InstId return_pattern_id,
                         SemIR::InstId self_arg_id,
                         llvm::ArrayRef<SemIR::InstId> arg_refs,
-                        llvm::ArrayRef<SemIR::InstId> return_arg_ids,
-                        bool is_operator_syntax) -> SemIR::InstBlockId;
+                        SemIR::InstId return_arg_id, bool is_operator_syntax)
+    -> SemIR::InstBlockId;
 
 // Emits the pattern-match IR for a local pattern matching operation with the
 // given pattern and scrutinee.

+ 202 - 214
toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon

@@ -337,12 +337,12 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     entity_name7800003F: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: inst<none>}
 // CHECK:STDOUT:   cpp_global_vars: {}
 // CHECK:STDOUT:   functions:
-// CHECK:STDOUT:     function78000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block78000011, call_params_id: inst_block78000012, return_type_inst_id: inst78000030, return_form_inst_id: inst78000032, return_patterns_id: inst_block78000010, body: [inst_block78000019]}
-// CHECK:STDOUT:     function78000001: {name: name4, parent_scope: name_scope78000003, call_param_patterns_id: inst_block7800001F, return_type_inst_id: inst78000060, return_form_inst_id: inst78000061, return_patterns_id: inst_block78000021}
-// CHECK:STDOUT:     function78000002: {name: name4, parent_scope: name_scope78000004, call_param_patterns_id: inst_block7800002B, return_type_inst_id: inst78000080, return_form_inst_id: inst78000081, return_patterns_id: inst_block7800002D}
-// CHECK:STDOUT:     function78000003: {name: name4, parent_scope: name_scope78000009, call_param_patterns_id: inst_block78000042, return_type_inst_id: inst780000C8, return_form_inst_id: inst780000C9, return_patterns_id: inst_block78000044}
-// CHECK:STDOUT:     function78000004: {name: name4, parent_scope: name_scope7800000C, call_param_patterns_id: inst_block78000050, return_type_inst_id: inst780000ED, return_form_inst_id: inst780000EE, return_patterns_id: inst_block78000052}
-// CHECK:STDOUT:     function78000005: {name: name4, parent_scope: name_scope7800000D, call_param_patterns_id: inst_block7800006D, return_type_inst_id: inst78000131, return_form_inst_id: inst78000132, return_patterns_id: inst_block7800006F}
+// CHECK:STDOUT:     function78000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block78000010, call_params_id: inst_block78000011, return_type_inst_id: inst78000030, return_form_inst_id: inst78000032, return_pattern_id: inst78000038, body: [inst_block78000018]}
+// CHECK:STDOUT:     function78000001: {name: name4, parent_scope: name_scope78000003, call_param_patterns_id: inst_block7800001E, return_type_inst_id: inst78000060, return_form_inst_id: inst78000061, return_pattern_id: inst7800005C}
+// CHECK:STDOUT:     function78000002: {name: name4, parent_scope: name_scope78000004, call_param_patterns_id: inst_block78000029, return_type_inst_id: inst78000080, return_form_inst_id: inst78000081, return_pattern_id: inst7800007C}
+// CHECK:STDOUT:     function78000003: {name: name4, parent_scope: name_scope78000009, call_param_patterns_id: inst_block7800003F, return_type_inst_id: inst780000C8, return_form_inst_id: inst780000C9, return_pattern_id: inst780000C4}
+// CHECK:STDOUT:     function78000004: {name: name4, parent_scope: name_scope7800000C, call_param_patterns_id: inst_block7800004C, return_type_inst_id: inst780000ED, return_form_inst_id: inst780000EE, return_pattern_id: inst780000E9}
+// CHECK:STDOUT:     function78000005: {name: name4, parent_scope: name_scope7800000D, call_param_patterns_id: inst_block78000068, return_type_inst_id: inst78000131, return_form_inst_id: inst78000132, return_pattern_id: inst7800012D}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   interfaces:
 // CHECK:STDOUT:     interface78000000: {name: name3, parent_scope: name_scope78000001, require_impls_block_id: require_block_empty}
@@ -359,57 +359,57 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     impl78000008:    {self: inst78000111, constraint: inst78000112, witness: inst780000DA}
 // CHECK:STDOUT:     impl78000009:    {self: inst7800015F, constraint: inst78000160, witness: inst7800011E}
 // CHECK:STDOUT:   generics:
-// CHECK:STDOUT:     generic78000000: {decl: inst7800003E, bindings: inst_block78000015, self_specific_id: specific78000000, decl_block_id: inst_block78000017, definition_block_id: inst_block78000091}
-// CHECK:STDOUT:     generic78000001: {decl: inst78000051, bindings: inst_block7800001C, self_specific_id: specific78000001, decl_block_id: inst_block_empty, definition_block_id: inst_block78000026}
-// CHECK:STDOUT:     generic78000002: {decl: inst78000056, bindings: inst_block78000022, self_specific_id: specific78000002, decl_block_id: inst_block78000023, definition_block_id: inst_block<none>}
-// CHECK:STDOUT:     generic78000003: {decl: inst78000070, bindings: inst_block78000037, self_specific_id: specific78000004, decl_block_id: inst_block78000039, definition_block_id: inst_block7800003B}
-// CHECK:STDOUT:     generic78000004: {decl: inst78000077, bindings: inst_block7800002E, self_specific_id: specific78000007, decl_block_id: inst_block7800002F, definition_block_id: inst_block78000034}
-// CHECK:STDOUT:     generic78000005: {decl: inst780000B5, bindings: inst_block7800003F, self_specific_id: specific7800000B, decl_block_id: inst_block78000041, definition_block_id: inst_block78000049}
-// CHECK:STDOUT:     generic78000006: {decl: inst780000C0, bindings: inst_block78000045, self_specific_id: specific7800000D, decl_block_id: inst_block78000046, definition_block_id: inst_block_empty}
-// CHECK:STDOUT:     generic78000007: {decl: inst780000DB, bindings: inst_block78000060, self_specific_id: specific7800000E, decl_block_id: inst_block78000064, definition_block_id: inst_block78000066}
-// CHECK:STDOUT:     generic78000008: {decl: inst780000E2, bindings: inst_block78000053, self_specific_id: specific78000011, decl_block_id: inst_block78000055, definition_block_id: inst_block7800005D}
-// CHECK:STDOUT:     generic78000009: {decl: inst7800011F, bindings: inst_block7800007F, self_specific_id: specific78000017, decl_block_id: inst_block78000083, definition_block_id: inst_block78000085}
-// CHECK:STDOUT:     generic7800000A: {decl: inst78000126, bindings: inst_block78000070, self_specific_id: specific7800001A, decl_block_id: inst_block78000072, definition_block_id: inst_block7800007C}
+// CHECK:STDOUT:     generic78000000: {decl: inst7800003E, bindings: inst_block78000014, self_specific_id: specific78000000, decl_block_id: inst_block78000016, definition_block_id: inst_block7800008B}
+// CHECK:STDOUT:     generic78000001: {decl: inst78000051, bindings: inst_block7800001B, self_specific_id: specific78000001, decl_block_id: inst_block_empty, definition_block_id: inst_block78000024}
+// CHECK:STDOUT:     generic78000002: {decl: inst78000056, bindings: inst_block78000020, self_specific_id: specific78000002, decl_block_id: inst_block78000021, definition_block_id: inst_block<none>}
+// CHECK:STDOUT:     generic78000003: {decl: inst78000070, bindings: inst_block78000034, self_specific_id: specific78000004, decl_block_id: inst_block78000036, definition_block_id: inst_block78000038}
+// CHECK:STDOUT:     generic78000004: {decl: inst78000077, bindings: inst_block7800002B, self_specific_id: specific78000007, decl_block_id: inst_block7800002C, definition_block_id: inst_block78000031}
+// CHECK:STDOUT:     generic78000005: {decl: inst780000B5, bindings: inst_block7800003C, self_specific_id: specific7800000B, decl_block_id: inst_block7800003E, definition_block_id: inst_block78000045}
+// CHECK:STDOUT:     generic78000006: {decl: inst780000C0, bindings: inst_block78000041, self_specific_id: specific7800000D, decl_block_id: inst_block78000042, definition_block_id: inst_block_empty}
+// CHECK:STDOUT:     generic78000007: {decl: inst780000DB, bindings: inst_block7800005B, self_specific_id: specific7800000E, decl_block_id: inst_block7800005F, definition_block_id: inst_block78000061}
+// CHECK:STDOUT:     generic78000008: {decl: inst780000E2, bindings: inst_block7800004E, self_specific_id: specific78000011, decl_block_id: inst_block78000050, definition_block_id: inst_block78000058}
+// CHECK:STDOUT:     generic78000009: {decl: inst7800011F, bindings: inst_block78000079, self_specific_id: specific78000017, decl_block_id: inst_block7800007D, definition_block_id: inst_block7800007F}
+// CHECK:STDOUT:     generic7800000A: {decl: inst78000126, bindings: inst_block7800006A, self_specific_id: specific7800001A, decl_block_id: inst_block7800006C, definition_block_id: inst_block78000076}
 // CHECK:STDOUT:   specifics:
-// CHECK:STDOUT:     specific78000000: {generic: generic78000000, args: inst_block78000016, decl_block_id: inst_block78000018, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000001: {generic: generic78000001, args: inst_block7800001D, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block7800001E, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000002: {generic: generic78000002, args: inst_block7800001D, decl_block_id: inst_block78000024, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000003: {generic: generic78000001, args: inst_block78000025, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000004: {generic: generic78000003, args: inst_block78000028, decl_block_id: inst_block78000029, decl_has_error: 0, definition_block_id: inst_block7800002A, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000005: {generic: generic78000001, args: inst_block78000028, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block78000030, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000006: {generic: generic78000002, args: inst_block78000028, decl_block_id: inst_block78000031, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000007: {generic: generic78000004, args: inst_block78000028, decl_block_id: inst_block78000035, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000008: {generic: generic78000001, args: inst_block78000032, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000009: {generic: generic78000002, args: inst_block78000032, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000A: {generic: generic78000003, args: inst_block78000038, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000B: {generic: generic78000005, args: inst_block78000016, decl_block_id: inst_block7800003D, decl_has_error: 0, definition_block_id: inst_block78000086, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000C: {generic: generic78000005, args: inst_block78000040, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000D: {generic: generic78000006, args: inst_block78000016, decl_block_id: inst_block78000047, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000E: {generic: generic78000007, args: inst_block7800004C, decl_block_id: inst_block7800004E, decl_has_error: 0, definition_block_id: inst_block7800004F, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800000F: {generic: generic78000001, args: inst_block78000056, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block78000057, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000010: {generic: generic78000002, args: inst_block78000056, decl_block_id: inst_block78000058, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000011: {generic: generic78000008, args: inst_block7800004C, decl_block_id: inst_block7800005E, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000012: {generic: generic78000001, args: inst_block78000059, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000013: {generic: generic78000002, args: inst_block78000059, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000014: {generic: generic78000001, args: inst_block7800005B, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000015: {generic: generic78000002, args: inst_block7800005B, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000016: {generic: generic78000007, args: inst_block78000061, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000017: {generic: generic78000009, args: inst_block78000069, decl_block_id: inst_block7800006B, decl_has_error: 0, definition_block_id: inst_block7800006C, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000018: {generic: generic78000001, args: inst_block78000073, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block78000074, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000019: {generic: generic78000002, args: inst_block78000073, decl_block_id: inst_block78000075, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001A: {generic: generic7800000A, args: inst_block78000069, decl_block_id: inst_block7800007D, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001B: {generic: generic78000001, args: inst_block78000076, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001C: {generic: generic78000002, args: inst_block78000076, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001D: {generic: generic78000001, args: inst_block78000078, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001E: {generic: generic78000002, args: inst_block78000078, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific7800001F: {generic: generic78000001, args: inst_block7800007A, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000020: {generic: generic78000002, args: inst_block7800007A, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000021: {generic: generic78000009, args: inst_block78000080, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000022: {generic: generic78000005, args: inst_block78000087, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000023: {generic: generic78000001, args: inst_block78000089, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block7800008A, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000024: {generic: generic78000001, args: inst_block7800008C, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000025: {generic: generic78000002, args: inst_block78000089, decl_block_id: inst_block7800008D, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
-// CHECK:STDOUT:     specific78000026: {generic: generic78000002, args: inst_block7800008C, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000000: {generic: generic78000000, args: inst_block78000015, decl_block_id: inst_block78000017, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000001: {generic: generic78000001, args: inst_block7800001C, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block7800001D, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000002: {generic: generic78000002, args: inst_block7800001C, decl_block_id: inst_block78000022, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000003: {generic: generic78000001, args: inst_block78000023, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000004: {generic: generic78000003, args: inst_block78000026, decl_block_id: inst_block78000027, decl_has_error: 0, definition_block_id: inst_block78000028, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000005: {generic: generic78000001, args: inst_block78000026, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block7800002D, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000006: {generic: generic78000002, args: inst_block78000026, decl_block_id: inst_block7800002E, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000007: {generic: generic78000004, args: inst_block78000026, decl_block_id: inst_block78000032, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000008: {generic: generic78000001, args: inst_block7800002F, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000009: {generic: generic78000002, args: inst_block7800002F, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000A: {generic: generic78000003, args: inst_block78000035, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000B: {generic: generic78000005, args: inst_block78000015, decl_block_id: inst_block7800003A, decl_has_error: 0, definition_block_id: inst_block78000080, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000C: {generic: generic78000005, args: inst_block7800003D, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000D: {generic: generic78000006, args: inst_block78000015, decl_block_id: inst_block78000043, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000E: {generic: generic78000007, args: inst_block78000048, decl_block_id: inst_block7800004A, decl_has_error: 0, definition_block_id: inst_block7800004B, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800000F: {generic: generic78000001, args: inst_block78000051, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block78000052, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000010: {generic: generic78000002, args: inst_block78000051, decl_block_id: inst_block78000053, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000011: {generic: generic78000008, args: inst_block78000048, decl_block_id: inst_block78000059, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000012: {generic: generic78000001, args: inst_block78000054, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000013: {generic: generic78000002, args: inst_block78000054, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000014: {generic: generic78000001, args: inst_block78000056, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000015: {generic: generic78000002, args: inst_block78000056, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000016: {generic: generic78000007, args: inst_block7800005C, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000017: {generic: generic78000009, args: inst_block78000064, decl_block_id: inst_block78000066, decl_has_error: 0, definition_block_id: inst_block78000067, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000018: {generic: generic78000001, args: inst_block7800006D, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block7800006E, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000019: {generic: generic78000002, args: inst_block7800006D, decl_block_id: inst_block7800006F, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001A: {generic: generic7800000A, args: inst_block78000064, decl_block_id: inst_block78000077, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001B: {generic: generic78000001, args: inst_block78000070, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001C: {generic: generic78000002, args: inst_block78000070, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001D: {generic: generic78000001, args: inst_block78000072, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001E: {generic: generic78000002, args: inst_block78000072, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific7800001F: {generic: generic78000001, args: inst_block78000074, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000020: {generic: generic78000002, args: inst_block78000074, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000021: {generic: generic78000009, args: inst_block7800007A, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000022: {generic: generic78000005, args: inst_block78000081, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000023: {generic: generic78000001, args: inst_block78000083, decl_block_id: inst_block_empty, decl_has_error: 0, definition_block_id: inst_block78000084, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000024: {generic: generic78000001, args: inst_block78000086, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000025: {generic: generic78000002, args: inst_block78000083, decl_block_id: inst_block78000087, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
+// CHECK:STDOUT:     specific78000026: {generic: generic78000002, args: inst_block78000086, decl_block_id: inst_block<none>, decl_has_error: 0, definition_block_id: inst_block<none>, definition_has_error: 0}
 // CHECK:STDOUT:   specific_interfaces:
 // CHECK:STDOUT:     specific_interface78000000: {interface_id: interface78000000, specific_id: specific<none>}
 // CHECK:STDOUT:   struct_type_fields:
@@ -571,7 +571,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst7800003B:    {kind: SpliceBlock, arg0: inst_block78000007, arg1: inst7800001C, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800003C:    {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(symbolic_constant7800000A)}
 // CHECK:STDOUT:     inst7800003D:    {kind: ReturnSlot, arg0: inst7800002F, arg1: inst7800003C, type: type(symbolic_constant7800000A)}
-// CHECK:STDOUT:     inst7800003E:    {kind: FunctionDecl, arg0: function78000000, arg1: inst_block78000014, type: type(inst7800003F)}
+// CHECK:STDOUT:     inst7800003E:    {kind: FunctionDecl, arg0: function78000000, arg1: inst_block78000013, type: type(inst7800003F)}
 // CHECK:STDOUT:     inst7800003F:    {kind: FunctionType, arg0: function78000000, arg1: specific<none>, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000040:    {kind: StructValue, arg0: inst_block_empty, type: type(inst7800003F)}
 // CHECK:STDOUT:     inst78000041:    {kind: RequireCompleteType, arg0: inst7800001D, type: type(inst(WitnessType))}
@@ -583,7 +583,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000047:    {kind: RequireCompleteType, arg0: inst78000031, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst78000048:    {kind: NameRef, arg0: name2, arg1: inst78000022, type: type(symbolic_constant78000004)}
 // CHECK:STDOUT:     inst78000049:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst78000026)}
-// CHECK:STDOUT:     inst7800004A:    {kind: TupleLiteral, arg0: inst_block7800001A, type: type(symbolic_constant7800000A)}
+// CHECK:STDOUT:     inst7800004A:    {kind: TupleLiteral, arg0: inst_block78000019, type: type(symbolic_constant7800000A)}
 // CHECK:STDOUT:     inst7800004B:    {kind: RequireCompleteType, arg0: inst7800002F, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst7800004C:    {kind: TupleAccess, arg0: inst7800003C, arg1: element0, type: type(symbolic_constant78000004)}
 // CHECK:STDOUT:     inst7800004D:    {kind: RequireCompleteType, arg0: inst7800001D, type: type(inst(WitnessType))}
@@ -626,7 +626,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000072:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000071, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000073:    {kind: ConstType, arg0: inst78000072, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000074:    {kind: ImportRefUnloaded, arg0: import_ir_inst19, arg1: entity_name<none>}
-// CHECK:STDOUT:     inst78000075:    {kind: ImplWitnessTable, arg0: inst_block78000027, arg1: impl78000000}
+// CHECK:STDOUT:     inst78000075:    {kind: ImplWitnessTable, arg0: inst_block78000025, arg1: impl78000000}
 // CHECK:STDOUT:     inst78000076:    {kind: ImplWitness, arg0: inst78000075, arg1: specific78000004, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst78000077:    {kind: FunctionDecl, arg0: function78000002, arg1: inst_block_empty, type: type(symbolic_constant78000031)}
 // CHECK:STDOUT:     inst78000078:    {kind: FunctionType, arg0: function78000002, arg1: specific78000004, type: type(TypeType)}
@@ -692,7 +692,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst780000B4:    {kind: ImportRefLoaded, arg0: import_ir_inst49, arg1: entity_name<none>, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst780000B5:    {kind: ImplDecl, arg0: impl78000005, arg1: inst_block_empty}
 // CHECK:STDOUT:     inst780000B6:    {kind: ImportRefUnloaded, arg0: import_ir_inst4B, arg1: entity_name<none>}
-// CHECK:STDOUT:     inst780000B7:    {kind: ImplWitnessTable, arg0: inst_block7800003C, arg1: impl78000005}
+// CHECK:STDOUT:     inst780000B7:    {kind: ImplWitnessTable, arg0: inst_block78000039, arg1: impl78000005}
 // CHECK:STDOUT:     inst780000B8:    {kind: ImplWitness, arg0: inst780000B7, arg1: specific7800000B, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst780000B9:    {kind: SymbolicBindingPattern, arg0: entity_name78000019, type: type(inst78000016)}
 // CHECK:STDOUT:     inst780000BA:    {kind: ImportRefLoaded, arg0: import_ir_inst4E, arg1: entity_name<none>, type: type(TypeType)}
@@ -731,15 +731,15 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst780000DB:    {kind: ImplDecl, arg0: impl78000008, arg1: inst_block_empty}
 // CHECK:STDOUT:     inst780000DC:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst780000DD:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst780000DC, type: type(TypeType)}
-// CHECK:STDOUT:     inst780000DE:    {kind: TupleType, arg0: inst_block7800004A, type: type(TypeType)}
+// CHECK:STDOUT:     inst780000DE:    {kind: TupleType, arg0: inst_block78000046, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000DF:    {kind: ImportRefUnloaded, arg0: import_ir_inst6D, arg1: entity_name<none>}
-// CHECK:STDOUT:     inst780000E0:    {kind: ImplWitnessTable, arg0: inst_block7800004B, arg1: impl78000008}
+// CHECK:STDOUT:     inst780000E0:    {kind: ImplWitnessTable, arg0: inst_block78000047, arg1: impl78000008}
 // CHECK:STDOUT:     inst780000E1:    {kind: ImplWitness, arg0: inst780000E0, arg1: specific7800000E, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst780000E2:    {kind: FunctionDecl, arg0: function78000004, arg1: inst_block_empty, type: type(symbolic_constant78000089)}
 // CHECK:STDOUT:     inst780000E3:    {kind: FunctionType, arg0: function78000004, arg1: specific7800000E, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000E4:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000089)}
-// CHECK:STDOUT:     inst780000E5:    {kind: TupleType, arg0: inst_block7800004D, type: type(TypeType)}
-// CHECK:STDOUT:     inst780000E6:    {kind: TupleValue, arg0: inst_block7800004C, type: type(inst780000E5)}
+// CHECK:STDOUT:     inst780000E5:    {kind: TupleType, arg0: inst_block78000049, type: type(TypeType)}
+// CHECK:STDOUT:     inst780000E6:    {kind: TupleValue, arg0: inst_block78000048, type: type(inst780000E5)}
 // CHECK:STDOUT:     inst780000E7:    {kind: PatternType, arg0: inst780000DE, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000E8:    {kind: OutParamPattern, arg0: name(ReturnSlot), type: type(symbolic_constant7800008F)}
 // CHECK:STDOUT:     inst780000E9:    {kind: ReturnSlotPattern, arg0: inst780000E8, arg1: inst<none>, type: type(symbolic_constant7800008F)}
@@ -754,7 +754,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst780000F2:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst780000F1, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000F3:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst780000F4:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst780000F3, type: type(TypeType)}
-// CHECK:STDOUT:     inst780000F5:    {kind: TupleType, arg0: inst_block78000054, type: type(TypeType)}
+// CHECK:STDOUT:     inst780000F5:    {kind: TupleType, arg0: inst_block7800004F, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000F6:    {kind: PatternType, arg0: inst780000F5, type: type(TypeType)}
 // CHECK:STDOUT:     inst780000F7:    {kind: InitForm, arg0: inst780000F5, type: type(inst(FormType))}
 // CHECK:STDOUT:     inst780000F8:    {kind: LookupImplWitness, arg0: inst780000DC, arg1: specific_interface78000000, type: type(inst(WitnessType))}
@@ -788,10 +788,10 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000114:    {kind: ImportRefLoaded, arg0: import_ir_inst91, arg1: entity_name<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000115:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000116:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}
-// CHECK:STDOUT:     inst78000117:    {kind: TupleValue, arg0: inst_block78000061, type: type(inst780000E5)}
+// CHECK:STDOUT:     inst78000117:    {kind: TupleValue, arg0: inst_block7800005C, type: type(inst780000E5)}
 // CHECK:STDOUT:     inst78000118:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000115, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000119:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000116, type: type(TypeType)}
-// CHECK:STDOUT:     inst7800011A:    {kind: TupleType, arg0: inst_block78000062, type: type(TypeType)}
+// CHECK:STDOUT:     inst7800011A:    {kind: TupleType, arg0: inst_block7800005D, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800011B:    {kind: ImplWitness, arg0: inst780000E0, arg1: specific78000016, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst7800011C:    {kind: FunctionType, arg0: function78000004, arg1: specific78000016, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800011D:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000D4)}
@@ -799,15 +799,15 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst7800011F:    {kind: ImplDecl, arg0: impl78000009, arg1: inst_block_empty}
 // CHECK:STDOUT:     inst78000120:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000121:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst78000120, type: type(TypeType)}
-// CHECK:STDOUT:     inst78000122:    {kind: TupleType, arg0: inst_block78000067, type: type(TypeType)}
+// CHECK:STDOUT:     inst78000122:    {kind: TupleType, arg0: inst_block78000062, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000123:    {kind: ImportRefUnloaded, arg0: import_ir_inst9D, arg1: entity_name<none>}
-// CHECK:STDOUT:     inst78000124:    {kind: ImplWitnessTable, arg0: inst_block78000068, arg1: impl78000009}
+// CHECK:STDOUT:     inst78000124:    {kind: ImplWitnessTable, arg0: inst_block78000063, arg1: impl78000009}
 // CHECK:STDOUT:     inst78000125:    {kind: ImplWitness, arg0: inst78000124, arg1: specific78000017, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst78000126:    {kind: FunctionDecl, arg0: function78000005, arg1: inst_block_empty, type: type(symbolic_constant780000DC)}
 // CHECK:STDOUT:     inst78000127:    {kind: FunctionType, arg0: function78000005, arg1: specific78000017, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000128:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000DC)}
-// CHECK:STDOUT:     inst78000129:    {kind: TupleType, arg0: inst_block7800006A, type: type(TypeType)}
-// CHECK:STDOUT:     inst7800012A:    {kind: TupleValue, arg0: inst_block78000069, type: type(inst78000129)}
+// CHECK:STDOUT:     inst78000129:    {kind: TupleType, arg0: inst_block78000065, type: type(TypeType)}
+// CHECK:STDOUT:     inst7800012A:    {kind: TupleValue, arg0: inst_block78000064, type: type(inst78000129)}
 // CHECK:STDOUT:     inst7800012B:    {kind: PatternType, arg0: inst78000122, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800012C:    {kind: OutParamPattern, arg0: name(ReturnSlot), type: type(symbolic_constant780000E2)}
 // CHECK:STDOUT:     inst7800012D:    {kind: ReturnSlotPattern, arg0: inst7800012C, arg1: inst<none>, type: type(symbolic_constant780000E2)}
@@ -825,7 +825,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000139:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000138, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800013A:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst7800013B:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst7800013A, type: type(TypeType)}
-// CHECK:STDOUT:     inst7800013C:    {kind: TupleType, arg0: inst_block78000071, type: type(TypeType)}
+// CHECK:STDOUT:     inst7800013C:    {kind: TupleType, arg0: inst_block7800006B, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800013D:    {kind: PatternType, arg0: inst7800013C, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800013E:    {kind: InitForm, arg0: inst7800013C, type: type(inst(FormType))}
 // CHECK:STDOUT:     inst7800013F:    {kind: LookupImplWitness, arg0: inst78000120, arg1: specific_interface78000000, type: type(inst(WitnessType))}
@@ -868,11 +868,11 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000164:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000165:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000166:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}
-// CHECK:STDOUT:     inst78000167:    {kind: TupleValue, arg0: inst_block78000080, type: type(inst78000129)}
+// CHECK:STDOUT:     inst78000167:    {kind: TupleValue, arg0: inst_block7800007A, type: type(inst78000129)}
 // CHECK:STDOUT:     inst78000168:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000164, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000169:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000165, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800016A:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst78000166, type: type(TypeType)}
-// CHECK:STDOUT:     inst7800016B:    {kind: TupleType, arg0: inst_block78000081, type: type(TypeType)}
+// CHECK:STDOUT:     inst7800016B:    {kind: TupleType, arg0: inst_block7800007B, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800016C:    {kind: ImplWitness, arg0: inst78000124, arg1: specific78000021, type: type(inst(WitnessType))}
 // CHECK:STDOUT:     inst7800016D:    {kind: FunctionType, arg0: function78000005, arg1: specific78000021, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800016E:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant7800013C)}
@@ -880,14 +880,14 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000170:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
 // CHECK:STDOUT:     inst78000171:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}
 // CHECK:STDOUT:     inst78000172:    {kind: RequireSpecificDefinition, arg0: specific78000022, type: type(inst(RequireSpecificDefinitionType))}
-// CHECK:STDOUT:     inst78000173:    {kind: FacetValue, arg0: inst7800001D, arg1: inst_block78000088, type: type(inst78000050)}
+// CHECK:STDOUT:     inst78000173:    {kind: FacetValue, arg0: inst7800001D, arg1: inst_block78000082, type: type(inst78000050)}
 // CHECK:STDOUT:     inst78000174:    {kind: FunctionType, arg0: function78000001, arg1: specific78000023, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000175:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000143)}
 // CHECK:STDOUT:     inst78000176:    {kind: FunctionTypeWithSelfType, arg0: inst78000174, arg1: inst78000173, type: type(TypeType)}
 // CHECK:STDOUT:     inst78000177:    {kind: ImplWitnessAccess, arg0: inst7800016F, arg1: element0, type: type(symbolic_constant7800014A)}
 // CHECK:STDOUT:     inst78000178:    {kind: ImplWitnessAccess, arg0: inst7800016F, arg1: element0, type: type(symbolic_constant78000145)}
 // CHECK:STDOUT:     inst78000179:    {kind: LookupImplWitness, arg0: inst7800001E, arg1: specific_interface78000000, type: type(inst(WitnessType))}
-// CHECK:STDOUT:     inst7800017A:    {kind: FacetValue, arg0: inst7800001E, arg1: inst_block7800008B, type: type(inst78000050)}
+// CHECK:STDOUT:     inst7800017A:    {kind: FacetValue, arg0: inst7800001E, arg1: inst_block78000085, type: type(inst78000050)}
 // CHECK:STDOUT:     inst7800017B:    {kind: FunctionType, arg0: function78000001, arg1: specific78000024, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800017C:    {kind: FunctionTypeWithSelfType, arg0: inst7800017B, arg1: inst7800017A, type: type(TypeType)}
 // CHECK:STDOUT:     inst7800017D:    {kind: ImplWitnessAccess, arg0: inst78000179, arg1: element0, type: type(symbolic_constant7800014A)}
@@ -896,13 +896,13 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     inst78000180:    {kind: SpecificImplFunction, arg0: inst78000178, arg1: specific78000025, type: type(inst(SpecificFunctionType))}
 // CHECK:STDOUT:     inst78000181:    {kind: SpecificImplFunction, arg0: inst7800017D, arg1: specific78000026, type: type(inst(SpecificFunctionType))}
 // CHECK:STDOUT:     inst78000182:    {kind: BoundMethod, arg0: inst78000048, arg1: inst7800017F, type: type(inst(BoundMethodType))}
-// CHECK:STDOUT:     inst78000183:    {kind: Call, arg0: inst78000182, arg1: inst_block7800008F, type: type(symbolic_constant78000004)}
+// CHECK:STDOUT:     inst78000183:    {kind: Call, arg0: inst78000182, arg1: inst_block78000089, type: type(symbolic_constant78000004)}
 // CHECK:STDOUT:     inst78000184:    {kind: InPlaceInit, arg0: inst78000183, arg1: inst7800004C, type: type(symbolic_constant78000004)}
 // CHECK:STDOUT:     inst78000185:    {kind: TupleAccess, arg0: inst7800003C, arg1: element1, type: type(inst78000026)}
 // CHECK:STDOUT:     inst78000186:    {kind: TupleInit, arg0: inst_block_empty, arg1: inst78000185, type: type(inst78000026)}
 // CHECK:STDOUT:     inst78000187:    {kind: Converted, arg0: inst78000049, arg1: inst78000186, type: type(inst78000026)}
 // CHECK:STDOUT:     inst78000188:    {kind: InPlaceInit, arg0: inst78000187, arg1: inst78000185, type: type(inst78000026)}
-// CHECK:STDOUT:     inst78000189:    {kind: TupleInit, arg0: inst_block78000090, arg1: inst7800003C, type: type(symbolic_constant7800000A)}
+// CHECK:STDOUT:     inst78000189:    {kind: TupleInit, arg0: inst_block7800008A, arg1: inst7800003C, type: type(symbolic_constant7800000A)}
 // CHECK:STDOUT:     inst7800018A:    {kind: Converted, arg0: inst7800004A, arg1: inst78000189, type: type(symbolic_constant7800000A)}
 // CHECK:STDOUT:     inst7800018B:    {kind: ReturnExpr, arg0: inst7800018A, arg1: inst7800003C}
 // CHECK:STDOUT:   constant_values:
@@ -1759,20 +1759,18 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       0:               inst7800001E
 // CHECK:STDOUT:       1:               inst78000026
 // CHECK:STDOUT:     inst_block78000010:
-// CHECK:STDOUT:       0:               inst78000038
-// CHECK:STDOUT:     inst_block78000011:
 // CHECK:STDOUT:       0:               inst78000020
 // CHECK:STDOUT:       1:               inst78000036
-// CHECK:STDOUT:     inst_block78000012:
+// CHECK:STDOUT:     inst_block78000011:
 // CHECK:STDOUT:       0:               inst7800003A
 // CHECK:STDOUT:       1:               inst7800003C
-// CHECK:STDOUT:     inst_block78000013:
+// CHECK:STDOUT:     inst_block78000012:
 // CHECK:STDOUT:       0:               inst7800001A
 // CHECK:STDOUT:       1:               inst78000020
 // CHECK:STDOUT:       2:               inst78000023
 // CHECK:STDOUT:       3:               inst78000036
 // CHECK:STDOUT:       4:               inst78000038
-// CHECK:STDOUT:     inst_block78000014:
+// CHECK:STDOUT:     inst_block78000013:
 // CHECK:STDOUT:       0:               inst78000024
 // CHECK:STDOUT:       1:               inst78000025
 // CHECK:STDOUT:       2:               inst78000027
@@ -1787,11 +1785,11 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       11:              inst78000022
 // CHECK:STDOUT:       12:              inst7800003C
 // CHECK:STDOUT:       13:              inst7800003D
-// CHECK:STDOUT:     inst_block78000015:
+// CHECK:STDOUT:     inst_block78000014:
 // CHECK:STDOUT:       0:               inst78000017
-// CHECK:STDOUT:     inst_block78000016:
+// CHECK:STDOUT:     inst_block78000015:
 // CHECK:STDOUT:       0:               inst78000018
-// CHECK:STDOUT:     inst_block78000017:
+// CHECK:STDOUT:     inst_block78000016:
 // CHECK:STDOUT:       0:               inst78000019
 // CHECK:STDOUT:       1:               inst7800001E
 // CHECK:STDOUT:       2:               inst78000021
@@ -1799,7 +1797,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst78000031
 // CHECK:STDOUT:       5:               inst78000034
 // CHECK:STDOUT:       6:               inst78000037
-// CHECK:STDOUT:     inst_block78000018:
+// CHECK:STDOUT:     inst_block78000017:
 // CHECK:STDOUT:       0:               inst78000018
 // CHECK:STDOUT:       1:               inst7800001D
 // CHECK:STDOUT:       2:               inst7800001F
@@ -1807,7 +1805,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst7800002F
 // CHECK:STDOUT:       5:               inst78000033
 // CHECK:STDOUT:       6:               inst78000035
-// CHECK:STDOUT:     inst_block78000019:
+// CHECK:STDOUT:     inst_block78000018:
 // CHECK:STDOUT:       0:               inst78000048
 // CHECK:STDOUT:       1:               inst78000049
 // CHECK:STDOUT:       2:               inst7800004A
@@ -1825,85 +1823,81 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       14:              inst78000189
 // CHECK:STDOUT:       15:              inst7800018A
 // CHECK:STDOUT:       16:              inst7800018B
-// CHECK:STDOUT:     inst_block7800001A:
+// CHECK:STDOUT:     inst_block78000019:
 // CHECK:STDOUT:       0:               inst78000048
 // CHECK:STDOUT:       1:               inst78000049
-// CHECK:STDOUT:     inst_block7800001B:
+// CHECK:STDOUT:     inst_block7800001A:
 // CHECK:STDOUT:       0:               inst78000054
-// CHECK:STDOUT:     inst_block7800001C:
+// CHECK:STDOUT:     inst_block7800001B:
 // CHECK:STDOUT:       0:               inst78000055
-// CHECK:STDOUT:     inst_block7800001D:
+// CHECK:STDOUT:     inst_block7800001C:
 // CHECK:STDOUT:       0:               inst78000052
-// CHECK:STDOUT:     inst_block7800001E:
+// CHECK:STDOUT:     inst_block7800001D:
 // CHECK:STDOUT:       0:               inst78000052
 // CHECK:STDOUT:       1:               inst78000057
 // CHECK:STDOUT:       2:               inst78000058
-// CHECK:STDOUT:     inst_block7800001F:
+// CHECK:STDOUT:     inst_block7800001E:
 // CHECK:STDOUT:       0:               inst7800005D
 // CHECK:STDOUT:       1:               inst7800005B
-// CHECK:STDOUT:     inst_block78000020:
+// CHECK:STDOUT:     inst_block7800001F:
 // CHECK:STDOUT:       0:               inst7800005E
-// CHECK:STDOUT:     inst_block78000021:
-// CHECK:STDOUT:       0:               inst7800005C
-// CHECK:STDOUT:     inst_block78000022:
+// CHECK:STDOUT:     inst_block78000020:
 // CHECK:STDOUT:       0:               inst78000062
-// CHECK:STDOUT:     inst_block78000023:
+// CHECK:STDOUT:     inst_block78000021:
 // CHECK:STDOUT:       0:               inst78000063
 // CHECK:STDOUT:       1:               inst78000064
 // CHECK:STDOUT:       2:               inst78000065
 // CHECK:STDOUT:       3:               inst78000066
-// CHECK:STDOUT:     inst_block78000024:
+// CHECK:STDOUT:     inst_block78000022:
 // CHECK:STDOUT:       0:               inst78000052
 // CHECK:STDOUT:       1:               inst78000059
 // CHECK:STDOUT:       2:               inst7800005A
 // CHECK:STDOUT:       3:               inst7800005F
-// CHECK:STDOUT:     inst_block78000025:
+// CHECK:STDOUT:     inst_block78000023:
 // CHECK:STDOUT:       0:               inst78000067
-// CHECK:STDOUT:     inst_block78000026:
+// CHECK:STDOUT:     inst_block78000024:
 // CHECK:STDOUT:       0:               inst78000067
 // CHECK:STDOUT:       1:               inst78000068
 // CHECK:STDOUT:       2:               inst78000069
-// CHECK:STDOUT:     inst_block78000027:
+// CHECK:STDOUT:     inst_block78000025:
 // CHECK:STDOUT:       0:               inst78000074
-// CHECK:STDOUT:     inst_block78000028:
+// CHECK:STDOUT:     inst_block78000026:
 // CHECK:STDOUT:       0:               inst78000071
-// CHECK:STDOUT:     inst_block78000029:
+// CHECK:STDOUT:     inst_block78000027:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000072
 // CHECK:STDOUT:       2:               inst78000073
 // CHECK:STDOUT:       3:               inst78000076
-// CHECK:STDOUT:     inst_block7800002A:
+// CHECK:STDOUT:     inst_block78000028:
 // CHECK:STDOUT:       0:               inst78000078
 // CHECK:STDOUT:       1:               inst78000079
-// CHECK:STDOUT:     inst_block7800002B:
+// CHECK:STDOUT:     inst_block78000029:
 // CHECK:STDOUT:       0:               inst7800007D
 // CHECK:STDOUT:       1:               inst7800007B
-// CHECK:STDOUT:     inst_block7800002C:
+// CHECK:STDOUT:     inst_block7800002A:
 // CHECK:STDOUT:       0:               inst7800007E
-// CHECK:STDOUT:     inst_block7800002D:
-// CHECK:STDOUT:       0:               inst7800007C
-// CHECK:STDOUT:     inst_block7800002E:
+// CHECK:STDOUT:     inst_block7800002B:
 // CHECK:STDOUT:       0:               inst78000082
-// CHECK:STDOUT:     inst_block7800002F:
+// CHECK:STDOUT:     inst_block7800002C:
 // CHECK:STDOUT:       0:               inst78000083
 // CHECK:STDOUT:       1:               inst78000084
 // CHECK:STDOUT:       2:               inst78000085
 // CHECK:STDOUT:       3:               inst78000086
 // CHECK:STDOUT:       4:               inst78000087
-// CHECK:STDOUT:     inst_block78000030:
+// CHECK:STDOUT:     inst_block7800002D:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000089
 // CHECK:STDOUT:       2:               inst7800008A
-// CHECK:STDOUT:     inst_block78000031:
+// CHECK:STDOUT:     inst_block7800002E:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000072
 // CHECK:STDOUT:       2:               inst7800008F
 // CHECK:STDOUT:       3:               inst7800008E
-// CHECK:STDOUT:     inst_block78000032:
+// CHECK:STDOUT:     inst_block7800002F:
 // CHECK:STDOUT:       0:               inst78000083
-// CHECK:STDOUT:     inst_block78000033:
+// CHECK:STDOUT:     inst_block78000030:
 // CHECK:STDOUT:       0:               inst78000083
-// CHECK:STDOUT:     inst_block78000034:
+// CHECK:STDOUT:     inst_block78000031:
 // CHECK:STDOUT:       0:               inst78000092
 // CHECK:STDOUT:       1:               inst78000093
 // CHECK:STDOUT:       2:               inst78000094
@@ -1911,81 +1905,79 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst78000096
 // CHECK:STDOUT:       5:               inst78000097
 // CHECK:STDOUT:       6:               inst78000098
-// CHECK:STDOUT:     inst_block78000035:
+// CHECK:STDOUT:     inst_block78000032:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000072
 // CHECK:STDOUT:       2:               inst78000073
 // CHECK:STDOUT:       3:               inst7800007A
 // CHECK:STDOUT:       4:               inst7800007F
-// CHECK:STDOUT:     inst_block78000036:
+// CHECK:STDOUT:     inst_block78000033:
 // CHECK:STDOUT:       0:               inst7800009A
-// CHECK:STDOUT:     inst_block78000037:
+// CHECK:STDOUT:     inst_block78000034:
 // CHECK:STDOUT:       0:               inst7800009D
-// CHECK:STDOUT:     inst_block78000038:
+// CHECK:STDOUT:     inst_block78000035:
 // CHECK:STDOUT:       0:               inst7800009E
-// CHECK:STDOUT:     inst_block78000039:
+// CHECK:STDOUT:     inst_block78000036:
 // CHECK:STDOUT:       0:               inst7800009E
 // CHECK:STDOUT:       1:               inst7800009F
 // CHECK:STDOUT:       2:               inst780000A0
 // CHECK:STDOUT:       3:               inst780000A1
-// CHECK:STDOUT:     inst_block7800003A:
+// CHECK:STDOUT:     inst_block78000037:
 // CHECK:STDOUT:       0:               inst7800009E
-// CHECK:STDOUT:     inst_block7800003B:
+// CHECK:STDOUT:     inst_block78000038:
 // CHECK:STDOUT:       0:               inst780000A2
 // CHECK:STDOUT:       1:               inst780000A3
-// CHECK:STDOUT:     inst_block7800003C:
+// CHECK:STDOUT:     inst_block78000039:
 // CHECK:STDOUT:       0:               inst780000B6
-// CHECK:STDOUT:     inst_block7800003D:
+// CHECK:STDOUT:     inst_block7800003A:
 // CHECK:STDOUT:       0:               inst78000018
 // CHECK:STDOUT:       1:               inst7800001D
 // CHECK:STDOUT:       2:               inst780000B8
-// CHECK:STDOUT:     inst_block7800003E:
+// CHECK:STDOUT:     inst_block7800003B:
 // CHECK:STDOUT:       0:               inst780000B9
-// CHECK:STDOUT:     inst_block7800003F:
+// CHECK:STDOUT:     inst_block7800003C:
 // CHECK:STDOUT:       0:               inst780000BC
-// CHECK:STDOUT:     inst_block78000040:
+// CHECK:STDOUT:     inst_block7800003D:
 // CHECK:STDOUT:       0:               inst780000BD
-// CHECK:STDOUT:     inst_block78000041:
+// CHECK:STDOUT:     inst_block7800003E:
 // CHECK:STDOUT:       0:               inst780000BD
 // CHECK:STDOUT:       1:               inst780000BE
 // CHECK:STDOUT:       2:               inst780000BF
-// CHECK:STDOUT:     inst_block78000042:
+// CHECK:STDOUT:     inst_block7800003F:
 // CHECK:STDOUT:       0:               inst780000C5
 // CHECK:STDOUT:       1:               inst780000C3
-// CHECK:STDOUT:     inst_block78000043:
+// CHECK:STDOUT:     inst_block78000040:
 // CHECK:STDOUT:       0:               inst780000C6
-// CHECK:STDOUT:     inst_block78000044:
-// CHECK:STDOUT:       0:               inst780000C4
-// CHECK:STDOUT:     inst_block78000045:
+// CHECK:STDOUT:     inst_block78000041:
 // CHECK:STDOUT:       0:               inst780000CA
-// CHECK:STDOUT:     inst_block78000046:
+// CHECK:STDOUT:     inst_block78000042:
 // CHECK:STDOUT:       0:               inst780000CB
 // CHECK:STDOUT:       1:               inst780000CC
 // CHECK:STDOUT:       2:               inst780000CD
 // CHECK:STDOUT:       3:               inst780000CE
-// CHECK:STDOUT:     inst_block78000047:
+// CHECK:STDOUT:     inst_block78000043:
 // CHECK:STDOUT:       0:               inst78000018
 // CHECK:STDOUT:       1:               inst7800001D
 // CHECK:STDOUT:       2:               inst7800001F
 // CHECK:STDOUT:       3:               inst780000C7
-// CHECK:STDOUT:     inst_block78000048:
+// CHECK:STDOUT:     inst_block78000044:
 // CHECK:STDOUT:       0:               inst780000BD
-// CHECK:STDOUT:     inst_block78000049:
+// CHECK:STDOUT:     inst_block78000045:
 // CHECK:STDOUT:       0:               inst780000CF
 // CHECK:STDOUT:       1:               inst780000D0
 // CHECK:STDOUT:       2:               inst780000D1
-// CHECK:STDOUT:     inst_block7800004A:
+// CHECK:STDOUT:     inst_block78000046:
 // CHECK:STDOUT:       0:               inst78000072
 // CHECK:STDOUT:       1:               inst780000DD
-// CHECK:STDOUT:     inst_block7800004B:
+// CHECK:STDOUT:     inst_block78000047:
 // CHECK:STDOUT:       0:               inst780000DF
-// CHECK:STDOUT:     inst_block7800004C:
+// CHECK:STDOUT:     inst_block78000048:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst780000DC
-// CHECK:STDOUT:     inst_block7800004D:
+// CHECK:STDOUT:     inst_block78000049:
 // CHECK:STDOUT:       0:               inst78000050
 // CHECK:STDOUT:       1:               inst78000050
-// CHECK:STDOUT:     inst_block7800004E:
+// CHECK:STDOUT:     inst_block7800004A:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst780000DC
 // CHECK:STDOUT:       2:               inst780000E6
@@ -1993,23 +1985,21 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst780000DD
 // CHECK:STDOUT:       5:               inst780000DE
 // CHECK:STDOUT:       6:               inst780000E1
-// CHECK:STDOUT:     inst_block7800004F:
+// CHECK:STDOUT:     inst_block7800004B:
 // CHECK:STDOUT:       0:               inst780000E3
 // CHECK:STDOUT:       1:               inst780000E4
-// CHECK:STDOUT:     inst_block78000050:
+// CHECK:STDOUT:     inst_block7800004C:
 // CHECK:STDOUT:       0:               inst780000EA
 // CHECK:STDOUT:       1:               inst780000E8
-// CHECK:STDOUT:     inst_block78000051:
+// CHECK:STDOUT:     inst_block7800004D:
 // CHECK:STDOUT:       0:               inst780000EB
-// CHECK:STDOUT:     inst_block78000052:
-// CHECK:STDOUT:       0:               inst780000E9
-// CHECK:STDOUT:     inst_block78000053:
+// CHECK:STDOUT:     inst_block7800004E:
 // CHECK:STDOUT:       0:               inst780000EF
 // CHECK:STDOUT:       1:               inst780000F0
-// CHECK:STDOUT:     inst_block78000054:
+// CHECK:STDOUT:     inst_block7800004F:
 // CHECK:STDOUT:       0:               inst780000F2
 // CHECK:STDOUT:       1:               inst780000F4
-// CHECK:STDOUT:     inst_block78000055:
+// CHECK:STDOUT:     inst_block78000050:
 // CHECK:STDOUT:       0:               inst780000F1
 // CHECK:STDOUT:       1:               inst780000F2
 // CHECK:STDOUT:       2:               inst780000F3
@@ -2017,26 +2007,26 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst780000F5
 // CHECK:STDOUT:       5:               inst780000F6
 // CHECK:STDOUT:       6:               inst780000F7
-// CHECK:STDOUT:     inst_block78000056:
+// CHECK:STDOUT:     inst_block78000051:
 // CHECK:STDOUT:       0:               inst780000DC
-// CHECK:STDOUT:     inst_block78000057:
+// CHECK:STDOUT:     inst_block78000052:
 // CHECK:STDOUT:       0:               inst780000DC
 // CHECK:STDOUT:       1:               inst780000F9
 // CHECK:STDOUT:       2:               inst780000FA
-// CHECK:STDOUT:     inst_block78000058:
+// CHECK:STDOUT:     inst_block78000053:
 // CHECK:STDOUT:       0:               inst780000DC
 // CHECK:STDOUT:       1:               inst780000DD
 // CHECK:STDOUT:       2:               inst780000FF
 // CHECK:STDOUT:       3:               inst780000FE
-// CHECK:STDOUT:     inst_block78000059:
+// CHECK:STDOUT:     inst_block78000054:
 // CHECK:STDOUT:       0:               inst780000F1
-// CHECK:STDOUT:     inst_block7800005A:
+// CHECK:STDOUT:     inst_block78000055:
 // CHECK:STDOUT:       0:               inst780000F1
-// CHECK:STDOUT:     inst_block7800005B:
+// CHECK:STDOUT:     inst_block78000056:
 // CHECK:STDOUT:       0:               inst780000F3
-// CHECK:STDOUT:     inst_block7800005C:
+// CHECK:STDOUT:     inst_block78000057:
 // CHECK:STDOUT:       0:               inst780000F3
-// CHECK:STDOUT:     inst_block7800005D:
+// CHECK:STDOUT:     inst_block78000058:
 // CHECK:STDOUT:       0:               inst78000102
 // CHECK:STDOUT:       1:               inst78000103
 // CHECK:STDOUT:       2:               inst78000104
@@ -2050,7 +2040,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       10:              inst7800010C
 // CHECK:STDOUT:       11:              inst7800010D
 // CHECK:STDOUT:       12:              inst7800010E
-// CHECK:STDOUT:     inst_block7800005E:
+// CHECK:STDOUT:     inst_block78000059:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000072
 // CHECK:STDOUT:       2:               inst780000DC
@@ -2058,22 +2048,22 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst780000DE
 // CHECK:STDOUT:       5:               inst780000E7
 // CHECK:STDOUT:       6:               inst780000EC
-// CHECK:STDOUT:     inst_block7800005F:
+// CHECK:STDOUT:     inst_block7800005A:
 // CHECK:STDOUT:       0:               inst78000110
 // CHECK:STDOUT:       1:               inst7800010F
-// CHECK:STDOUT:     inst_block78000060:
+// CHECK:STDOUT:     inst_block7800005B:
 // CHECK:STDOUT:       0:               inst78000113
 // CHECK:STDOUT:       1:               inst78000114
-// CHECK:STDOUT:     inst_block78000061:
+// CHECK:STDOUT:     inst_block7800005C:
 // CHECK:STDOUT:       0:               inst78000115
 // CHECK:STDOUT:       1:               inst78000116
-// CHECK:STDOUT:     inst_block78000062:
+// CHECK:STDOUT:     inst_block7800005D:
 // CHECK:STDOUT:       0:               inst78000118
 // CHECK:STDOUT:       1:               inst78000119
-// CHECK:STDOUT:     inst_block78000063:
+// CHECK:STDOUT:     inst_block7800005E:
 // CHECK:STDOUT:       0:               inst78000115
 // CHECK:STDOUT:       1:               inst78000116
-// CHECK:STDOUT:     inst_block78000064:
+// CHECK:STDOUT:     inst_block7800005F:
 // CHECK:STDOUT:       0:               inst78000115
 // CHECK:STDOUT:       1:               inst78000116
 // CHECK:STDOUT:       2:               inst78000117
@@ -2081,27 +2071,27 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       4:               inst78000119
 // CHECK:STDOUT:       5:               inst7800011A
 // CHECK:STDOUT:       6:               inst7800011B
-// CHECK:STDOUT:     inst_block78000065:
+// CHECK:STDOUT:     inst_block78000060:
 // CHECK:STDOUT:       0:               inst78000115
 // CHECK:STDOUT:       1:               inst78000116
-// CHECK:STDOUT:     inst_block78000066:
+// CHECK:STDOUT:     inst_block78000061:
 // CHECK:STDOUT:       0:               inst7800011C
 // CHECK:STDOUT:       1:               inst7800011D
-// CHECK:STDOUT:     inst_block78000067:
+// CHECK:STDOUT:     inst_block78000062:
 // CHECK:STDOUT:       0:               inst78000072
 // CHECK:STDOUT:       1:               inst780000DD
 // CHECK:STDOUT:       2:               inst78000121
-// CHECK:STDOUT:     inst_block78000068:
+// CHECK:STDOUT:     inst_block78000063:
 // CHECK:STDOUT:       0:               inst78000123
-// CHECK:STDOUT:     inst_block78000069:
+// CHECK:STDOUT:     inst_block78000064:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst780000DC
 // CHECK:STDOUT:       2:               inst78000120
-// CHECK:STDOUT:     inst_block7800006A:
+// CHECK:STDOUT:     inst_block78000065:
 // CHECK:STDOUT:       0:               inst78000050
 // CHECK:STDOUT:       1:               inst78000050
 // CHECK:STDOUT:       2:               inst78000050
-// CHECK:STDOUT:     inst_block7800006B:
+// CHECK:STDOUT:     inst_block78000066:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst780000DC
 // CHECK:STDOUT:       2:               inst78000120
@@ -2111,25 +2101,23 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       6:               inst78000121
 // CHECK:STDOUT:       7:               inst78000122
 // CHECK:STDOUT:       8:               inst78000125
-// CHECK:STDOUT:     inst_block7800006C:
+// CHECK:STDOUT:     inst_block78000067:
 // CHECK:STDOUT:       0:               inst78000127
 // CHECK:STDOUT:       1:               inst78000128
-// CHECK:STDOUT:     inst_block7800006D:
+// CHECK:STDOUT:     inst_block78000068:
 // CHECK:STDOUT:       0:               inst7800012E
 // CHECK:STDOUT:       1:               inst7800012C
-// CHECK:STDOUT:     inst_block7800006E:
+// CHECK:STDOUT:     inst_block78000069:
 // CHECK:STDOUT:       0:               inst7800012F
-// CHECK:STDOUT:     inst_block7800006F:
-// CHECK:STDOUT:       0:               inst7800012D
-// CHECK:STDOUT:     inst_block78000070:
+// CHECK:STDOUT:     inst_block7800006A:
 // CHECK:STDOUT:       0:               inst78000133
 // CHECK:STDOUT:       1:               inst78000134
 // CHECK:STDOUT:       2:               inst78000135
-// CHECK:STDOUT:     inst_block78000071:
+// CHECK:STDOUT:     inst_block7800006B:
 // CHECK:STDOUT:       0:               inst78000137
 // CHECK:STDOUT:       1:               inst78000139
 // CHECK:STDOUT:       2:               inst7800013B
-// CHECK:STDOUT:     inst_block78000072:
+// CHECK:STDOUT:     inst_block7800006C:
 // CHECK:STDOUT:       0:               inst78000136
 // CHECK:STDOUT:       1:               inst78000137
 // CHECK:STDOUT:       2:               inst78000138
@@ -2139,30 +2127,30 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       6:               inst7800013C
 // CHECK:STDOUT:       7:               inst7800013D
 // CHECK:STDOUT:       8:               inst7800013E
-// CHECK:STDOUT:     inst_block78000073:
+// CHECK:STDOUT:     inst_block7800006D:
 // CHECK:STDOUT:       0:               inst78000120
-// CHECK:STDOUT:     inst_block78000074:
+// CHECK:STDOUT:     inst_block7800006E:
 // CHECK:STDOUT:       0:               inst78000120
 // CHECK:STDOUT:       1:               inst78000140
 // CHECK:STDOUT:       2:               inst78000141
-// CHECK:STDOUT:     inst_block78000075:
+// CHECK:STDOUT:     inst_block7800006F:
 // CHECK:STDOUT:       0:               inst78000120
 // CHECK:STDOUT:       1:               inst78000121
 // CHECK:STDOUT:       2:               inst78000146
 // CHECK:STDOUT:       3:               inst78000145
-// CHECK:STDOUT:     inst_block78000076:
+// CHECK:STDOUT:     inst_block78000070:
 // CHECK:STDOUT:       0:               inst78000136
-// CHECK:STDOUT:     inst_block78000077:
+// CHECK:STDOUT:     inst_block78000071:
 // CHECK:STDOUT:       0:               inst78000136
-// CHECK:STDOUT:     inst_block78000078:
+// CHECK:STDOUT:     inst_block78000072:
 // CHECK:STDOUT:       0:               inst78000138
-// CHECK:STDOUT:     inst_block78000079:
+// CHECK:STDOUT:     inst_block78000073:
 // CHECK:STDOUT:       0:               inst78000138
-// CHECK:STDOUT:     inst_block7800007A:
+// CHECK:STDOUT:     inst_block78000074:
 // CHECK:STDOUT:       0:               inst7800013A
-// CHECK:STDOUT:     inst_block7800007B:
+// CHECK:STDOUT:     inst_block78000075:
 // CHECK:STDOUT:       0:               inst7800013A
-// CHECK:STDOUT:     inst_block7800007C:
+// CHECK:STDOUT:     inst_block78000076:
 // CHECK:STDOUT:       0:               inst78000149
 // CHECK:STDOUT:       1:               inst7800014A
 // CHECK:STDOUT:       2:               inst7800014B
@@ -2182,7 +2170,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       16:              inst78000159
 // CHECK:STDOUT:       17:              inst7800015A
 // CHECK:STDOUT:       18:              inst7800015B
-// CHECK:STDOUT:     inst_block7800007D:
+// CHECK:STDOUT:     inst_block78000077:
 // CHECK:STDOUT:       0:               inst78000071
 // CHECK:STDOUT:       1:               inst78000072
 // CHECK:STDOUT:       2:               inst780000DC
@@ -2192,27 +2180,27 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       6:               inst78000122
 // CHECK:STDOUT:       7:               inst7800012B
 // CHECK:STDOUT:       8:               inst78000130
-// CHECK:STDOUT:     inst_block7800007E:
+// CHECK:STDOUT:     inst_block78000078:
 // CHECK:STDOUT:       0:               inst7800015E
 // CHECK:STDOUT:       1:               inst7800015D
 // CHECK:STDOUT:       2:               inst7800015C
-// CHECK:STDOUT:     inst_block7800007F:
+// CHECK:STDOUT:     inst_block78000079:
 // CHECK:STDOUT:       0:               inst78000161
 // CHECK:STDOUT:       1:               inst78000162
 // CHECK:STDOUT:       2:               inst78000163
-// CHECK:STDOUT:     inst_block78000080:
+// CHECK:STDOUT:     inst_block7800007A:
 // CHECK:STDOUT:       0:               inst78000164
 // CHECK:STDOUT:       1:               inst78000165
 // CHECK:STDOUT:       2:               inst78000166
-// CHECK:STDOUT:     inst_block78000081:
+// CHECK:STDOUT:     inst_block7800007B:
 // CHECK:STDOUT:       0:               inst78000168
 // CHECK:STDOUT:       1:               inst78000169
 // CHECK:STDOUT:       2:               inst7800016A
-// CHECK:STDOUT:     inst_block78000082:
+// CHECK:STDOUT:     inst_block7800007C:
 // CHECK:STDOUT:       0:               inst78000164
 // CHECK:STDOUT:       1:               inst78000165
 // CHECK:STDOUT:       2:               inst78000166
-// CHECK:STDOUT:     inst_block78000083:
+// CHECK:STDOUT:     inst_block7800007D:
 // CHECK:STDOUT:       0:               inst78000164
 // CHECK:STDOUT:       1:               inst78000165
 // CHECK:STDOUT:       2:               inst78000166
@@ -2222,44 +2210,44 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       6:               inst7800016A
 // CHECK:STDOUT:       7:               inst7800016B
 // CHECK:STDOUT:       8:               inst7800016C
-// CHECK:STDOUT:     inst_block78000084:
+// CHECK:STDOUT:     inst_block7800007E:
 // CHECK:STDOUT:       0:               inst78000164
 // CHECK:STDOUT:       1:               inst78000165
 // CHECK:STDOUT:       2:               inst78000166
-// CHECK:STDOUT:     inst_block78000085:
+// CHECK:STDOUT:     inst_block7800007F:
 // CHECK:STDOUT:       0:               inst7800016D
 // CHECK:STDOUT:       1:               inst7800016E
-// CHECK:STDOUT:     inst_block78000086:
+// CHECK:STDOUT:     inst_block78000080:
 // CHECK:STDOUT:       0:               inst780000C1
 // CHECK:STDOUT:       1:               inst780000C2
 // CHECK:STDOUT:       2:               inst78000042
-// CHECK:STDOUT:     inst_block78000087:
+// CHECK:STDOUT:     inst_block78000081:
 // CHECK:STDOUT:       0:               inst78000019
-// CHECK:STDOUT:     inst_block78000088:
+// CHECK:STDOUT:     inst_block78000082:
 // CHECK:STDOUT:       0:               inst7800016F
-// CHECK:STDOUT:     inst_block78000089:
+// CHECK:STDOUT:     inst_block78000083:
 // CHECK:STDOUT:       0:               inst78000173
-// CHECK:STDOUT:     inst_block7800008A:
+// CHECK:STDOUT:     inst_block78000084:
 // CHECK:STDOUT:       0:               inst78000173
 // CHECK:STDOUT:       1:               inst78000174
 // CHECK:STDOUT:       2:               inst78000175
-// CHECK:STDOUT:     inst_block7800008B:
+// CHECK:STDOUT:     inst_block78000085:
 // CHECK:STDOUT:       0:               inst78000179
-// CHECK:STDOUT:     inst_block7800008C:
+// CHECK:STDOUT:     inst_block78000086:
 // CHECK:STDOUT:       0:               inst7800017A
-// CHECK:STDOUT:     inst_block7800008D:
+// CHECK:STDOUT:     inst_block78000087:
 // CHECK:STDOUT:       0:               inst78000173
 // CHECK:STDOUT:       1:               inst7800001D
 // CHECK:STDOUT:       2:               inst7800001F
 // CHECK:STDOUT:       3:               inst780000C7
-// CHECK:STDOUT:     inst_block7800008E:
+// CHECK:STDOUT:     inst_block78000088:
 // CHECK:STDOUT:       0:               inst7800017A
-// CHECK:STDOUT:     inst_block7800008F:
+// CHECK:STDOUT:     inst_block78000089:
 // CHECK:STDOUT:       0:               inst78000048
-// CHECK:STDOUT:     inst_block78000090:
+// CHECK:STDOUT:     inst_block7800008A:
 // CHECK:STDOUT:       0:               inst78000184
 // CHECK:STDOUT:       1:               inst78000188
-// CHECK:STDOUT:     inst_block78000091:
+// CHECK:STDOUT:     inst_block7800008B:
 // CHECK:STDOUT:       0:               inst78000043
 // CHECK:STDOUT:       1:               inst78000047
 // CHECK:STDOUT:       2:               inst78000172
@@ -2269,7 +2257,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:       6:               inst7800017C
 // CHECK:STDOUT:       7:               inst7800017D
 // CHECK:STDOUT:       8:               inst78000181
-// CHECK:STDOUT:     inst_block78000092:
+// CHECK:STDOUT:     inst_block7800008C:
 // CHECK:STDOUT:       0:               instF
 // CHECK:STDOUT:       1:               inst78000010
 // CHECK:STDOUT:       2:               inst7800003E

+ 13 - 15
toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon

@@ -34,7 +34,7 @@ fn Foo(n: ()) -> ((), ()) {
 // CHECK:STDOUT:     entity_name50000000: {name: name1, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: inst<none>}
 // CHECK:STDOUT:   cpp_global_vars: {}
 // CHECK:STDOUT:   functions:
-// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block5000000C, call_params_id: inst_block5000000D, return_type_inst_id: inst50000020, return_form_inst_id: inst50000021, return_patterns_id: inst_block5000000B, body: [inst_block50000010]}
+// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block5000000B, call_params_id: inst_block5000000C, return_type_inst_id: inst50000020, return_form_inst_id: inst50000021, return_pattern_id: inst50000025, body: [inst_block5000000F]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   interfaces:      {}
 // CHECK:STDOUT:   associated_constants: {}
@@ -114,21 +114,21 @@ fn Foo(n: ()) -> ((), ()) {
 // CHECK:STDOUT:     inst50000027:    {kind: SpliceBlock, arg0: inst_block50000005, arg1: inst50000013, type: type(TypeType)}
 // CHECK:STDOUT:     inst50000028:    {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(inst5000001A)}
 // CHECK:STDOUT:     inst50000029:    {kind: ReturnSlot, arg0: inst5000001A, arg1: inst50000028, type: type(inst5000001A)}
-// CHECK:STDOUT:     inst5000002A:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block5000000F, type: type(inst5000002B)}
+// CHECK:STDOUT:     inst5000002A:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block5000000E, type: type(inst5000002B)}
 // CHECK:STDOUT:     inst5000002B:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}
 // CHECK:STDOUT:     inst5000002C:    {kind: StructValue, arg0: inst_block_empty, type: type(inst5000002B)}
 // CHECK:STDOUT:     inst5000002D:    {kind: NameRef, arg0: name1, arg1: inst50000016, type: type(inst50000010)}
 // CHECK:STDOUT:     inst5000002E:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst50000010)}
-// CHECK:STDOUT:     inst5000002F:    {kind: TupleLiteral, arg0: inst_block50000011, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst5000002F:    {kind: TupleLiteral, arg0: inst_block50000010, type: type(inst5000001A)}
 // CHECK:STDOUT:     inst50000030:    {kind: TupleAccess, arg0: inst50000028, arg1: element0, type: type(inst50000010)}
-// CHECK:STDOUT:     inst50000031:    {kind: TupleInit, arg0: inst_block50000012, arg1: inst50000030, type: type(inst50000010)}
+// CHECK:STDOUT:     inst50000031:    {kind: TupleInit, arg0: inst_block50000011, arg1: inst50000030, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000032:    {kind: Converted, arg0: inst5000002D, arg1: inst50000031, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000033:    {kind: InPlaceInit, arg0: inst50000032, arg1: inst50000030, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000034:    {kind: TupleAccess, arg0: inst50000028, arg1: element1, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000035:    {kind: TupleInit, arg0: inst_block_empty, arg1: inst50000034, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000036:    {kind: Converted, arg0: inst5000002E, arg1: inst50000035, type: type(inst50000010)}
 // CHECK:STDOUT:     inst50000037:    {kind: InPlaceInit, arg0: inst50000036, arg1: inst50000034, type: type(inst50000010)}
-// CHECK:STDOUT:     inst50000038:    {kind: TupleInit, arg0: inst_block50000013, arg1: inst50000028, type: type(inst5000001A)}
+// CHECK:STDOUT:     inst50000038:    {kind: TupleInit, arg0: inst_block50000012, arg1: inst50000028, type: type(inst5000001A)}
 // CHECK:STDOUT:     inst50000039:    {kind: Converted, arg0: inst5000002F, arg1: inst50000038, type: type(inst5000001A)}
 // CHECK:STDOUT:     inst5000003A:    {kind: ReturnExpr, arg0: inst50000039, arg1: inst50000028}
 // CHECK:STDOUT:   constant_values:
@@ -194,19 +194,17 @@ fn Foo(n: ()) -> ((), ()) {
 // CHECK:STDOUT:       0:               inst5000001E
 // CHECK:STDOUT:       1:               inst5000001F
 // CHECK:STDOUT:     inst_block5000000B:
-// CHECK:STDOUT:       0:               inst50000025
-// CHECK:STDOUT:     inst_block5000000C:
 // CHECK:STDOUT:       0:               inst50000015
 // CHECK:STDOUT:       1:               inst50000024
-// CHECK:STDOUT:     inst_block5000000D:
+// CHECK:STDOUT:     inst_block5000000C:
 // CHECK:STDOUT:       0:               inst50000026
 // CHECK:STDOUT:       1:               inst50000028
-// CHECK:STDOUT:     inst_block5000000E:
+// CHECK:STDOUT:     inst_block5000000D:
 // CHECK:STDOUT:       0:               inst50000015
 // CHECK:STDOUT:       1:               inst50000017
 // CHECK:STDOUT:       2:               inst50000024
 // CHECK:STDOUT:       3:               inst50000025
-// CHECK:STDOUT:     inst_block5000000F:
+// CHECK:STDOUT:     inst_block5000000E:
 // CHECK:STDOUT:       0:               inst50000018
 // CHECK:STDOUT:       1:               inst50000019
 // CHECK:STDOUT:       2:               inst5000001B
@@ -219,7 +217,7 @@ fn Foo(n: ()) -> ((), ()) {
 // CHECK:STDOUT:       9:               inst50000016
 // CHECK:STDOUT:       10:              inst50000028
 // CHECK:STDOUT:       11:              inst50000029
-// CHECK:STDOUT:     inst_block50000010:
+// CHECK:STDOUT:     inst_block5000000F:
 // CHECK:STDOUT:       0:               inst5000002D
 // CHECK:STDOUT:       1:               inst5000002E
 // CHECK:STDOUT:       2:               inst5000002F
@@ -234,14 +232,14 @@ fn Foo(n: ()) -> ((), ()) {
 // CHECK:STDOUT:       11:              inst50000038
 // CHECK:STDOUT:       12:              inst50000039
 // CHECK:STDOUT:       13:              inst5000003A
-// CHECK:STDOUT:     inst_block50000011:
+// CHECK:STDOUT:     inst_block50000010:
 // CHECK:STDOUT:       0:               inst5000002D
 // CHECK:STDOUT:       1:               inst5000002E
-// CHECK:STDOUT:     inst_block50000012: {}
-// CHECK:STDOUT:     inst_block50000013:
+// CHECK:STDOUT:     inst_block50000011: {}
+// CHECK:STDOUT:     inst_block50000012:
 // CHECK:STDOUT:       0:               inst50000033
 // CHECK:STDOUT:       1:               inst50000037
-// CHECK:STDOUT:     inst_block50000014:
+// CHECK:STDOUT:     inst_block50000013:
 // CHECK:STDOUT:       0:               instF
 // CHECK:STDOUT:       1:               inst5000002A
 // CHECK:STDOUT:   value_stores:

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

@@ -231,12 +231,14 @@ class Class {
 // CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {
 // CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern [concrete]
 // CHECK:STDOUT:     %self.patt: %pattern_type.904 = at_binding_pattern self, %self.param_patt [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %self.ref: %Class = name_ref self, %self
 // CHECK:STDOUT:     %.loc12: type = converted %self.ref, <error> [concrete = <error>]
 // CHECK:STDOUT:     %self.param: %Class = value_param call_param0
 // CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]
 // CHECK:STDOUT:     %self: %Class = value_binding self, %self.param
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type

+ 1 - 1
toolchain/check/testdata/eval/call.carbon

@@ -99,7 +99,7 @@ fn UseFGenerically(X:! i32) {
   // CHECK:STDERR:   var unused v: F(X) = {};
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_todo_dependent_call_type.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Core.Destroy` in type `<cannot stringify inst7C00018B: {kind: Call, arg0: inst7C00003E, arg1: inst_block7C000091, type: type(TypeType)}>` that does not implement that interface [MissingImplInMemberAccess]
+  // CHECK:STDERR: fail_todo_dependent_call_type.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Core.Destroy` in type `<cannot stringify inst7C00018B: {kind: Call, arg0: inst7C00003E, arg1: inst_block7C00008A, type: type(TypeType)}>` that does not implement that interface [MissingImplInMemberAccess]
   // CHECK:STDERR:   var unused v: F(X) = {};
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:

+ 16 - 6
toolchain/check/testdata/function/call/form.carbon

@@ -434,15 +434,20 @@ fn F(Form:! Core.Form()) ->? Form;
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %.1da: Core.Form = ref_form %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %.loc4_8.1: %pattern_type.7ce = ref_return_pattern [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern %.loc4_8.1, constants.%i32 [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc4: Core.Form = ref_form %i32 [concrete = constants.%.1da]
+// CHECK:STDOUT:     %.loc4_17: Core.Form = ref_form %i32 [concrete = constants.%.1da]
+// CHECK:STDOUT:     %.loc4_8.2: ref %i32 = ref_return
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %.loc4_8.2
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -519,15 +524,20 @@ fn F(Form:! Core.Form()) ->? Form;
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %.754: Core.Form = value_form %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %.loc4_8.1: %pattern_type.7ce = value_return_pattern [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern %.loc4_8.1, constants.%i32 [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
-// CHECK:STDOUT:     %.loc4: Core.Form = value_form %i32 [concrete = constants.%.754]
+// CHECK:STDOUT:     %.loc4_17: Core.Form = value_form %i32 [concrete = constants.%.754]
+// CHECK:STDOUT:     %.loc4_8.2: %i32 = value_return
+// CHECK:STDOUT:     %return: %i32 = return_slot %.loc4_8.2
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 7 - 2
toolchain/check/testdata/function/declaration/ref.carbon

@@ -29,11 +29,11 @@ fn G() {
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %.1da: Core.Form = ref_form %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -52,10 +52,15 @@ fn G() {
 // CHECK:STDOUT:     .G = %G.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %.loc4_8.1: %pattern_type.7ce = ref_return_pattern [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern %.loc4_8.1, %i32 [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
 // CHECK:STDOUT:     %.loc4_11.1: type = ref_tag %i32
 // CHECK:STDOUT:     %.loc4_11.2: Core.Form = ref_form %i32 [concrete = constants.%.1da]
+// CHECK:STDOUT:     %.loc4_8.2: ref %i32 = ref_return
+// CHECK:STDOUT:     %return: ref %i32 = return_slot %.loc4_8.2
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}
 // CHECK:STDOUT: }

+ 8 - 2
toolchain/check/testdata/impl/import_use_generic.carbon

@@ -284,13 +284,18 @@ fn H() -> C({}).(I.F)() {}
 // CHECK:STDOUT:     %C: type = class_type @C, @C(constants.%empty_struct_type) [concrete = constants.%C.850]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %c: ref %C.850 = ref_binding c, %c.var [concrete = %c.var]
-// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {
+// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %c.ref: ref %C.850 = name_ref c, file.%c [concrete = file.%c.var]
 // CHECK:STDOUT:     %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type]
 // CHECK:STDOUT:     %F.ref: %I.assoc_type = name_ref F, imports.%Main.import_ref.a54 [concrete = constants.%assoc0]
 // CHECK:STDOUT:     %.loc16: %I.type = converted %c.ref, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {} {
+// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C.generic]
 // CHECK:STDOUT:     %.loc25_14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:     %.loc25_15: type = converted %.loc25_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]
@@ -303,6 +308,7 @@ fn H() -> C({}).(I.F)() {}
 // CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @C.as.I.impl.F(constants.%empty_struct_type) [concrete = constants.%C.as.I.impl.F.specific_fn]
 // CHECK:STDOUT:     %C.as.I.impl.F.call: init %empty_tuple.type = call %specific_fn()
 // CHECK:STDOUT:     %.loc25_23: type = converted %C.as.I.impl.F.call, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/impl/incomplete.carbon

@@ -697,10 +697,13 @@ interface B {
 // CHECK:STDOUT: interface @Incomplete;
 // CHECK:STDOUT:
 // CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc8_13 {
-// CHECK:STDOUT:   %C.as.I.impl.F.decl: %C.as.I.impl.F.type = fn_decl @C.as.I.impl.F [concrete = constants.%C.as.I.impl.F] {} {
+// CHECK:STDOUT:   %C.as.I.impl.F.decl: %C.as.I.impl.F.type = fn_decl @C.as.I.impl.F [concrete = constants.%C.as.I.impl.F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %Self.ref: type = name_ref Self, @C.as.I.impl.%C.ref [concrete = constants.%C]
 // CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [concrete = constants.%Incomplete.type]
 // CHECK:STDOUT:     %T.ref: <error> = name_ref T, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]
 // CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]

+ 12 - 1
toolchain/check/testdata/impl/use_assoc_entity.carbon

@@ -2650,6 +2650,7 @@ fn F() {
 // CHECK:STDOUT:   %E.as.J.impl.F.decl.loc27_21.1: %E.as.J.impl.F.type.4b5c2a.1 = fn_decl @E.as.J.impl.F.loc27_21.1 [concrete = constants.%E.as.J.impl.F.b4e6ab.1] {
 // CHECK:STDOUT:     %u.param_patt: <error> = value_param_pattern [concrete]
 // CHECK:STDOUT:     %u.patt: <error> = at_binding_pattern u, %u.param_patt [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %U.ref.loc27_19: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.ebd]
 // CHECK:STDOUT:     %.loc27_19: type = converted %U.ref.loc27_19, <error> [concrete = <error>]
@@ -2659,6 +2660,7 @@ fn F() {
 // CHECK:STDOUT:       %.loc27_13: type = converted %U.ref.loc27_13, <error> [concrete = <error>]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %u: <error> = value_binding u, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc5_17.1: type = specific_constant @J.WithSelf.F.%U.ref.loc5_17, @J.WithSelf.F(constants.%J.facet) [concrete = constants.%i32]
 // CHECK:STDOUT:   %.loc5_17.2: type = specific_constant @J.WithSelf.F.%.loc5_17.2, @J.WithSelf.F(constants.%J.facet) [concrete = constants.%.ff5]
@@ -3158,9 +3160,12 @@ fn F() {
 // CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc8_32.2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %E.G.decl: %E.G.type = fn_decl @E.G [concrete = constants.%E.G] {} {
+// CHECK:STDOUT:   %E.G.decl: %E.G.type = fn_decl @E.G [concrete = constants.%E.G] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %X.ref: %J.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.df0]
 // CHECK:STDOUT:     %.loc18_13: type = converted %X.ref, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
@@ -3304,6 +3309,7 @@ fn F() {
 // CHECK:STDOUT:     %self.patt: @J2.WithSelf.F.%pattern_type (%pattern_type.21d) = at_binding_pattern self, %self.param_patt [concrete]
 // CHECK:STDOUT:     %z.param_patt: <error> = value_param_pattern [concrete]
 // CHECK:STDOUT:     %z.patt: <error> = at_binding_pattern z, %z.param_patt [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %Self.ref.loc19_35: %J2.type = name_ref Self, @J2.%Self [symbolic = %Self (constants.%Self)]
 // CHECK:STDOUT:     %Self.as_type.loc19_39: type = facet_access_type %Self.ref.loc19_35 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
@@ -3324,6 +3330,7 @@ fn F() {
 // CHECK:STDOUT:       %U2.ref.loc19_27: <error> = name_ref U2, <error> [concrete = <error>]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %z: <error> = value_binding z, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %assoc1: %J2.assoc_type = assoc_entity element1, %J2.WithSelf.F.decl [concrete = constants.%assoc1]
 // CHECK:STDOUT:
@@ -3365,9 +3372,11 @@ fn F() {
 // CHECK:STDOUT:   %empty_tuple.type.as.J2.impl.F.decl.loc23_40.2: %empty_tuple.type.as.J2.impl.F.type.56bdaf.2 = fn_decl @empty_tuple.type.as.J2.impl.F.loc23_40.2 [concrete = constants.%empty_tuple.type.as.J2.impl.F.7b8679.2] {
 // CHECK:STDOUT:     %self.param_patt: %pattern_type.cb1 = value_param_pattern [concrete]
 // CHECK:STDOUT:     %self.patt: %pattern_type.cb1 = at_binding_pattern self, %self.param_patt [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, invalid [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %self.param: %empty_tuple.type = value_param call_param0
 // CHECK:STDOUT:     %self: %empty_tuple.type = value_binding self, %self.param
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %J2.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, %empty_tuple.type.as.J2.impl.F.decl.loc23_40.2), @empty_tuple.type.as.J2.impl [concrete]
 // CHECK:STDOUT:   %J2.impl_witness: <witness> = impl_witness %J2.impl_witness_table [concrete = constants.%J2.impl_witness.941]
@@ -3403,9 +3412,11 @@ fn F() {
 // CHECK:STDOUT:   %C2.as.J2.impl.F.decl.loc32_40.2: %C2.as.J2.impl.F.type.d2a210.2 = fn_decl @C2.as.J2.impl.F.loc32_40.2 [concrete = constants.%C2.as.J2.impl.F.720bb2.2] {
 // CHECK:STDOUT:     %self.param_patt: %pattern_type.8df = value_param_pattern [concrete]
 // CHECK:STDOUT:     %self.patt: %pattern_type.8df = at_binding_pattern self, %self.param_patt [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, invalid [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %self.param: %C2 = value_param call_param0
 // CHECK:STDOUT:     %self: %C2 = value_binding self, %self.param
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %J2.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, %C2.as.J2.impl.F.decl.loc32_40.2), @C2.as.J2.impl [concrete]
 // CHECK:STDOUT:   %J2.impl_witness: <witness> = impl_witness %J2.impl_witness_table [concrete = constants.%J2.impl_witness.30f]

+ 4 - 1
toolchain/check/testdata/interface/fail_lookup_undefined.carbon

@@ -87,9 +87,12 @@ interface BeingDefined {
 // CHECK:STDOUT:   %BeingDefined.WithSelf.decl = interface_with_self_decl @BeingDefined [concrete]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !with Self:
-// CHECK:STDOUT:   %BeingDefined.WithSelf.H.decl: @BeingDefined.WithSelf.%BeingDefined.WithSelf.H.type (%BeingDefined.WithSelf.H.type) = fn_decl @BeingDefined.WithSelf.H [symbolic = @BeingDefined.WithSelf.%BeingDefined.WithSelf.H (constants.%BeingDefined.WithSelf.H)] {} {
+// CHECK:STDOUT:   %BeingDefined.WithSelf.H.decl: @BeingDefined.WithSelf.%BeingDefined.WithSelf.H.type (%BeingDefined.WithSelf.H.type) = fn_decl @BeingDefined.WithSelf.H [symbolic = @BeingDefined.WithSelf.%BeingDefined.WithSelf.H (constants.%BeingDefined.WithSelf.H)] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %BeingDefined.ref: type = name_ref BeingDefined, file.%BeingDefined.decl [concrete = constants.%BeingDefined.type]
 // CHECK:STDOUT:     %T.ref: <error> = name_ref T, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %assoc0: %BeingDefined.assoc_type = assoc_entity element0, %BeingDefined.WithSelf.H.decl [concrete = constants.%assoc0]
 // CHECK:STDOUT:   %BeingDefined.WithSelf.I.decl: @BeingDefined.WithSelf.%BeingDefined.WithSelf.I.type (%BeingDefined.WithSelf.I.type) = fn_decl @BeingDefined.WithSelf.I [symbolic = @BeingDefined.WithSelf.%BeingDefined.WithSelf.I (constants.%BeingDefined.WithSelf.I)] {} {}

+ 2 - 0
toolchain/check/testdata/interface/fail_member_lookup.carbon

@@ -97,6 +97,7 @@ fn G(U:! Different) -> U.(Interface.T);
 // CHECK:STDOUT:   %Different.decl: type = interface_decl @Different [concrete = constants.%Different.type] {} {}
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
 // CHECK:STDOUT:     %U.patt: %pattern_type.cb4 = symbolic_binding_pattern U, 0 [concrete]
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %U.ref: %Different.type = name_ref U, %U.loc32_7.2 [symbolic = %U.loc32_7.1 (constants.%U)]
 // CHECK:STDOUT:     %Interface.ref: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]
@@ -107,6 +108,7 @@ fn G(U:! Different) -> U.(Interface.T);
 // CHECK:STDOUT:       %Different.ref: type = name_ref Different, file.%Different.decl [concrete = constants.%Different.type]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %U.loc32_7.2: %Different.type = symbolic_binding U, 0 [symbolic = %U.loc32_7.1 (constants.%U)]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 8 - 2
toolchain/check/testdata/let/compile_time_bindings.carbon

@@ -622,8 +622,11 @@ impl i32 as Empty {
 // CHECK:STDOUT:     %.loc9_11.2: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %T: type = value_binding T, %i32
-// CHECK:STDOUT:   %I.F.decl: %I.F.type = fn_decl @I.F [concrete = constants.%I.F] {} {
+// CHECK:STDOUT:   %I.F.decl: %I.F.type = fn_decl @I.F [concrete = constants.%I.F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref: type = name_ref T, @I.%T
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
@@ -674,8 +677,11 @@ impl i32 as Empty {
 // CHECK:STDOUT:     %.loc8_9.2: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %T: type = value_binding T, @__global_init.%i32
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref: type = name_ref T, file.%T
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/packages/export_import.carbon

@@ -900,8 +900,11 @@ export Poison;
 // CHECK:STDOUT:     .Poison = <poisoned>
 // CHECK:STDOUT:     .F = %F.decl
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %Poison.ref: <error> = name_ref Poison, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/return/fail_call_in_type.carbon

@@ -74,11 +74,14 @@ fn Six() -> ReturnType() { return 6; }
 // CHECK:STDOUT:     %return.param: ref type = out_param call_param0
 // CHECK:STDOUT:     %return: ref type = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {} {
+// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %ReturnType.ref: %ReturnType.type = name_ref ReturnType, file.%ReturnType.decl [concrete = constants.%ReturnType]
 // CHECK:STDOUT:     %ReturnType.call: init type = call %ReturnType.ref()
 // CHECK:STDOUT:     %.loc22_24.1: type = value_of_initializer %ReturnType.call
 // CHECK:STDOUT:     %.loc22_24.2: type = converted %ReturnType.call, %.loc22_24.1
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/return/fail_error_in_type.carbon

@@ -39,8 +39,11 @@ fn Six() -> x;
 // CHECK:STDOUT:     .Six = %Six.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {} {
+// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %x.ref: <error> = name_ref x, <error> [concrete = <error>]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 12 - 3
toolchain/check/testdata/return/fail_let_in_type.carbon

@@ -87,8 +87,11 @@ fn FirstPerfectNumber() -> z { return 6; }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc15: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   %x: type = value_binding x, @__global_init.%i32.loc15
-// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {} {
+// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %x.ref: type = name_ref x, file.%x
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %y.patt: %pattern_type.98f = value_binding_pattern y [concrete]
@@ -98,8 +101,11 @@ fn FirstPerfectNumber() -> z { return 6; }
 // CHECK:STDOUT:     %.loc27_9.2: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %y: type = value_binding y, @__global_init.%i32.loc27
-// CHECK:STDOUT:   %HalfDozen.decl: %HalfDozen.type = fn_decl @HalfDozen [concrete = constants.%HalfDozen] {} {
+// CHECK:STDOUT:   %HalfDozen.decl: %HalfDozen.type = fn_decl @HalfDozen [concrete = constants.%HalfDozen] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %y.ref: type = name_ref y, file.%y
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %z.patt: %pattern_type.98f = value_binding_pattern z [concrete]
@@ -109,8 +115,11 @@ fn FirstPerfectNumber() -> z { return 6; }
 // CHECK:STDOUT:     %.loc39_18.2: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %z: type = value_binding z, @__global_init.%i32.loc39
-// CHECK:STDOUT:   %FirstPerfectNumber.decl: %FirstPerfectNumber.type = fn_decl @FirstPerfectNumber [concrete = constants.%FirstPerfectNumber] {} {
+// CHECK:STDOUT:   %FirstPerfectNumber.decl: %FirstPerfectNumber.type = fn_decl @FirstPerfectNumber [concrete = constants.%FirstPerfectNumber] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %z.ref: type = name_ref z, file.%z
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/return/fail_var_in_type.carbon

@@ -67,9 +67,12 @@ fn Six() -> x { return 6; }
 // CHECK:STDOUT:   %x.var: ref type = var %x.var_patt [concrete]
 // CHECK:STDOUT:   %.loc15: type = type_literal type [concrete = type]
 // CHECK:STDOUT:   %x: ref type = ref_binding x, %x.var [concrete = %x.var]
-// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {} {
+// CHECK:STDOUT:   %Six.decl: %Six.type = fn_decl @Six [concrete = constants.%Six] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %x.ref: ref type = name_ref x, file.%x [concrete = file.%x.var]
 // CHECK:STDOUT:     %.loc20: type = acquire_value %x.ref
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 4 - 1
toolchain/check/testdata/struct/fail_duplicate_name.carbon

@@ -98,12 +98,15 @@ var y: {.b: i32, .c: i32} = {.b = 3, .b = 4};
 // CHECK:STDOUT:     .y = %y
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
-// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {
+// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
+// CHECK:STDOUT:     %return.patt: <error> = return_slot_pattern <error>, <error> [concrete]
+// CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %i32.loc22_16: type = type_literal constants.%i32 [concrete = constants.%i32]
 // CHECK:STDOUT:     %i32.loc22_27: type = type_literal constants.%i32 [concrete = constants.%i32]
 // CHECK:STDOUT:     %i32.loc22_36: type = type_literal constants.%i32 [concrete = constants.%i32]
 // CHECK:STDOUT:     %i32.loc22_47: type = type_literal constants.%i32 [concrete = constants.%i32]
 // CHECK:STDOUT:     %i32.loc22_56: type = type_literal constants.%i32 [concrete = constants.%i32]
+// CHECK:STDOUT:     %return: <error> = return_slot <error>
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %v.patt: <error> = value_binding_pattern v [concrete]

+ 26 - 10
toolchain/check/thunk.cpp

@@ -125,10 +125,27 @@ static auto ClonePattern(Context& context, SemIR::SpecificId specific_id,
     new_pattern_id = CloneBindingPattern(context, pattern_id, *binding,
                                          get_type(pattern_id));
   } else if (auto return_slot = pattern.TryAs<SemIR::ReturnSlotPattern>()) {
-    auto new_subpattern_id = RebuildPatternInst<SemIR::OutParamPattern>(
-        context, return_slot->subpattern_id,
-        {.type_id = get_type(return_slot->subpattern_id),
-         .pretty_name_id = SemIR::NameId::ReturnSlot});
+    auto new_subpattern_id = SemIR::InstId::None;
+    auto subpattern = context.insts().Get(return_slot->subpattern_id);
+    CARBON_KIND_SWITCH(subpattern) {
+      case SemIR::OutParamPattern::Kind:
+      case SemIR::RefReturnPattern::Kind:
+      case SemIR::ValueReturnPattern::Kind:
+        // These are leaf insts, so we can reuse their contents after updating
+        // the type.
+        subpattern.SetType(get_type(return_slot->subpattern_id));
+        new_subpattern_id =
+            RebuildPatternInst(context, return_slot->subpattern_id, subpattern);
+        break;
+      case SemIR::ErrorInst::Kind:
+        subpattern.SetType(SemIR::ErrorInst::TypeId);
+        new_subpattern_id = SemIR::ErrorInst::InstId;
+        break;
+      default:
+        CARBON_FATAL("Unexpected kind for return slot subpattern {0}",
+                     subpattern);
+    }
+
     new_pattern_id = RebuildPatternInst<SemIR::ReturnSlotPattern>(
         context, pattern_id,
         {.type_id = get_type(pattern_id),
@@ -200,8 +217,8 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id,
       context, signature_specific_id, signature.implicit_param_patterns_id);
   auto param_patterns_id = ClonePatternBlock(context, signature_specific_id,
                                              signature.param_patterns_id);
-  auto return_patterns_id = ClonePatternBlock(context, signature_specific_id,
-                                              signature.return_patterns_id);
+  auto return_pattern_id =
+      ClonePattern(context, signature_specific_id, signature.return_pattern_id);
   auto return_type_inst_id = CloneTypeInstId(context, signature_specific_id,
                                              signature.return_type_inst_id);
   auto return_form_inst_id = CloneInstId(context, signature_specific_id,
@@ -211,9 +228,8 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id,
 
   // Perform callee-side pattern matching to rebuild the parameter list.
   context.inst_block_stack().Push();
-  auto match_results =
-      CalleePatternMatch(context, implicit_param_patterns_id, param_patterns_id,
-                         return_patterns_id);
+  auto match_results = CalleePatternMatch(context, implicit_param_patterns_id,
+                                          param_patterns_id, return_pattern_id);
   auto decl_block_id = context.inst_block_stack().Pop();
 
   // Create the `FunctionDecl` instruction.
@@ -244,7 +260,7 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id,
               .call_param_ranges = match_results.param_ranges,
               .return_type_inst_id = return_type_inst_id,
               .return_form_inst_id = return_form_inst_id,
-              .return_patterns_id = return_patterns_id,
+              .return_pattern_id = return_pattern_id,
               .virtual_modifier = callee.virtual_modifier,
               .virtual_index = callee.virtual_index,
               .evaluation_mode = signature.evaluation_mode,

+ 18 - 0
toolchain/lower/handle.cpp

@@ -321,6 +321,15 @@ auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/,
   }
 }
 
+auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
+                SemIR::RefReturn /*inst*/) -> void {
+  // A `RefReturn` is a placeholder that represents the absence of a storage
+  // location, so it should never actually be used, but in some cases it will
+  // be propagated, so we poison it.
+  context.SetLocal(inst_id,
+                   llvm::PoisonValue::get(context.GetTypeOfInst(inst_id)));
+}
+
 auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
                 SemIR::SpecificFunction /*inst*/) -> void {
   // Nothing to do. This value should never be consumed.
@@ -367,6 +376,15 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
                    llvm::PoisonValue::get(context.GetTypeOfInst(inst_id)));
 }
 
+auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
+                SemIR::ValueReturn /*inst*/) -> void {
+  // A `ValueReturn` is a placeholder that represents the absence of a storage
+  // location, so it should never actually be used, but in some cases it will
+  // be propagated, so we poison it.
+  context.SetLocal(inst_id,
+                   llvm::PoisonValue::get(context.GetTypeOfInst(inst_id)));
+}
+
 auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
                 SemIR::VarStorage /* inst */) -> void {
   context.SetLocal(inst_id,

+ 8 - 11
toolchain/sem_ir/function.h

@@ -116,16 +116,13 @@ struct FunctionFields {
   // any.
   InstId return_form_inst_id;
 
-  // The parameter pattern insts that are declared by the function's return
-  // form declaration. They will all be OutParamPatterns, and there will be one
-  // for each primitive initializing form in the return form, but they may or
-  // may not be used, depending on whether the type has an in-place initializing
-  // representation.
+  // The parameter pattern inst that is declared by the function's return
+  // declaration. This will be a ReturnSlotPattern, or None if the function
+  // doesn't have a return declaration. It may or may not be used, depending on
+  // whether the type has an in-place initializing representation.
   //
-  // Note: As of this writing we don't support non-initializing return forms,
-  // so this will always be have exactly 1 element if the function has an
-  // explicitly declared return type.
-  InstBlockId return_patterns_id;
+  // TODO: Extend this to support composite return forms.
+  InstId return_pattern_id;
 
   // Which kind of special function this is, if any. This is used in cases where
   // a special function would otherwise be indistinguishable from a normal
@@ -195,8 +192,8 @@ struct Function : public EntityWithParamsBase,
     if (return_type_inst_id.has_value()) {
       out << ", return_form_inst_id: " << return_form_inst_id;
     }
-    if (return_patterns_id.has_value()) {
-      out << ", return_patterns_id: " << return_patterns_id;
+    if (return_pattern_id.has_value()) {
+      out << ", return_pattern_id: " << return_pattern_id;
     }
     if (!body_block_ids.empty()) {
       out << llvm::formatv(

+ 16 - 0
toolchain/sem_ir/inst_categories.h

@@ -387,6 +387,22 @@ struct AnyStructType {
   AnyRawId arg1;
 };
 
+// clang-format off
+#define AnyReturnPattern_CARBON_INST_CATEGORY(X, Sep) \
+  X(::Carbon::SemIR::RefReturnPattern) Sep()          \
+  X(::Carbon::SemIR::ValueReturnPattern)
+// clang-format on
+
+#define AnyReturnPattern_CARBON_KIND_ANY_EXPAND \
+  CARBON_INST_CATEGORY_ANY_EXPAND(AnyReturnPattern)
+
+struct AnyReturnPattern {
+  using CategoryInfo = CARBON_INST_CATEGORY_INFO(AnyReturnPattern);
+
+  InstKind kind;
+  TypeId type_id;
+};
+
 // clang-format off
 #define AnyVarPattern_CARBON_INST_CATEGORY(X, Sep) \
   X(::Carbon::SemIR::VarParamPattern) Sep()        \

+ 4 - 0
toolchain/sem_ir/inst_kind.def

@@ -119,6 +119,8 @@ CARBON_SEM_IR_INST_KIND(RefBindingPattern)
 CARBON_SEM_IR_INST_KIND(RefForm)
 CARBON_SEM_IR_INST_KIND(RefParam)
 CARBON_SEM_IR_INST_KIND(RefParamPattern)
+CARBON_SEM_IR_INST_KIND(RefReturn)
+CARBON_SEM_IR_INST_KIND(RefReturnPattern)
 CARBON_SEM_IR_INST_KIND(RefTagExpr)
 CARBON_SEM_IR_INST_KIND(RefineTypeAction)
 CARBON_SEM_IR_INST_KIND(RequireCompleteType)
@@ -171,6 +173,8 @@ CARBON_SEM_IR_INST_KIND(ValueForm)
 CARBON_SEM_IR_INST_KIND(ValueOfInitializer)
 CARBON_SEM_IR_INST_KIND(ValueParam)
 CARBON_SEM_IR_INST_KIND(ValueParamPattern)
+CARBON_SEM_IR_INST_KIND(ValueReturn)
+CARBON_SEM_IR_INST_KIND(ValueReturnPattern)
 CARBON_SEM_IR_INST_KIND(VarParamPattern)
 CARBON_SEM_IR_INST_KIND(VarPattern)
 CARBON_SEM_IR_INST_KIND(VarStorage)

+ 54 - 1
toolchain/sem_ir/typed_insts.h

@@ -1490,6 +1490,32 @@ struct RefParamPattern {
   NameId pretty_name_id;
 };
 
+// Represents a reference return form within the function body, in the same
+// way that `OutParam` represents an initializing return form. It is used where
+// output storage would otherwise be expected, and signifies that the output
+// in question is not written to memory, but is instead returned directly,
+// as the result (or part of the result) of the `Call` inst.
+struct RefReturn {
+  static constexpr auto Kind = InstKind::RefReturn.Define<Parse::NodeId>(
+      {.ir_name = "ref_return",
+       .expr_category = ExprCategory::EphemeralRef,
+       .constant_kind = InstConstantKind::Never});
+
+  TypeId type_id;
+};
+
+// A pattern that represents a reference return form, in the same way that an
+// OutParamPattern represents an initializing return form.
+struct RefReturnPattern {
+  static constexpr auto Kind = InstKind::RefReturnPattern.Define<Parse::NodeId>(
+      {.ir_name = "ref_return_pattern",
+       .expr_category = ExprCategory::Pattern,
+       .constant_kind = InstConstantKind::AlwaysUnique,
+       .is_lowered = false});
+
+  TypeId type_id;
+};
+
 // A `ref x` expression. The semantics of this instruction depend on the usage
 // context:
 // - As an argument to a `ref` parameter, it evaluates to `x`, but requires
@@ -1656,7 +1682,7 @@ struct ReturnExpr {
 struct ReturnSlot {
   static constexpr auto Kind = InstKind::ReturnSlot.Define<Parse::NodeId>(
       {.ir_name = "return_slot",
-       .expr_category = ExprCategory::DurableRef,
+       .expr_category = ComputedExprCategory::SameAsSecondOperand,
        .constant_kind = InstConstantKind::Never});
 
   // The type of the value that will be stored in this slot (i.e. the return
@@ -2212,6 +2238,33 @@ struct ValueParamPattern {
   NameId pretty_name_id;
 };
 
+// Represents a value return form within the function body, in the same way
+// that `OutParam` represents an initializing return form. It is used where
+// output storage would otherwise be expected, and signifies that the output
+// in question is not written to memory, but is instead returned directly,
+// as the result (or part of the result) of the `Call` inst.
+struct ValueReturn {
+  static constexpr auto Kind = InstKind::ValueReturn.Define<Parse::NodeId>(
+      {.ir_name = "value_return",
+       .expr_category = ExprCategory::Value,
+       .constant_kind = InstConstantKind::Never});
+
+  TypeId type_id;
+};
+
+// A pattern that represents a value return form, in the same way that an
+// OutParamPattern represents an initializing return form.
+struct ValueReturnPattern {
+  static constexpr auto Kind =
+      InstKind::ValueReturnPattern.Define<Parse::NodeId>(
+          {.ir_name = "value_return_pattern",
+           .expr_category = ExprCategory::Pattern,
+           .constant_kind = InstConstantKind::AlwaysUnique,
+           .is_lowered = false});
+
+  TypeId type_id;
+};
+
 // A `var` pattern that is a `Call` parameter. See `AnyVarPattern` for member
 // documentation. Note that there is no `VarParam` -- a `VarParamPattern`
 // corresponds to a `RefParam`.