Эх сурвалжийг харах

Don't treat dependent types as having a copy value representation. (#6055)

Add `Dependent` value and initializing representations for types whose
representations are unknown because they are dependent. When generating
SemIR in such cases, use a worst-case initializing representation that
both provides a destination address and also propagates a potential
result value.

Use this to fix incorrect lowering and lowering crashes for specific
functions involving generic types that don't use a copy value
representation.

In lowering, be careful to distinguish between whether the initializing
representation for the generic return type uses a return slot (which
affects whether the SemIR declaration and call have one) and whether the
initializing representation for the specific return type uses a return
slot (which affects whether the LLVM IR declaration and call have one).
Richard Smith 7 сар өмнө
parent
commit
b44ba47cf3
53 өөрчлөгдсөн 1376 нэмэгдсэн , 671 устгасан
  1. 1 0
      toolchain/check/call.cpp
  2. 54 40
      toolchain/check/convert.cpp
  3. 7 2
      toolchain/check/pending_block.h
  4. 147 147
      toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon
  5. 1 1
      toolchain/check/testdata/builtins/int/make_type_signed.carbon
  6. 1 1
      toolchain/check/testdata/builtins/int/make_type_unsigned.carbon
  7. 6 5
      toolchain/check/testdata/class/generic/base_is_generic.carbon
  8. 3 2
      toolchain/check/testdata/class/generic/basic.carbon
  9. 6 4
      toolchain/check/testdata/class/generic/field.carbon
  10. 7 5
      toolchain/check/testdata/class/generic/init.carbon
  11. 3 2
      toolchain/check/testdata/class/generic/member_access.carbon
  12. 6 4
      toolchain/check/testdata/class/generic/member_inline.carbon
  13. 6 4
      toolchain/check/testdata/class/generic/member_lookup.carbon
  14. 6 4
      toolchain/check/testdata/class/generic/member_out_of_line.carbon
  15. 5 4
      toolchain/check/testdata/class/generic/member_type.carbon
  16. 8 6
      toolchain/check/testdata/deduce/array.carbon
  17. 4 3
      toolchain/check/testdata/deduce/generic_type.carbon
  18. 3 2
      toolchain/check/testdata/deduce/tuple.carbon
  19. 16 12
      toolchain/check/testdata/deduce/type_operator.carbon
  20. 1 1
      toolchain/check/testdata/eval/aggregates.carbon
  21. 9 6
      toolchain/check/testdata/facet/access.carbon
  22. 12 8
      toolchain/check/testdata/function/generic/call.carbon
  23. 5 4
      toolchain/check/testdata/function/generic/return_slot.carbon
  24. 3 2
      toolchain/check/testdata/generic/dependent_param.carbon
  25. 6 4
      toolchain/check/testdata/impl/impl_thunk.carbon
  26. 68 28
      toolchain/check/testdata/impl/use_assoc_const.carbon
  27. 1 1
      toolchain/check/testdata/interface/member_lookup.carbon
  28. 7 21
      toolchain/check/testdata/interop/cpp/enum/copy.carbon
  29. 16 16
      toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon
  30. 1 1
      toolchain/check/testdata/interop/cpp/function/full_semir.carbon
  31. 2 2
      toolchain/check/testdata/interop/cpp/function/inline.carbon
  32. 2 2
      toolchain/check/testdata/interop/cpp/function/overloads.carbon
  33. 3 2
      toolchain/check/testdata/operators/overloaded/implicit_as.carbon
  34. 9 2
      toolchain/check/type_completion.cpp
  35. 14 8
      toolchain/lower/file_context.cpp
  36. 5 0
      toolchain/lower/function_context.cpp
  37. 4 4
      toolchain/lower/handle.cpp
  38. 10 1
      toolchain/lower/handle_aggregates.cpp
  39. 8 0
      toolchain/lower/handle_call.cpp
  40. 7 0
      toolchain/lower/handle_expr_category.cpp
  41. 27 29
      toolchain/lower/testdata/array/field.carbon
  42. 143 56
      toolchain/lower/testdata/class/generic.carbon
  43. 103 7
      toolchain/lower/testdata/for/bindings.carbon
  44. 167 130
      toolchain/lower/testdata/function/generic/call_basic.carbon
  45. 4 1
      toolchain/lower/testdata/function/generic/call_basic_depth.carbon
  46. 15 9
      toolchain/lower/testdata/function/generic/call_deref_ptr.carbon
  47. 18 2
      toolchain/lower/testdata/function/generic/call_different_impls_with_const.carbon
  48. 15 9
      toolchain/lower/testdata/function/generic/call_different_specific.carbon
  49. 93 66
      toolchain/lower/testdata/function/generic/call_recursive_basic.carbon
  50. 278 0
      toolchain/lower/testdata/function/generic/type_representation.carbon
  51. 3 0
      toolchain/sem_ir/expr_info.cpp
  52. 6 0
      toolchain/sem_ir/type_info.cpp
  53. 21 1
      toolchain/sem_ir/type_info.h

+ 1 - 0
toolchain/check/call.cpp

@@ -229,6 +229,7 @@ static auto PerformCallToFunction(Context& context, SemIR::LocId loc_id,
   SemIR::InstId return_slot_arg_id = SemIR::InstId::None;
   switch (return_info.init_repr.kind) {
     case SemIR::InitRepr::InPlace:
+    case SemIR::InitRepr::Dependent:
       // Tentatively put storage for a temporary in the function's return slot.
       // This will be replaced if necessary when we perform initialization.
       return_slot_arg_id = AddInst<SemIR::TemporaryStorage>(

+ 54 - 40
toolchain/check/convert.cpp

@@ -42,8 +42,8 @@ namespace Carbon::Check {
 
 // Marks the initializer `init_id` as initializing `target_id`.
 static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id,
-                               SemIR::InstId target_id,
-                               PendingBlock& target_block) -> void {
+                               ConversionTarget& target) -> void {
+  CARBON_CHECK(target.is_initializer());
   auto return_slot_arg_id = FindReturnSlotArgForInitializer(sem_ir, init_id);
   if (return_slot_arg_id.has_value()) {
     // Replace the temporary in the return slot with a reference to our target.
@@ -52,7 +52,8 @@ static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id,
                  "Return slot for initializer does not contain a temporary; "
                  "initialized multiple times? Have {0}",
                  sem_ir.insts().Get(return_slot_arg_id));
-    target_block.MergeReplacing(return_slot_arg_id, target_id);
+    target.init_id =
+        target.init_block->MergeReplacing(return_slot_arg_id, target.init_id);
   }
 }
 
@@ -146,6 +147,29 @@ static auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id,
   }
 }
 
+// Get the conversion target kind to use when initializing an element of an
+// aggregate.
+static auto GetAggregateElementConversionTargetKind(SemIR::File& sem_ir,
+                                                    ConversionTarget target)
+    -> ConversionTarget::Kind {
+  // If we're forming an initializer, then we want an initializer for each
+  // element.
+  if (target.is_initializer()) {
+    // Perform a final destination store if we're performing an in-place
+    // initialization.
+    auto init_repr = SemIR::InitRepr::ForType(sem_ir, target.type_id);
+    CARBON_CHECK(init_repr.kind != SemIR::InitRepr::Dependent,
+                 "Aggregate should not have dependent init kind");
+    if (init_repr.kind == SemIR::InitRepr::InPlace) {
+      return ConversionTarget::FullInitializer;
+    }
+    return ConversionTarget::Initializer;
+  }
+
+  // Otherwise, we want a value representation for each element.
+  return ConversionTarget::Value;
+}
+
 // Converts an element of one aggregate so that it can be used as an element of
 // another aggregate.
 //
@@ -336,17 +360,8 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
     return SemIR::ErrorInst::InstId;
   }
 
-  // If we're forming an initializer, then we want an initializer for each
-  // element. Otherwise, we want a value representation for each element.
-  // Perform a final destination store if we're performing an in-place
-  // initialization.
-  bool is_init = target.is_initializer();
   ConversionTarget::Kind inner_kind =
-      !is_init ? ConversionTarget::Value
-      : SemIR::InitRepr::ForType(sem_ir, target.type_id).kind ==
-              SemIR::InitRepr::InPlace
-          ? ConversionTarget::FullInitializer
-          : ConversionTarget::Initializer;
+      GetAggregateElementConversionTargetKind(sem_ir, target);
 
   // Initialize each element of the destination from the corresponding element
   // of the source.
@@ -373,7 +388,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
     new_block.Set(i, init_id);
   }
 
-  if (is_init) {
+  if (target.is_initializer()) {
     target.init_block->InsertHere();
     return AddInst<SemIR::TupleInit>(context, value_loc_id,
                                      {.type_id = target.type_id,
@@ -447,17 +462,8 @@ static auto ConvertStructToStructOrClass(
     }
   }
 
-  // If we're forming an initializer, then we want an initializer for each
-  // element. Otherwise, we want a value representation for each element.
-  // Perform a final destination store if we're performing an in-place
-  // initialization.
-  bool is_init = target.is_initializer();
   ConversionTarget::Kind inner_kind =
-      !is_init ? ConversionTarget::Value
-      : SemIR::InitRepr::ForType(sem_ir, target.type_id).kind ==
-              SemIR::InitRepr::InPlace
-          ? ConversionTarget::FullInitializer
-          : ConversionTarget::Initializer;
+      GetAggregateElementConversionTargetKind(sem_ir, target);
 
   // Initialize each element of the destination from the corresponding element
   // of the source.
@@ -545,6 +551,7 @@ static auto ConvertStructToStructOrClass(
     new_block.Set(i, init_id);
   }
 
+  bool is_init = target.is_initializer();
   if (ToClass) {
     target.init_block->InsertHere();
     CARBON_CHECK(is_init,
@@ -1282,30 +1289,33 @@ static auto IsCppEnum(Context& context, SemIR::TypeId type_id) -> bool {
 }
 
 // Given a value expression, form a corresponding initializer that copies from
-// that value, if it is possible to do so.
-static auto PerformCopy(Context& context, SemIR::InstId expr_id, bool diagnose)
-    -> SemIR::InstId {
+// that value to the specified target, if it is possible to do so.
+static auto PerformCopy(Context& context, SemIR::InstId expr_id,
+                        ConversionTarget& target) -> SemIR::InstId {
   // TODO: We don't have a mechanism yet to generate `Copy` impls for each enum
   // type imported from C++. For now we fake it by providing a direct copy.
-  if (IsCppEnum(context, context.insts().Get(expr_id).type_id())) {
-    return CopyValueToTemporary(context, expr_id);
+  auto type_id = context.insts().Get(expr_id).type_id();
+  if (IsCppEnum(context, type_id)) {
+    return expr_id;
   }
 
-  return BuildUnaryOperator(
+  auto copy_id = BuildUnaryOperator(
       context, SemIR::LocId(expr_id), {"Copy"}, expr_id, [&] {
-        if (!diagnose) {
+        if (!target.diagnose) {
           return context.emitter().BuildSuppressed();
         }
         CARBON_DIAGNOSTIC(CopyOfUncopyableType, Error,
                           "cannot copy value of type {0}", TypeOfInstId);
         return context.emitter().Build(expr_id, CopyOfUncopyableType, expr_id);
       });
+  MarkInitializerFor(context.sem_ir(), copy_id, target);
+  return copy_id;
 }
 
 // Convert a value expression so that it can be used to initialize a C++ thunk
 // parameter.
-static auto ConvertValueForCppThunkRef(Context& context, SemIR::InstId expr_id,
-                                       bool diagnose) -> SemIR::InstId {
+static auto ConvertValueForCppThunkRef(Context& context, SemIR::InstId expr_id)
+    -> SemIR::InstId {
   auto expr = context.insts().Get(expr_id);
 
   // If the expression has a pointer value representation, extract that and use
@@ -1319,8 +1329,13 @@ static auto ConvertValueForCppThunkRef(Context& context, SemIR::InstId expr_id,
 
   // Otherwise, we need a temporary to pass as the thunk argument. Create a copy
   // and initialize a temporary from it.
-  expr_id = PerformCopy(context, expr_id, diagnose);
-  return MaterializeIfInitializing(context, expr_id);
+  auto temporary_id = AddInst<SemIR::TemporaryStorage>(
+      context, SemIR::LocId(expr_id), {.type_id = expr.type_id()});
+  expr_id = Initialize(context, SemIR::LocId(expr_id), temporary_id, expr_id);
+  return AddInstWithCleanup<SemIR::Temporary>(context, SemIR::LocId(expr_id),
+                                              {.type_id = expr.type_id(),
+                                               .storage_id = temporary_id,
+                                               .init_id = expr_id});
 }
 
 // Returns the Core interface name to use for a given kind of conversion.
@@ -1524,8 +1539,7 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
           // a conversion. In that case, we will have created it with the
           // target already set.
           // TODO: Find a better way to track whether we need to do this.
-          MarkInitializerFor(sem_ir, expr_id, target.init_id,
-                             *target.init_block);
+          MarkInitializerFor(sem_ir, expr_id, target);
         }
         break;
       }
@@ -1577,13 +1591,13 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
 
       // When initializing from a value, perform a copy.
       if (target.is_initializer()) {
-        expr_id = PerformCopy(context, expr_id, target.diagnose);
+        expr_id = PerformCopy(context, expr_id, target);
       }
 
       // When initializing a C++ thunk parameter, form a reference, creating a
       // temporary if needed.
       if (target.kind == ConversionTarget::CppThunkRef) {
-        expr_id = ConvertValueForCppThunkRef(context, expr_id, target.diagnose);
+        expr_id = ConvertValueForCppThunkRef(context, expr_id);
       }
 
       break;
@@ -1592,7 +1606,7 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
   // Perform a final destination store, if necessary.
   if (target.kind == ConversionTarget::FullInitializer) {
     if (auto init_rep = SemIR::InitRepr::ForType(sem_ir, target.type_id);
-        init_rep.kind == SemIR::InitRepr::ByCopy) {
+        init_rep.MightBeByCopy()) {
       target.init_block->InsertHere();
       expr_id = AddInst<SemIR::InitializeFrom>(context, loc_id,
                                                {.type_id = target.type_id,

+ 7 - 2
toolchain/check/pending_block.h

@@ -68,13 +68,17 @@ class PendingBlock {
   }
 
   // Replace the instruction at target_id with the instructions in this block.
-  // The new value for target_id should be value_id.
-  auto MergeReplacing(SemIR::InstId target_id, SemIR::InstId value_id) -> void {
+  // The new value for target_id should be value_id. Returns the InstId that
+  // should be used to refer to the result from now on.
+  auto MergeReplacing(SemIR::InstId target_id, SemIR::InstId value_id)
+      -> SemIR::InstId {
     SemIR::LocIdAndInst value = context_->insts().GetWithLocId(value_id);
 
+    auto result_id = value_id;
     if (insts_.size() == 1 && insts_[0] == value_id) {
       // The block is {value_id}. Replace `target_id` with the instruction
       // referred to by `value_id`. This is intended to be the common case.
+      result_id = target_id;
     } else {
       // Anything else: splice it into the IR, replacing `target_id`. This
       // includes empty blocks, which `Add` handles.
@@ -88,6 +92,7 @@ class PendingBlock {
 
     // Prepare to stash more pending instructions.
     insts_.clear();
+    return result_id;
   }
 
  private:

+ 147 - 147
toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon

@@ -74,154 +74,154 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
 // CHECK:STDOUT:     import_ir_inst43: {ir_id: ir4, inst_id: inst145}
 // CHECK:STDOUT:     import_ir_inst44: {ir_id: ir4, inst_id: inst146}
 // CHECK:STDOUT:     import_ir_inst45: {ir_id: ir4, inst_id: inst151}
-// CHECK:STDOUT:     import_ir_inst46: {ir_id: ir4, inst_id: inst171}
-// CHECK:STDOUT:     import_ir_inst47: {ir_id: ir4, inst_id: inst169}
-// CHECK:STDOUT:     import_ir_inst48: {ir_id: ir4, inst_id: inst167}
-// CHECK:STDOUT:     import_ir_inst49: {ir_id: ir4, inst_id: inst168}
-// CHECK:STDOUT:     import_ir_inst50: {ir_id: ir4, inst_id: inst195}
-// CHECK:STDOUT:     import_ir_inst51: {ir_id: ir4, inst_id: inst193}
-// CHECK:STDOUT:     import_ir_inst52: {ir_id: ir4, inst_id: inst191}
-// CHECK:STDOUT:     import_ir_inst53: {ir_id: ir4, inst_id: inst192}
-// CHECK:STDOUT:     import_ir_inst54: {ir_id: ir4, inst_id: inst219}
-// CHECK:STDOUT:     import_ir_inst55: {ir_id: ir4, inst_id: inst217}
-// CHECK:STDOUT:     import_ir_inst56: {ir_id: ir4, inst_id: inst215}
-// CHECK:STDOUT:     import_ir_inst57: {ir_id: ir4, inst_id: inst216}
-// CHECK:STDOUT:     import_ir_inst58: {ir_id: ir4, inst_id: inst243}
-// CHECK:STDOUT:     import_ir_inst59: {ir_id: ir4, inst_id: inst241}
-// CHECK:STDOUT:     import_ir_inst60: {ir_id: ir4, inst_id: inst239}
-// CHECK:STDOUT:     import_ir_inst61: {ir_id: ir4, inst_id: inst240}
-// CHECK:STDOUT:     import_ir_inst62: {ir_id: ir4, inst_id: inst272}
-// CHECK:STDOUT:     import_ir_inst63: {ir_id: ir4, inst_id: inst270}
-// CHECK:STDOUT:     import_ir_inst64: {ir_id: ir4, inst_id: inst264}
-// CHECK:STDOUT:     import_ir_inst65: {ir_id: ir4, inst_id: inst261}
-// CHECK:STDOUT:     import_ir_inst66: {ir_id: ir4, inst_id: inst266}
-// CHECK:STDOUT:     import_ir_inst67: {ir_id: ir4, inst_id: inst269}
-// CHECK:STDOUT:     import_ir_inst68: {ir_id: ir4, inst_id: inst289}
-// CHECK:STDOUT:     import_ir_inst69: {ir_id: ir4, inst_id: inst271}
-// CHECK:STDOUT:     import_ir_inst70: {ir_id: ir4, inst_id: inst263}
-// CHECK:STDOUT:     import_ir_inst71: {ir_id: ir4, inst_id: inst268}
-// CHECK:STDOUT:     import_ir_inst72: {ir_id: ir4, inst_id: inst274}
-// CHECK:STDOUT:     import_ir_inst73: {ir_id: ir4, inst_id: inst289}
-// CHECK:STDOUT:     import_ir_inst74: {ir_id: ir4, inst_id: inst284}
-// CHECK:STDOUT:     import_ir_inst75: {ir_id: ir4, inst_id: inst285}
-// CHECK:STDOUT:     import_ir_inst76: {ir_id: ir4, inst_id: inst280}
-// CHECK:STDOUT:     import_ir_inst77: {ir_id: ir4, inst_id: inst282}
-// CHECK:STDOUT:     import_ir_inst78: {ir_id: ir4, inst_id: inst261}
-// CHECK:STDOUT:     import_ir_inst79: {ir_id: ir4, inst_id: inst292}
-// CHECK:STDOUT:     import_ir_inst80: {ir_id: ir4, inst_id: inst293}
-// CHECK:STDOUT:     import_ir_inst81: {ir_id: ir4, inst_id: inst296}
-// CHECK:STDOUT:     import_ir_inst82: {ir_id: ir4, inst_id: inst276}
-// CHECK:STDOUT:     import_ir_inst83: {ir_id: ir4, inst_id: inst277}
-// CHECK:STDOUT:     import_ir_inst84: {ir_id: ir4, inst_id: inst281}
-// CHECK:STDOUT:     import_ir_inst85: {ir_id: ir4, inst_id: inst302}
-// CHECK:STDOUT:     import_ir_inst86: {ir_id: ir4, inst_id: inst300}
+// CHECK:STDOUT:     import_ir_inst46: {ir_id: ir4, inst_id: inst172}
+// CHECK:STDOUT:     import_ir_inst47: {ir_id: ir4, inst_id: inst170}
+// CHECK:STDOUT:     import_ir_inst48: {ir_id: ir4, inst_id: inst168}
+// CHECK:STDOUT:     import_ir_inst49: {ir_id: ir4, inst_id: inst169}
+// CHECK:STDOUT:     import_ir_inst50: {ir_id: ir4, inst_id: inst196}
+// CHECK:STDOUT:     import_ir_inst51: {ir_id: ir4, inst_id: inst194}
+// CHECK:STDOUT:     import_ir_inst52: {ir_id: ir4, inst_id: inst192}
+// CHECK:STDOUT:     import_ir_inst53: {ir_id: ir4, inst_id: inst193}
+// CHECK:STDOUT:     import_ir_inst54: {ir_id: ir4, inst_id: inst220}
+// CHECK:STDOUT:     import_ir_inst55: {ir_id: ir4, inst_id: inst218}
+// CHECK:STDOUT:     import_ir_inst56: {ir_id: ir4, inst_id: inst216}
+// CHECK:STDOUT:     import_ir_inst57: {ir_id: ir4, inst_id: inst217}
+// CHECK:STDOUT:     import_ir_inst58: {ir_id: ir4, inst_id: inst244}
+// CHECK:STDOUT:     import_ir_inst59: {ir_id: ir4, inst_id: inst242}
+// CHECK:STDOUT:     import_ir_inst60: {ir_id: ir4, inst_id: inst240}
+// CHECK:STDOUT:     import_ir_inst61: {ir_id: ir4, inst_id: inst241}
+// CHECK:STDOUT:     import_ir_inst62: {ir_id: ir4, inst_id: inst273}
+// CHECK:STDOUT:     import_ir_inst63: {ir_id: ir4, inst_id: inst271}
+// CHECK:STDOUT:     import_ir_inst64: {ir_id: ir4, inst_id: inst265}
+// CHECK:STDOUT:     import_ir_inst65: {ir_id: ir4, inst_id: inst262}
+// CHECK:STDOUT:     import_ir_inst66: {ir_id: ir4, inst_id: inst267}
+// CHECK:STDOUT:     import_ir_inst67: {ir_id: ir4, inst_id: inst270}
+// CHECK:STDOUT:     import_ir_inst68: {ir_id: ir4, inst_id: inst290}
+// CHECK:STDOUT:     import_ir_inst69: {ir_id: ir4, inst_id: inst272}
+// CHECK:STDOUT:     import_ir_inst70: {ir_id: ir4, inst_id: inst264}
+// CHECK:STDOUT:     import_ir_inst71: {ir_id: ir4, inst_id: inst269}
+// CHECK:STDOUT:     import_ir_inst72: {ir_id: ir4, inst_id: inst275}
+// CHECK:STDOUT:     import_ir_inst73: {ir_id: ir4, inst_id: inst290}
+// CHECK:STDOUT:     import_ir_inst74: {ir_id: ir4, inst_id: inst285}
+// CHECK:STDOUT:     import_ir_inst75: {ir_id: ir4, inst_id: inst286}
+// CHECK:STDOUT:     import_ir_inst76: {ir_id: ir4, inst_id: inst281}
+// CHECK:STDOUT:     import_ir_inst77: {ir_id: ir4, inst_id: inst283}
+// CHECK:STDOUT:     import_ir_inst78: {ir_id: ir4, inst_id: inst262}
+// CHECK:STDOUT:     import_ir_inst79: {ir_id: ir4, inst_id: inst293}
+// CHECK:STDOUT:     import_ir_inst80: {ir_id: ir4, inst_id: inst294}
+// CHECK:STDOUT:     import_ir_inst81: {ir_id: ir4, inst_id: inst297}
+// CHECK:STDOUT:     import_ir_inst82: {ir_id: ir4, inst_id: inst277}
+// CHECK:STDOUT:     import_ir_inst83: {ir_id: ir4, inst_id: inst278}
+// CHECK:STDOUT:     import_ir_inst84: {ir_id: ir4, inst_id: inst282}
+// CHECK:STDOUT:     import_ir_inst85: {ir_id: ir4, inst_id: inst303}
+// CHECK:STDOUT:     import_ir_inst86: {ir_id: ir4, inst_id: inst301}
 // CHECK:STDOUT:     import_ir_inst87: {ir_id: ir4, inst_id: inst(TypeType)}
-// CHECK:STDOUT:     import_ir_inst88: {ir_id: ir4, inst_id: inst299}
-// CHECK:STDOUT:     import_ir_inst89: {ir_id: ir4, inst_id: inst323}
-// CHECK:STDOUT:     import_ir_inst90: {ir_id: ir4, inst_id: inst321}
-// CHECK:STDOUT:     import_ir_inst91: {ir_id: ir4, inst_id: inst319}
-// CHECK:STDOUT:     import_ir_inst92: {ir_id: ir4, inst_id: inst320}
-// CHECK:STDOUT:     import_ir_inst93: {ir_id: ir4, inst_id: inst371}
-// CHECK:STDOUT:     import_ir_inst94: {ir_id: ir4, inst_id: inst369}
-// CHECK:STDOUT:     import_ir_inst95: {ir_id: ir4, inst_id: inst350}
-// CHECK:STDOUT:     import_ir_inst96: {ir_id: ir4, inst_id: inst344}
-// CHECK:STDOUT:     import_ir_inst97: {ir_id: ir4, inst_id: inst342}
-// CHECK:STDOUT:     import_ir_inst98: {ir_id: ir4, inst_id: inst347}
-// CHECK:STDOUT:     import_ir_inst99: {ir_id: ir4, inst_id: inst364}
-// CHECK:STDOUT:     import_ir_inst100: {ir_id: ir4, inst_id: inst366}
-// CHECK:STDOUT:     import_ir_inst101: {ir_id: ir4, inst_id: inst393}
-// CHECK:STDOUT:     import_ir_inst102: {ir_id: ir4, inst_id: inst370}
-// CHECK:STDOUT:     import_ir_inst103: {ir_id: ir4, inst_id: inst343}
-// CHECK:STDOUT:     import_ir_inst104: {ir_id: ir4, inst_id: inst349}
-// CHECK:STDOUT:     import_ir_inst105: {ir_id: ir4, inst_id: inst357}
-// CHECK:STDOUT:     import_ir_inst106: {ir_id: ir4, inst_id: inst361}
-// CHECK:STDOUT:     import_ir_inst107: {ir_id: ir4, inst_id: inst365}
-// CHECK:STDOUT:     import_ir_inst108: {ir_id: ir4, inst_id: inst373}
-// CHECK:STDOUT:     import_ir_inst109: {ir_id: ir4, inst_id: inst393}
-// CHECK:STDOUT:     import_ir_inst110: {ir_id: ir4, inst_id: inst388}
-// CHECK:STDOUT:     import_ir_inst111: {ir_id: ir4, inst_id: inst389}
-// CHECK:STDOUT:     import_ir_inst112: {ir_id: ir4, inst_id: inst384}
-// CHECK:STDOUT:     import_ir_inst113: {ir_id: ir4, inst_id: inst386}
-// CHECK:STDOUT:     import_ir_inst114: {ir_id: ir4, inst_id: inst342}
-// CHECK:STDOUT:     import_ir_inst115: {ir_id: ir4, inst_id: inst347}
-// CHECK:STDOUT:     import_ir_inst116: {ir_id: ir4, inst_id: inst396}
-// CHECK:STDOUT:     import_ir_inst117: {ir_id: ir4, inst_id: inst397}
-// CHECK:STDOUT:     import_ir_inst118: {ir_id: ir4, inst_id: inst377}
-// CHECK:STDOUT:     import_ir_inst119: {ir_id: ir4, inst_id: inst378}
-// CHECK:STDOUT:     import_ir_inst120: {ir_id: ir4, inst_id: inst379}
-// CHECK:STDOUT:     import_ir_inst121: {ir_id: ir4, inst_id: inst380}
-// CHECK:STDOUT:     import_ir_inst122: {ir_id: ir4, inst_id: inst381}
-// CHECK:STDOUT:     import_ir_inst123: {ir_id: ir4, inst_id: inst385}
-// CHECK:STDOUT:     import_ir_inst124: {ir_id: ir4, inst_id: inst402}
-// CHECK:STDOUT:     import_ir_inst125: {ir_id: ir4, inst_id: inst410}
-// CHECK:STDOUT:     import_ir_inst126: {ir_id: ir4, inst_id: inst416}
-// CHECK:STDOUT:     import_ir_inst127: {ir_id: ir4, inst_id: inst418}
-// CHECK:STDOUT:     import_ir_inst128: {ir_id: ir4, inst_id: inst419}
-// CHECK:STDOUT:     import_ir_inst129: {ir_id: ir4, inst_id: inst420}
-// CHECK:STDOUT:     import_ir_inst130: {ir_id: ir4, inst_id: inst423}
-// CHECK:STDOUT:     import_ir_inst131: {ir_id: ir4, inst_id: inst434}
-// CHECK:STDOUT:     import_ir_inst132: {ir_id: ir4, inst_id: inst441}
-// CHECK:STDOUT:     import_ir_inst133: {ir_id: ir4, inst_id: inst446}
-// CHECK:STDOUT:     import_ir_inst134: {ir_id: ir4, inst_id: inst447}
-// CHECK:STDOUT:     import_ir_inst135: {ir_id: ir4, inst_id: inst448}
-// CHECK:STDOUT:     import_ir_inst136: {ir_id: ir4, inst_id: inst453}
-// CHECK:STDOUT:     import_ir_inst137: {ir_id: ir4, inst_id: inst509}
-// CHECK:STDOUT:     import_ir_inst138: {ir_id: ir4, inst_id: inst507}
-// CHECK:STDOUT:     import_ir_inst139: {ir_id: ir4, inst_id: inst483}
-// CHECK:STDOUT:     import_ir_inst140: {ir_id: ir4, inst_id: inst477}
-// CHECK:STDOUT:     import_ir_inst141: {ir_id: ir4, inst_id: inst472}
-// CHECK:STDOUT:     import_ir_inst142: {ir_id: ir4, inst_id: inst470}
-// CHECK:STDOUT:     import_ir_inst143: {ir_id: ir4, inst_id: inst475}
-// CHECK:STDOUT:     import_ir_inst144: {ir_id: ir4, inst_id: inst480}
-// CHECK:STDOUT:     import_ir_inst145: {ir_id: ir4, inst_id: inst501}
-// CHECK:STDOUT:     import_ir_inst146: {ir_id: ir4, inst_id: inst503}
-// CHECK:STDOUT:     import_ir_inst147: {ir_id: ir4, inst_id: inst534}
-// CHECK:STDOUT:     import_ir_inst148: {ir_id: ir4, inst_id: inst508}
-// CHECK:STDOUT:     import_ir_inst149: {ir_id: ir4, inst_id: inst471}
-// CHECK:STDOUT:     import_ir_inst150: {ir_id: ir4, inst_id: inst476}
-// CHECK:STDOUT:     import_ir_inst151: {ir_id: ir4, inst_id: inst482}
-// CHECK:STDOUT:     import_ir_inst152: {ir_id: ir4, inst_id: inst491}
-// CHECK:STDOUT:     import_ir_inst153: {ir_id: ir4, inst_id: inst494}
-// CHECK:STDOUT:     import_ir_inst154: {ir_id: ir4, inst_id: inst498}
-// CHECK:STDOUT:     import_ir_inst155: {ir_id: ir4, inst_id: inst502}
-// CHECK:STDOUT:     import_ir_inst156: {ir_id: ir4, inst_id: inst511}
-// CHECK:STDOUT:     import_ir_inst157: {ir_id: ir4, inst_id: inst534}
-// CHECK:STDOUT:     import_ir_inst158: {ir_id: ir4, inst_id: inst529}
-// CHECK:STDOUT:     import_ir_inst159: {ir_id: ir4, inst_id: inst530}
-// CHECK:STDOUT:     import_ir_inst160: {ir_id: ir4, inst_id: inst525}
-// CHECK:STDOUT:     import_ir_inst161: {ir_id: ir4, inst_id: inst527}
-// CHECK:STDOUT:     import_ir_inst162: {ir_id: ir4, inst_id: inst470}
-// CHECK:STDOUT:     import_ir_inst163: {ir_id: ir4, inst_id: inst475}
-// CHECK:STDOUT:     import_ir_inst164: {ir_id: ir4, inst_id: inst480}
-// CHECK:STDOUT:     import_ir_inst165: {ir_id: ir4, inst_id: inst537}
-// CHECK:STDOUT:     import_ir_inst166: {ir_id: ir4, inst_id: inst538}
-// CHECK:STDOUT:     import_ir_inst167: {ir_id: ir4, inst_id: inst516}
-// CHECK:STDOUT:     import_ir_inst168: {ir_id: ir4, inst_id: inst517}
-// CHECK:STDOUT:     import_ir_inst169: {ir_id: ir4, inst_id: inst518}
-// CHECK:STDOUT:     import_ir_inst170: {ir_id: ir4, inst_id: inst519}
-// CHECK:STDOUT:     import_ir_inst171: {ir_id: ir4, inst_id: inst520}
-// CHECK:STDOUT:     import_ir_inst172: {ir_id: ir4, inst_id: inst521}
-// CHECK:STDOUT:     import_ir_inst173: {ir_id: ir4, inst_id: inst522}
-// CHECK:STDOUT:     import_ir_inst174: {ir_id: ir4, inst_id: inst526}
-// CHECK:STDOUT:     import_ir_inst175: {ir_id: ir4, inst_id: inst543}
-// CHECK:STDOUT:     import_ir_inst176: {ir_id: ir4, inst_id: inst550}
-// CHECK:STDOUT:     import_ir_inst177: {ir_id: ir4, inst_id: inst556}
-// CHECK:STDOUT:     import_ir_inst178: {ir_id: ir4, inst_id: inst558}
-// CHECK:STDOUT:     import_ir_inst179: {ir_id: ir4, inst_id: inst559}
-// CHECK:STDOUT:     import_ir_inst180: {ir_id: ir4, inst_id: inst560}
-// CHECK:STDOUT:     import_ir_inst181: {ir_id: ir4, inst_id: inst563}
-// CHECK:STDOUT:     import_ir_inst182: {ir_id: ir4, inst_id: inst572}
-// CHECK:STDOUT:     import_ir_inst183: {ir_id: ir4, inst_id: inst578}
-// CHECK:STDOUT:     import_ir_inst184: {ir_id: ir4, inst_id: inst580}
-// CHECK:STDOUT:     import_ir_inst185: {ir_id: ir4, inst_id: inst581}
-// CHECK:STDOUT:     import_ir_inst186: {ir_id: ir4, inst_id: inst582}
-// CHECK:STDOUT:     import_ir_inst187: {ir_id: ir4, inst_id: inst585}
-// CHECK:STDOUT:     import_ir_inst188: {ir_id: ir4, inst_id: inst596}
-// CHECK:STDOUT:     import_ir_inst189: {ir_id: ir4, inst_id: inst603}
-// CHECK:STDOUT:     import_ir_inst190: {ir_id: ir4, inst_id: inst608}
-// CHECK:STDOUT:     import_ir_inst191: {ir_id: ir4, inst_id: inst609}
-// CHECK:STDOUT:     import_ir_inst192: {ir_id: ir4, inst_id: inst610}
-// CHECK:STDOUT:     import_ir_inst193: {ir_id: ir4, inst_id: inst615}
+// CHECK:STDOUT:     import_ir_inst88: {ir_id: ir4, inst_id: inst300}
+// CHECK:STDOUT:     import_ir_inst89: {ir_id: ir4, inst_id: inst324}
+// CHECK:STDOUT:     import_ir_inst90: {ir_id: ir4, inst_id: inst322}
+// CHECK:STDOUT:     import_ir_inst91: {ir_id: ir4, inst_id: inst320}
+// CHECK:STDOUT:     import_ir_inst92: {ir_id: ir4, inst_id: inst321}
+// CHECK:STDOUT:     import_ir_inst93: {ir_id: ir4, inst_id: inst372}
+// CHECK:STDOUT:     import_ir_inst94: {ir_id: ir4, inst_id: inst370}
+// CHECK:STDOUT:     import_ir_inst95: {ir_id: ir4, inst_id: inst351}
+// CHECK:STDOUT:     import_ir_inst96: {ir_id: ir4, inst_id: inst345}
+// CHECK:STDOUT:     import_ir_inst97: {ir_id: ir4, inst_id: inst343}
+// CHECK:STDOUT:     import_ir_inst98: {ir_id: ir4, inst_id: inst348}
+// CHECK:STDOUT:     import_ir_inst99: {ir_id: ir4, inst_id: inst365}
+// CHECK:STDOUT:     import_ir_inst100: {ir_id: ir4, inst_id: inst367}
+// CHECK:STDOUT:     import_ir_inst101: {ir_id: ir4, inst_id: inst394}
+// CHECK:STDOUT:     import_ir_inst102: {ir_id: ir4, inst_id: inst371}
+// CHECK:STDOUT:     import_ir_inst103: {ir_id: ir4, inst_id: inst344}
+// CHECK:STDOUT:     import_ir_inst104: {ir_id: ir4, inst_id: inst350}
+// CHECK:STDOUT:     import_ir_inst105: {ir_id: ir4, inst_id: inst358}
+// CHECK:STDOUT:     import_ir_inst106: {ir_id: ir4, inst_id: inst362}
+// CHECK:STDOUT:     import_ir_inst107: {ir_id: ir4, inst_id: inst366}
+// CHECK:STDOUT:     import_ir_inst108: {ir_id: ir4, inst_id: inst374}
+// CHECK:STDOUT:     import_ir_inst109: {ir_id: ir4, inst_id: inst394}
+// CHECK:STDOUT:     import_ir_inst110: {ir_id: ir4, inst_id: inst389}
+// CHECK:STDOUT:     import_ir_inst111: {ir_id: ir4, inst_id: inst390}
+// CHECK:STDOUT:     import_ir_inst112: {ir_id: ir4, inst_id: inst385}
+// CHECK:STDOUT:     import_ir_inst113: {ir_id: ir4, inst_id: inst387}
+// CHECK:STDOUT:     import_ir_inst114: {ir_id: ir4, inst_id: inst343}
+// CHECK:STDOUT:     import_ir_inst115: {ir_id: ir4, inst_id: inst348}
+// CHECK:STDOUT:     import_ir_inst116: {ir_id: ir4, inst_id: inst397}
+// CHECK:STDOUT:     import_ir_inst117: {ir_id: ir4, inst_id: inst398}
+// CHECK:STDOUT:     import_ir_inst118: {ir_id: ir4, inst_id: inst378}
+// CHECK:STDOUT:     import_ir_inst119: {ir_id: ir4, inst_id: inst379}
+// CHECK:STDOUT:     import_ir_inst120: {ir_id: ir4, inst_id: inst380}
+// CHECK:STDOUT:     import_ir_inst121: {ir_id: ir4, inst_id: inst381}
+// CHECK:STDOUT:     import_ir_inst122: {ir_id: ir4, inst_id: inst382}
+// CHECK:STDOUT:     import_ir_inst123: {ir_id: ir4, inst_id: inst386}
+// CHECK:STDOUT:     import_ir_inst124: {ir_id: ir4, inst_id: inst403}
+// CHECK:STDOUT:     import_ir_inst125: {ir_id: ir4, inst_id: inst411}
+// CHECK:STDOUT:     import_ir_inst126: {ir_id: ir4, inst_id: inst417}
+// CHECK:STDOUT:     import_ir_inst127: {ir_id: ir4, inst_id: inst419}
+// CHECK:STDOUT:     import_ir_inst128: {ir_id: ir4, inst_id: inst420}
+// CHECK:STDOUT:     import_ir_inst129: {ir_id: ir4, inst_id: inst421}
+// CHECK:STDOUT:     import_ir_inst130: {ir_id: ir4, inst_id: inst424}
+// CHECK:STDOUT:     import_ir_inst131: {ir_id: ir4, inst_id: inst436}
+// CHECK:STDOUT:     import_ir_inst132: {ir_id: ir4, inst_id: inst443}
+// CHECK:STDOUT:     import_ir_inst133: {ir_id: ir4, inst_id: inst448}
+// CHECK:STDOUT:     import_ir_inst134: {ir_id: ir4, inst_id: inst449}
+// CHECK:STDOUT:     import_ir_inst135: {ir_id: ir4, inst_id: inst450}
+// CHECK:STDOUT:     import_ir_inst136: {ir_id: ir4, inst_id: inst455}
+// CHECK:STDOUT:     import_ir_inst137: {ir_id: ir4, inst_id: inst512}
+// CHECK:STDOUT:     import_ir_inst138: {ir_id: ir4, inst_id: inst510}
+// CHECK:STDOUT:     import_ir_inst139: {ir_id: ir4, inst_id: inst486}
+// CHECK:STDOUT:     import_ir_inst140: {ir_id: ir4, inst_id: inst480}
+// CHECK:STDOUT:     import_ir_inst141: {ir_id: ir4, inst_id: inst475}
+// CHECK:STDOUT:     import_ir_inst142: {ir_id: ir4, inst_id: inst473}
+// CHECK:STDOUT:     import_ir_inst143: {ir_id: ir4, inst_id: inst478}
+// CHECK:STDOUT:     import_ir_inst144: {ir_id: ir4, inst_id: inst483}
+// CHECK:STDOUT:     import_ir_inst145: {ir_id: ir4, inst_id: inst504}
+// CHECK:STDOUT:     import_ir_inst146: {ir_id: ir4, inst_id: inst506}
+// CHECK:STDOUT:     import_ir_inst147: {ir_id: ir4, inst_id: inst537}
+// CHECK:STDOUT:     import_ir_inst148: {ir_id: ir4, inst_id: inst511}
+// CHECK:STDOUT:     import_ir_inst149: {ir_id: ir4, inst_id: inst474}
+// CHECK:STDOUT:     import_ir_inst150: {ir_id: ir4, inst_id: inst479}
+// CHECK:STDOUT:     import_ir_inst151: {ir_id: ir4, inst_id: inst485}
+// CHECK:STDOUT:     import_ir_inst152: {ir_id: ir4, inst_id: inst494}
+// CHECK:STDOUT:     import_ir_inst153: {ir_id: ir4, inst_id: inst497}
+// CHECK:STDOUT:     import_ir_inst154: {ir_id: ir4, inst_id: inst501}
+// CHECK:STDOUT:     import_ir_inst155: {ir_id: ir4, inst_id: inst505}
+// CHECK:STDOUT:     import_ir_inst156: {ir_id: ir4, inst_id: inst514}
+// CHECK:STDOUT:     import_ir_inst157: {ir_id: ir4, inst_id: inst537}
+// CHECK:STDOUT:     import_ir_inst158: {ir_id: ir4, inst_id: inst532}
+// CHECK:STDOUT:     import_ir_inst159: {ir_id: ir4, inst_id: inst533}
+// CHECK:STDOUT:     import_ir_inst160: {ir_id: ir4, inst_id: inst528}
+// CHECK:STDOUT:     import_ir_inst161: {ir_id: ir4, inst_id: inst530}
+// CHECK:STDOUT:     import_ir_inst162: {ir_id: ir4, inst_id: inst473}
+// CHECK:STDOUT:     import_ir_inst163: {ir_id: ir4, inst_id: inst478}
+// CHECK:STDOUT:     import_ir_inst164: {ir_id: ir4, inst_id: inst483}
+// CHECK:STDOUT:     import_ir_inst165: {ir_id: ir4, inst_id: inst540}
+// CHECK:STDOUT:     import_ir_inst166: {ir_id: ir4, inst_id: inst541}
+// CHECK:STDOUT:     import_ir_inst167: {ir_id: ir4, inst_id: inst519}
+// CHECK:STDOUT:     import_ir_inst168: {ir_id: ir4, inst_id: inst520}
+// CHECK:STDOUT:     import_ir_inst169: {ir_id: ir4, inst_id: inst521}
+// CHECK:STDOUT:     import_ir_inst170: {ir_id: ir4, inst_id: inst522}
+// CHECK:STDOUT:     import_ir_inst171: {ir_id: ir4, inst_id: inst523}
+// CHECK:STDOUT:     import_ir_inst172: {ir_id: ir4, inst_id: inst524}
+// CHECK:STDOUT:     import_ir_inst173: {ir_id: ir4, inst_id: inst525}
+// CHECK:STDOUT:     import_ir_inst174: {ir_id: ir4, inst_id: inst529}
+// CHECK:STDOUT:     import_ir_inst175: {ir_id: ir4, inst_id: inst546}
+// CHECK:STDOUT:     import_ir_inst176: {ir_id: ir4, inst_id: inst553}
+// CHECK:STDOUT:     import_ir_inst177: {ir_id: ir4, inst_id: inst559}
+// CHECK:STDOUT:     import_ir_inst178: {ir_id: ir4, inst_id: inst561}
+// CHECK:STDOUT:     import_ir_inst179: {ir_id: ir4, inst_id: inst562}
+// CHECK:STDOUT:     import_ir_inst180: {ir_id: ir4, inst_id: inst563}
+// CHECK:STDOUT:     import_ir_inst181: {ir_id: ir4, inst_id: inst566}
+// CHECK:STDOUT:     import_ir_inst182: {ir_id: ir4, inst_id: inst576}
+// CHECK:STDOUT:     import_ir_inst183: {ir_id: ir4, inst_id: inst582}
+// CHECK:STDOUT:     import_ir_inst184: {ir_id: ir4, inst_id: inst584}
+// CHECK:STDOUT:     import_ir_inst185: {ir_id: ir4, inst_id: inst585}
+// CHECK:STDOUT:     import_ir_inst186: {ir_id: ir4, inst_id: inst586}
+// CHECK:STDOUT:     import_ir_inst187: {ir_id: ir4, inst_id: inst589}
+// CHECK:STDOUT:     import_ir_inst188: {ir_id: ir4, inst_id: inst601}
+// CHECK:STDOUT:     import_ir_inst189: {ir_id: ir4, inst_id: inst608}
+// CHECK:STDOUT:     import_ir_inst190: {ir_id: ir4, inst_id: inst613}
+// CHECK:STDOUT:     import_ir_inst191: {ir_id: ir4, inst_id: inst614}
+// CHECK:STDOUT:     import_ir_inst192: {ir_id: ir4, inst_id: inst615}
+// CHECK:STDOUT:     import_ir_inst193: {ir_id: ir4, inst_id: inst620}
 // CHECK:STDOUT:   name_scopes:
 // CHECK:STDOUT:     name_scope0:     {inst: inst14, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst16, name0: inst53}}
 // CHECK:STDOUT:     name_scope1:     {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst69}}

+ 1 - 1
toolchain/check/testdata/builtins/int/make_type_signed.carbon

@@ -23,7 +23,7 @@ library "[[@TEST_NAME]]";
 
 import library "types";
 
-fn Copy[T:! type](x: T) -> T = "primitive_copy";
+fn Copy[N:! IntLiteral()](x: Int(N)) -> Int(N) = "primitive_copy";
 
 fn F(n: Int(64)) ->
     //@dump-sem-ir-begin

+ 1 - 1
toolchain/check/testdata/builtins/int/make_type_unsigned.carbon

@@ -23,7 +23,7 @@ library "[[@TEST_NAME]]";
 
 import library "types";
 
-fn Copy[T:! type](x: T) -> T = "primitive_copy";
+fn Copy[N:! IntLiteral()](x: UInt(N)) -> UInt(N) = "primitive_copy";
 
 fn F(n: UInt(64)) ->
     //@dump-sem-ir-begin

+ 6 - 5
toolchain/check/testdata/class/generic/base_is_generic.carbon

@@ -974,12 +974,13 @@ fn H() {
 // CHECK:STDOUT:   %X.G: @X.G.%X.G.type (%X.G.type.56f312.1) = struct_value () [symbolic = %X.G (constants.%X.G.b504c4.1)]
 // CHECK:STDOUT:   %X.G.specific_fn.loc5_24.2: <specific function> = specific_function %X.G, @X.G(%U) [symbolic = %X.G.specific_fn.loc5_24.2 (constants.%X.G.specific_fn.169)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @X.G.%U (%U) {
+// CHECK:STDOUT:   fn() -> %return.param: @X.G.%U (%U) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %.loc5: @X.G.%X.G.type (%X.G.type.56f312.1) = specific_constant @X.%X.G.decl, @X(constants.%U) [symbolic = %X.G (constants.%X.G.b504c4.1)]
-// CHECK:STDOUT:     %G.ref: @X.G.%X.G.type (%X.G.type.56f312.1) = name_ref G, %.loc5 [symbolic = %X.G (constants.%X.G.b504c4.1)]
+// CHECK:STDOUT:     %.loc5_24: @X.G.%X.G.type (%X.G.type.56f312.1) = specific_constant @X.%X.G.decl, @X(constants.%U) [symbolic = %X.G (constants.%X.G.b504c4.1)]
+// CHECK:STDOUT:     %G.ref: @X.G.%X.G.type (%X.G.type.56f312.1) = name_ref G, %.loc5_24 [symbolic = %X.G (constants.%X.G.b504c4.1)]
 // CHECK:STDOUT:     %X.G.specific_fn.loc5_24.1: <specific function> = specific_function %G.ref, @X.G(constants.%U) [symbolic = %X.G.specific_fn.loc5_24.2 (constants.%X.G.specific_fn.169)]
-// CHECK:STDOUT:     %X.G.call: init @X.G.%U (%U) = call %X.G.specific_fn.loc5_24.1()
+// CHECK:STDOUT:     %.loc5_10: ref @X.G.%U (%U) = splice_block %return {}
+// CHECK:STDOUT:     %X.G.call: init @X.G.%U (%U) = call %X.G.specific_fn.loc5_24.1() to %.loc5_10
 // CHECK:STDOUT:     return %X.G.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -1174,7 +1175,7 @@ fn H() {
 // CHECK:STDOUT:   %Main.import_ref.b8a: @X.%X.G.type (%X.G.type.56f312.1) = import_ref Main//extend_generic_symbolic_base, loc5_15, loaded [symbolic = @X.%X.G (constants.%X.G.b504c4.1)]
 // CHECK:STDOUT:   %Main.import_ref.5ab3ec.2: type = import_ref Main//extend_generic_symbolic_base, loc8_9, loaded [symbolic = @C.%T (constants.%T)]
 // CHECK:STDOUT:   %Main.import_ref.93f: <witness> = import_ref Main//extend_generic_symbolic_base, loc10_1, loaded [symbolic = @C.%complete_type (constants.%complete_type.768)]
-// CHECK:STDOUT:   %Main.import_ref.4c0 = import_ref Main//extend_generic_symbolic_base, inst117 [no loc], unloaded
+// CHECK:STDOUT:   %Main.import_ref.4c0 = import_ref Main//extend_generic_symbolic_base, inst118 [no loc], unloaded
 // CHECK:STDOUT:   %Main.import_ref.65d = import_ref Main//extend_generic_symbolic_base, loc9_20, unloaded
 // CHECK:STDOUT:   %Main.import_ref.561eb2.2: type = import_ref Main//extend_generic_symbolic_base, loc9_19, loaded [symbolic = @C.%X (constants.%X.75b6d8.2)]
 // CHECK:STDOUT:   %Main.import_ref.5ab3ec.3: type = import_ref Main//extend_generic_symbolic_base, loc4_14, loaded [symbolic = @X.%U (constants.%U)]

+ 3 - 2
toolchain/check/testdata/class/generic/basic.carbon

@@ -272,7 +272,7 @@ class Declaration(T:! type);
 // CHECK:STDOUT:   %impl.elem0.loc11_16.2: @Class.GetValue.%.loc11_16.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc11_16.2: <specific function> = specific_impl_function %impl.elem0.loc11_16.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @Class.GetValue.%Class (%Class)) -> @Class.GetValue.%T.as_type.loc10_32.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%self.param: @Class.GetValue.%Class (%Class)) -> %return.param: @Class.GetValue.%T.as_type.loc10_32.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @Class.GetValue.%Class (%Class) = name_ref self, %self
 // CHECK:STDOUT:     %k.ref: @Class.GetValue.%Class.elem (%Class.elem) = name_ref k, @Class.%.loc14_8 [concrete = @Class.%.loc14_8]
@@ -282,7 +282,8 @@ class Declaration(T:! type);
 // CHECK:STDOUT:     %bound_method.loc11_16.1: <bound method> = bound_method %.loc11_16.2, %impl.elem0.loc11_16.1
 // CHECK:STDOUT:     %specific_impl_fn.loc11_16.1: <specific function> = specific_impl_function %impl.elem0.loc11_16.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc11_16.2: <bound method> = bound_method %.loc11_16.2, %specific_impl_fn.loc11_16.1
-// CHECK:STDOUT:     %.loc11_16.3: init @Class.GetValue.%T.as_type.loc10_32.1 (%T.as_type) = call %bound_method.loc11_16.2(%.loc11_16.2)
+// CHECK:STDOUT:     %.loc10_29: ref @Class.GetValue.%T.as_type.loc10_32.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc11_16.3: init @Class.GetValue.%T.as_type.loc10_32.1 (%T.as_type) = call %bound_method.loc11_16.2(%.loc11_16.2) to %.loc10_29
 // CHECK:STDOUT:     return %.loc11_16.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 6 - 4
toolchain/check/testdata/class/generic/field.carbon

@@ -310,7 +310,7 @@ fn H(U:! Core.Copy, c: Class(U)) -> U {
 // CHECK:STDOUT:   %impl.elem0.loc14_11.2: @G.%.loc14_11.4 (%.c500ab.1) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_11.2 (constants.%impl.elem0.792e99.1)]
 // CHECK:STDOUT:   %specific_impl_fn.loc14_11.2: <specific function> = specific_impl_function %impl.elem0.loc14_11.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc14_11.2 (constants.%specific_impl_fn.547931.1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%c.param: @G.%Class.loc13_31.1 (%Class.a5ccb5.1)) -> @G.%T.as_type.loc13_31.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%c.param: @G.%Class.loc13_31.1 (%Class.a5ccb5.1)) -> %return.param: @G.%T.as_type.loc13_31.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %c.ref: @G.%Class.loc13_31.1 (%Class.a5ccb5.1) = name_ref c, %c
 // CHECK:STDOUT:     %x.ref: @G.%Class.elem (%Class.elem.14abad.1) = name_ref x, @Class.%.loc6 [concrete = @Class.%.loc6]
@@ -320,7 +320,8 @@ fn H(U:! Core.Copy, c: Class(U)) -> U {
 // CHECK:STDOUT:     %bound_method.loc14_11.1: <bound method> = bound_method %.loc14_11.2, %impl.elem0.loc14_11.1
 // CHECK:STDOUT:     %specific_impl_fn.loc14_11.1: <specific function> = specific_impl_function %impl.elem0.loc14_11.1, @Copy.Op(constants.%Copy.facet.021101.1) [symbolic = %specific_impl_fn.loc14_11.2 (constants.%specific_impl_fn.547931.1)]
 // CHECK:STDOUT:     %bound_method.loc14_11.2: <bound method> = bound_method %.loc14_11.2, %specific_impl_fn.loc14_11.1
-// CHECK:STDOUT:     %.loc14_11.3: init @G.%T.as_type.loc13_31.1 (%T.as_type) = call %bound_method.loc14_11.2(%.loc14_11.2)
+// CHECK:STDOUT:     %.loc13_34: ref @G.%T.as_type.loc13_31.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc14_11.3: init @G.%T.as_type.loc13_31.1 (%T.as_type) = call %bound_method.loc14_11.2(%.loc14_11.2) to %.loc13_34
 // CHECK:STDOUT:     return %.loc14_11.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -342,7 +343,7 @@ fn H(U:! Core.Copy, c: Class(U)) -> U {
 // CHECK:STDOUT:   %impl.elem0.loc18_11.2: @H.%.loc18_11.4 (%.c500ab.2) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc18_11.2 (constants.%impl.elem0.792e99.2)]
 // CHECK:STDOUT:   %specific_impl_fn.loc18_11.2: <specific function> = specific_impl_function %impl.elem0.loc18_11.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc18_11.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%c.param: @H.%Class.loc17_31.1 (%Class.a5ccb5.2)) -> @H.%U.as_type.loc17_31.1 (%U.as_type.870) {
+// CHECK:STDOUT:   fn(%c.param: @H.%Class.loc17_31.1 (%Class.a5ccb5.2)) -> %return.param: @H.%U.as_type.loc17_31.1 (%U.as_type.870) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %c.ref: @H.%Class.loc17_31.1 (%Class.a5ccb5.2) = name_ref c, %c
 // CHECK:STDOUT:     %x.ref: @H.%Class.elem (%Class.elem.14abad.2) = name_ref x, @Class.%.loc6 [concrete = @Class.%.loc6]
@@ -352,7 +353,8 @@ fn H(U:! Core.Copy, c: Class(U)) -> U {
 // CHECK:STDOUT:     %bound_method.loc18_11.1: <bound method> = bound_method %.loc18_11.2, %impl.elem0.loc18_11.1
 // CHECK:STDOUT:     %specific_impl_fn.loc18_11.1: <specific function> = specific_impl_function %impl.elem0.loc18_11.1, @Copy.Op(constants.%Copy.facet.021101.2) [symbolic = %specific_impl_fn.loc18_11.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:     %bound_method.loc18_11.2: <bound method> = bound_method %.loc18_11.2, %specific_impl_fn.loc18_11.1
-// CHECK:STDOUT:     %.loc18_11.3: init @H.%U.as_type.loc17_31.1 (%U.as_type.870) = call %bound_method.loc18_11.2(%.loc18_11.2)
+// CHECK:STDOUT:     %.loc17_34: ref @H.%U.as_type.loc17_31.1 (%U.as_type.870) = splice_block %return {}
+// CHECK:STDOUT:     %.loc18_11.3: init @H.%U.as_type.loc17_31.1 (%U.as_type.870) = call %bound_method.loc18_11.2(%.loc18_11.2) to %.loc17_34
 // CHECK:STDOUT:     return %.loc18_11.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 7 - 5
toolchain/check/testdata/class/generic/init.carbon

@@ -195,7 +195,7 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   %ptr: type = ptr_type %Class.loc10_17.2 [symbolic = %ptr (constants.%ptr.e19)]
 // CHECK:STDOUT:   %require_complete.loc10_3: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc10_3 (constants.%require_complete.3cb)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type)) -> @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type)) -> %return.param: @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     name_binding_decl {
 // CHECK:STDOUT:       %v.patt: @InitFromStructGeneric.%pattern_type.loc10 (%pattern_type.0a3) = binding_pattern v [concrete]
@@ -208,8 +208,8 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:     %bound_method.loc10_27.1: <bound method> = bound_method %x.ref, %impl.elem0.loc10_27.1
 // CHECK:STDOUT:     %specific_impl_fn.loc10_27.1: <specific function> = specific_impl_function %impl.elem0.loc10_27.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc10_27.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc10_27.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_27.1
-// CHECK:STDOUT:     %.loc10_27.1: init @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = call %bound_method.loc10_27.2(%x.ref)
 // CHECK:STDOUT:     %.loc10_28.2: ref @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = class_element_access %v.var, element0
+// CHECK:STDOUT:     %.loc10_27.1: init @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = call %bound_method.loc10_27.2(%x.ref) to %.loc10_28.2
 // CHECK:STDOUT:     %.loc10_28.3: init @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = initialize_from %.loc10_27.1 to %.loc10_28.2
 // CHECK:STDOUT:     %.loc10_28.4: init @InitFromStructGeneric.%Class.loc10_17.2 (%Class.a5c) = class_init (%.loc10_28.3), %v.var
 // CHECK:STDOUT:     %.loc10_3.1: init @InitFromStructGeneric.%Class.loc10_17.2 (%Class.a5c) = converted %.loc10_28.1, %.loc10_28.4
@@ -230,7 +230,8 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:     %bound_method.loc11_11.1: <bound method> = bound_method %.loc11_11.2, %impl.elem0.loc11
 // CHECK:STDOUT:     %specific_impl_fn.loc11: <specific function> = specific_impl_function %impl.elem0.loc11, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc10_27.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc11_11.2: <bound method> = bound_method %.loc11_11.2, %specific_impl_fn.loc11
-// CHECK:STDOUT:     %.loc11_11.3: init @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = call %bound_method.loc11_11.2(%.loc11_11.2)
+// CHECK:STDOUT:     %.loc9_47: ref @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc11_11.3: init @InitFromStructGeneric.%T.as_type.loc9_44.1 (%T.as_type) = call %bound_method.loc11_11.2(%.loc11_11.2) to %.loc9_47
 // CHECK:STDOUT:     %impl.elem0.loc10_3: @InitFromStructGeneric.%.loc10_3.2 (%.4f0) = impl_witness_access constants.%Destroy.impl_witness.a5d, element0 [symbolic = %Class.as.Destroy.impl.Op (constants.%Class.as.Destroy.impl.Op.d2f)]
 // CHECK:STDOUT:     %bound_method.loc10_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc10_3
 // CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0.loc10_3, @Class.as.Destroy.impl.Op(constants.%T.as_type) [symbolic = %Class.as.Destroy.impl.Op.specific_fn (constants.%Class.as.Destroy.impl.Op.specific_fn.8ad)]
@@ -407,7 +408,7 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   %impl.elem0.loc10_26.2: @InitFromAdaptedGeneric.%.loc10_26.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_26.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc10_26.2: <specific function> = specific_impl_function %impl.elem0.loc10_26.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc10_26.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type)) -> @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type)) -> %return.param: @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %Adapt.ref: %Adapt.type = name_ref Adapt, file.%Adapt.decl [concrete = constants.%Adapt.generic]
@@ -426,7 +427,8 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:     %bound_method.loc10_26.1: <bound method> = bound_method %.loc10_26.2, %impl.elem0.loc10_26.1
 // CHECK:STDOUT:     %specific_impl_fn.loc10_26.1: <specific function> = specific_impl_function %impl.elem0.loc10_26.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc10_26.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc10_26.2: <bound method> = bound_method %.loc10_26.2, %specific_impl_fn.loc10_26.1
-// CHECK:STDOUT:     %.loc10_26.3: init @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) = call %bound_method.loc10_26.2(%.loc10_26.2)
+// CHECK:STDOUT:     %.loc9_48: ref @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc10_26.3: init @InitFromAdaptedGeneric.%T.as_type.loc9_45.1 (%T.as_type) = call %bound_method.loc10_26.2(%.loc10_26.2) to %.loc9_48
 // CHECK:STDOUT:     return %.loc10_26.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 3 - 2
toolchain/check/testdata/class/generic/member_access.carbon

@@ -193,7 +193,7 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %impl.elem0.loc9_16.2: @Class.Get.%.loc9_16.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_16.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc9_16.2: <specific function> = specific_impl_function %impl.elem0.loc9_16.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc9_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @Class.Get.%Class (%Class.2c5)) -> @Class.Get.%T.as_type.loc7_27.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%self.param: @Class.Get.%Class (%Class.2c5)) -> %return.param: @Class.Get.%T.as_type.loc7_27.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @Class.Get.%Class (%Class.2c5) = name_ref self, %self
 // CHECK:STDOUT:     %x.ref: @Class.Get.%Class.elem (%Class.elem.3a8) = name_ref x, @Class.%.loc5_8 [concrete = @Class.%.loc5_8]
@@ -203,7 +203,8 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:     %bound_method.loc9_16.1: <bound method> = bound_method %.loc9_16.2, %impl.elem0.loc9_16.1
 // CHECK:STDOUT:     %specific_impl_fn.loc9_16.1: <specific function> = specific_impl_function %impl.elem0.loc9_16.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc9_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc9_16.2: <bound method> = bound_method %.loc9_16.2, %specific_impl_fn.loc9_16.1
-// CHECK:STDOUT:     %.loc9_16.3: init @Class.Get.%T.as_type.loc7_27.1 (%T.as_type) = call %bound_method.loc9_16.2(%.loc9_16.2)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %.loc9_16.3: init @Class.Get.%T.as_type.loc7_27.1 (%T.as_type) = call %bound_method.loc9_16.2(%.loc9_16.2) to %.loc7_24
 // CHECK:STDOUT:     return %.loc9_16.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 6 - 4
toolchain/check/testdata/class/generic/member_inline.carbon

@@ -220,14 +220,15 @@ class C(T:! Core.Copy) {
 // CHECK:STDOUT:   %impl.elem0.loc7_12.2: @Class.F.%.loc7_12.2 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc7_12.2: <specific function> = specific_impl_function %impl.elem0.loc7_12.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%n.param: @Class.F.%T.as_type.loc6_11.1 (%T.as_type)) -> @Class.F.%T.as_type.loc6_11.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%n.param: @Class.F.%T.as_type.loc6_11.1 (%T.as_type)) -> %return.param: @Class.F.%T.as_type.loc6_11.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %n.ref: @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = name_ref n, %n
 // CHECK:STDOUT:     %impl.elem0.loc7_12.1: @Class.F.%.loc7_12.2 (%.c50) = impl_witness_access constants.%Copy.lookup_impl_witness.e15, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:     %bound_method.loc7_12.1: <bound method> = bound_method %n.ref, %impl.elem0.loc7_12.1
 // CHECK:STDOUT:     %specific_impl_fn.loc7_12.1: <specific function> = specific_impl_function %impl.elem0.loc7_12.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc7_12.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc7_12.1
-// CHECK:STDOUT:     %.loc7_12.1: init @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = call %bound_method.loc7_12.2(%n.ref)
+// CHECK:STDOUT:     %.loc6_14: ref @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc7_12.1: init @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = call %bound_method.loc7_12.2(%n.ref) to %.loc6_14
 // CHECK:STDOUT:     return %.loc7_12.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -249,7 +250,7 @@ class C(T:! Core.Copy) {
 // CHECK:STDOUT:   %impl.elem0.loc11_16.2: @Class.G.%.loc11_16.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc11_16.2: <specific function> = specific_impl_function %impl.elem0.loc11_16.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @Class.G.%Class (%Class)) -> @Class.G.%T.as_type.loc10_25.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%self.param: @Class.G.%Class (%Class)) -> %return.param: @Class.G.%T.as_type.loc10_25.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @Class.G.%Class (%Class) = name_ref self, %self
 // CHECK:STDOUT:     %n.ref: @Class.G.%Class.elem (%Class.elem) = name_ref n, @Class.%.loc14_8 [concrete = @Class.%.loc14_8]
@@ -259,7 +260,8 @@ class C(T:! Core.Copy) {
 // CHECK:STDOUT:     %bound_method.loc11_16.1: <bound method> = bound_method %.loc11_16.2, %impl.elem0.loc11_16.1
 // CHECK:STDOUT:     %specific_impl_fn.loc11_16.1: <specific function> = specific_impl_function %impl.elem0.loc11_16.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc11_16.2: <bound method> = bound_method %.loc11_16.2, %specific_impl_fn.loc11_16.1
-// CHECK:STDOUT:     %.loc11_16.3: init @Class.G.%T.as_type.loc10_25.1 (%T.as_type) = call %bound_method.loc11_16.2(%.loc11_16.2)
+// CHECK:STDOUT:     %.loc10_22: ref @Class.G.%T.as_type.loc10_25.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc11_16.3: init @Class.G.%T.as_type.loc10_25.1 (%T.as_type) = call %bound_method.loc11_16.2(%.loc11_16.2) to %.loc10_22
 // CHECK:STDOUT:     return %.loc11_16.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 6 - 4
toolchain/check/testdata/class/generic/member_lookup.carbon

@@ -113,7 +113,7 @@ fn AccessMissingConcrete(x: Derived(i32)) -> i32 {
 // CHECK:STDOUT:   %impl.elem0.loc15_11.2: @AccessDerived.%.loc15_11.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc15_11.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc15_11.2: <specific function> = specific_impl_function %impl.elem0.loc15_11.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc15_11.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @AccessDerived.%Derived.loc13_45.1 (%Derived.3ba)) -> @AccessDerived.%T.as_type.loc13_45.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @AccessDerived.%Derived.loc13_45.1 (%Derived.3ba)) -> %return.param: @AccessDerived.%T.as_type.loc13_45.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @AccessDerived.%Derived.loc13_45.1 (%Derived.3ba) = name_ref x, %x
 // CHECK:STDOUT:     %d.ref: @AccessDerived.%Derived.elem (%Derived.elem.1c7) = name_ref d, @Derived.%.loc10 [concrete = @Derived.%.loc10]
@@ -123,7 +123,8 @@ fn AccessMissingConcrete(x: Derived(i32)) -> i32 {
 // CHECK:STDOUT:     %bound_method.loc15_11.1: <bound method> = bound_method %.loc15_11.2, %impl.elem0.loc15_11.1
 // CHECK:STDOUT:     %specific_impl_fn.loc15_11.1: <specific function> = specific_impl_function %impl.elem0.loc15_11.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc15_11.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc15_11.2: <bound method> = bound_method %.loc15_11.2, %specific_impl_fn.loc15_11.1
-// CHECK:STDOUT:     %.loc15_11.3: init @AccessDerived.%T.as_type.loc13_45.1 (%T.as_type) = call %bound_method.loc15_11.2(%.loc15_11.2)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %.loc15_11.3: init @AccessDerived.%T.as_type.loc13_45.1 (%T.as_type) = call %bound_method.loc15_11.2(%.loc15_11.2) to %.loc13_48
 // CHECK:STDOUT:     return %.loc15_11.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -143,7 +144,7 @@ fn AccessMissingConcrete(x: Derived(i32)) -> i32 {
 // CHECK:STDOUT:   %impl.elem0.loc21_11.2: @AccessBase.%.loc21_11.6 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc21_11.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc21_11.2: <specific function> = specific_impl_function %impl.elem0.loc21_11.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc21_11.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @AccessBase.%Derived.loc19_42.1 (%Derived.3ba)) -> @AccessBase.%T.as_type.loc19_42.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @AccessBase.%Derived.loc19_42.1 (%Derived.3ba)) -> %return.param: @AccessBase.%T.as_type.loc19_42.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @AccessBase.%Derived.loc19_42.1 (%Derived.3ba) = name_ref x, %x
 // CHECK:STDOUT:     %b.ref: @AccessBase.%Base.elem (%Base.elem.58f) = name_ref b, @Base.%.loc5 [concrete = @Base.%.loc5]
@@ -155,7 +156,8 @@ fn AccessMissingConcrete(x: Derived(i32)) -> i32 {
 // CHECK:STDOUT:     %bound_method.loc21_11.1: <bound method> = bound_method %.loc21_11.4, %impl.elem0.loc21_11.1
 // CHECK:STDOUT:     %specific_impl_fn.loc21_11.1: <specific function> = specific_impl_function %impl.elem0.loc21_11.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc21_11.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc21_11.2: <bound method> = bound_method %.loc21_11.4, %specific_impl_fn.loc21_11.1
-// CHECK:STDOUT:     %.loc21_11.5: init @AccessBase.%T.as_type.loc19_42.1 (%T.as_type) = call %bound_method.loc21_11.2(%.loc21_11.4)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %.loc21_11.5: init @AccessBase.%T.as_type.loc19_42.1 (%T.as_type) = call %bound_method.loc21_11.2(%.loc21_11.4) to %.loc19_45
 // CHECK:STDOUT:     return %.loc21_11.5 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 6 - 4
toolchain/check/testdata/class/generic/member_out_of_line.carbon

@@ -336,14 +336,15 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:   %impl.elem0.loc12_10.2: @Class.F.%.loc12_10.2 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc12_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc12_10.2: <specific function> = specific_impl_function %impl.elem0.loc12_10.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc12_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%n.param.loc11: @Class.F.%T.as_type.loc6_11.1 (%T.as_type)) -> @Class.F.%T.as_type.loc6_11.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%n.param.loc11: @Class.F.%T.as_type.loc6_11.1 (%T.as_type)) -> %return.param.loc11: @Class.F.%T.as_type.loc6_11.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %n.ref: @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = name_ref n, %n.loc11
 // CHECK:STDOUT:     %impl.elem0.loc12_10.1: @Class.F.%.loc12_10.2 (%.c50) = impl_witness_access constants.%Copy.lookup_impl_witness.e15, element0 [symbolic = %impl.elem0.loc12_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:     %bound_method.loc12_10.1: <bound method> = bound_method %n.ref, %impl.elem0.loc12_10.1
 // CHECK:STDOUT:     %specific_impl_fn.loc12_10.1: <specific function> = specific_impl_function %impl.elem0.loc12_10.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc12_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc12_10.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc12_10.1
-// CHECK:STDOUT:     %.loc12_10.1: init @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = call %bound_method.loc12_10.2(%n.ref)
+// CHECK:STDOUT:     %.loc11_33: ref @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = splice_block %return.loc11 {}
+// CHECK:STDOUT:     %.loc12_10.1: init @Class.F.%T.as_type.loc6_11.1 (%T.as_type) = call %bound_method.loc12_10.2(%n.ref) to %.loc11_33
 // CHECK:STDOUT:     return %.loc12_10.1 to %return.loc11
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -365,7 +366,7 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:   %impl.elem0.loc16_14.2: @Class.G.%.loc16_14.4 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_14.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc16_14.2: <specific function> = specific_impl_function %impl.elem0.loc16_14.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc16_14.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param.loc15: @Class.G.%Class (%Class)) -> @Class.G.%T.as_type.loc7_25.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%self.param.loc15: @Class.G.%Class (%Class)) -> %return.param.loc15: @Class.G.%T.as_type.loc7_25.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @Class.G.%Class (%Class) = name_ref self, %self.loc15
 // CHECK:STDOUT:     %n.ref: @Class.G.%Class.elem (%Class.elem) = name_ref n, @Class.%.loc8_8 [concrete = @Class.%.loc8_8]
@@ -375,7 +376,8 @@ fn Generic(T:! ()).WrongType() {}
 // CHECK:STDOUT:     %bound_method.loc16_14.1: <bound method> = bound_method %.loc16_14.2, %impl.elem0.loc16_14.1
 // CHECK:STDOUT:     %specific_impl_fn.loc16_14.1: <specific function> = specific_impl_function %impl.elem0.loc16_14.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc16_14.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc16_14.2: <bound method> = bound_method %.loc16_14.2, %specific_impl_fn.loc16_14.1
-// CHECK:STDOUT:     %.loc16_14.3: init @Class.G.%T.as_type.loc7_25.1 (%T.as_type) = call %bound_method.loc16_14.2(%.loc16_14.2)
+// CHECK:STDOUT:     %.loc15_41: ref @Class.G.%T.as_type.loc7_25.1 (%T.as_type) = splice_block %return.loc15 {}
+// CHECK:STDOUT:     %.loc16_14.3: init @Class.G.%T.as_type.loc7_25.1 (%T.as_type) = call %bound_method.loc16_14.2(%.loc16_14.2) to %.loc15_41
 // CHECK:STDOUT:     return %.loc16_14.3 to %return.loc15
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 5 - 4
toolchain/check/testdata/class/generic/member_type.carbon

@@ -368,8 +368,8 @@ fn Test() -> i32 {
 // CHECK:STDOUT:     %bound_method.loc9_38.1: <bound method> = bound_method %n.ref, %impl.elem0.loc9_38.1
 // CHECK:STDOUT:     %specific_impl_fn.loc9_38.1: <specific function> = specific_impl_function %impl.elem0.loc9_38.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc9_38.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc9_38.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc9_38.1
-// CHECK:STDOUT:     %.loc9_38.1: init @Outer.F.%T.as_type.loc9_11.1 (%T.as_type) = call %bound_method.loc9_38.2(%n.ref)
 // CHECK:STDOUT:     %.loc9_39.2: ref @Outer.F.%T.as_type.loc9_11.1 (%T.as_type) = class_element_access %return, element0
+// CHECK:STDOUT:     %.loc9_38.1: init @Outer.F.%T.as_type.loc9_11.1 (%T.as_type) = call %bound_method.loc9_38.2(%n.ref) to %.loc9_39.2
 // CHECK:STDOUT:     %.loc9_39.3: init @Outer.F.%T.as_type.loc9_11.1 (%T.as_type) = initialize_from %.loc9_38.1 to %.loc9_39.2
 // CHECK:STDOUT:     %.loc9_39.4: init @Outer.F.%Inner (%Inner.6ee) = class_init (%.loc9_39.3), %return
 // CHECK:STDOUT:     %.loc9_40: init @Outer.F.%Inner (%Inner.6ee) = converted %.loc9_39.1, %.loc9_39.4
@@ -944,7 +944,7 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %pattern_type.loc6_10: type = pattern_type %Self.as_type.loc6_16.1 [symbolic = %pattern_type.loc6_10 (constants.%pattern_type.120)]
 // CHECK:STDOUT:   %pattern_type.loc6_24: type = pattern_type %T [symbolic = %pattern_type.loc6_24 (constants.%pattern_type.7dc)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @Inner.F.%Self.as_type.loc6_16.1 (%Self.as_type.bd3)) -> @Inner.F.%T (%T);
+// CHECK:STDOUT:   fn(%self.param: @Inner.F.%Self.as_type.loc6_16.1 (%Self.as_type.bd3)) -> %return.param: @Inner.F.%T (%T);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @C.as.Inner.impl.F(@Outer.%T.loc4_13.2: type) {
@@ -967,7 +967,7 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %impl.elem0.loc11_41.2: @C.as.Inner.impl.F.%.loc11_41 (%.4e7) = impl_witness_access %Inner.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_41.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:   %specific_impl_fn.loc11_41.2: <specific function> = specific_impl_function %impl.elem0.loc11_41.2, @Inner.F(%T, %Inner.facet) [symbolic = %specific_impl_fn.loc11_41.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @C.as.Inner.impl.F.%C (%C.390)) -> @C.as.Inner.impl.F.%T (%T) {
+// CHECK:STDOUT:   fn(%self.param: @C.as.Inner.impl.F.%C (%C.390)) -> %return.param: @C.as.Inner.impl.F.%T (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %self.ref: @C.as.Inner.impl.F.%C (%C.390) = name_ref self, %self
 // CHECK:STDOUT:     %.loc11_43: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.type (constants.%Inner.type.d07)]
@@ -978,7 +978,8 @@ fn Test() -> i32 {
 // CHECK:STDOUT:     %bound_method.loc11_41: <bound method> = bound_method %self.ref, %impl.elem0.loc11_41.1
 // CHECK:STDOUT:     %specific_impl_fn.loc11_41.1: <specific function> = specific_impl_function %impl.elem0.loc11_41.1, @Inner.F(constants.%T, constants.%Inner.facet.949) [symbolic = %specific_impl_fn.loc11_41.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:     %bound_method.loc11_52: <bound method> = bound_method %self.ref, %specific_impl_fn.loc11_41.1
-// CHECK:STDOUT:     %.loc11_52: init @C.as.Inner.impl.F.%T (%T) = call %bound_method.loc11_52(%self.ref)
+// CHECK:STDOUT:     %.loc11_23: ref @C.as.Inner.impl.F.%T (%T) = splice_block %return {}
+// CHECK:STDOUT:     %.loc11_52: init @C.as.Inner.impl.F.%T (%T) = call %bound_method.loc11_52(%self.ref) to %.loc11_23
 // CHECK:STDOUT:     return %.loc11_52 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 8 - 6
toolchain/check/testdata/deduce/array.carbon

@@ -200,7 +200,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %a.param: @F.%array_type.loc6_29.1 (%array_type.743) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.743)] {
+// CHECK:STDOUT:     %.loc6_29: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.743)] {
 // CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]
 // CHECK:STDOUT:       %array_type.loc6_29.2: type = array_type %int_3, %T.ref.loc6_25 [symbolic = %array_type.loc6_29.1 (constants.%array_type.743)]
@@ -260,12 +260,13 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %array_type.loc6_29.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.06f)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_46.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.743)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.743)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %a.ref: @F.%array_type.loc6_29.1 (%array_type.743) = name_ref a, %a
 // CHECK:STDOUT:     %F.specific_fn.loc6_46.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_46.1(%a.ref)
+// CHECK:STDOUT:     %.loc6_32: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_46.1(%a.ref) to %.loc6_32
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -872,7 +873,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %a.param: @F.%array_type.loc6_29.1 (%array_type.9d4) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.9d4)] {
+// CHECK:STDOUT:     %.loc6_29: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.9d4)] {
 // CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]
 // CHECK:STDOUT:       %array_type.loc6_29.2: type = array_type %int_2, %T.ref.loc6_25 [symbolic = %array_type.loc6_29.1 (constants.%array_type.9d4)]
@@ -932,12 +933,13 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %array_type.loc6_29.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.d11)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_46.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.9d4)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.9d4)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %a.ref: @F.%array_type.loc6_29.1 (%array_type.9d4) = name_ref a, %a
 // CHECK:STDOUT:     %F.specific_fn.loc6_46.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_46.1(%a.ref)
+// CHECK:STDOUT:     %.loc6_32: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_46.1(%a.ref) to %.loc6_32
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 4 - 3
toolchain/check/testdata/deduce/generic_type.carbon

@@ -145,7 +145,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc7_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]
 // CHECK:STDOUT:     %p.param: @F.%C.loc7_22.1 (%C.f2e) = value_param call_param0
-// CHECK:STDOUT:     %.loc7: type = splice_block %C.loc7_22.2 [symbolic = %C.loc7_22.1 (constants.%C.f2e)] {
+// CHECK:STDOUT:     %.loc7_22: type = splice_block %C.loc7_22.2 [symbolic = %C.loc7_22.1 (constants.%C.f2e)] {
 // CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
 // CHECK:STDOUT:       %T.ref.loc7_21: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]
 // CHECK:STDOUT:       %C.loc7_22.2: type = class_type @C, @C(constants.%T) [symbolic = %C.loc7_22.1 (constants.%C.f2e)]
@@ -272,12 +272,13 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %require_complete.loc7_17: <witness> = require_complete_type %C.loc7_22.1 [symbolic = %require_complete.loc7_17 (constants.%require_complete.389)]
 // CHECK:STDOUT:   %F.specific_fn.loc7_39.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%p.param: @F.%C.loc7_22.1 (%C.f2e)) -> @F.%T.loc7_6.1 (%T) {
+// CHECK:STDOUT:   fn(%p.param: @F.%C.loc7_22.1 (%C.f2e)) -> %return.param: @F.%T.loc7_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%C.loc7_22.1 (%C.f2e) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc7_39.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc7_6.1 (%T) = call %F.specific_fn.loc7_39.1(%p.ref)
+// CHECK:STDOUT:     %.loc7_25: ref @F.%T.loc7_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc7_6.1 (%T) = call %F.specific_fn.loc7_39.1(%p.ref) to %.loc7_25
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 3 - 2
toolchain/check/testdata/deduce/tuple.carbon

@@ -235,12 +235,13 @@ fn G(pair: (C, D)) -> D {
 // CHECK:STDOUT:   %require_complete.loc7_30: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc7_30 (constants.%require_complete.fe1)]
 // CHECK:STDOUT:   %F.specific_fn.loc7_54.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1, %U.loc7_16.1) [symbolic = %F.specific_fn.loc7_54.2 (constants.%F.specific_fn.dd9)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%pair.param: @F.%tuple.type (%tuple.type.30b)) -> @F.%U.loc7_16.1 (%U) {
+// CHECK:STDOUT:   fn(%pair.param: @F.%tuple.type (%tuple.type.30b)) -> %return.param: @F.%U.loc7_16.1 (%U) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %pair.ref: @F.%tuple.type (%tuple.type.30b) = name_ref pair, %pair
 // CHECK:STDOUT:     %F.specific_fn.loc7_54.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [symbolic = %F.specific_fn.loc7_54.2 (constants.%F.specific_fn.dd9)]
-// CHECK:STDOUT:     %F.call: init @F.%U.loc7_16.1 (%U) = call %F.specific_fn.loc7_54.1(%pair.ref)
+// CHECK:STDOUT:     %.loc7_40: ref @F.%U.loc7_16.1 (%U) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%U.loc7_16.1 (%U) = call %F.specific_fn.loc7_54.1(%pair.ref) to %.loc7_40
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 16 - 12
toolchain/check/testdata/deduce/type_operator.carbon

@@ -128,7 +128,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %p.param: @F.%ptr.loc6_20.1 (%ptr.79f) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)] {
+// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)] {
 // CHECK:STDOUT:       %T.ref.loc6_19: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref.loc6_19 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)]
 // CHECK:STDOUT:     }
@@ -195,12 +195,13 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.6e5)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_37.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.79f)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.79f)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_20.1 (%ptr.79f) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc6_37.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_37.1(%p.ref)
+// CHECK:STDOUT:     %.loc6_23: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_37.1(%p.ref) to %.loc6_23
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -304,7 +305,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %p.param: @F.%ptr.loc6_26.1 (%ptr.6d4) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)] {
+// CHECK:STDOUT:     %.loc6_26: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)] {
 // CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %const.loc6_19.2: type = const_type %T.ref.loc6_25 [symbolic = %const.loc6_19.1 (constants.%const.a1a)]
 // CHECK:STDOUT:       %ptr.loc6_26.2: type = ptr_type %const.loc6_19.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)]
@@ -374,12 +375,13 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_26.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.20b)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_43.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.6d4)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.6d4)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_26.1 (%ptr.6d4) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc6_43.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_43.1(%p.ref)
+// CHECK:STDOUT:     %.loc6_29: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_43.1(%p.ref) to %.loc6_29
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -484,7 +486,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %p.param: @F.%ptr.loc6_20.1 (%ptr.79f) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)] {
+// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)] {
 // CHECK:STDOUT:       %T.ref.loc6_19: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref.loc6_19 [symbolic = %ptr.loc6_20.1 (constants.%ptr.79f)]
 // CHECK:STDOUT:     }
@@ -553,12 +555,13 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.6e5)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_37.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.79f)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.79f)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_20.1 (%ptr.79f) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc6_37.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.ef1)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_37.1(%p.ref)
+// CHECK:STDOUT:     %.loc6_23: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_37.1(%p.ref) to %.loc6_23
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -658,7 +661,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:     %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:     %T.loc6_6.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:     %p.param: @F.%ptr.loc6_26.1 (%ptr.6d4) = value_param call_param0
-// CHECK:STDOUT:     %.loc6: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)] {
+// CHECK:STDOUT:     %.loc6_26: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)] {
 // CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]
 // CHECK:STDOUT:       %const.loc6_19.2: type = const_type %T.ref.loc6_25 [symbolic = %const.loc6_19.1 (constants.%const.a1a)]
 // CHECK:STDOUT:       %ptr.loc6_26.2: type = ptr_type %const.loc6_19.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.6d4)]
@@ -728,12 +731,13 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_26.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.20b)]
 // CHECK:STDOUT:   %F.specific_fn.loc6_43.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.6d4)) -> @F.%T.loc6_6.1 (%T) {
+// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.6d4)) -> %return.param: @F.%T.loc6_6.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_26.1 (%ptr.6d4) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc6_43.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn)]
-// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_43.1(%p.ref)
+// CHECK:STDOUT:     %.loc6_29: ref @F.%T.loc6_6.1 (%T) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) = call %F.specific_fn.loc6_43.1(%p.ref) to %.loc6_29
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

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

@@ -502,7 +502,6 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %const: type = const_type %T [symbolic]
 // CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]
 // CHECK:STDOUT:   %tuple.type.4f2: type = tuple_type (%ptr.79f, %const) [symbolic]
-// CHECK:STDOUT:   %ptr.6cd: type = ptr_type %tuple.type.4f2 [symbolic]
 // CHECK:STDOUT:   %require_complete.155: <witness> = require_complete_type %tuple.type.4f2 [symbolic]
 // CHECK:STDOUT:   %pattern_type.973: type = pattern_type %tuple.type.4f2 [symbolic]
 // CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T} [symbolic]
@@ -528,6 +527,7 @@ fn G(N:! i32) {
 // CHECK:STDOUT:   %.aa5: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet.90b [symbolic]
 // CHECK:STDOUT:   %impl.elem0.d3d: %.aa5 = impl_witness_access %Destroy.lookup_impl_witness.b34, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.612: <specific function> = specific_impl_function %impl.elem0.d3d, @Destroy.Op(%Destroy.facet.90b) [symbolic]
+// CHECK:STDOUT:   %ptr.6cd: type = ptr_type %tuple.type.4f2 [symbolic]
 // CHECK:STDOUT:   %require_complete.66e: <witness> = require_complete_type %ptr.6cd [symbolic]
 // CHECK:STDOUT:   %Destroy.lookup_impl_witness.a8a: <witness> = lookup_impl_witness %tuple.type.4f2, @Destroy [symbolic]
 // CHECK:STDOUT:   %Destroy.facet.6c8: %Destroy.type = facet_value %tuple.type.4f2, (%Destroy.lookup_impl_witness.a8a) [symbolic]

+ 9 - 6
toolchain/check/testdata/facet/access.carbon

@@ -265,7 +265,7 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:   %impl.elem0.loc10_11.2: @Use.%.loc10_11.2 (%.7cf) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:   %specific_impl_fn.loc10_11.2: <specific function> = specific_impl_function %impl.elem0.loc10_11.2, @I.Make(%I.facet) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @Use.%T.as_type.loc8_18.1 (%T.as_type) {
+// CHECK:STDOUT:   fn() -> %return.param: @Use.%T.as_type.loc8_18.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %T.ref.loc10: %I.type = name_ref T, %T.loc8_8.2 [symbolic = %T.loc8_8.1 (constants.%T)]
 // CHECK:STDOUT:     %Make.ref: %I.assoc_type = name_ref Make, @I.%assoc0 [concrete = constants.%assoc0]
@@ -273,7 +273,8 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:     %.loc10_11.1: type = converted %T.ref.loc10, %T.as_type.loc10 [symbolic = %T.as_type.loc8_18.1 (constants.%T.as_type)]
 // CHECK:STDOUT:     %impl.elem0.loc10_11.1: @Use.%.loc10_11.2 (%.7cf) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:     %specific_impl_fn.loc10_11.1: <specific function> = specific_impl_function %impl.elem0.loc10_11.1, @I.Make(constants.%I.facet) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]
-// CHECK:STDOUT:     %.loc10_17: init @Use.%T.as_type.loc8_18.1 (%T.as_type) = call %specific_impl_fn.loc10_11.1()
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %.loc10_17: init @Use.%T.as_type.loc8_18.1 (%T.as_type) = call %specific_impl_fn.loc10_11.1() to %.loc8_15
 // CHECK:STDOUT:     return %.loc10_17 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -349,7 +350,7 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:   %impl.elem0.loc10_11.2: @Use.%.loc10_11.2 (%.ee3) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:   %specific_impl_fn.loc10_11.2: <specific function> = specific_impl_function %impl.elem0.loc10_11.2, @I.Copy(%I.facet) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @Use.%T.as_type.loc9_18.1 (%T.as_type)) -> @Use.%T.as_type.loc9_18.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @Use.%T.as_type.loc9_18.1 (%T.as_type)) -> %return.param: @Use.%T.as_type.loc9_18.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @Use.%T.as_type.loc9_18.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %Copy.ref: %I.assoc_type = name_ref Copy, @I.%assoc0 [concrete = constants.%assoc0]
@@ -359,7 +360,8 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:     %bound_method.loc10_11: <bound method> = bound_method %x.ref, %impl.elem0.loc10_11.1
 // CHECK:STDOUT:     %specific_impl_fn.loc10_11.1: <specific function> = specific_impl_function %impl.elem0.loc10_11.1, @I.Copy(constants.%I.facet) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:     %bound_method.loc10_17: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_11.1
-// CHECK:STDOUT:     %.loc10_17: init @Use.%T.as_type.loc9_18.1 (%T.as_type) = call %bound_method.loc10_17(%x.ref)
+// CHECK:STDOUT:     %.loc9_21: ref @Use.%T.as_type.loc9_18.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc10_17: init @Use.%T.as_type.loc9_18.1 (%T.as_type) = call %bound_method.loc10_17(%x.ref) to %.loc9_21
 // CHECK:STDOUT:     return %.loc10_17 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -452,7 +454,7 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:   %impl.elem0.loc10_14.2: @UseIndirect.%.loc10_14.2 (%.ee3) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_14.2 (constants.%impl.elem0)]
 // CHECK:STDOUT:   %specific_impl_fn.loc10_14.2: <specific function> = specific_impl_function %impl.elem0.loc10_14.2, @I.Copy(%I.facet) [symbolic = %specific_impl_fn.loc10_14.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type)) -> @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type)) -> %return.param: @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %T.ref.loc10: %I.type = name_ref T, %T.loc8_16.2 [symbolic = %T.loc8_16.1 (constants.%T)]
@@ -463,7 +465,8 @@ fn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {
 // CHECK:STDOUT:     %bound_method.loc10_11: <bound method> = bound_method %x.ref, %impl.elem0.loc10_14.1
 // CHECK:STDOUT:     %specific_impl_fn.loc10_14.1: <specific function> = specific_impl_function %impl.elem0.loc10_14.1, @I.Copy(constants.%I.facet) [symbolic = %specific_impl_fn.loc10_14.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:     %bound_method.loc10_21: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_14.1
-// CHECK:STDOUT:     %.loc10_21: init @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type) = call %bound_method.loc10_21(%x.ref)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %.loc10_21: init @UseIndirect.%T.as_type.loc8_26.1 (%T.as_type) = call %bound_method.loc10_21(%x.ref) to %.loc8_29
 // CHECK:STDOUT:     return %.loc10_21 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 12 - 8
toolchain/check/testdata/function/generic/call.carbon

@@ -169,14 +169,15 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   %impl.elem0.loc6_10.2: @Function.%.loc6_10.2 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @Function.%T.as_type.loc5_31.1 (%T.as_type)) -> @Function.%T.as_type.loc5_31.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @Function.%T.as_type.loc5_31.1 (%T.as_type)) -> %return.param: @Function.%T.as_type.loc5_31.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @Function.%T.as_type.loc5_31.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %impl.elem0.loc6_10.1: @Function.%.loc6_10.2 (%.c50) = impl_witness_access constants.%Copy.lookup_impl_witness.e15, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %x.ref, %impl.elem0.loc6_10.1
 // CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc6_10.1
-// CHECK:STDOUT:     %.loc6_10.1: init @Function.%T.as_type.loc5_31.1 (%T.as_type) = call %bound_method.loc6_10.2(%x.ref)
+// CHECK:STDOUT:     %.loc5_34: ref @Function.%T.as_type.loc5_31.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc6_10.1: init @Function.%T.as_type.loc5_31.1 (%T.as_type) = call %bound_method.loc6_10.2(%x.ref) to %.loc5_34
 // CHECK:STDOUT:     return %.loc6_10.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -188,7 +189,7 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %Function.specific_fn.loc12_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc10_16.1) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.8cd)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type)) -> @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type)) -> %return.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]
 // CHECK:STDOUT:     %T.ref.loc12: %Copy.type = name_ref T, %T.loc10_16.2 [symbolic = %T.loc10_16.1 (constants.%T.be8)]
@@ -196,7 +197,8 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:     %.loc12_23.1: %Copy.type = converted constants.%T.as_type, constants.%T.be8 [symbolic = %T.loc10_16.1 (constants.%T.be8)]
 // CHECK:STDOUT:     %.loc12_23.2: %Copy.type = converted constants.%T.as_type, constants.%T.be8 [symbolic = %T.loc10_16.1 (constants.%T.be8)]
 // CHECK:STDOUT:     %Function.specific_fn.loc12_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T.be8) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.8cd)]
-// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) = call %Function.specific_fn.loc12_10.1(%x.ref)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) = call %Function.specific_fn.loc12_10.1(%x.ref) to %.loc10_37
 // CHECK:STDOUT:     return %Function.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -398,14 +400,15 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   %impl.elem0.loc6_10.2: @Function.%.loc6_10.2 (%.c50) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @Function.%T.as_type.loc5_31.1 (%T.as_type)) -> @Function.%T.as_type.loc5_31.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @Function.%T.as_type.loc5_31.1 (%T.as_type)) -> %return.param: @Function.%T.as_type.loc5_31.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @Function.%T.as_type.loc5_31.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %impl.elem0.loc6_10.1: @Function.%.loc6_10.2 (%.c50) = impl_witness_access constants.%Copy.lookup_impl_witness.e15, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %x.ref, %impl.elem0.loc6_10.1
 // CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc6_10.1
-// CHECK:STDOUT:     %.loc6_10.1: init @Function.%T.as_type.loc5_31.1 (%T.as_type) = call %bound_method.loc6_10.2(%x.ref)
+// CHECK:STDOUT:     %.loc5_34: ref @Function.%T.as_type.loc5_31.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc6_10.1: init @Function.%T.as_type.loc5_31.1 (%T.as_type) = call %bound_method.loc6_10.2(%x.ref) to %.loc5_34
 // CHECK:STDOUT:     return %.loc6_10.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -417,14 +420,15 @@ fn CallSpecific(x: C*) -> C* {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %Function.specific_fn.loc12_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc10_16.1) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.8cd)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type)) -> @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) {
+// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type)) -> %return.param: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]
 // CHECK:STDOUT:     %x.ref: @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) = name_ref x, %x
 // CHECK:STDOUT:     %.loc12_20.1: %Copy.type = converted constants.%T.as_type, constants.%T.be8 [symbolic = %T.loc10_16.1 (constants.%T.be8)]
 // CHECK:STDOUT:     %.loc12_20.2: %Copy.type = converted constants.%T.as_type, constants.%T.be8 [symbolic = %T.loc10_16.1 (constants.%T.be8)]
 // CHECK:STDOUT:     %Function.specific_fn.loc12_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T.be8) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.8cd)]
-// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) = call %Function.specific_fn.loc12_10.1(%x.ref)
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.as_type.loc10_34.1 (%T.as_type) = call %Function.specific_fn.loc12_10.1(%x.ref) to %.loc10_37
 // CHECK:STDOUT:     return %Function.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 5 - 4
toolchain/check/testdata/function/generic/return_slot.carbon

@@ -226,12 +226,13 @@ fn G() {
 // CHECK:STDOUT:   %Wrap.Make: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.652) = struct_value () [symbolic = %Wrap.Make (constants.%Wrap.Make.eb2)]
 // CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2: <specific function> = specific_function %Wrap.Make, @Wrap.Make(%T) [symbolic = %Wrap.Make.specific_fn.loc16_27.2 (constants.%Wrap.Make.specific_fn.bf1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @Wrap.Make.%T (%T) {
+// CHECK:STDOUT:   fn() -> %return.param: @Wrap.Make.%T (%T) {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %.loc16: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.652) = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%T) [symbolic = %Wrap.Make (constants.%Wrap.Make.eb2)]
-// CHECK:STDOUT:     %Make.ref: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.652) = name_ref Make, %.loc16 [symbolic = %Wrap.Make (constants.%Wrap.Make.eb2)]
+// CHECK:STDOUT:     %.loc16_27: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.652) = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%T) [symbolic = %Wrap.Make (constants.%Wrap.Make.eb2)]
+// CHECK:STDOUT:     %Make.ref: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.652) = name_ref Make, %.loc16_27 [symbolic = %Wrap.Make (constants.%Wrap.Make.eb2)]
 // CHECK:STDOUT:     %Wrap.Make.specific_fn.loc16_27.1: <specific function> = specific_function %Make.ref, @Wrap.Make(constants.%T) [symbolic = %Wrap.Make.specific_fn.loc16_27.2 (constants.%Wrap.Make.specific_fn.bf1)]
-// CHECK:STDOUT:     %Wrap.Make.call: init @Wrap.Make.%T (%T) = call %Wrap.Make.specific_fn.loc16_27.1()
+// CHECK:STDOUT:     %.loc16_13: ref @Wrap.Make.%T (%T) = splice_block %return {}
+// CHECK:STDOUT:     %Wrap.Make.call: init @Wrap.Make.%T (%T) = call %Wrap.Make.specific_fn.loc16_27.1() to %.loc16_13
 // CHECK:STDOUT:     return %Wrap.Make.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 3 - 2
toolchain/check/testdata/generic/dependent_param.carbon

@@ -215,14 +215,15 @@ var n: i32 = Outer(i32).Inner(42).Get();
 // CHECK:STDOUT:   %specific_impl_fn.loc7_28.2: <specific function> = specific_impl_function %impl.elem0.loc7_28.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc7_28.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:   %bound_method.loc7_28.4: <bound method> = bound_method %U, %specific_impl_fn.loc7_28.2 [symbolic = %bound_method.loc7_28.4 (constants.%bound_method.088)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) {
+// CHECK:STDOUT:   fn() -> %return.param: @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %U.ref: @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) = name_ref U, @Inner.%U.loc5_15.2 [symbolic = %U (constants.%U.afe)]
 // CHECK:STDOUT:     %impl.elem0.loc7_28.1: @Inner.Get.%.loc7_28.2 (%.c50) = impl_witness_access constants.%Copy.lookup_impl_witness.e15, element0 [symbolic = %impl.elem0.loc7_28.2 (constants.%impl.elem0.792)]
 // CHECK:STDOUT:     %bound_method.loc7_28.1: <bound method> = bound_method %U.ref, %impl.elem0.loc7_28.1 [symbolic = %bound_method.loc7_28.3 (constants.%bound_method.ba2)]
 // CHECK:STDOUT:     %specific_impl_fn.loc7_28.1: <specific function> = specific_impl_function %impl.elem0.loc7_28.1, @Copy.Op(constants.%Copy.facet.021) [symbolic = %specific_impl_fn.loc7_28.2 (constants.%specific_impl_fn.547)]
 // CHECK:STDOUT:     %bound_method.loc7_28.2: <bound method> = bound_method %U.ref, %specific_impl_fn.loc7_28.1 [symbolic = %bound_method.loc7_28.4 (constants.%bound_method.088)]
-// CHECK:STDOUT:     %.loc7_28.1: init @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) = call %bound_method.loc7_28.2(%U.ref)
+// CHECK:STDOUT:     %.loc7_14: ref @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) = splice_block %return {}
+// CHECK:STDOUT:     %.loc7_28.1: init @Inner.Get.%T.as_type.loc7_17.1 (%T.as_type) = call %bound_method.loc7_28.2(%U.ref) to %.loc7_14
 // CHECK:STDOUT:     return %.loc7_28.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 6 - 4
toolchain/check/testdata/impl/impl_thunk.carbon

@@ -800,14 +800,15 @@ impl () as I({}) {
 // CHECK:STDOUT:   %impl.elem0.loc10_43.2: @empty_tuple.type.as.I.impl.F.loc10_34.1.%.loc10_43.2 (%.c500ab.2) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_43.2 (constants.%impl.elem0.792e99.2)]
 // CHECK:STDOUT:   %specific_impl_fn.loc10_43.2: <specific function> = specific_impl_function %impl.elem0.loc10_43.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc10_43.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870)) -> @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) {
+// CHECK:STDOUT:   fn(%x.param: @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870)) -> %return.param: @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) = name_ref x, %x
 // CHECK:STDOUT:     %impl.elem0.loc10_43.1: @empty_tuple.type.as.I.impl.F.loc10_34.1.%.loc10_43.2 (%.c500ab.2) = impl_witness_access constants.%Copy.lookup_impl_witness.e15cec.2, element0 [symbolic = %impl.elem0.loc10_43.2 (constants.%impl.elem0.792e99.2)]
 // CHECK:STDOUT:     %bound_method.loc10_43.1: <bound method> = bound_method %x.ref, %impl.elem0.loc10_43.1
 // CHECK:STDOUT:     %specific_impl_fn.loc10_43.1: <specific function> = specific_impl_function %impl.elem0.loc10_43.1, @Copy.Op(constants.%Copy.facet.021101.2) [symbolic = %specific_impl_fn.loc10_43.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:     %bound_method.loc10_43.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_43.1
-// CHECK:STDOUT:     %.loc10_43.1: init @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) = call %bound_method.loc10_43.2(%x.ref)
+// CHECK:STDOUT:     %.loc10_29: ref @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) = splice_block %return {}
+// CHECK:STDOUT:     %.loc10_43.1: init @empty_tuple.type.as.I.impl.F.loc10_34.1.%U.as_type.loc10_26.1 (%U.as_type.870) = call %bound_method.loc10_43.2(%x.ref) to %.loc10_29
 // CHECK:STDOUT:     return %.loc10_43.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -955,14 +956,15 @@ impl () as I({}) {
 // CHECK:STDOUT:   %impl.elem0.loc19_53.2: @empty_tuple.type.as.I.impl.F.loc19_44.1.%.loc19_53.2 (%.c500ab.2) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc19_53.2 (constants.%impl.elem0.792e99.2)]
 // CHECK:STDOUT:   %specific_impl_fn.loc19_53.2: <specific function> = specific_impl_function %impl.elem0.loc19_53.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc19_53.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: %empty_tuple.type, %x.param: @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870)) -> @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) {
+// CHECK:STDOUT:   fn(%self.param: %empty_tuple.type, %x.param: @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870)) -> %return.param: @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %x.ref: @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) = name_ref x, %x
 // CHECK:STDOUT:     %impl.elem0.loc19_53.1: @empty_tuple.type.as.I.impl.F.loc19_44.1.%.loc19_53.2 (%.c500ab.2) = impl_witness_access constants.%Copy.lookup_impl_witness.e15cec.2, element0 [symbolic = %impl.elem0.loc19_53.2 (constants.%impl.elem0.792e99.2)]
 // CHECK:STDOUT:     %bound_method.loc19_53.1: <bound method> = bound_method %x.ref, %impl.elem0.loc19_53.1
 // CHECK:STDOUT:     %specific_impl_fn.loc19_53.1: <specific function> = specific_impl_function %impl.elem0.loc19_53.1, @Copy.Op(constants.%Copy.facet.021101.2) [symbolic = %specific_impl_fn.loc19_53.2 (constants.%specific_impl_fn.547931.2)]
 // CHECK:STDOUT:     %bound_method.loc19_53.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc19_53.1
-// CHECK:STDOUT:     %.loc19_53.1: init @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) = call %bound_method.loc19_53.2(%x.ref)
+// CHECK:STDOUT:     %.loc19_39: ref @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) = splice_block %return {}
+// CHECK:STDOUT:     %.loc19_53.1: init @empty_tuple.type.as.I.impl.F.loc19_44.1.%U.as_type.loc19_36.1 (%U.as_type.870) = call %bound_method.loc19_53.2(%x.ref) to %.loc19_39
 // CHECK:STDOUT:     return %.loc19_53.1 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 68 - 28
toolchain/check/testdata/impl/use_assoc_const.carbon

@@ -1509,7 +1509,7 @@ fn F() {
 // CHECK:STDOUT:   %impl.elem1.loc29_11.2: @GenericCallF.%.loc29_11.2 (%.38a) = impl_witness_access %J.lookup_impl_witness, element1 [symbolic = %impl.elem1.loc29_11.2 (constants.%impl.elem1)]
 // CHECK:STDOUT:   %specific_impl_fn.loc29_11.2: <specific function> = specific_impl_function %impl.elem1.loc29_11.2, @J.F(%J.facet) [symbolic = %specific_impl_fn.loc29_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%t.param: @GenericCallF.%T.as_type.loc28_27.1 (%T.as_type), %u.param: @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2)) -> @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) {
+// CHECK:STDOUT:   fn(%t.param: @GenericCallF.%T.as_type.loc28_27.1 (%T.as_type), %u.param: @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2)) -> %return.param: @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %t.ref: @GenericCallF.%T.as_type.loc28_27.1 (%T.as_type) = name_ref t, %t
 // CHECK:STDOUT:     %F.ref: %J.assoc_type = name_ref F, @J.%assoc1 [concrete = constants.%assoc1.572]
@@ -1518,7 +1518,8 @@ fn F() {
 // CHECK:STDOUT:     %impl.elem1.loc29_11.1: @GenericCallF.%.loc29_11.2 (%.38a) = impl_witness_access constants.%J.lookup_impl_witness.0802bc.2, element1 [symbolic = %impl.elem1.loc29_11.2 (constants.%impl.elem1)]
 // CHECK:STDOUT:     %u.ref: @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) = name_ref u, %u
 // CHECK:STDOUT:     %specific_impl_fn.loc29_11.1: <specific function> = specific_impl_function %impl.elem1.loc29_11.1, @J.F(constants.%J.facet.c211a5.2) [symbolic = %specific_impl_fn.loc29_11.2 (constants.%specific_impl_fn)]
-// CHECK:STDOUT:     %.loc29_15: init @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) = call %specific_impl_fn.loc29_11.1(%u.ref)
+// CHECK:STDOUT:     %.loc28_38: ref @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) = splice_block %return {}
+// CHECK:STDOUT:     %.loc29_15: init @GenericCallF.%impl.elem0.loc28_34.1 (%impl.elem0.312582.2) = call %specific_impl_fn.loc29_11.1(%u.ref) to %.loc28_38
 // CHECK:STDOUT:     return %.loc29_15 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -1625,6 +1626,7 @@ fn F() {
 // CHECK:STDOUT:   %Self.as_type.a67: type = facet_access_type %Self.7ee [symbolic]
 // CHECK:STDOUT:   %pattern_type.d22: type = pattern_type %Self.as_type.a67 [symbolic]
 // CHECK:STDOUT:   %I.Op.type: type = fn_type @I.Op [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %I.Op: %I.Op.type = struct_value () [concrete]
 // CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]
 // CHECK:STDOUT:   %assoc0.ea8: %I.assoc_type = assoc_entity element0, @I.%I.Op.decl [concrete]
@@ -1643,11 +1645,11 @@ fn F() {
 // CHECK:STDOUT:   %assoc1: %J.assoc_type = assoc_entity element1, @J.%J.F.decl [concrete]
 // CHECK:STDOUT:   %type: type = facet_type <type> [concrete]
 // CHECK:STDOUT:   %.Self: %type = bind_symbolic_name .Self [symbolic_self]
-// CHECK:STDOUT:   %T: %J.type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %T.bf6: %J.type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.84b: type = pattern_type %J.type [concrete]
-// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T [symbolic]
+// CHECK:STDOUT:   %T.as_type: type = facet_access_type %T.bf6 [symbolic]
 // CHECK:STDOUT:   %pattern_type.8ba: type = pattern_type %T.as_type [symbolic]
-// CHECK:STDOUT:   %J.lookup_impl_witness.0802bc.2: <witness> = lookup_impl_witness %T, @J [symbolic]
+// CHECK:STDOUT:   %J.lookup_impl_witness.0802bc.2: <witness> = lookup_impl_witness %T.bf6, @J [symbolic]
 // CHECK:STDOUT:   %J.facet.c211a5.2: %J.type = facet_value %T.as_type, (%J.lookup_impl_witness.0802bc.2) [symbolic]
 // CHECK:STDOUT:   %impl.elem0.7d7539.2: %I.type = impl_witness_access %J.lookup_impl_witness.0802bc.2, element0 [symbolic]
 // CHECK:STDOUT:   %as_type.0c2809.2: type = facet_access_type %impl.elem0.7d7539.2 [symbolic]
@@ -1664,13 +1666,24 @@ fn F() {
 // CHECK:STDOUT:   %.8ad: type = fn_type_with_self_type %I.Op.type, %I.facet [symbolic]
 // CHECK:STDOUT:   %impl.elem0.658: %.8ad = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.28c: <specific function> = specific_impl_function %impl.elem0.658, @I.Op(%I.facet) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
+// CHECK:STDOUT:   %ptr.c06: type = ptr_type %as_type.0c2809.2 [symbolic]
+// CHECK:STDOUT:   %require_complete.225: <witness> = require_complete_type %ptr.c06 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0.7d7539.2, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %as_type.0c2809.2, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.766: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet [symbolic]
+// CHECK:STDOUT:   %impl.elem0.2f7: %.766 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.d51: <specific function> = specific_impl_function %impl.elem0.2f7, @Destroy.Op(%Destroy.facet) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -1692,7 +1705,7 @@ fn F() {
 // CHECK:STDOUT:     %return.patt: @GenericResult.%pattern_type.loc12_31 (%pattern_type.c97a06.2) = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: @GenericResult.%pattern_type.loc12_31 (%pattern_type.c97a06.2) = out_param_pattern %return.patt, call_param2 [concrete]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc12_42: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc12_42: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:     %U.ref.loc12_43: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.dfc]
 // CHECK:STDOUT:     %T.as_type.loc12_43: type = facet_access_type %T.ref.loc12_42 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:     %.loc12_43.1: type = converted %T.ref.loc12_42, %T.as_type.loc12_43 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
@@ -1703,17 +1716,17 @@ fn F() {
 // CHECK:STDOUT:       %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
 // CHECK:STDOUT:       %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %T.loc12_18.2: %J.type = bind_symbolic_name T, 0 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:     %T.loc12_18.2: %J.type = bind_symbolic_name T, 0 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:     %t.param: @GenericResult.%T.as_type.loc12_28.1 (%T.as_type) = value_param call_param0
 // CHECK:STDOUT:     %.loc12_28.1: type = splice_block %.loc12_28.2 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)] {
-// CHECK:STDOUT:       %T.ref.loc12_28: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:       %T.ref.loc12_28: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:       %T.as_type.loc12_28.2: type = facet_access_type %T.ref.loc12_28 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:       %.loc12_28.2: type = converted %T.ref.loc12_28, %T.as_type.loc12_28.2 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %t: @GenericResult.%T.as_type.loc12_28.1 (%T.as_type) = bind_name t, %t.param
 // CHECK:STDOUT:     %u.param: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = value_param call_param1
 // CHECK:STDOUT:     %.loc12_35.1: type = splice_block %.loc12_35.3 [symbolic = %as_type.loc12_35.1 (constants.%as_type.0c2809.2)] {
-// CHECK:STDOUT:       %T.ref.loc12_34: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:       %T.ref.loc12_34: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:       %U.ref.loc12_35: %J.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0.dfc]
 // CHECK:STDOUT:       %T.as_type.loc12_35: type = facet_access_type %T.ref.loc12_34 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:       %.loc12_35.2: type = converted %T.ref.loc12_34, %T.as_type.loc12_35 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
@@ -1824,7 +1837,7 @@ fn F() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @GenericResult(%T.loc12_18.2: %J.type) {
-// CHECK:STDOUT:   %T.loc12_18.1: %J.type = bind_symbolic_name T, 0 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:   %T.loc12_18.1: %J.type = bind_symbolic_name T, 0 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:   %T.as_type.loc12_28.1: type = facet_access_type %T.loc12_18.1 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:   %pattern_type.loc12_25: type = pattern_type %T.as_type.loc12_28.1 [symbolic = %pattern_type.loc12_25 (constants.%pattern_type.8ba)]
 // CHECK:STDOUT:   %J.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc12_18.1, @J [symbolic = %J.lookup_impl_witness (constants.%J.lookup_impl_witness.0802bc.2)]
@@ -1844,24 +1857,32 @@ fn F() {
 // CHECK:STDOUT:   %.loc13_16: type = fn_type_with_self_type constants.%I.Op.type, %I.facet [symbolic = %.loc13_16 (constants.%.8ad)]
 // CHECK:STDOUT:   %impl.elem0.loc13_16.2: @GenericResult.%.loc13_16 (%.8ad) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_16.2 (constants.%impl.elem0.658)]
 // CHECK:STDOUT:   %specific_impl_fn.loc13_16.2: <specific function> = specific_impl_function %impl.elem0.loc13_16.2, @I.Op(%I.facet) [symbolic = %specific_impl_fn.loc13_16.2 (constants.%specific_impl_fn.28c)]
-// CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%t.param: @GenericResult.%T.as_type.loc12_28.1 (%T.as_type), %u.param: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2)) -> @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) {
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %impl.elem0.loc12_35.1, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %as_type.loc12_35.1, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]
+// CHECK:STDOUT:   %.loc13_29.9: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc13_29.9 (constants.%.766)]
+// CHECK:STDOUT:   %impl.elem0.loc13_29.2: @GenericResult.%.loc13_29.9 (%.766) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_29.2 (constants.%impl.elem0.2f7)]
+// CHECK:STDOUT:   %specific_impl_fn.loc13_29.2: <specific function> = specific_impl_function %impl.elem0.loc13_29.2, @Destroy.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc13_29.2 (constants.%specific_impl_fn.d51)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %as_type.loc12_35.1 [symbolic = %ptr (constants.%ptr.c06)]
+// CHECK:STDOUT:   %require_complete.loc13: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc13 (constants.%require_complete.225)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn(%t.param: @GenericResult.%T.as_type.loc12_28.1 (%T.as_type), %u.param: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2)) -> %return.param: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %t.ref: @GenericResult.%T.as_type.loc12_28.1 (%T.as_type) = name_ref t, %t
 // CHECK:STDOUT:     %F.ref.loc13_11: %J.assoc_type = name_ref F, @J.%assoc1 [concrete = constants.%assoc1]
-// CHECK:STDOUT:     %T.as_type.loc13_11: type = facet_access_type constants.%T [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
-// CHECK:STDOUT:     %.loc13_11.1: type = converted constants.%T, %T.as_type.loc13_11 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
+// CHECK:STDOUT:     %T.as_type.loc13_11: type = facet_access_type constants.%T.bf6 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
+// CHECK:STDOUT:     %.loc13_11.1: type = converted constants.%T.bf6, %T.as_type.loc13_11 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:     %impl.elem1.loc13_11.1: @GenericResult.%.loc13_11.2 (%.38a) = impl_witness_access constants.%J.lookup_impl_witness.0802bc.2, element1 [symbolic = %impl.elem1.loc13_11.2 (constants.%impl.elem1)]
 // CHECK:STDOUT:     %u.ref.loc13_14: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = name_ref u, %u
 // CHECK:STDOUT:     %.loc13_15.1: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %.loc13_15.2: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %specific_impl_fn.loc13_11.1: <specific function> = specific_impl_function %impl.elem1.loc13_11.1, @J.F(constants.%J.facet.c211a5.2) [symbolic = %specific_impl_fn.loc13_11.2 (constants.%specific_impl_fn.260)]
-// CHECK:STDOUT:     %.loc13_15.3: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %specific_impl_fn.loc13_11.1(%u.ref.loc13_14)
+// CHECK:STDOUT:     %.loc13_15.3: ref @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = temporary_storage
+// CHECK:STDOUT:     %.loc13_15.4: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %specific_impl_fn.loc13_11.1(%u.ref.loc13_14) to %.loc13_15.3
 // CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]
 // CHECK:STDOUT:     %Op.ref: %I.assoc_type = name_ref Op, @I.%assoc0 [concrete = constants.%assoc0.ea8]
 // CHECK:STDOUT:     %impl.elem0.loc13_16.1: @GenericResult.%.loc13_16 (%.8ad) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_16.2 (constants.%impl.elem0.658)]
-// CHECK:STDOUT:     %bound_method.loc13_16: <bound method> = bound_method %.loc13_15.3, %impl.elem0.loc13_16.1
-// CHECK:STDOUT:     %T.ref.loc13: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T)]
+// CHECK:STDOUT:     %bound_method.loc13_16: <bound method> = bound_method %.loc13_15.4, %impl.elem0.loc13_16.1
+// CHECK:STDOUT:     %T.ref.loc13: %J.type = name_ref T, %T.loc12_18.2 [symbolic = %T.loc12_18.1 (constants.%T.bf6)]
 // CHECK:STDOUT:     %F.ref.loc13_25: %J.assoc_type = name_ref F, @J.%assoc1 [concrete = constants.%assoc1]
 // CHECK:STDOUT:     %T.as_type.loc13_25: type = facet_access_type %T.ref.loc13 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
 // CHECK:STDOUT:     %.loc13_25: type = converted %T.ref.loc13, %T.as_type.loc13_25 [symbolic = %T.as_type.loc12_28.1 (constants.%T.as_type)]
@@ -1870,16 +1891,34 @@ fn F() {
 // CHECK:STDOUT:     %.loc13_29.1: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %.loc13_29.2: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %specific_impl_fn.loc13_25: <specific function> = specific_impl_function %impl.elem1.loc13_25, @J.F(constants.%J.facet.c211a5.2) [symbolic = %specific_impl_fn.loc13_11.2 (constants.%specific_impl_fn.260)]
-// CHECK:STDOUT:     %.loc13_29.3: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %specific_impl_fn.loc13_25(%u.ref.loc13_28)
+// CHECK:STDOUT:     %.loc13_29.3: ref @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = temporary_storage
+// CHECK:STDOUT:     %.loc13_29.4: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %specific_impl_fn.loc13_25(%u.ref.loc13_28) to %.loc13_29.3
 // CHECK:STDOUT:     %.loc13_30.1: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %.loc13_30.2: %I.type = converted constants.%as_type.0c2809.2, constants.%impl.elem0.7d7539.2 [symbolic = %impl.elem0.loc12_35.1 (constants.%impl.elem0.7d7539.2)]
 // CHECK:STDOUT:     %specific_impl_fn.loc13_16.1: <specific function> = specific_impl_function %impl.elem0.loc13_16.1, @I.Op(constants.%I.facet) [symbolic = %specific_impl_fn.loc13_16.2 (constants.%specific_impl_fn.28c)]
-// CHECK:STDOUT:     %bound_method.loc13_30: <bound method> = bound_method %.loc13_15.3, %specific_impl_fn.loc13_16.1
-// CHECK:STDOUT:     %.loc13_15.4: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = value_of_initializer %.loc13_15.3
-// CHECK:STDOUT:     %.loc13_15.5: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = converted %.loc13_15.3, %.loc13_15.4
-// CHECK:STDOUT:     %.loc13_29.4: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = value_of_initializer %.loc13_29.3
-// CHECK:STDOUT:     %.loc13_29.5: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = converted %.loc13_29.3, %.loc13_29.4
-// CHECK:STDOUT:     %.loc13_30.3: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %bound_method.loc13_30(%.loc13_15.5, %.loc13_29.5)
+// CHECK:STDOUT:     %bound_method.loc13_30: <bound method> = bound_method %.loc13_15.4, %specific_impl_fn.loc13_16.1
+// CHECK:STDOUT:     %.loc12_39: ref @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = splice_block %return {}
+// CHECK:STDOUT:     %.loc13_15.5: ref @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = temporary %.loc13_15.3, %.loc13_15.4
+// CHECK:STDOUT:     %.loc13_15.6: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = bind_value %.loc13_15.5
+// CHECK:STDOUT:     %.loc13_29.5: ref @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = temporary %.loc13_29.3, %.loc13_29.4
+// CHECK:STDOUT:     %.loc13_29.6: @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = bind_value %.loc13_29.5
+// CHECK:STDOUT:     %.loc13_30.3: init @GenericResult.%as_type.loc12_35.1 (%as_type.0c2809.2) = call %bound_method.loc13_30(%.loc13_15.6, %.loc13_29.6) to %.loc12_39
+// CHECK:STDOUT:     %as_type.loc13_29: type = facet_access_type constants.%impl.elem0.7d7539.2 [symbolic = %as_type.loc12_35.1 (constants.%as_type.0c2809.2)]
+// CHECK:STDOUT:     %.loc13_29.7: type = converted constants.%impl.elem0.7d7539.2, %as_type.loc13_29 [symbolic = %as_type.loc12_35.1 (constants.%as_type.0c2809.2)]
+// CHECK:STDOUT:     %impl.elem0.loc13_29.1: @GenericResult.%.loc13_29.9 (%.766) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_29.2 (constants.%impl.elem0.2f7)]
+// CHECK:STDOUT:     %bound_method.loc13_29.1: <bound method> = bound_method %.loc13_29.5, %impl.elem0.loc13_29.1
+// CHECK:STDOUT:     %specific_impl_fn.loc13_29.1: <specific function> = specific_impl_function %impl.elem0.loc13_29.1, @Destroy.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc13_29.2 (constants.%specific_impl_fn.d51)]
+// CHECK:STDOUT:     %bound_method.loc13_29.2: <bound method> = bound_method %.loc13_29.5, %specific_impl_fn.loc13_29.1
+// CHECK:STDOUT:     %addr.loc13_29: @GenericResult.%ptr (%ptr.c06) = addr_of %.loc13_29.5
+// CHECK:STDOUT:     %.loc13_29.8: init %empty_tuple.type = call %bound_method.loc13_29.2(%addr.loc13_29)
+// CHECK:STDOUT:     %as_type.loc13_15: type = facet_access_type constants.%impl.elem0.7d7539.2 [symbolic = %as_type.loc12_35.1 (constants.%as_type.0c2809.2)]
+// CHECK:STDOUT:     %.loc13_15.7: type = converted constants.%impl.elem0.7d7539.2, %as_type.loc13_15 [symbolic = %as_type.loc12_35.1 (constants.%as_type.0c2809.2)]
+// CHECK:STDOUT:     %impl.elem0.loc13_15: @GenericResult.%.loc13_29.9 (%.766) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_29.2 (constants.%impl.elem0.2f7)]
+// CHECK:STDOUT:     %bound_method.loc13_15.1: <bound method> = bound_method %.loc13_15.5, %impl.elem0.loc13_15
+// CHECK:STDOUT:     %specific_impl_fn.loc13_15: <specific function> = specific_impl_function %impl.elem0.loc13_15, @Destroy.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc13_29.2 (constants.%specific_impl_fn.d51)]
+// CHECK:STDOUT:     %bound_method.loc13_15.2: <bound method> = bound_method %.loc13_15.5, %specific_impl_fn.loc13_15
+// CHECK:STDOUT:     %addr.loc13_15: @GenericResult.%ptr (%ptr.c06) = addr_of %.loc13_15.5
+// CHECK:STDOUT:     %.loc13_15.8: init %empty_tuple.type = call %bound_method.loc13_15.2(%addr.loc13_15)
 // CHECK:STDOUT:     return %.loc13_30.3 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -1904,8 +1943,8 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @U(constants.%J.facet.c211a5.2) {}
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @GenericResult(constants.%T) {
-// CHECK:STDOUT:   %T.loc12_18.1 => constants.%T
+// CHECK:STDOUT: specific @GenericResult(constants.%T.bf6) {
+// CHECK:STDOUT:   %T.loc12_18.1 => constants.%T.bf6
 // CHECK:STDOUT:   %T.as_type.loc12_28.1 => constants.%T.as_type
 // CHECK:STDOUT:   %pattern_type.loc12_25 => constants.%pattern_type.8ba
 // CHECK:STDOUT:   %J.lookup_impl_witness => constants.%J.lookup_impl_witness.0802bc.2
@@ -2089,7 +2128,7 @@ fn F() {
 // CHECK:STDOUT:   %impl.elem1.loc9_11.2: @GenericCallInterfaceQualified.%.loc9_11 (%.9ef) = impl_witness_access %J.lookup_impl_witness, element1 [symbolic = %impl.elem1.loc9_11.2 (constants.%impl.elem1)]
 // CHECK:STDOUT:   %specific_impl_fn.loc9_11.2: <specific function> = specific_impl_function %impl.elem1.loc9_11.2, @J.G(%J.facet) [symbolic = %specific_impl_fn.loc9_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%t.param: @GenericCallInterfaceQualified.%T.as_type.loc8_44.1 (%T.as_type), %u.param: @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2)) -> @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) {
+// CHECK:STDOUT:   fn(%t.param: @GenericCallInterfaceQualified.%T.as_type.loc8_44.1 (%T.as_type), %u.param: @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2)) -> %return.param: @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %t.ref: @GenericCallInterfaceQualified.%T.as_type.loc8_44.1 (%T.as_type) = name_ref t, %t
 // CHECK:STDOUT:     %J.ref.loc9: type = name_ref J, file.%J.decl [concrete = constants.%J.type]
@@ -2099,7 +2138,8 @@ fn F() {
 // CHECK:STDOUT:     %u.ref: @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) = name_ref u, %u
 // CHECK:STDOUT:     %specific_impl_fn.loc9_11.1: <specific function> = specific_impl_function %impl.elem1.loc9_11.1, @J.G(constants.%J.facet.c211a5.2) [symbolic = %specific_impl_fn.loc9_11.2 (constants.%specific_impl_fn)]
 // CHECK:STDOUT:     %bound_method.loc9_19: <bound method> = bound_method %t.ref, %specific_impl_fn.loc9_11.1
-// CHECK:STDOUT:     %.loc9_19: init @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) = call %bound_method.loc9_19(%t.ref, %u.ref)
+// CHECK:STDOUT:     %.loc8_55: ref @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) = splice_block %return {}
+// CHECK:STDOUT:     %.loc9_19: init @GenericCallInterfaceQualified.%impl.elem0.loc8_51.1 (%impl.elem0.312582.2) = call %bound_method.loc9_19(%t.ref, %u.ref) to %.loc8_55
 // CHECK:STDOUT:     return %.loc9_19 to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 1 - 1
toolchain/check/testdata/interface/member_lookup.carbon

@@ -477,7 +477,7 @@ fn AccessMissingConcrete(I:! Interface(i32)) -> i32 {
 // CHECK:STDOUT:   %require_complete.loc8: <witness> = require_complete_type %T.loc8_25.1 [symbolic = %require_complete.loc8 (constants.%require_complete.4ae)]
 // CHECK:STDOUT:   %require_complete.loc13: <witness> = require_complete_type %Interface.type.loc8_50.1 [symbolic = %require_complete.loc13 (constants.%require_complete.a60)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @AccessMissingGeneric.%T.loc8_25.1 (%T) {
+// CHECK:STDOUT:   fn() -> %return.param: @AccessMissingGeneric.%T.loc8_25.1 (%T) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %I.ref: @AccessMissingGeneric.%Interface.type.loc8_50.1 (%Interface.type.cc2) = name_ref I, %I.loc8_35.2 [symbolic = %I.loc8_35.1 (constants.%I.01f)]
 // CHECK:STDOUT:     %nonesuch.ref: <error> = name_ref nonesuch, <error> [concrete = <error>]

+ 7 - 21
toolchain/check/testdata/interop/cpp/enum/copy.carbon

@@ -67,10 +67,8 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc8_21: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Enum.ref.loc8_24: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
 // CHECK:STDOUT:   %a.ref.loc8: %Enum = name_ref a, imports.%int_0 [concrete = constants.%int_0]
-// CHECK:STDOUT:   %.loc8_29.1: ref %Enum = temporary_storage
-// CHECK:STDOUT:   %.loc8_29.2: ref %Enum = temporary %.loc8_29.1, %a.ref.loc8
-// CHECK:STDOUT:   assign %a.var, %.loc8_29.2
-// CHECK:STDOUT:   %.loc8_13: type = splice_block %Enum.ref.loc8_13 [concrete = constants.%Enum] {
+// CHECK:STDOUT:   assign %a.var, %a.ref.loc8
+// CHECK:STDOUT:   %.loc8: type = splice_block %Enum.ref.loc8_13 [concrete = constants.%Enum] {
 // CHECK:STDOUT:     %Cpp.ref.loc8_10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:     %Enum.ref.loc8_13: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
 // CHECK:STDOUT:   }
@@ -79,24 +77,12 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Enum.ref.loc10: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum]
 // CHECK:STDOUT:   %b.ref: %Enum = name_ref b, imports.%int_1 [concrete = constants.%int_1]
-// CHECK:STDOUT:   %.loc10_15.1: ref %Enum = temporary_storage
-// CHECK:STDOUT:   %.loc10_15.2: ref %Enum = temporary %.loc10_15.1, %b.ref
-// CHECK:STDOUT:   assign %a.ref.loc10, %.loc10_15.2
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound.loc10: <bound method> = bound_method %.loc10_15.2, constants.%T.as.Destroy.impl.Op.cd4
+// CHECK:STDOUT:   assign %a.ref.loc10, %b.ref
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%T.as.Destroy.impl.Op.cd4
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %bound_method.loc10: <bound method> = bound_method %.loc10_15.2, %T.as.Destroy.impl.Op.specific_fn.1
-// CHECK:STDOUT:   %addr.loc10: %ptr.47b = addr_of %.loc10_15.2
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call.loc10: init %empty_tuple.type = call %bound_method.loc10(%addr.loc10)
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound.loc8_29: <bound method> = bound_method %.loc8_29.2, constants.%T.as.Destroy.impl.Op.cd4
-// CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %bound_method.loc8_29: <bound method> = bound_method %.loc8_29.2, %T.as.Destroy.impl.Op.specific_fn.2
-// CHECK:STDOUT:   %addr.loc8_29: %ptr.47b = addr_of %.loc8_29.2
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call.loc8_29: init %empty_tuple.type = call %bound_method.loc8_29(%addr.loc8_29)
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound.loc8_3: <bound method> = bound_method %a.var, constants.%T.as.Destroy.impl.Op.cd4
-// CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %bound_method.loc8_3: <bound method> = bound_method %a.var, %T.as.Destroy.impl.Op.specific_fn.3
-// CHECK:STDOUT:   %addr.loc8_3: %ptr.47b = addr_of %a.var
-// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call.loc8_3: init %empty_tuple.type = call %bound_method.loc8_3(%addr.loc8_3)
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.var, %T.as.Destroy.impl.Op.specific_fn
+// CHECK:STDOUT:   %addr: %ptr.47b = addr_of %a.var
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 16 - 16
toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon

@@ -732,10 +732,10 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]
+// CHECK:STDOUT:   %.loc8_11.1: ref bool = temporary_storage
 // CHECK:STDOUT:   %impl.elem0: %.05c = impl_witness_access constants.%Copy.impl_witness.a56, element0 [concrete = constants.%bool.as.Copy.impl.Op]
 // CHECK:STDOUT:   %bound_method.loc8_11.1: <bound method> = bound_method %true, %impl.elem0 [concrete = constants.%bool.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %bool.as.Copy.impl.Op.call: init bool = call %bound_method.loc8_11.1(%true) [concrete = constants.%true]
-// CHECK:STDOUT:   %.loc8_11.1: ref bool = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.2: ref bool = temporary %.loc8_11.1, %bool.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_15: %ptr.bb2 = addr_of %.loc8_11.2
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_15)
@@ -789,10 +789,10 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]
+// CHECK:STDOUT:   %.loc8_11.1: ref bool = temporary_storage
 // CHECK:STDOUT:   %impl.elem0: %.05c = impl_witness_access constants.%Copy.impl_witness.a56, element0 [concrete = constants.%bool.as.Copy.impl.Op]
 // CHECK:STDOUT:   %bound_method.loc8_11.1: <bound method> = bound_method %false, %impl.elem0 [concrete = constants.%bool.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %bool.as.Copy.impl.Op.call: init bool = call %bound_method.loc8_11.1(%false) [concrete = constants.%false]
-// CHECK:STDOUT:   %.loc8_11.1: ref bool = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.2: ref bool = temporary %.loc8_11.1, %bool.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_16: %ptr.bb2 = addr_of %.loc8_11.2
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_16)
@@ -893,12 +893,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i8 = call %bound_method.loc8_11.3(%.loc8_11.2) [concrete = constants.%int_-1.416]
 // CHECK:STDOUT:   %.loc8_11.3: %i8 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_-1.416]
 // CHECK:STDOUT:   %.loc8_11.4: %i8 = converted %Core.IntLiteral.as.Negate.impl.Op.call, %.loc8_11.3 [concrete = constants.%int_-1.416]
+// CHECK:STDOUT:   %.loc8_11.5: ref %i8 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_11.2: %.216 = impl_witness_access constants.%Copy.impl_witness.f5f, element0 [concrete = constants.%Int.as.Copy.impl.Op.342]
 // CHECK:STDOUT:   %bound_method.loc8_11.4: <bound method> = bound_method %.loc8_11.4, %impl.elem0.loc8_11.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_11.2: <specific function> = specific_function %impl.elem0.loc8_11.2, @Int.as.Copy.impl.Op(constants.%int_8) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_11.5: <bound method> = bound_method %.loc8_11.4, %specific_fn.loc8_11.2 [concrete = constants.%bound_method.db2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i8 = call %bound_method.loc8_11.5(%.loc8_11.4) [concrete = constants.%int_-1.416]
-// CHECK:STDOUT:   %.loc8_11.5: ref %i8 = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.6: ref %i8 = temporary %.loc8_11.5, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_13: %ptr.5c1 = addr_of %.loc8_11.6
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_13)
@@ -982,12 +982,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %u8 = call %bound_method.loc8_11.2(%int_1) [concrete = constants.%int_1.e80]
 // CHECK:STDOUT:   %.loc8_11.1: %u8 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.e80]
 // CHECK:STDOUT:   %.loc8_11.2: %u8 = converted %int_1, %.loc8_11.1 [concrete = constants.%int_1.e80]
+// CHECK:STDOUT:   %.loc8_11.3: ref %u8 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_11.2: %.c54 = impl_witness_access constants.%Copy.impl_witness.3d6, element0 [concrete = constants.%UInt.as.Copy.impl.Op.0cf]
 // CHECK:STDOUT:   %bound_method.loc8_11.3: <bound method> = bound_method %.loc8_11.2, %impl.elem0.loc8_11.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_11.2: <specific function> = specific_function %impl.elem0.loc8_11.2, @UInt.as.Copy.impl.Op(constants.%int_8) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_11.4: <bound method> = bound_method %.loc8_11.2, %specific_fn.loc8_11.2 [concrete = constants.%bound_method.501]
 // CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call: init %u8 = call %bound_method.loc8_11.4(%.loc8_11.2) [concrete = constants.%int_1.e80]
-// CHECK:STDOUT:   %.loc8_11.3: ref %u8 = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.4: ref %u8 = temporary %.loc8_11.3, %UInt.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_12: %ptr.3e8 = addr_of %.loc8_11.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_12)
@@ -1058,10 +1058,10 @@ fn F() {
 // CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.call: init %Char = call %bound_method.loc8_11.1(%.loc8_11.1) [concrete = constants.%int_88]
 // CHECK:STDOUT:   %.loc8_11.2: %Char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_88]
 // CHECK:STDOUT:   %.loc8_11.3: %Char = converted %.loc8_11.1, %.loc8_11.2 [concrete = constants.%int_88]
+// CHECK:STDOUT:   %.loc8_11.4: ref %Char = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_11.2: %.1ed = impl_witness_access constants.%Copy.impl_witness.9ba, element0 [concrete = constants.%Char.as.Copy.impl.Op]
 // CHECK:STDOUT:   %bound_method.loc8_11.2: <bound method> = bound_method %.loc8_11.3, %impl.elem0.loc8_11.2 [concrete = constants.%Char.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %Char.as.Copy.impl.Op.call: init %Char = call %bound_method.loc8_11.2(%.loc8_11.3) [concrete = constants.%int_88]
-// CHECK:STDOUT:   %.loc8_11.4: ref %Char = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.5: ref %Char = temporary %.loc8_11.4, %Char.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_14: %ptr.fb0 = addr_of %.loc8_11.5
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_14)
@@ -1276,12 +1276,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)
@@ -1365,12 +1365,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i16 = call %bound_method.loc8_11.2(%int_32767) [concrete = constants.%int_32767.faa]
 // CHECK:STDOUT:   %.loc8_11.1: %i16 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_32767.faa]
 // CHECK:STDOUT:   %.loc8_11.2: %i16 = converted %int_32767, %.loc8_11.1 [concrete = constants.%int_32767.faa]
+// CHECK:STDOUT:   %.loc8_11.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_11.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_11.3: <bound method> = bound_method %.loc8_11.2, %impl.elem0.loc8_11.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_11.2: <specific function> = specific_function %impl.elem0.loc8_11.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_11.4: <bound method> = bound_method %.loc8_11.2, %specific_fn.loc8_11.2 [concrete = constants.%bound_method.556]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_11.4(%.loc8_11.2) [concrete = constants.%int_32767.faa]
-// CHECK:STDOUT:   %.loc8_11.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.4: ref %i16 = temporary %.loc8_11.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_17: %ptr.251 = addr_of %.loc8_11.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_17)
@@ -1471,12 +1471,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i16 = call %bound_method.loc8_11.3(%.loc8_11.2) [concrete = constants.%int_-32768.7e5]
 // CHECK:STDOUT:   %.loc8_11.3: %i16 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_-32768.7e5]
 // CHECK:STDOUT:   %.loc8_11.4: %i16 = converted %Core.IntLiteral.as.Negate.impl.Op.call, %.loc8_11.3 [concrete = constants.%int_-32768.7e5]
+// CHECK:STDOUT:   %.loc8_11.5: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_11.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_11.4: <bound method> = bound_method %.loc8_11.4, %impl.elem0.loc8_11.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_11.2: <specific function> = specific_function %impl.elem0.loc8_11.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_11.5: <bound method> = bound_method %.loc8_11.4, %specific_fn.loc8_11.2 [concrete = constants.%bound_method.b72]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_11.5(%.loc8_11.4) [concrete = constants.%int_-32768.7e5]
-// CHECK:STDOUT:   %.loc8_11.5: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_11.6: ref %i16 = temporary %.loc8_11.5, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_18: %ptr.251 = addr_of %.loc8_11.6
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_18)
@@ -1562,12 +1562,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)
@@ -1653,12 +1653,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)
@@ -1744,12 +1744,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)
@@ -1835,12 +1835,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)
@@ -2134,12 +2134,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.call: init %f16.a6a = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.032]
 // CHECK:STDOUT:   %.loc8_15.1: %f16.a6a = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.032]
 // CHECK:STDOUT:   %.loc8_15.2: %f16.a6a = converted %float, %.loc8_15.1 [concrete = constants.%float.032]
+// CHECK:STDOUT:   %.loc8_15.3: ref %f16.a6a = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_15.2: %.98a = impl_witness_access constants.%Copy.impl_witness.3e9, element0 [concrete = constants.%Float.as.Copy.impl.Op.9e9]
 // CHECK:STDOUT:   %bound_method.loc8_15.3: <bound method> = bound_method %.loc8_15.2, %impl.elem0.loc8_15.2 [concrete = constants.%Float.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_15.2: <specific function> = specific_function %impl.elem0.loc8_15.2, @Float.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Float.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_15.4: <bound method> = bound_method %.loc8_15.2, %specific_fn.loc8_15.2 [concrete = constants.%bound_method.086]
 // CHECK:STDOUT:   %Float.as.Copy.impl.Op.call: init %f16.a6a = call %bound_method.loc8_15.4(%.loc8_15.2) [concrete = constants.%float.032]
-// CHECK:STDOUT:   %.loc8_15.3: ref %f16.a6a = temporary_storage
 // CHECK:STDOUT:   %.loc8_15.4: ref %f16.a6a = temporary %.loc8_15.3, %Float.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_21: %ptr.823 = addr_of %.loc8_15.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
@@ -2224,12 +2224,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.call: init %f32.97e = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.4cb]
 // CHECK:STDOUT:   %.loc8_15.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.4cb]
 // CHECK:STDOUT:   %.loc8_15.2: %f32.97e = converted %float, %.loc8_15.1 [concrete = constants.%float.4cb]
+// CHECK:STDOUT:   %.loc8_15.3: ref %f32.97e = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_15.2: %.377 = impl_witness_access constants.%Copy.impl_witness.c6d, element0 [concrete = constants.%Float.as.Copy.impl.Op.4fd]
 // CHECK:STDOUT:   %bound_method.loc8_15.3: <bound method> = bound_method %.loc8_15.2, %impl.elem0.loc8_15.2 [concrete = constants.%Float.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_15.2: <specific function> = specific_function %impl.elem0.loc8_15.2, @Float.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Float.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_15.4: <bound method> = bound_method %.loc8_15.2, %specific_fn.loc8_15.2 [concrete = constants.%bound_method.21c]
 // CHECK:STDOUT:   %Float.as.Copy.impl.Op.call: init %f32.97e = call %bound_method.loc8_15.4(%.loc8_15.2) [concrete = constants.%float.4cb]
-// CHECK:STDOUT:   %.loc8_15.3: ref %f32.97e = temporary_storage
 // CHECK:STDOUT:   %.loc8_15.4: ref %f32.97e = temporary %.loc8_15.3, %Float.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_21: %ptr.0bc = addr_of %.loc8_15.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
@@ -2314,12 +2314,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.call: init %f64.d77 = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.0fc]
 // CHECK:STDOUT:   %.loc8_15.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.0fc]
 // CHECK:STDOUT:   %.loc8_15.2: %f64.d77 = converted %float, %.loc8_15.1 [concrete = constants.%float.0fc]
+// CHECK:STDOUT:   %.loc8_15.3: ref %f64.d77 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_15.2: %.5d7 = impl_witness_access constants.%Copy.impl_witness.911, element0 [concrete = constants.%Float.as.Copy.impl.Op.5b0]
 // CHECK:STDOUT:   %bound_method.loc8_15.3: <bound method> = bound_method %.loc8_15.2, %impl.elem0.loc8_15.2 [concrete = constants.%Float.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_15.2: <specific function> = specific_function %impl.elem0.loc8_15.2, @Float.as.Copy.impl.Op(constants.%int_64) [concrete = constants.%Float.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_15.4: <bound method> = bound_method %.loc8_15.2, %specific_fn.loc8_15.2 [concrete = constants.%bound_method.c97]
 // CHECK:STDOUT:   %Float.as.Copy.impl.Op.call: init %f64.d77 = call %bound_method.loc8_15.4(%.loc8_15.2) [concrete = constants.%float.0fc]
-// CHECK:STDOUT:   %.loc8_15.3: ref %f64.d77 = temporary_storage
 // CHECK:STDOUT:   %.loc8_15.4: ref %f64.d77 = temporary %.loc8_15.3, %Float.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_21: %ptr.bcc = addr_of %.loc8_15.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
@@ -2404,12 +2404,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.call: init %f128.b8c = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.709]
 // CHECK:STDOUT:   %.loc8_15.1: %f128.b8c = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.709]
 // CHECK:STDOUT:   %.loc8_15.2: %f128.b8c = converted %float, %.loc8_15.1 [concrete = constants.%float.709]
+// CHECK:STDOUT:   %.loc8_15.3: ref %f128.b8c = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_15.2: %.421 = impl_witness_access constants.%Copy.impl_witness.1fe, element0 [concrete = constants.%Float.as.Copy.impl.Op.249]
 // CHECK:STDOUT:   %bound_method.loc8_15.3: <bound method> = bound_method %.loc8_15.2, %impl.elem0.loc8_15.2 [concrete = constants.%Float.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_15.2: <specific function> = specific_function %impl.elem0.loc8_15.2, @Float.as.Copy.impl.Op(constants.%int_128) [concrete = constants.%Float.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_15.4: <bound method> = bound_method %.loc8_15.2, %specific_fn.loc8_15.2 [concrete = constants.%bound_method.435]
 // CHECK:STDOUT:   %Float.as.Copy.impl.Op.call: init %f128.b8c = call %bound_method.loc8_15.4(%.loc8_15.2) [concrete = constants.%float.709]
-// CHECK:STDOUT:   %.loc8_15.3: ref %f128.b8c = temporary_storage
 // CHECK:STDOUT:   %.loc8_15.4: ref %f128.b8c = temporary %.loc8_15.3, %Float.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_22: %ptr.402 = addr_of %.loc8_15.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_22)

+ 1 - 1
toolchain/check/testdata/interop/cpp/function/full_semir.carbon

@@ -179,12 +179,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc7_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc7_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc7_13.2: %i16 = converted %int_1, %.loc7_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc7_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc7_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc7_13.3: <bound method> = bound_method %.loc7_13.2, %impl.elem0.loc7_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc7_13.2: <specific function> = specific_function %impl.elem0.loc7_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc7_13.4: <bound method> = bound_method %.loc7_13.2, %specific_fn.loc7_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc7_13.4(%.loc7_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc7_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc7_13.4: ref %i16 = temporary %.loc7_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc7_19: %ptr.251 = addr_of %.loc7_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc7_19)

+ 2 - 2
toolchain/check/testdata/interop/cpp/function/inline.carbon

@@ -279,12 +279,12 @@ fn MyF() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14: init %i16 = call %bound_method.loc14_32.2(%int_1.loc14) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc14_32.1: %i16 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14 [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc14_32.2: %i16 = converted %int_1.loc14, %.loc14_32.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc14_32.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc14_32.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc14_32.3: <bound method> = bound_method %.loc14_32.2, %impl.elem0.loc14_32.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc14_32.2: <specific function> = specific_function %impl.elem0.loc14_32.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc14_32.4: <bound method> = bound_method %.loc14_32.2, %specific_fn.loc14_32.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc14: init %i16 = call %bound_method.loc14_32.4(%.loc14_32.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc14_32.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc14_32.4: ref %i16 = temporary %.loc14_32.3, %Int.as.Copy.impl.Op.call.loc14
 // CHECK:STDOUT:   %addr.loc14_33: %ptr.251 = addr_of %.loc14_32.4
 // CHECK:STDOUT:   %ThunkOnArg__carbon_thunk.call: init %i32 = call imports.%ThunkOnArg__carbon_thunk.decl(%addr.loc14_33)
@@ -332,12 +332,12 @@ fn MyF() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16: init %i16 = call %bound_method.loc16_33.2(%int_1.loc16) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc16_33.1: %i16 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16 [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc16_33.2: %i16 = converted %int_1.loc16, %.loc16_33.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc16_33.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc16_33.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc16_33.3: <bound method> = bound_method %.loc16_33.2, %impl.elem0.loc16_33.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc16_33.2: <specific function> = specific_function %impl.elem0.loc16_33.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc16_33.4: <bound method> = bound_method %.loc16_33.2, %specific_fn.loc16_33.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc16: init %i16 = call %bound_method.loc16_33.4(%.loc16_33.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc16_33.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc16_33.4: ref %i16 = temporary %.loc16_33.3, %Int.as.Copy.impl.Op.call.loc16
 // CHECK:STDOUT:   %addr.loc16_34.1: %ptr.251 = addr_of %.loc16_33.4
 // CHECK:STDOUT:   %.loc16_34.1: ref %i16 = temporary_storage

+ 2 - 2
toolchain/check/testdata/interop/cpp/function/overloads.carbon

@@ -480,12 +480,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc7_13.2(%int_1) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc7_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc7_13.2: %i16 = converted %int_1, %.loc7_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc7_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc7_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc7_13.3: <bound method> = bound_method %.loc7_13.2, %impl.elem0.loc7_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc7_13.2: <specific function> = specific_function %impl.elem0.loc7_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc7_13.4: <bound method> = bound_method %.loc7_13.2, %specific_fn.loc7_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc7_13.4(%.loc7_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc7_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc7_13.4: ref %i16 = temporary %.loc7_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc7_19: %ptr.251 = addr_of %.loc7_13.4
 // CHECK:STDOUT:   %bar__carbon_thunk.call: init %empty_tuple.type = call imports.%bar__carbon_thunk.decl(%addr.loc7_19)
@@ -751,12 +751,12 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call.loc8: init %i16 = call %bound_method.loc8_13.2(%int_1.loc8) [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call.loc8 [concrete = constants.%int_1.f90]
 // CHECK:STDOUT:   %.loc8_13.2: %i16 = converted %int_1.loc8, %.loc8_13.1 [concrete = constants.%int_1.f90]
+// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %impl.elem0.loc8_13.2: %.798 = impl_witness_access constants.%Copy.impl_witness.2f8, element0 [concrete = constants.%Int.as.Copy.impl.Op.3dc]
 // CHECK:STDOUT:   %bound_method.loc8_13.3: <bound method> = bound_method %.loc8_13.2, %impl.elem0.loc8_13.2 [concrete = constants.%Int.as.Copy.impl.Op.bound]
 // CHECK:STDOUT:   %specific_fn.loc8_13.2: <specific function> = specific_function %impl.elem0.loc8_13.2, @Int.as.Copy.impl.Op(constants.%int_16) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc8_13.4: <bound method> = bound_method %.loc8_13.2, %specific_fn.loc8_13.2 [concrete = constants.%bound_method.7c2]
 // CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i16 = call %bound_method.loc8_13.4(%.loc8_13.2) [concrete = constants.%int_1.f90]
-// CHECK:STDOUT:   %.loc8_13.3: ref %i16 = temporary_storage
 // CHECK:STDOUT:   %.loc8_13.4: ref %i16 = temporary %.loc8_13.3, %Int.as.Copy.impl.Op.call
 // CHECK:STDOUT:   %addr.loc8_19: %ptr.251 = addr_of %.loc8_13.4
 // CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_19)

+ 3 - 2
toolchain/check/testdata/operators/overloaded/implicit_as.carbon

@@ -307,12 +307,13 @@ fn Test() {
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc31_11.1 [symbolic = %require_complete (constants.%require_complete.4ae)]
 // CHECK:STDOUT:   %Source.specific_fn.loc31_35.2: <specific function> = specific_function constants.%Source, @Source(%T.loc31_11.1) [symbolic = %Source.specific_fn.loc31_35.2 (constants.%Source.specific_fn.ff0)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn() -> @Source.%T.loc31_11.1 (%T.8b3) {
+// CHECK:STDOUT:   fn() -> %return.param: @Source.%T.loc31_11.1 (%T.8b3) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %Source.ref: %Source.type = name_ref Source, file.%Source.decl [concrete = constants.%Source]
 // CHECK:STDOUT:     %T.ref.loc31_42: type = name_ref T, %T.loc31_11.2 [symbolic = %T.loc31_11.1 (constants.%T.8b3)]
 // CHECK:STDOUT:     %Source.specific_fn.loc31_35.1: <specific function> = specific_function %Source.ref, @Source(constants.%T.8b3) [symbolic = %Source.specific_fn.loc31_35.2 (constants.%Source.specific_fn.ff0)]
-// CHECK:STDOUT:     %Source.call: init @Source.%T.loc31_11.1 (%T.8b3) = call %Source.specific_fn.loc31_35.1()
+// CHECK:STDOUT:     %.loc31: ref @Source.%T.loc31_11.1 (%T.8b3) = splice_block %return {}
+// CHECK:STDOUT:     %Source.call: init @Source.%T.loc31_11.1 (%T.8b3) = call %Source.specific_fn.loc31_35.1() to %.loc31
 // CHECK:STDOUT:     return %Source.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 9 - 2
toolchain/check/type_completion.cpp

@@ -66,6 +66,9 @@ class TypeCompleter {
   // state, such as empty structs and tuples.
   auto MakeEmptyValueRepr() const -> SemIR::ValueRepr;
 
+  // Makes a dependent value representation, which is used for symbolic types.
+  auto MakeDependentValueRepr(SemIR::TypeId type_id) const -> SemIR::ValueRepr;
+
   // Makes a value representation that uses pass-by-copy, copying the given
   // type.
   auto MakeCopyValueRepr(SemIR::TypeId rep_id,
@@ -165,8 +168,7 @@ class TypeCompleter {
     requires(InstT::Kind.is_symbolic_when_type())
   auto BuildInfoForInst(SemIR::TypeId type_id, InstT /*inst*/) const
       -> SemIR::CompleteTypeInfo {
-    // For symbolic types, we arbitrarily pick a copy representation.
-    return {.value_repr = MakeCopyValueRepr(type_id)};
+    return {.value_repr = MakeDependentValueRepr(type_id)};
   }
 
   // Builds and returns the `CompleteTypeInfo` for the given type. All nested
@@ -363,6 +365,11 @@ auto TypeCompleter::MakeEmptyValueRepr() const -> SemIR::ValueRepr {
           .type_id = GetTupleType(*context_, {})};
 }
 
+auto TypeCompleter::MakeDependentValueRepr(SemIR::TypeId type_id) const
+    -> SemIR::ValueRepr {
+  return {.kind = SemIR::ValueRepr::Dependent, .type_id = type_id};
+}
+
 auto TypeCompleter::MakeCopyValueRepr(
     SemIR::TypeId rep_id, SemIR::ValueRepr::AggregateKind aggregate_kind) const
     -> SemIR::ValueRepr {

+ 14 - 8
toolchain/lower/file_context.cpp

@@ -357,6 +357,8 @@ auto FileContext::BuildFunctionTypeInfo(const SemIR::Function& function,
         return {.type = llvm::FunctionType::get(
                     llvm::Type::getVoidTy(llvm_context()),
                     /*isVarArg=*/false)};
+      case SemIR::ValueRepr::Dependent:
+        CARBON_FATAL("Lowering function with dependent parameter type");
       case SemIR::ValueRepr::None:
         break;
       case SemIR::ValueRepr::Copy:
@@ -630,10 +632,9 @@ auto FileContext::BuildFunctionBody(SemIR::FunctionId function_id,
     function_lowering.SetLocal(param_id, param_value);
   };
 
-  // The subset of call_param_ids that is already in the order that the LLVM
-  // calling convention expects.
-  llvm::ArrayRef<SemIR::InstId> sequential_param_ids;
+  // Lower the return slot parameter.
   if (declaration_function.return_slot_pattern_id.has_value()) {
+    auto call_param_id = call_param_ids.consume_back();
     // The LLVM calling convention has the return slot first rather than last.
     // Note that this queries whether there is a return slot at the LLVM level,
     // whereas `function.return_slot_pattern_id.has_value()` queries whether
@@ -641,14 +642,19 @@ auto FileContext::BuildFunctionBody(SemIR::FunctionId function_id,
     if (SemIR::ReturnTypeInfo::ForFunction(sem_ir(), declaration_function,
                                            specific_id)
             .has_return_slot()) {
-      lower_param(call_param_ids.back());
+      lower_param(call_param_id);
+    } else {
+      // The return slot might still be mentioned as a destination location, but
+      // shouldn't actually be used for anything, so we can use a poison value
+      // for it.
+      function_lowering.SetLocal(call_param_id,
+                                 llvm::PoisonValue::get(llvm::PointerType::get(
+                                     llvm_context(), /*AddressSpace=*/0)));
     }
-    sequential_param_ids = call_param_ids.drop_back();
-  } else {
-    sequential_param_ids = call_param_ids;
   }
 
-  for (auto param_id : sequential_param_ids) {
+  // Lower the remaining call parameters.
+  for (auto param_id : call_param_ids) {
     lower_param(param_id);
   }
 

+ 5 - 0
toolchain/lower/function_context.cpp

@@ -285,6 +285,9 @@ auto FunctionContext::FinishInit(TypeInFile type, SemIR::InstId dest_id,
     case SemIR::InitRepr::Incomplete:
       CARBON_FATAL("Lowering aggregate initialization of incomplete type {0}",
                    type.file->types().GetAsInst(type.type_id));
+    case SemIR::InitRepr::Dependent:
+      CARBON_FATAL("Lowering aggregate initialization of dependent type {0}",
+                   type.file->types().GetAsInst(type.type_id));
   }
 }
 
@@ -368,6 +371,8 @@ auto FunctionContext::CopyValue(TypeInFile type, SemIR::InstId source_id,
   switch (GetValueRepr(type).repr.kind) {
     case SemIR::ValueRepr::Unknown:
       CARBON_FATAL("Attempt to copy incomplete type");
+    case SemIR::ValueRepr::Dependent:
+      CARBON_FATAL("Attempt to copy dependent type");
     case SemIR::ValueRepr::None:
       break;
     case SemIR::ValueRepr::Copy:

+ 4 - 4
toolchain/lower/handle.cpp

@@ -232,10 +232,7 @@ auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
 
 auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
                 SemIR::ReturnSlot inst) -> void {
-  if (context.GetInitRepr(context.GetTypeIdOfInst(inst_id)).kind ==
-      SemIR::InitRepr::InPlace) {
-    context.SetLocal(inst_id, context.GetValue(inst.storage_id));
-  }
+  context.SetLocal(inst_id, context.GetValue(inst.storage_id));
 }
 
 auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/,
@@ -262,6 +259,9 @@ auto HandleInst(FunctionContext& context, SemIR::InstId /*inst_id*/,
     case SemIR::InitRepr::Incomplete:
       CARBON_FATAL("Lowering return of incomplete type {0}",
                    result_type.file->types().GetAsInst(result_type.type_id));
+    case SemIR::InitRepr::Dependent:
+      CARBON_FATAL("Lowering return of dependent type {0}",
+                   result_type.file->types().GetAsInst(result_type.type_id));
   }
 }
 

+ 10 - 1
toolchain/lower/handle_aggregates.cpp

@@ -79,6 +79,8 @@ static auto GetAggregateElement(FunctionContext& context,
       switch (value_repr.repr.kind) {
         case SemIR::ValueRepr::Unknown:
           CARBON_FATAL("Lowering access to incomplete aggregate type");
+        case SemIR::ValueRepr::Dependent:
+          CARBON_FATAL("Lowering access to dependent aggregate type");
         case SemIR::ValueRepr::None:
           return aggr_value;
         case SemIR::ValueRepr::Copy:
@@ -207,6 +209,10 @@ static auto EmitAggregateInitializer(FunctionContext& context,
     case SemIR::InitRepr::Incomplete:
       CARBON_FATAL("Lowering aggregate initialization of incomplete type {0}",
                    type.file->types().GetAsInst(type.type_id));
+
+    case SemIR::InitRepr::Dependent:
+      CARBON_FATAL("Lowering aggregate initialization of dependent type {0}",
+                   type.file->types().GetAsInst(type.type_id));
   }
 }
 
@@ -241,7 +247,10 @@ static auto EmitAggregateValueRepr(FunctionContext& context,
   auto value_type = value_repr.type();
   switch (value_repr.repr.kind) {
     case SemIR::ValueRepr::Unknown:
-      CARBON_FATAL("Incomplete aggregate type in lowering");
+      CARBON_FATAL("Lowering value of incomplete aggregate type");
+
+    case SemIR::ValueRepr::Dependent:
+      CARBON_FATAL("Lowering value of dependent aggregate type");
 
     case SemIR::ValueRepr::None:
       // TODO: Add a helper to get a "no value representation" value.

+ 8 - 0
toolchain/lower/handle_call.cpp

@@ -522,8 +522,16 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
   std::vector<llvm::Value*> args;
 
   auto inst_type = context.GetTypeIdOfInst(inst_id);
+  bool call_has_return_slot =
+      SemIR::ReturnTypeInfo::ForType(context.sem_ir(), inst.type_id)
+          .has_return_slot();
   if (context.GetReturnTypeInfo(inst_type).info.has_return_slot()) {
+    CARBON_CHECK(call_has_return_slot);
     args.push_back(context.GetValue(arg_ids.consume_back()));
+  } else if (call_has_return_slot) {
+    // Call instruction has a return slot but this specific callee does not.
+    // Just ignore it.
+    arg_ids.consume_back();
   }
 
   for (auto arg_id : arg_ids) {

+ 7 - 0
toolchain/lower/handle_expr_category.cpp

@@ -15,6 +15,9 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
     case SemIR::ValueRepr::Unknown:
       CARBON_FATAL(
           "Value binding for type with incomplete value representation");
+    case SemIR::ValueRepr::Dependent:
+      CARBON_FATAL(
+          "Value binding for type with dependent value representation");
     case SemIR::ValueRepr::None:
       // Nothing should use this value, but StubRef needs a value to
       // propagate.
@@ -51,6 +54,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
       switch (context.GetValueRepr(type).repr.kind) {
         case SemIR::ValueRepr::Unknown:
           CARBON_FATAL("Unexpected incomplete type");
+        case SemIR::ValueRepr::Dependent:
+          CARBON_FATAL("Unexpected dependent type");
         case SemIR::ValueRepr::None:
         case SemIR::ValueRepr::Pointer:
           break;
@@ -64,6 +69,8 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
       break;
     case SemIR::InitRepr::Incomplete:
       CARBON_FATAL("Unexpected incomplete type");
+    case SemIR::InitRepr::Dependent:
+      CARBON_FATAL("Unexpected dependent type");
   }
 
   context.SetLocal(inst_id, value);

+ 27 - 29
toolchain/lower/testdata/array/field.carbon

@@ -13,8 +13,6 @@
 class A {
   var v: array(i32, 2);
 
-  // TODO: The LLVM IR we create for this crashes LLVM instruction selection.
-  // The gep indexes are completely bogus.
   fn Init() -> A { return {.v = (1, 2)}; }
 
   fn Access[self: Self]() -> i32 {
@@ -30,34 +28,34 @@ class A {
 // CHECK:STDOUT: ; ModuleID = 'field.carbon'
 // CHECK:STDOUT: source_filename = "field.carbon"
 // CHECK:STDOUT:
-// CHECK:STDOUT: @A.val.loc18_40 = internal constant { [2 x i32] } { [2 x i32] [i32 1, i32 2] }
+// CHECK:STDOUT: @A.val.loc16_40 = internal constant { [2 x i32] } { [2 x i32] [i32 1, i32 2] }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define void @_CInit.A.Main(ptr sret({ [2 x i32] }) %return) !dbg !4 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc18_39.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %return, i32 0, i32 0, !dbg !7
-// CHECK:STDOUT:   %.loc18_38.3.array.index = getelementptr inbounds [2 x i32], ptr %.loc18_39.2.v, i32 0, i64 0, !dbg !8
-// CHECK:STDOUT:   %.loc18_38.6.array.index = getelementptr inbounds [2 x i32], ptr %.loc18_39.2.v, i32 0, i64 1, !dbg !8
-// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %return, ptr align 4 @A.val.loc18_40, i64 8, i1 false), !dbg !9
+// CHECK:STDOUT:   %.loc16_39.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %return, i32 0, i32 0, !dbg !7
+// CHECK:STDOUT:   %.loc16_38.3.array.index = getelementptr inbounds [2 x i32], ptr %.loc16_39.2.v, i32 0, i64 0, !dbg !8
+// CHECK:STDOUT:   %.loc16_38.6.array.index = getelementptr inbounds [2 x i32], ptr %.loc16_39.2.v, i32 0, i64 1, !dbg !8
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %return, ptr align 4 @A.val.loc16_40, i64 8, i1 false), !dbg !9
 // CHECK:STDOUT:   ret void, !dbg !9
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define i32 @_CAccess.A.Main(ptr %self) !dbg !10 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc21_16.1.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !11
-// CHECK:STDOUT:   %.loc21_20.2.array.index = getelementptr inbounds [2 x i32], ptr %.loc21_16.1.v, i32 0, i32 0, !dbg !11
-// CHECK:STDOUT:   %.loc21_20.3 = load i32, ptr %.loc21_20.2.array.index, align 4, !dbg !11
-// CHECK:STDOUT:   ret i32 %.loc21_20.3, !dbg !12
+// CHECK:STDOUT:   %.loc19_16.1.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !11
+// CHECK:STDOUT:   %.loc19_20.2.array.index = getelementptr inbounds [2 x i32], ptr %.loc19_16.1.v, i32 0, i32 0, !dbg !11
+// CHECK:STDOUT:   %.loc19_20.3 = load i32, ptr %.loc19_20.2.array.index, align 4, !dbg !11
+// CHECK:STDOUT:   ret i32 %.loc19_20.3, !dbg !12
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define i32 @_CUse.A.Main(ptr %self) !dbg !13 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc25_9.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !14
-// CHECK:STDOUT:   %.loc25_14.array.index = getelementptr inbounds [2 x i32], ptr %.loc25_9.2.v, i32 0, i32 0, !dbg !14
-// CHECK:STDOUT:   store i32 1, ptr %.loc25_14.array.index, align 4, !dbg !14
-// CHECK:STDOUT:   %.loc26_16.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !15
-// CHECK:STDOUT:   %.loc26_21.1.array.index = getelementptr inbounds [2 x i32], ptr %.loc26_16.2.v, i32 0, i32 1, !dbg !15
-// CHECK:STDOUT:   %.loc26_21.2 = load i32, ptr %.loc26_21.1.array.index, align 4, !dbg !15
-// CHECK:STDOUT:   ret i32 %.loc26_21.2, !dbg !16
+// CHECK:STDOUT:   %.loc23_9.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !14
+// CHECK:STDOUT:   %.loc23_14.array.index = getelementptr inbounds [2 x i32], ptr %.loc23_9.2.v, i32 0, i32 0, !dbg !14
+// CHECK:STDOUT:   store i32 1, ptr %.loc23_14.array.index, align 4, !dbg !14
+// CHECK:STDOUT:   %.loc24_16.2.v = getelementptr inbounds nuw { [2 x i32] }, ptr %self, i32 0, i32 0, !dbg !15
+// CHECK:STDOUT:   %.loc24_21.1.array.index = getelementptr inbounds [2 x i32], ptr %.loc24_16.2.v, i32 0, i32 1, !dbg !15
+// CHECK:STDOUT:   %.loc24_21.2 = load i32, ptr %.loc24_21.1.array.index, align 4, !dbg !15
+// CHECK:STDOUT:   ret i32 %.loc24_21.2, !dbg !16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
@@ -72,16 +70,16 @@ class A {
 // CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
 // CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
 // CHECK:STDOUT: !3 = !DIFile(filename: "field.carbon", directory: "")
-// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Init", linkageName: "_CInit.A.Main", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Init", linkageName: "_CInit.A.Main", scope: null, file: !3, line: 16, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{}
-// CHECK:STDOUT: !7 = !DILocation(line: 18, column: 27, scope: !4)
-// CHECK:STDOUT: !8 = !DILocation(line: 18, column: 33, scope: !4)
-// CHECK:STDOUT: !9 = !DILocation(line: 18, column: 20, scope: !4)
-// CHECK:STDOUT: !10 = distinct !DISubprogram(name: "Access", linkageName: "_CAccess.A.Main", scope: null, file: !3, line: 20, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !11 = !DILocation(line: 21, column: 12, scope: !10)
-// CHECK:STDOUT: !12 = !DILocation(line: 21, column: 5, scope: !10)
-// CHECK:STDOUT: !13 = distinct !DISubprogram(name: "Use", linkageName: "_CUse.A.Main", scope: null, file: !3, line: 24, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !14 = !DILocation(line: 25, column: 5, scope: !13)
-// CHECK:STDOUT: !15 = !DILocation(line: 26, column: 12, scope: !13)
-// CHECK:STDOUT: !16 = !DILocation(line: 26, column: 5, scope: !13)
+// CHECK:STDOUT: !7 = !DILocation(line: 16, column: 27, scope: !4)
+// CHECK:STDOUT: !8 = !DILocation(line: 16, column: 33, scope: !4)
+// CHECK:STDOUT: !9 = !DILocation(line: 16, column: 20, scope: !4)
+// CHECK:STDOUT: !10 = distinct !DISubprogram(name: "Access", linkageName: "_CAccess.A.Main", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !11 = !DILocation(line: 19, column: 12, scope: !10)
+// CHECK:STDOUT: !12 = !DILocation(line: 19, column: 5, scope: !10)
+// CHECK:STDOUT: !13 = distinct !DISubprogram(name: "Use", linkageName: "_CUse.A.Main", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !14 = !DILocation(line: 23, column: 5, scope: !13)
+// CHECK:STDOUT: !15 = !DILocation(line: 24, column: 12, scope: !13)
+// CHECK:STDOUT: !16 = !DILocation(line: 24, column: 5, scope: !13)

+ 143 - 56
toolchain/lower/testdata/class/generic.carbon

@@ -62,15 +62,10 @@ fn Empty() -> A(()) {
   return Make((), ());
 }
 
-// TODO: Reintroduce this once it doesn't crash.
-// fn Tuples() -> A((i32, i32)) {
-//   let x: (i32, i32) = (1, 2);
-//   // TODO: This fails to initialize the `A` object's fields.
-//   // This happens because we generate SemIR assuming that the dependent
-//   // type will have a copy value representation, and will need changes
-//   // in SemIR for us to properly lower it.
-//   return Make(x, x);
-// }
+fn Tuples() -> A((i32, i32)) {
+  let x: (i32, i32) = (1, 2);
+  return Make(x, x);
+}
 
 // --- access.carbon
 
@@ -102,18 +97,10 @@ fn AccessEmpty() -> () {
   return c.GetT();
 }
 
-// TODO: Reintroduce this once it doesn't crash.
-// fn AccessTuple() -> (i32, i32, i32) {
-//   // CHECK:STDERR: access.carbon:[[@LINE+7]]:10: error: cannot convert type `(i32, i32, i32)` into type implementing `Core.Copy` [ConversionFailureTypeToFacet]
-//   // CHECK:STDERR:   var c: C((i32, i32, i32)) = {.v = true, .w = (1, 2, 3)};
-//   // CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~
-//   // CHECK:STDERR: access.carbon:[[@LINE-30]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]
-//   // CHECK:STDERR: class C(T:! Core.Copy) {
-//   // CHECK:STDERR:         ^
-//   // CHECK:STDERR:
-//   var c: C((i32, i32, i32)) = {.v = true, .w = (1, 2, 3)};
-//   return c.GetT();
-// }
+fn AccessTuple() -> (i32, i32, i32) {
+  var c: C((i32, i32, i32)) = {.v = true, .w = (1, 2, 3)};
+  return c.GetT();
+}
 
 // CHECK:STDOUT: ; ModuleID = 'classes.carbon'
 // CHECK:STDOUT: source_filename = "classes.carbon"
@@ -169,6 +156,8 @@ fn AccessEmpty() -> () {
 // CHECK:STDOUT: ; ModuleID = 'create_generic.carbon'
 // CHECK:STDOUT: source_filename = "create_generic.carbon"
 // CHECK:STDOUT:
+// CHECK:STDOUT: @tuple.loc22_28.6 = internal constant { i32, i32 } { i32 1, i32 2 }
+// CHECK:STDOUT:
 // CHECK:STDOUT: define void @_CInts.Main(ptr sret({ i32, i32 }) %return) !dbg !4 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   call void @_CMake.Main.de631560529e9861(ptr %return, i32 1, i32 2), !dbg !7
@@ -181,22 +170,52 @@ fn AccessEmpty() -> () {
 // CHECK:STDOUT:   ret void, !dbg !11
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CMake.Main.de631560529e9861(ptr sret({ i32, i32 }) %return, i32 %x, i32 %y) !dbg !12 {
+// CHECK:STDOUT: define void @_CTuples.Main(ptr sret({ { i32, i32 }, { i32, i32 } }) %return) !dbg !12 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc10_25.2.x = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !13
-// CHECK:STDOUT:   store i32 %x, ptr %.loc10_25.2.x, align 4, !dbg !13
-// CHECK:STDOUT:   %.loc10_25.4.y = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !13
-// CHECK:STDOUT:   store i32 %y, ptr %.loc10_25.4.y, align 4, !dbg !13
+// CHECK:STDOUT:   call void @_CMake.Main.d9506acff356e5d2(ptr %return, ptr @tuple.loc22_28.6, ptr @tuple.loc22_28.6), !dbg !13
 // CHECK:STDOUT:   ret void, !dbg !14
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CMake.Main.cf13cead63317d44(ptr sret({ {}, {} }) %return) !dbg !15 {
+// CHECK:STDOUT: define linkonce_odr void @_CMake.Main.de631560529e9861(ptr sret({ i32, i32 }) %return, i32 %x, i32 %y) !dbg !15 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc10_25.2.x = getelementptr inbounds nuw { {}, {} }, ptr %return, i32 0, i32 0, !dbg !16
-// CHECK:STDOUT:   %.loc10_25.4.y = getelementptr inbounds nuw { {}, {} }, ptr %return, i32 0, i32 1, !dbg !16
+// CHECK:STDOUT:   %.loc10_25.2.x = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !16
+// CHECK:STDOUT:   store i32 %x, ptr %.loc10_25.2.x, align 4, !dbg !16
+// CHECK:STDOUT:   %.loc10_25.4.y = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !16
+// CHECK:STDOUT:   store i32 %y, ptr %.loc10_25.4.y, align 4, !dbg !16
 // CHECK:STDOUT:   ret void, !dbg !17
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CMake.Main.cf13cead63317d44(ptr sret({ {}, {} }) %return) !dbg !18 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %.loc10_25.2.x = getelementptr inbounds nuw { {}, {} }, ptr %return, i32 0, i32 0, !dbg !19
+// CHECK:STDOUT:   %.loc10_25.4.y = getelementptr inbounds nuw { {}, {} }, ptr %return, i32 0, i32 1, !dbg !19
+// CHECK:STDOUT:   ret void, !dbg !20
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CMake.Main.d9506acff356e5d2(ptr sret({ { i32, i32 }, { i32, i32 } }) %return, ptr %x, ptr %y) !dbg !21 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %.loc10_25.2.x = getelementptr inbounds nuw { { i32, i32 }, { i32, i32 } }, ptr %return, i32 0, i32 0, !dbg !22
+// CHECK:STDOUT:   call void @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9"(ptr %.loc10_25.2.x, ptr %x), !dbg !23
+// CHECK:STDOUT:   %.loc10_25.4.y = getelementptr inbounds nuw { { i32, i32 }, { i32, i32 } }, ptr %return, i32 0, i32 1, !dbg !22
+// CHECK:STDOUT:   call void @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9"(ptr %.loc10_25.4.y, ptr %y), !dbg !24
+// CHECK:STDOUT:   ret void, !dbg !25
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9"(ptr sret({ i32, i32 }) %return, ptr %self) !dbg !26 {
+// CHECK:STDOUT:   %tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 0, !dbg !28
+// CHECK:STDOUT:   %tuple.elem.load = load i32, ptr %tuple.elem, align 4, !dbg !28
+// CHECK:STDOUT:   %tuple.elem1 = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !29
+// CHECK:STDOUT:   %tuple.elem2 = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 1, !dbg !30
+// CHECK:STDOUT:   %tuple.elem.load3 = load i32, ptr %tuple.elem2, align 4, !dbg !30
+// CHECK:STDOUT:   %tuple.elem4 = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !29
+// CHECK:STDOUT:   store i32 %tuple.elem.load, ptr %tuple.elem1, align 4, !dbg !29
+// CHECK:STDOUT:   store i32 %tuple.elem.load3, ptr %tuple.elem4, align 4, !dbg !29
+// CHECK:STDOUT:   ret void, !dbg !31
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: ; uselistorder directives
+// CHECK:STDOUT: uselistorder ptr @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9", { 1, 0 }
+// CHECK:STDOUT:
 // CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
 // CHECK:STDOUT: !llvm.dbg.cu = !{!2}
 // CHECK:STDOUT:
@@ -212,17 +231,32 @@ fn AccessEmpty() -> () {
 // CHECK:STDOUT: !9 = distinct !DISubprogram(name: "Empty", linkageName: "_CEmpty.Main", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !10 = !DILocation(line: 18, column: 10, scope: !9)
 // CHECK:STDOUT: !11 = !DILocation(line: 18, column: 3, scope: !9)
-// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "Make", linkageName: "_CMake.Main.de631560529e9861", scope: null, file: !3, line: 9, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !13 = !DILocation(line: 10, column: 10, scope: !12)
-// CHECK:STDOUT: !14 = !DILocation(line: 10, column: 3, scope: !12)
-// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "Make", linkageName: "_CMake.Main.cf13cead63317d44", scope: null, file: !3, line: 9, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "Tuples", linkageName: "_CTuples.Main", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !13 = !DILocation(line: 23, column: 10, scope: !12)
+// CHECK:STDOUT: !14 = !DILocation(line: 23, column: 3, scope: !12)
+// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "Make", linkageName: "_CMake.Main.de631560529e9861", scope: null, file: !3, line: 9, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !16 = !DILocation(line: 10, column: 10, scope: !15)
 // CHECK:STDOUT: !17 = !DILocation(line: 10, column: 3, scope: !15)
+// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "Make", linkageName: "_CMake.Main.cf13cead63317d44", scope: null, file: !3, line: 9, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !19 = !DILocation(line: 10, column: 10, scope: !18)
+// CHECK:STDOUT: !20 = !DILocation(line: 10, column: 3, scope: !18)
+// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "Make", linkageName: "_CMake.Main.d9506acff356e5d2", scope: null, file: !3, line: 9, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !22 = !DILocation(line: 10, column: 10, scope: !21)
+// CHECK:STDOUT: !23 = !DILocation(line: 10, column: 16, scope: !21)
+// CHECK:STDOUT: !24 = !DILocation(line: 10, column: 24, scope: !21)
+// CHECK:STDOUT: !25 = !DILocation(line: 10, column: 3, scope: !21)
+// CHECK:STDOUT: !26 = distinct !DISubprogram(name: "Op", linkageName: "_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9", scope: null, file: !27, line: 48, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !27 = !DIFile(filename: "min_prelude/parts/copy.carbon", directory: "")
+// CHECK:STDOUT: !28 = !DILocation(line: 49, column: 13, scope: !26)
+// CHECK:STDOUT: !29 = !DILocation(line: 49, column: 12, scope: !26)
+// CHECK:STDOUT: !30 = !DILocation(line: 49, column: 26, scope: !26)
+// CHECK:STDOUT: !31 = !DILocation(line: 49, column: 5, scope: !26)
 // CHECK:STDOUT: ; ModuleID = 'access.carbon'
 // CHECK:STDOUT: source_filename = "access.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT: @C.val.bc7.loc16_3 = internal constant { i1, i32 } { i1 true, i32 0 }
 // CHECK:STDOUT: @C.val.f52.loc26_3 = internal constant { i1, {} } { i1 true, {} zeroinitializer }
+// CHECK:STDOUT: @C.val.e10.loc31_3 = internal constant { i1, { i32, i32, i32 } } { i1 true, { i32, i32, i32 } { i32 1, i32 2, i32 3 } }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define i1 @_CAccessBool.Main() !dbg !4 {
 // CHECK:STDOUT: entry:
@@ -257,36 +291,73 @@ fn AccessEmpty() -> () {
 // CHECK:STDOUT:   ret void, !dbg !20
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CAccessTuple.Main(ptr sret({ i32, i32, i32 }) %return) !dbg !21 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %c.var = alloca { i1, { i32, i32, i32 } }, align 8, !dbg !22
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !22
+// CHECK:STDOUT:   %.loc31_57.2.v = getelementptr inbounds nuw { i1, { i32, i32, i32 } }, ptr %c.var, i32 0, i32 0, !dbg !23
+// CHECK:STDOUT:   %.loc31_57.4.w = getelementptr inbounds nuw { i1, { i32, i32, i32 } }, ptr %c.var, i32 0, i32 1, !dbg !23
+// CHECK:STDOUT:   %tuple.elem0.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %.loc31_57.4.w, i32 0, i32 0, !dbg !24
+// CHECK:STDOUT:   %tuple.elem1.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %.loc31_57.4.w, i32 0, i32 1, !dbg !24
+// CHECK:STDOUT:   %tuple.elem2.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %.loc31_57.4.w, i32 0, i32 2, !dbg !24
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %c.var, ptr align 4 @C.val.e10.loc31_3, i64 16, i1 false), !dbg !22
+// CHECK:STDOUT:   call void @_CGetT.C.Main.d11cadb9c9049708(ptr %return, ptr %c.var), !dbg !25
+// CHECK:STDOUT:   ret void, !dbg !26
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
 // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
 // CHECK:STDOUT: declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #1
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr i1 @_CGetBool.C.Main.de631560529e9861(ptr %self) !dbg !21 {
+// CHECK:STDOUT: define linkonce_odr i1 @_CGetBool.C.Main.de631560529e9861(ptr %self) !dbg !27 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc6_16.1.v = getelementptr inbounds nuw { i1, i32 }, ptr %self, i32 0, i32 0, !dbg !22
-// CHECK:STDOUT:   %.loc6_16.2 = load i8, ptr %.loc6_16.1.v, align 1, !dbg !22
-// CHECK:STDOUT:   %.loc6_16.21 = trunc i8 %.loc6_16.2 to i1, !dbg !22
-// CHECK:STDOUT:   ret i1 %.loc6_16.21, !dbg !23
+// CHECK:STDOUT:   %.loc6_16.1.v = getelementptr inbounds nuw { i1, i32 }, ptr %self, i32 0, i32 0, !dbg !28
+// CHECK:STDOUT:   %.loc6_16.2 = load i8, ptr %.loc6_16.1.v, align 1, !dbg !28
+// CHECK:STDOUT:   %.loc6_16.21 = trunc i8 %.loc6_16.2 to i1, !dbg !28
+// CHECK:STDOUT:   ret i1 %.loc6_16.21, !dbg !29
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr i32 @_CGetT.C.Main.de631560529e9861(ptr %self) !dbg !24 {
+// CHECK:STDOUT: define linkonce_odr i32 @_CGetT.C.Main.de631560529e9861(ptr %self) !dbg !30 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc9_16.1.w = getelementptr inbounds nuw { i1, i32 }, ptr %self, i32 0, i32 1, !dbg !25
-// CHECK:STDOUT:   %.loc9_16.2 = load i32, ptr %.loc9_16.1.w, align 4, !dbg !25
-// CHECK:STDOUT:   ret i32 %.loc9_16.2, !dbg !26
+// CHECK:STDOUT:   %.loc9_16.1.w = getelementptr inbounds nuw { i1, i32 }, ptr %self, i32 0, i32 1, !dbg !31
+// CHECK:STDOUT:   %.loc9_16.2 = load i32, ptr %.loc9_16.1.w, align 4, !dbg !31
+// CHECK:STDOUT:   ret i32 %.loc9_16.2, !dbg !32
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CGetT.C.Main.cf13cead63317d44(ptr %self) !dbg !27 {
+// CHECK:STDOUT: define linkonce_odr void @_CGetT.C.Main.cf13cead63317d44(ptr %self) !dbg !33 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc9_16.1.w = getelementptr inbounds nuw { i1, {} }, ptr %self, i32 0, i32 1, !dbg !28
-// CHECK:STDOUT:   ret void, !dbg !29
+// CHECK:STDOUT:   %.loc9_16.1.w = getelementptr inbounds nuw { i1, {} }, ptr %self, i32 0, i32 1, !dbg !34
+// CHECK:STDOUT:   ret void, !dbg !35
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CGetT.C.Main.d11cadb9c9049708(ptr sret({ i32, i32, i32 }) %return, ptr %self) !dbg !36 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %.loc9_16.1.w = getelementptr inbounds nuw { i1, { i32, i32, i32 } }, ptr %self, i32 0, i32 1, !dbg !37
+// CHECK:STDOUT:   call void @"_COp.3f62beca1745278c:Copy.Core.03f4bad6da36de16"(ptr %return, ptr %.loc9_16.1.w), !dbg !37
+// CHECK:STDOUT:   ret void, !dbg !38
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @"_COp.3f62beca1745278c:Copy.Core.03f4bad6da36de16"(ptr sret({ i32, i32, i32 }) %return, ptr %self) !dbg !39 {
+// CHECK:STDOUT:   %tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %self, i32 0, i32 0, !dbg !41
+// CHECK:STDOUT:   %tuple.elem.load = load i32, ptr %tuple.elem, align 4, !dbg !41
+// CHECK:STDOUT:   %tuple.elem1 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 0, !dbg !42
+// CHECK:STDOUT:   %tuple.elem2 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %self, i32 0, i32 1, !dbg !43
+// CHECK:STDOUT:   %tuple.elem.load3 = load i32, ptr %tuple.elem2, align 4, !dbg !43
+// CHECK:STDOUT:   %tuple.elem4 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 1, !dbg !42
+// CHECK:STDOUT:   %tuple.elem5 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %self, i32 0, i32 2, !dbg !44
+// CHECK:STDOUT:   %tuple.elem.load6 = load i32, ptr %tuple.elem5, align 4, !dbg !44
+// CHECK:STDOUT:   %tuple.elem7 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 2, !dbg !42
+// CHECK:STDOUT:   store i32 %tuple.elem.load, ptr %tuple.elem1, align 4, !dbg !42
+// CHECK:STDOUT:   store i32 %tuple.elem.load3, ptr %tuple.elem4, align 4, !dbg !42
+// CHECK:STDOUT:   store i32 %tuple.elem.load6, ptr %tuple.elem7, align 4, !dbg !42
+// CHECK:STDOUT:   ret void, !dbg !45
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 2, 1, 0 }
-// CHECK:STDOUT: uselistorder ptr @llvm.memcpy.p0.p0.i64, { 2, 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 3, 2, 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.memcpy.p0.p0.i64, { 3, 2, 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
@@ -315,12 +386,28 @@ fn AccessEmpty() -> () {
 // CHECK:STDOUT: !18 = !DILocation(line: 26, column: 18, scope: !16)
 // CHECK:STDOUT: !19 = !DILocation(line: 27, column: 10, scope: !16)
 // CHECK:STDOUT: !20 = !DILocation(line: 27, column: 3, scope: !16)
-// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "GetBool", linkageName: "_CGetBool.C.Main.de631560529e9861", scope: null, file: !3, line: 5, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !22 = !DILocation(line: 6, column: 12, scope: !21)
-// CHECK:STDOUT: !23 = !DILocation(line: 6, column: 5, scope: !21)
-// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "GetT", linkageName: "_CGetT.C.Main.de631560529e9861", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !25 = !DILocation(line: 9, column: 12, scope: !24)
-// CHECK:STDOUT: !26 = !DILocation(line: 9, column: 5, scope: !24)
-// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "GetT", linkageName: "_CGetT.C.Main.cf13cead63317d44", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !28 = !DILocation(line: 9, column: 12, scope: !27)
-// CHECK:STDOUT: !29 = !DILocation(line: 9, column: 5, scope: !27)
+// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "AccessTuple", linkageName: "_CAccessTuple.Main", scope: null, file: !3, line: 30, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !22 = !DILocation(line: 31, column: 3, scope: !21)
+// CHECK:STDOUT: !23 = !DILocation(line: 31, column: 31, scope: !21)
+// CHECK:STDOUT: !24 = !DILocation(line: 31, column: 48, scope: !21)
+// CHECK:STDOUT: !25 = !DILocation(line: 32, column: 10, scope: !21)
+// CHECK:STDOUT: !26 = !DILocation(line: 32, column: 3, scope: !21)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "GetBool", linkageName: "_CGetBool.C.Main.de631560529e9861", scope: null, file: !3, line: 5, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !28 = !DILocation(line: 6, column: 12, scope: !27)
+// CHECK:STDOUT: !29 = !DILocation(line: 6, column: 5, scope: !27)
+// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "GetT", linkageName: "_CGetT.C.Main.de631560529e9861", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !31 = !DILocation(line: 9, column: 12, scope: !30)
+// CHECK:STDOUT: !32 = !DILocation(line: 9, column: 5, scope: !30)
+// CHECK:STDOUT: !33 = distinct !DISubprogram(name: "GetT", linkageName: "_CGetT.C.Main.cf13cead63317d44", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !34 = !DILocation(line: 9, column: 12, scope: !33)
+// CHECK:STDOUT: !35 = !DILocation(line: 9, column: 5, scope: !33)
+// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "GetT", linkageName: "_CGetT.C.Main.d11cadb9c9049708", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !37 = !DILocation(line: 9, column: 12, scope: !36)
+// CHECK:STDOUT: !38 = !DILocation(line: 9, column: 5, scope: !36)
+// CHECK:STDOUT: !39 = distinct !DISubprogram(name: "Op", linkageName: "_COp.3f62beca1745278c:Copy.Core.03f4bad6da36de16", scope: null, file: !40, line: 54, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !40 = !DIFile(filename: "min_prelude/parts/copy.carbon", directory: "")
+// CHECK:STDOUT: !41 = !DILocation(line: 55, column: 13, scope: !39)
+// CHECK:STDOUT: !42 = !DILocation(line: 55, column: 12, scope: !39)
+// CHECK:STDOUT: !43 = !DILocation(line: 55, column: 26, scope: !39)
+// CHECK:STDOUT: !44 = !DILocation(line: 55, column: 39, scope: !39)
+// CHECK:STDOUT: !45 = !DILocation(line: 55, column: 5, scope: !39)

+ 103 - 7
toolchain/lower/testdata/for/bindings.carbon

@@ -26,10 +26,9 @@ fn F(m: i32, n: i32*);
 fn For() {
   var r: EmptyRange((i32, i32)) = {};
 
-  // TODO: This causes a crash.
-  // for ((m: i32, var n: i32) in r) {
-  //   F(m, &n);
-  // }
+  for ((m: i32, var n: i32) in r) {
+    F(m, &n);
+  }
 }
 
 // CHECK:STDOUT: ; ModuleID = 'bindings.carbon'
@@ -37,14 +36,41 @@ fn For() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: @EmptyRange.val.loc27_3 = internal constant {} zeroinitializer
 // CHECK:STDOUT:
-// CHECK:STDOUT: declare void @_CF.Main()
+// CHECK:STDOUT: declare void @_CF.Main(i32, ptr)
 // CHECK:STDOUT:
 // CHECK:STDOUT: define void @_CFor.Main() !dbg !4 {
 // CHECK:STDOUT: entry:
 // CHECK:STDOUT:   %r.var = alloca {}, align 8, !dbg !7
+// CHECK:STDOUT:   %var = alloca {}, align 8, !dbg !8
+// CHECK:STDOUT:   %.loc29_33.1.temp = alloca { i1, { i32, i32 } }, align 8, !dbg !8
+// CHECK:STDOUT:   %n.var = alloca i32, align 4, !dbg !9
+// CHECK:STDOUT:   %.loc29_33.8.temp = alloca { i32, i32 }, align 8, !dbg !8
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %r.var), !dbg !7
 // CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 1 %r.var, ptr align 1 @EmptyRange.val.loc27_3, i64 0, i1 false), !dbg !7
-// CHECK:STDOUT:   ret void, !dbg !8
+// CHECK:STDOUT:   call void @"_CNewCursor.EmptyRange.Main:Iterate.Core.d9506acff356e5d2"(ptr %r.var), !dbg !8
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %var), !dbg !8
+// CHECK:STDOUT:   br label %for.next, !dbg !8
+// CHECK:STDOUT:
+// CHECK:STDOUT: for.next:                                         ; preds = %for.body, %entry
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc29_33.1.temp), !dbg !8
+// CHECK:STDOUT:   call void @"_CNext.EmptyRange.Main:Iterate.Core.d9506acff356e5d2"(ptr %.loc29_33.1.temp, ptr %r.var, ptr %var), !dbg !8
+// CHECK:STDOUT:   %Optional.HasValue.call = call i1 @_CHasValue.Optional.Core.d9506acff356e5d2(ptr %.loc29_33.1.temp), !dbg !8
+// CHECK:STDOUT:   br i1 %Optional.HasValue.call, label %for.body, label %for.done, !dbg !8
+// CHECK:STDOUT:
+// CHECK:STDOUT: for.body:                                         ; preds = %for.next
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !9
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc29_33.8.temp), !dbg !8
+// CHECK:STDOUT:   call void @_CGet.Optional.Core.d9506acff356e5d2(ptr %.loc29_33.8.temp, ptr %.loc29_33.1.temp), !dbg !8
+// CHECK:STDOUT:   %tuple.elem0.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %.loc29_33.8.temp, i32 0, i32 0, !dbg !8
+// CHECK:STDOUT:   %tuple.elem1.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %.loc29_33.8.temp, i32 0, i32 1, !dbg !8
+// CHECK:STDOUT:   %.loc29_33.11 = load i32, ptr %tuple.elem0.tuple.elem, align 4, !dbg !8
+// CHECK:STDOUT:   %.loc29_33.12 = load i32, ptr %tuple.elem1.tuple.elem, align 4, !dbg !8
+// CHECK:STDOUT:   store i32 %.loc29_33.12, ptr %n.var, align 4, !dbg !9
+// CHECK:STDOUT:   call void @_CF.Main(i32 %.loc29_33.11, ptr %n.var), !dbg !10
+// CHECK:STDOUT:   br label %for.next, !dbg !11
+// CHECK:STDOUT:
+// CHECK:STDOUT: for.done:                                         ; preds = %for.next
+// CHECK:STDOUT:   ret void, !dbg !12
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -53,6 +79,51 @@ fn For() {
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
 // CHECK:STDOUT: declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #1
 // CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @"_CNewCursor.EmptyRange.Main:Iterate.Core.d9506acff356e5d2"(ptr %self) !dbg !13 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   ret void, !dbg !14
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @"_CNext.EmptyRange.Main:Iterate.Core.d9506acff356e5d2"(ptr sret({ i1, { i32, i32 } }) %return, ptr %self, ptr %cursor) !dbg !15 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @_CNone.Optional.Core.d9506acff356e5d2(ptr %return), !dbg !16
+// CHECK:STDOUT:   ret void, !dbg !17
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr i1 @_CHasValue.Optional.Core.d9506acff356e5d2(ptr %self) !dbg !18 {
+// CHECK:STDOUT:   %has_value = getelementptr inbounds nuw { i1, { i32, i32 } }, ptr %self, i32 0, i32 0, !dbg !20
+// CHECK:STDOUT:   %1 = load i8, ptr %has_value, align 1, !dbg !20
+// CHECK:STDOUT:   %2 = trunc i8 %1 to i1, !dbg !20
+// CHECK:STDOUT:   ret i1 %2, !dbg !21
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CGet.Optional.Core.d9506acff356e5d2(ptr sret({ i32, i32 }) %return, ptr %self) !dbg !22 {
+// CHECK:STDOUT:   %value = getelementptr inbounds nuw { i1, { i32, i32 } }, ptr %self, i32 0, i32 1, !dbg !23
+// CHECK:STDOUT:   call void @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9"(ptr %return, ptr %value), !dbg !23
+// CHECK:STDOUT:   ret void, !dbg !24
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CNone.Optional.Core.d9506acff356e5d2(ptr sret({ i1, { i32, i32 } }) %return) !dbg !25 {
+// CHECK:STDOUT:   %has_value = getelementptr inbounds nuw { i1, { i32, i32 } }, ptr %return, i32 0, i32 0, !dbg !26
+// CHECK:STDOUT:   store i8 0, ptr %has_value, align 1, !dbg !26
+// CHECK:STDOUT:   ret void, !dbg !27
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @"_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9"(ptr sret({ i32, i32 }) %return, ptr %self) !dbg !28 {
+// CHECK:STDOUT:   %tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 0, !dbg !30
+// CHECK:STDOUT:   %tuple.elem.load = load i32, ptr %tuple.elem, align 4, !dbg !30
+// CHECK:STDOUT:   %tuple.elem1 = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !31
+// CHECK:STDOUT:   %tuple.elem2 = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 1, !dbg !32
+// CHECK:STDOUT:   %tuple.elem.load3 = load i32, ptr %tuple.elem2, align 4, !dbg !32
+// CHECK:STDOUT:   %tuple.elem4 = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !31
+// CHECK:STDOUT:   store i32 %tuple.elem.load, ptr %tuple.elem1, align 4, !dbg !31
+// CHECK:STDOUT:   store i32 %tuple.elem.load3, ptr %tuple.elem4, align 4, !dbg !31
+// CHECK:STDOUT:   ret void, !dbg !33
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: ; uselistorder directives
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 4, 3, 2, 1, 0 }
+// CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT:
@@ -67,4 +138,29 @@ fn For() {
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{}
 // CHECK:STDOUT: !7 = !DILocation(line: 27, column: 3, scope: !4)
-// CHECK:STDOUT: !8 = !DILocation(line: 26, column: 1, scope: !4)
+// CHECK:STDOUT: !8 = !DILocation(line: 29, column: 7, scope: !4)
+// CHECK:STDOUT: !9 = !DILocation(line: 29, column: 17, scope: !4)
+// CHECK:STDOUT: !10 = !DILocation(line: 30, column: 5, scope: !4)
+// CHECK:STDOUT: !11 = !DILocation(line: 29, column: 3, scope: !4)
+// CHECK:STDOUT: !12 = !DILocation(line: 26, column: 1, scope: !4)
+// CHECK:STDOUT: !13 = distinct !DISubprogram(name: "NewCursor", linkageName: "_CNewCursor.EmptyRange.Main:Iterate.Core.d9506acff356e5d2", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !14 = !DILocation(line: 16, column: 7, scope: !13)
+// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "Next", linkageName: "_CNext.EmptyRange.Main:Iterate.Core.d9506acff356e5d2", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !16 = !DILocation(line: 19, column: 14, scope: !15)
+// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 7, scope: !15)
+// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "HasValue", linkageName: "_CHasValue.Optional.Core.d9506acff356e5d2", scope: null, file: !19, line: 30, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !19 = !DIFile(filename: "{{.*}}/prelude/types/optional.carbon", directory: "")
+// CHECK:STDOUT: !20 = !DILocation(line: 30, column: 46, scope: !18)
+// CHECK:STDOUT: !21 = !DILocation(line: 30, column: 39, scope: !18)
+// CHECK:STDOUT: !22 = distinct !DISubprogram(name: "Get", linkageName: "_CGet.Optional.Core.d9506acff356e5d2", scope: null, file: !19, line: 31, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !23 = !DILocation(line: 31, column: 38, scope: !22)
+// CHECK:STDOUT: !24 = !DILocation(line: 31, column: 31, scope: !22)
+// CHECK:STDOUT: !25 = distinct !DISubprogram(name: "None", linkageName: "_CNone.Optional.Core.d9506acff356e5d2", scope: null, file: !19, line: 20, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !26 = !DILocation(line: 22, column: 5, scope: !25)
+// CHECK:STDOUT: !27 = !DILocation(line: 23, column: 5, scope: !25)
+// CHECK:STDOUT: !28 = distinct !DISubprogram(name: "Op", linkageName: "_COp.52304025ab0e7af9:Copy.Core.58c6957df82926a9", scope: null, file: !29, line: 58, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !29 = !DIFile(filename: "{{.*}}/prelude/copy.carbon", directory: "")
+// CHECK:STDOUT: !30 = !DILocation(line: 59, column: 13, scope: !28)
+// CHECK:STDOUT: !31 = !DILocation(line: 59, column: 12, scope: !28)
+// CHECK:STDOUT: !32 = !DILocation(line: 59, column: 26, scope: !28)
+// CHECK:STDOUT: !33 = !DILocation(line: 59, column: 5, scope: !28)

+ 167 - 130
toolchain/lower/testdata/function/generic/call_basic.carbon

@@ -40,8 +40,7 @@ fn G[T:! Core.Copy](x: T) -> T {
   var ptr_i8 : i8*;
   H(ptr_i8);
   var c: C;
-  // TODO: This causes a crash.
-  // H(c);
+  H(c);
 
   return x;
 }
@@ -83,16 +82,16 @@ fn M() {
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %p.var), !dbg !11
 // CHECK:STDOUT:   store double 1.000000e+00, ptr %p.var, align 8, !dbg !11
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %q.var), !dbg !12
-// CHECK:STDOUT:   %.loc55 = load i32, ptr %n.var, align 4, !dbg !13
-// CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(i32 %.loc55), !dbg !14
-// CHECK:STDOUT:   %.loc56_9 = load i32, ptr %n.var, align 4, !dbg !15
-// CHECK:STDOUT:   %G.call.loc56 = call i32 @_CG.Main.de631560529e9861(i32 %.loc56_9), !dbg !16
-// CHECK:STDOUT:   store i32 %G.call.loc56, ptr %m.var, align 4, !dbg !17
-// CHECK:STDOUT:   %.loc57 = load double, ptr %p.var, align 8, !dbg !18
-// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(double %.loc57), !dbg !19
-// CHECK:STDOUT:   %.loc58_9 = load double, ptr %p.var, align 8, !dbg !20
-// CHECK:STDOUT:   %G.call.loc58 = call double @_CG.Main.3836ccc537683c19(double %.loc58_9), !dbg !21
-// CHECK:STDOUT:   store double %G.call.loc58, ptr %q.var, align 8, !dbg !22
+// CHECK:STDOUT:   %.loc54 = load i32, ptr %n.var, align 4, !dbg !13
+// CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(i32 %.loc54), !dbg !14
+// CHECK:STDOUT:   %.loc55_9 = load i32, ptr %n.var, align 4, !dbg !15
+// CHECK:STDOUT:   %G.call.loc55 = call i32 @_CG.Main.de631560529e9861(i32 %.loc55_9), !dbg !16
+// CHECK:STDOUT:   store i32 %G.call.loc55, ptr %m.var, align 4, !dbg !17
+// CHECK:STDOUT:   %.loc56 = load double, ptr %p.var, align 8, !dbg !18
+// CHECK:STDOUT:   call void @_CF.Main.d4b5665541d5d7a8(double %.loc56), !dbg !19
+// CHECK:STDOUT:   %.loc57_9 = load double, ptr %p.var, align 8, !dbg !20
+// CHECK:STDOUT:   %G.call.loc57 = call double @_CG.Main.3836ccc537683c19(double %.loc57_9), !dbg !21
+// CHECK:STDOUT:   store double %G.call.loc57, ptr %q.var, align 8, !dbg !22
 // CHECK:STDOUT:   ret void, !dbg !23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -109,89 +108,122 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr i32 @_CG.Main.de631560529e9861(i32 %x) !dbg !26 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %var_f64.var = alloca double, align 8, !dbg !27
-// CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !28
-// CHECK:STDOUT:   %ptr_f64.var = alloca ptr, align 8, !dbg !29
-// CHECK:STDOUT:   %ptr_i8.var = alloca ptr, align 8, !dbg !30
-// CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !31
-// CHECK:STDOUT:   %H.call.loc29 = call i32 @_CH.Main.de631560529e9861(i32 %x), !dbg !32
-// CHECK:STDOUT:   %H.call.loc30 = call %type @_CH.Main.402deed6b8733082(%type zeroinitializer), !dbg !33
-// CHECK:STDOUT:   %G.call = call i32 @_CG.Main.de631560529e9861(i32 %x), !dbg !34
-// CHECK:STDOUT:   %H.call.loc31 = call i32 @_CH.Main.de631560529e9861(i32 %G.call), !dbg !35
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %var_f64.var), !dbg !27
-// CHECK:STDOUT:   %.loc35_5 = load double, ptr %var_f64.var, align 8, !dbg !36
-// CHECK:STDOUT:   %H.call.loc35 = call double @_CH.Main.3836ccc537683c19(double %.loc35_5), !dbg !37
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i32.var), !dbg !28
-// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !38
-// CHECK:STDOUT:   %H.call.loc37 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc37_5), !dbg !39
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_f64.var), !dbg !29
-// CHECK:STDOUT:   %.loc39_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !40
-// CHECK:STDOUT:   %H.call.loc39 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc39_5), !dbg !41
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i8.var), !dbg !30
-// CHECK:STDOUT:   %.loc41_5 = load ptr, ptr %ptr_i8.var, align 8, !dbg !42
-// CHECK:STDOUT:   %H.call.loc41 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc41_5), !dbg !43
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !31
-// CHECK:STDOUT:   ret i32 %x, !dbg !44
+// CHECK:STDOUT:   %.loc29_6.3.temp = alloca i32, align 4, !dbg !27
+// CHECK:STDOUT:   %.loc31_8.3.temp = alloca i32, align 4, !dbg !28
+// CHECK:STDOUT:   %.loc31_9.3.temp = alloca i32, align 4, !dbg !29
+// CHECK:STDOUT:   %var_f64.var = alloca double, align 8, !dbg !30
+// CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !31
+// CHECK:STDOUT:   %ptr_f64.var = alloca ptr, align 8, !dbg !32
+// CHECK:STDOUT:   %ptr_i8.var = alloca ptr, align 8, !dbg !33
+// CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !34
+// CHECK:STDOUT:   %.loc43_6.3.temp = alloca {}, align 8, !dbg !35
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc29_6.3.temp), !dbg !27
+// CHECK:STDOUT:   %H.call.loc29 = call i32 @_CH.Main.de631560529e9861(i32 %x), !dbg !27
+// CHECK:STDOUT:   store i32 %H.call.loc29, ptr %.loc29_6.3.temp, align 4, !dbg !27
+// CHECK:STDOUT:   %H.call.loc30 = call %type @_CH.Main.402deed6b8733082(%type zeroinitializer), !dbg !36
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc31_8.3.temp), !dbg !28
+// CHECK:STDOUT:   %G.call = call i32 @_CG.Main.de631560529e9861(i32 %x), !dbg !28
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc31_9.3.temp), !dbg !29
+// CHECK:STDOUT:   store i32 %G.call, ptr %.loc31_8.3.temp, align 4, !dbg !28
+// CHECK:STDOUT:   %.loc31_8.5 = load i32, ptr %.loc31_8.3.temp, align 4, !dbg !28
+// CHECK:STDOUT:   %H.call.loc31 = call i32 @_CH.Main.de631560529e9861(i32 %.loc31_8.5), !dbg !29
+// CHECK:STDOUT:   store i32 %H.call.loc31, ptr %.loc31_9.3.temp, align 4, !dbg !29
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %var_f64.var), !dbg !30
+// CHECK:STDOUT:   %.loc35_5 = load double, ptr %var_f64.var, align 8, !dbg !37
+// CHECK:STDOUT:   %H.call.loc35 = call double @_CH.Main.3836ccc537683c19(double %.loc35_5), !dbg !38
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i32.var), !dbg !31
+// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !39
+// CHECK:STDOUT:   %H.call.loc37 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc37_5), !dbg !40
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_f64.var), !dbg !32
+// CHECK:STDOUT:   %.loc39_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !41
+// CHECK:STDOUT:   %H.call.loc39 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc39_5), !dbg !42
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i8.var), !dbg !33
+// CHECK:STDOUT:   %.loc41_5 = load ptr, ptr %ptr_i8.var, align 8, !dbg !43
+// CHECK:STDOUT:   %H.call.loc41 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc41_5), !dbg !44
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !34
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc43_6.3.temp), !dbg !35
+// CHECK:STDOUT:   call void @_CH.Main.936d996ea935415c(ptr %.loc43_6.3.temp, ptr %c.var), !dbg !35
+// CHECK:STDOUT:   ret i32 %x, !dbg !45
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(double %x) !dbg !45 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.d4b5665541d5d7a8(double %x) !dbg !46 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   ret void, !dbg !46
+// CHECK:STDOUT:   ret void, !dbg !47
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CG.Main.3836ccc537683c19(double %x) !dbg !47 {
+// CHECK:STDOUT: define linkonce_odr double @_CG.Main.3836ccc537683c19(double %x) !dbg !48 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %var_f64.var = alloca double, align 8, !dbg !48
-// CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !49
-// CHECK:STDOUT:   %ptr_f64.var = alloca ptr, align 8, !dbg !50
-// CHECK:STDOUT:   %ptr_i8.var = alloca ptr, align 8, !dbg !51
-// CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !52
-// CHECK:STDOUT:   %H.call.loc29 = call double @_CH.Main.3836ccc537683c19(double %x), !dbg !53
-// CHECK:STDOUT:   %H.call.loc30 = call %type @_CH.Main.402deed6b8733082(%type zeroinitializer), !dbg !54
-// CHECK:STDOUT:   %G.call = call double @_CG.Main.3836ccc537683c19(double %x), !dbg !55
-// CHECK:STDOUT:   %H.call.loc31 = call double @_CH.Main.3836ccc537683c19(double %G.call), !dbg !56
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %var_f64.var), !dbg !48
-// CHECK:STDOUT:   %.loc35_5 = load double, ptr %var_f64.var, align 8, !dbg !57
-// CHECK:STDOUT:   %H.call.loc35 = call double @_CH.Main.3836ccc537683c19(double %.loc35_5), !dbg !58
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i32.var), !dbg !49
-// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !59
-// CHECK:STDOUT:   %H.call.loc37 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc37_5), !dbg !60
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_f64.var), !dbg !50
-// CHECK:STDOUT:   %.loc39_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !61
-// CHECK:STDOUT:   %H.call.loc39 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc39_5), !dbg !62
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i8.var), !dbg !51
-// CHECK:STDOUT:   %.loc41_5 = load ptr, ptr %ptr_i8.var, align 8, !dbg !63
-// CHECK:STDOUT:   %H.call.loc41 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc41_5), !dbg !64
-// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !52
-// CHECK:STDOUT:   ret double %x, !dbg !65
+// CHECK:STDOUT:   %.loc29_6.3.temp = alloca double, align 8, !dbg !49
+// CHECK:STDOUT:   %.loc31_8.3.temp = alloca double, align 8, !dbg !50
+// CHECK:STDOUT:   %.loc31_9.3.temp = alloca double, align 8, !dbg !51
+// CHECK:STDOUT:   %var_f64.var = alloca double, align 8, !dbg !52
+// CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !53
+// CHECK:STDOUT:   %ptr_f64.var = alloca ptr, align 8, !dbg !54
+// CHECK:STDOUT:   %ptr_i8.var = alloca ptr, align 8, !dbg !55
+// CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !56
+// CHECK:STDOUT:   %.loc43_6.3.temp = alloca {}, align 8, !dbg !57
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc29_6.3.temp), !dbg !49
+// CHECK:STDOUT:   %H.call.loc29 = call double @_CH.Main.3836ccc537683c19(double %x), !dbg !49
+// CHECK:STDOUT:   store double %H.call.loc29, ptr %.loc29_6.3.temp, align 8, !dbg !49
+// CHECK:STDOUT:   %H.call.loc30 = call %type @_CH.Main.402deed6b8733082(%type zeroinitializer), !dbg !58
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc31_8.3.temp), !dbg !50
+// CHECK:STDOUT:   %G.call = call double @_CG.Main.3836ccc537683c19(double %x), !dbg !50
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc31_9.3.temp), !dbg !51
+// CHECK:STDOUT:   store double %G.call, ptr %.loc31_8.3.temp, align 8, !dbg !50
+// CHECK:STDOUT:   %.loc31_8.5 = load double, ptr %.loc31_8.3.temp, align 8, !dbg !50
+// CHECK:STDOUT:   %H.call.loc31 = call double @_CH.Main.3836ccc537683c19(double %.loc31_8.5), !dbg !51
+// CHECK:STDOUT:   store double %H.call.loc31, ptr %.loc31_9.3.temp, align 8, !dbg !51
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %var_f64.var), !dbg !52
+// CHECK:STDOUT:   %.loc35_5 = load double, ptr %var_f64.var, align 8, !dbg !59
+// CHECK:STDOUT:   %H.call.loc35 = call double @_CH.Main.3836ccc537683c19(double %.loc35_5), !dbg !60
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i32.var), !dbg !53
+// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !61
+// CHECK:STDOUT:   %H.call.loc37 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc37_5), !dbg !62
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_f64.var), !dbg !54
+// CHECK:STDOUT:   %.loc39_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !63
+// CHECK:STDOUT:   %H.call.loc39 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc39_5), !dbg !64
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i8.var), !dbg !55
+// CHECK:STDOUT:   %.loc41_5 = load ptr, ptr %ptr_i8.var, align 8, !dbg !65
+// CHECK:STDOUT:   %H.call.loc41 = call ptr @_CH.Main.a194de4a3b8dbd0c(ptr %.loc41_5), !dbg !66
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !56
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc43_6.3.temp), !dbg !57
+// CHECK:STDOUT:   call void @_CH.Main.936d996ea935415c(ptr %.loc43_6.3.temp, ptr %c.var), !dbg !57
+// CHECK:STDOUT:   ret double %x, !dbg !67
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr i32 @_CH.Main.de631560529e9861(i32 %x) !dbg !66 {
+// CHECK:STDOUT: define linkonce_odr i32 @_CH.Main.de631560529e9861(i32 %x) !dbg !68 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   ret i32 %x, !dbg !67
+// CHECK:STDOUT:   ret i32 %x, !dbg !69
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr %type @_CH.Main.402deed6b8733082(%type %x) !dbg !68 {
+// CHECK:STDOUT: define linkonce_odr %type @_CH.Main.402deed6b8733082(%type %x) !dbg !70 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   ret %type %x, !dbg !69
+// CHECK:STDOUT:   ret %type %x, !dbg !71
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CH.Main.3836ccc537683c19(double %x) !dbg !70 {
+// CHECK:STDOUT: define linkonce_odr double @_CH.Main.3836ccc537683c19(double %x) !dbg !72 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   ret double %x, !dbg !71
+// CHECK:STDOUT:   ret double %x, !dbg !73
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr ptr @_CH.Main.a194de4a3b8dbd0c(ptr %x) !dbg !72 {
+// CHECK:STDOUT: define linkonce_odr ptr @_CH.Main.a194de4a3b8dbd0c(ptr %x) !dbg !74 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   ret ptr %x, !dbg !73
+// CHECK:STDOUT:   ret ptr %x, !dbg !75
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CH.Main.936d996ea935415c(ptr sret({}) %return, ptr %x) !dbg !76 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @"_COp.C.Main:Copy.Core"(ptr %return, ptr %x), !dbg !77
+// CHECK:STDOUT:   ret void, !dbg !78
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 12, 11, 10 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 20, 19, 18 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.de631560529e9861, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.402deed6b8733082, { 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.3836ccc537683c19, { 3, 2, 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CH.Main.a194de4a3b8dbd0c, { 5, 2, 0, 4, 3, 1 }
+// CHECK:STDOUT: uselistorder ptr @_CH.Main.936d996ea935415c, { 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -207,69 +239,74 @@ fn M() {
 // CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
 // CHECK:STDOUT: !6 = !{}
 // CHECK:STDOUT: !7 = !DILocation(line: 15, column: 35, scope: !4)
-// CHECK:STDOUT: !8 = distinct !DISubprogram(name: "M", linkageName: "_CM.Main", scope: null, file: !3, line: 49, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !9 = !DILocation(line: 50, column: 3, scope: !8)
-// CHECK:STDOUT: !10 = !DILocation(line: 51, column: 3, scope: !8)
-// CHECK:STDOUT: !11 = !DILocation(line: 52, column: 3, scope: !8)
-// CHECK:STDOUT: !12 = !DILocation(line: 53, column: 3, scope: !8)
-// CHECK:STDOUT: !13 = !DILocation(line: 55, column: 5, scope: !8)
-// CHECK:STDOUT: !14 = !DILocation(line: 55, column: 3, scope: !8)
-// CHECK:STDOUT: !15 = !DILocation(line: 56, column: 9, scope: !8)
-// CHECK:STDOUT: !16 = !DILocation(line: 56, column: 7, scope: !8)
-// CHECK:STDOUT: !17 = !DILocation(line: 56, column: 3, scope: !8)
-// CHECK:STDOUT: !18 = !DILocation(line: 57, column: 5, scope: !8)
-// CHECK:STDOUT: !19 = !DILocation(line: 57, column: 3, scope: !8)
-// CHECK:STDOUT: !20 = !DILocation(line: 58, column: 9, scope: !8)
-// CHECK:STDOUT: !21 = !DILocation(line: 58, column: 7, scope: !8)
-// CHECK:STDOUT: !22 = !DILocation(line: 58, column: 3, scope: !8)
-// CHECK:STDOUT: !23 = !DILocation(line: 49, column: 1, scope: !8)
+// CHECK:STDOUT: !8 = distinct !DISubprogram(name: "M", linkageName: "_CM.Main", scope: null, file: !3, line: 48, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !9 = !DILocation(line: 49, column: 3, scope: !8)
+// CHECK:STDOUT: !10 = !DILocation(line: 50, column: 3, scope: !8)
+// CHECK:STDOUT: !11 = !DILocation(line: 51, column: 3, scope: !8)
+// CHECK:STDOUT: !12 = !DILocation(line: 52, column: 3, scope: !8)
+// CHECK:STDOUT: !13 = !DILocation(line: 54, column: 5, scope: !8)
+// CHECK:STDOUT: !14 = !DILocation(line: 54, column: 3, scope: !8)
+// CHECK:STDOUT: !15 = !DILocation(line: 55, column: 9, scope: !8)
+// CHECK:STDOUT: !16 = !DILocation(line: 55, column: 7, scope: !8)
+// CHECK:STDOUT: !17 = !DILocation(line: 55, column: 3, scope: !8)
+// CHECK:STDOUT: !18 = !DILocation(line: 56, column: 5, scope: !8)
+// CHECK:STDOUT: !19 = !DILocation(line: 56, column: 3, scope: !8)
+// CHECK:STDOUT: !20 = !DILocation(line: 57, column: 9, scope: !8)
+// CHECK:STDOUT: !21 = !DILocation(line: 57, column: 7, scope: !8)
+// CHECK:STDOUT: !22 = !DILocation(line: 57, column: 3, scope: !8)
+// CHECK:STDOUT: !23 = !DILocation(line: 48, column: 1, scope: !8)
 // CHECK:STDOUT: !24 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.b88d1103f417c6d4", scope: null, file: !3, line: 19, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !25 = !DILocation(line: 19, column: 1, scope: !24)
 // CHECK:STDOUT: !26 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.de631560529e9861", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !27 = !DILocation(line: 34, column: 3, scope: !26)
-// CHECK:STDOUT: !28 = !DILocation(line: 36, column: 3, scope: !26)
-// CHECK:STDOUT: !29 = !DILocation(line: 38, column: 3, scope: !26)
-// CHECK:STDOUT: !30 = !DILocation(line: 40, column: 3, scope: !26)
-// CHECK:STDOUT: !31 = !DILocation(line: 42, column: 3, scope: !26)
-// CHECK:STDOUT: !32 = !DILocation(line: 29, column: 3, scope: !26)
-// CHECK:STDOUT: !33 = !DILocation(line: 30, column: 3, scope: !26)
-// CHECK:STDOUT: !34 = !DILocation(line: 31, column: 5, scope: !26)
-// CHECK:STDOUT: !35 = !DILocation(line: 31, column: 3, scope: !26)
-// CHECK:STDOUT: !36 = !DILocation(line: 35, column: 5, scope: !26)
-// CHECK:STDOUT: !37 = !DILocation(line: 35, column: 3, scope: !26)
-// CHECK:STDOUT: !38 = !DILocation(line: 37, column: 5, scope: !26)
-// CHECK:STDOUT: !39 = !DILocation(line: 37, column: 3, scope: !26)
-// CHECK:STDOUT: !40 = !DILocation(line: 39, column: 5, scope: !26)
-// CHECK:STDOUT: !41 = !DILocation(line: 39, column: 3, scope: !26)
-// CHECK:STDOUT: !42 = !DILocation(line: 41, column: 5, scope: !26)
-// CHECK:STDOUT: !43 = !DILocation(line: 41, column: 3, scope: !26)
-// CHECK:STDOUT: !44 = !DILocation(line: 46, column: 3, scope: !26)
-// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 19, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !46 = !DILocation(line: 19, column: 1, scope: !45)
-// CHECK:STDOUT: !47 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.3836ccc537683c19", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !48 = !DILocation(line: 34, column: 3, scope: !47)
-// CHECK:STDOUT: !49 = !DILocation(line: 36, column: 3, scope: !47)
-// CHECK:STDOUT: !50 = !DILocation(line: 38, column: 3, scope: !47)
-// CHECK:STDOUT: !51 = !DILocation(line: 40, column: 3, scope: !47)
-// CHECK:STDOUT: !52 = !DILocation(line: 42, column: 3, scope: !47)
-// CHECK:STDOUT: !53 = !DILocation(line: 29, column: 3, scope: !47)
-// CHECK:STDOUT: !54 = !DILocation(line: 30, column: 3, scope: !47)
-// CHECK:STDOUT: !55 = !DILocation(line: 31, column: 5, scope: !47)
-// CHECK:STDOUT: !56 = !DILocation(line: 31, column: 3, scope: !47)
-// CHECK:STDOUT: !57 = !DILocation(line: 35, column: 5, scope: !47)
-// CHECK:STDOUT: !58 = !DILocation(line: 35, column: 3, scope: !47)
-// CHECK:STDOUT: !59 = !DILocation(line: 37, column: 5, scope: !47)
-// CHECK:STDOUT: !60 = !DILocation(line: 37, column: 3, scope: !47)
-// CHECK:STDOUT: !61 = !DILocation(line: 39, column: 5, scope: !47)
-// CHECK:STDOUT: !62 = !DILocation(line: 39, column: 3, scope: !47)
-// CHECK:STDOUT: !63 = !DILocation(line: 41, column: 5, scope: !47)
-// CHECK:STDOUT: !64 = !DILocation(line: 41, column: 3, scope: !47)
-// CHECK:STDOUT: !65 = !DILocation(line: 46, column: 3, scope: !47)
-// CHECK:STDOUT: !66 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.de631560529e9861", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !67 = !DILocation(line: 23, column: 3, scope: !66)
-// CHECK:STDOUT: !68 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.402deed6b8733082", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !27 = !DILocation(line: 29, column: 3, scope: !26)
+// CHECK:STDOUT: !28 = !DILocation(line: 31, column: 5, scope: !26)
+// CHECK:STDOUT: !29 = !DILocation(line: 31, column: 3, scope: !26)
+// CHECK:STDOUT: !30 = !DILocation(line: 34, column: 3, scope: !26)
+// CHECK:STDOUT: !31 = !DILocation(line: 36, column: 3, scope: !26)
+// CHECK:STDOUT: !32 = !DILocation(line: 38, column: 3, scope: !26)
+// CHECK:STDOUT: !33 = !DILocation(line: 40, column: 3, scope: !26)
+// CHECK:STDOUT: !34 = !DILocation(line: 42, column: 3, scope: !26)
+// CHECK:STDOUT: !35 = !DILocation(line: 43, column: 3, scope: !26)
+// CHECK:STDOUT: !36 = !DILocation(line: 30, column: 3, scope: !26)
+// CHECK:STDOUT: !37 = !DILocation(line: 35, column: 5, scope: !26)
+// CHECK:STDOUT: !38 = !DILocation(line: 35, column: 3, scope: !26)
+// CHECK:STDOUT: !39 = !DILocation(line: 37, column: 5, scope: !26)
+// CHECK:STDOUT: !40 = !DILocation(line: 37, column: 3, scope: !26)
+// CHECK:STDOUT: !41 = !DILocation(line: 39, column: 5, scope: !26)
+// CHECK:STDOUT: !42 = !DILocation(line: 39, column: 3, scope: !26)
+// CHECK:STDOUT: !43 = !DILocation(line: 41, column: 5, scope: !26)
+// CHECK:STDOUT: !44 = !DILocation(line: 41, column: 3, scope: !26)
+// CHECK:STDOUT: !45 = !DILocation(line: 45, column: 3, scope: !26)
+// CHECK:STDOUT: !46 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.d4b5665541d5d7a8", scope: null, file: !3, line: 19, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !47 = !DILocation(line: 19, column: 1, scope: !46)
+// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "G", linkageName: "_CG.Main.3836ccc537683c19", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !49 = !DILocation(line: 29, column: 3, scope: !48)
+// CHECK:STDOUT: !50 = !DILocation(line: 31, column: 5, scope: !48)
+// CHECK:STDOUT: !51 = !DILocation(line: 31, column: 3, scope: !48)
+// CHECK:STDOUT: !52 = !DILocation(line: 34, column: 3, scope: !48)
+// CHECK:STDOUT: !53 = !DILocation(line: 36, column: 3, scope: !48)
+// CHECK:STDOUT: !54 = !DILocation(line: 38, column: 3, scope: !48)
+// CHECK:STDOUT: !55 = !DILocation(line: 40, column: 3, scope: !48)
+// CHECK:STDOUT: !56 = !DILocation(line: 42, column: 3, scope: !48)
+// CHECK:STDOUT: !57 = !DILocation(line: 43, column: 3, scope: !48)
+// CHECK:STDOUT: !58 = !DILocation(line: 30, column: 3, scope: !48)
+// CHECK:STDOUT: !59 = !DILocation(line: 35, column: 5, scope: !48)
+// CHECK:STDOUT: !60 = !DILocation(line: 35, column: 3, scope: !48)
+// CHECK:STDOUT: !61 = !DILocation(line: 37, column: 5, scope: !48)
+// CHECK:STDOUT: !62 = !DILocation(line: 37, column: 3, scope: !48)
+// CHECK:STDOUT: !63 = !DILocation(line: 39, column: 5, scope: !48)
+// CHECK:STDOUT: !64 = !DILocation(line: 39, column: 3, scope: !48)
+// CHECK:STDOUT: !65 = !DILocation(line: 41, column: 5, scope: !48)
+// CHECK:STDOUT: !66 = !DILocation(line: 41, column: 3, scope: !48)
+// CHECK:STDOUT: !67 = !DILocation(line: 45, column: 3, scope: !48)
+// CHECK:STDOUT: !68 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.de631560529e9861", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !69 = !DILocation(line: 23, column: 3, scope: !68)
-// CHECK:STDOUT: !70 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.3836ccc537683c19", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !70 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.402deed6b8733082", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !71 = !DILocation(line: 23, column: 3, scope: !70)
-// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.a194de4a3b8dbd0c", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.3836ccc537683c19", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !73 = !DILocation(line: 23, column: 3, scope: !72)
+// CHECK:STDOUT: !74 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.a194de4a3b8dbd0c", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !75 = !DILocation(line: 23, column: 3, scope: !74)
+// CHECK:STDOUT: !76 = distinct !DISubprogram(name: "H", linkageName: "_CH.Main.936d996ea935415c", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !77 = !DILocation(line: 23, column: 10, scope: !76)
+// CHECK:STDOUT: !78 = !DILocation(line: 23, column: 3, scope: !76)

+ 4 - 1
toolchain/lower/testdata/function/generic/call_basic_depth.carbon

@@ -63,7 +63,10 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr i32 @_CG.Main.de631560529e9861(i32 %x) !dbg !17 {
 // CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %.loc25_6.3.temp = alloca i32, align 4, !dbg !18
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc25_6.3.temp), !dbg !18
 // CHECK:STDOUT:   %H.call = call i32 @_CH.Main.de631560529e9861(i32 %x), !dbg !18
+// CHECK:STDOUT:   store i32 %H.call, ptr %.loc25_6.3.temp, align 4, !dbg !18
 // CHECK:STDOUT:   call void @_CF.Main.b88d1103f417c6d4(i32 %x), !dbg !19
 // CHECK:STDOUT:   ret i32 %x, !dbg !20
 // CHECK:STDOUT: }
@@ -75,7 +78,7 @@ fn M() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 2, 1 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT:

+ 15 - 9
toolchain/lower/testdata/function/generic/call_deref_ptr.carbon

@@ -82,15 +82,21 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CB.Main.de631560529e9861(ptr %x) !dbg !24 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc27_5.2 = load i32, ptr %x, align 4, !dbg !25
-// CHECK:STDOUT:   %D.call = call i32 @_CD.Main.de631560529e9861(i32 %.loc27_5.2), !dbg !26
+// CHECK:STDOUT:   %.loc27_7.3.temp = alloca i32, align 4, !dbg !25
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc27_7.3.temp), !dbg !25
+// CHECK:STDOUT:   %.loc27_5.2 = load i32, ptr %x, align 4, !dbg !26
+// CHECK:STDOUT:   %D.call = call i32 @_CD.Main.de631560529e9861(i32 %.loc27_5.2), !dbg !25
+// CHECK:STDOUT:   store i32 %D.call, ptr %.loc27_7.3.temp, align 4, !dbg !25
 // CHECK:STDOUT:   ret void, !dbg !27
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CB.Main.3836ccc537683c19(ptr %x) !dbg !28 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc27_5.2 = load double, ptr %x, align 8, !dbg !29
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.3836ccc537683c19(double %.loc27_5.2), !dbg !30
+// CHECK:STDOUT:   %.loc27_7.3.temp = alloca double, align 8, !dbg !29
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc27_7.3.temp), !dbg !29
+// CHECK:STDOUT:   %.loc27_5.2 = load double, ptr %x, align 8, !dbg !30
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.3836ccc537683c19(double %.loc27_5.2), !dbg !29
+// CHECK:STDOUT:   store double %D.call, ptr %.loc27_7.3.temp, align 8, !dbg !29
 // CHECK:STDOUT:   ret void, !dbg !31
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -105,7 +111,7 @@ fn M() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 1, 3, 2 }
 // CHECK:STDOUT: uselistorder ptr @_CA.Main.402deed6b8733082, { 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -138,12 +144,12 @@ fn M() {
 // CHECK:STDOUT: !22 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.402deed6b8733082", scope: null, file: !3, line: 18, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !23 = !DILocation(line: 19, column: 3, scope: !22)
 // CHECK:STDOUT: !24 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.de631560529e9861", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !25 = !DILocation(line: 27, column: 5, scope: !24)
-// CHECK:STDOUT: !26 = !DILocation(line: 27, column: 3, scope: !24)
+// CHECK:STDOUT: !25 = !DILocation(line: 27, column: 3, scope: !24)
+// CHECK:STDOUT: !26 = !DILocation(line: 27, column: 5, scope: !24)
 // CHECK:STDOUT: !27 = !DILocation(line: 26, column: 1, scope: !24)
 // CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.3836ccc537683c19", scope: null, file: !3, line: 26, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !29 = !DILocation(line: 27, column: 5, scope: !28)
-// CHECK:STDOUT: !30 = !DILocation(line: 27, column: 3, scope: !28)
+// CHECK:STDOUT: !29 = !DILocation(line: 27, column: 3, scope: !28)
+// CHECK:STDOUT: !30 = !DILocation(line: 27, column: 5, scope: !28)
 // CHECK:STDOUT: !31 = !DILocation(line: 26, column: 1, scope: !28)
 // CHECK:STDOUT: !32 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.de631560529e9861", scope: null, file: !3, line: 22, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !33 = !DILocation(line: 23, column: 3, scope: !32)

+ 18 - 2
toolchain/lower/testdata/function/generic/call_different_impls_with_const.carbon

@@ -70,18 +70,34 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CG.Main.0dbf1a1c1733b53e() !dbg !16 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc37_20.1 = call i1 @"_CF.X.Main:I.Main"(), !dbg !17
+// CHECK:STDOUT:   %.loc37_20.1.temp = alloca i1, align 1, !dbg !17
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc37_20.1.temp), !dbg !17
+// CHECK:STDOUT:   %.loc37_20.2 = call i1 @"_CF.X.Main:I.Main"(), !dbg !17
+// CHECK:STDOUT:   %.loc37_20.3 = zext i1 %.loc37_20.2 to i8, !dbg !17
+// CHECK:STDOUT:   store i8 %.loc37_20.3, ptr %.loc37_20.1.temp, align 1, !dbg !17
+// CHECK:STDOUT:   %.loc37_20.4 = load i8, ptr %.loc37_20.1.temp, align 1, !dbg !17
+// CHECK:STDOUT:   %.loc37_20.41 = trunc i8 %.loc37_20.4 to i1, !dbg !17
 // CHECK:STDOUT:   ret void, !dbg !18
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CG.Main.358c93ba71c2d336() !dbg !19 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc37_20.1 = call i32 @"_CF.Y.Main:I.Main"(), !dbg !20
+// CHECK:STDOUT:   %.loc37_20.1.temp = alloca i32, align 4, !dbg !20
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc37_20.1.temp), !dbg !20
+// CHECK:STDOUT:   %.loc37_20.2 = call i32 @"_CF.Y.Main:I.Main"(), !dbg !20
+// CHECK:STDOUT:   store i32 %.loc37_20.2, ptr %.loc37_20.1.temp, align 4, !dbg !20
+// CHECK:STDOUT:   %.loc37_20.4 = load i32, ptr %.loc37_20.1.temp, align 4, !dbg !20
 // CHECK:STDOUT:   ret void, !dbg !21
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
+// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0
+// CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
 // CHECK:STDOUT: uselistorder ptr @printf, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 }
+// CHECK:STDOUT:
+// CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
 // CHECK:STDOUT:
 // CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
 // CHECK:STDOUT: !llvm.dbg.cu = !{!2}

+ 15 - 9
toolchain/lower/testdata/function/generic/call_different_specific.carbon

@@ -89,15 +89,21 @@ fn M() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CB.Main.de631560529e9861(ptr %x) !dbg !24 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc34_5.2 = load i32, ptr %x, align 4, !dbg !25
-// CHECK:STDOUT:   %D.call = call i32 @_CD.Main.de631560529e9861(i32 %.loc34_5.2), !dbg !26
+// CHECK:STDOUT:   %.loc34_7.3.temp = alloca i32, align 4, !dbg !25
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc34_7.3.temp), !dbg !25
+// CHECK:STDOUT:   %.loc34_5.2 = load i32, ptr %x, align 4, !dbg !26
+// CHECK:STDOUT:   %D.call = call i32 @_CD.Main.de631560529e9861(i32 %.loc34_5.2), !dbg !25
+// CHECK:STDOUT:   store i32 %D.call, ptr %.loc34_7.3.temp, align 4, !dbg !25
 // CHECK:STDOUT:   ret void, !dbg !27
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: define linkonce_odr void @_CB.Main.3836ccc537683c19(ptr %x) !dbg !28 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %.loc34_5.2 = load double, ptr %x, align 8, !dbg !29
-// CHECK:STDOUT:   %D.call = call double @_CD.Main.3836ccc537683c19(double %.loc34_5.2), !dbg !30
+// CHECK:STDOUT:   %.loc34_7.3.temp = alloca double, align 8, !dbg !29
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc34_7.3.temp), !dbg !29
+// CHECK:STDOUT:   %.loc34_5.2 = load double, ptr %x, align 8, !dbg !30
+// CHECK:STDOUT:   %D.call = call double @_CD.Main.3836ccc537683c19(double %.loc34_5.2), !dbg !29
+// CHECK:STDOUT:   store double %D.call, ptr %.loc34_7.3.temp, align 8, !dbg !29
 // CHECK:STDOUT:   ret void, !dbg !31
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -112,7 +118,7 @@ fn M() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 0, 1, 3, 2 }
 // CHECK:STDOUT: uselistorder ptr @_CA.Main.402deed6b8733082, { 1, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -145,12 +151,12 @@ fn M() {
 // CHECK:STDOUT: !22 = distinct !DISubprogram(name: "A", linkageName: "_CA.Main.402deed6b8733082", scope: null, file: !3, line: 25, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !23 = !DILocation(line: 26, column: 3, scope: !22)
 // CHECK:STDOUT: !24 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.de631560529e9861", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !25 = !DILocation(line: 34, column: 5, scope: !24)
-// CHECK:STDOUT: !26 = !DILocation(line: 34, column: 3, scope: !24)
+// CHECK:STDOUT: !25 = !DILocation(line: 34, column: 3, scope: !24)
+// CHECK:STDOUT: !26 = !DILocation(line: 34, column: 5, scope: !24)
 // CHECK:STDOUT: !27 = !DILocation(line: 33, column: 1, scope: !24)
 // CHECK:STDOUT: !28 = distinct !DISubprogram(name: "B", linkageName: "_CB.Main.3836ccc537683c19", scope: null, file: !3, line: 33, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !29 = !DILocation(line: 34, column: 5, scope: !28)
-// CHECK:STDOUT: !30 = !DILocation(line: 34, column: 3, scope: !28)
+// CHECK:STDOUT: !29 = !DILocation(line: 34, column: 3, scope: !28)
+// CHECK:STDOUT: !30 = !DILocation(line: 34, column: 5, scope: !28)
 // CHECK:STDOUT: !31 = !DILocation(line: 33, column: 1, scope: !28)
 // CHECK:STDOUT: !32 = distinct !DISubprogram(name: "D", linkageName: "_CD.Main.de631560529e9861", scope: null, file: !3, line: 29, type: !5, spFlags: DISPFlagDefinition, unit: !2)
 // CHECK:STDOUT: !33 = !DILocation(line: 30, column: 3, scope: !32)

+ 93 - 66
toolchain/lower/testdata/function/generic/call_recursive_basic.carbon

@@ -36,11 +36,8 @@ fn M() {
   F(ptr_i32, 0);
   F(ptr_f64, 0);
 
-  // TODO: Crashes, hits assertion
-  // `(Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"'
-
-  // var c: C;
-  // F(c, 0);
+  var c: C;
+  F(c, 0);
 }
 
 // CHECK:STDOUT: ; ModuleID = 'call_recursive_basic.carbon'
@@ -60,21 +57,26 @@ fn M() {
 // CHECK:STDOUT:   %m.var = alloca double, align 8, !dbg !10
 // CHECK:STDOUT:   %ptr_i32.var = alloca ptr, align 8, !dbg !11
 // CHECK:STDOUT:   %ptr_f64.var = alloca ptr, align 8, !dbg !12
+// CHECK:STDOUT:   %c.var = alloca {}, align 8, !dbg !13
+// CHECK:STDOUT:   %.loc40_9.5.temp = alloca {}, align 8, !dbg !14
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !9
 // CHECK:STDOUT:   store i32 0, ptr %n.var, align 4, !dbg !9
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %m.var), !dbg !10
 // CHECK:STDOUT:   store double 1.000000e+00, ptr %m.var, align 8, !dbg !10
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_i32.var), !dbg !11
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %ptr_f64.var), !dbg !12
-// CHECK:STDOUT:   %.loc34_5 = load i32, ptr %n.var, align 4, !dbg !13
-// CHECK:STDOUT:   %F.call.loc34 = call i32 @_CF.Main.de631560529e9861(i32 %.loc34_5, i32 0), !dbg !14
-// CHECK:STDOUT:   %.loc35_5 = load double, ptr %m.var, align 8, !dbg !15
-// CHECK:STDOUT:   %F.call.loc35 = call double @_CF.Main.3836ccc537683c19(double %.loc35_5, i32 0), !dbg !16
-// CHECK:STDOUT:   %.loc36_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !17
-// CHECK:STDOUT:   %F.call.loc36 = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %.loc36_5, i32 0), !dbg !18
-// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !19
-// CHECK:STDOUT:   %F.call.loc37 = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %.loc37_5, i32 0), !dbg !20
-// CHECK:STDOUT:   ret void, !dbg !21
+// CHECK:STDOUT:   %.loc34_5 = load i32, ptr %n.var, align 4, !dbg !15
+// CHECK:STDOUT:   %F.call.loc34 = call i32 @_CF.Main.de631560529e9861(i32 %.loc34_5, i32 0), !dbg !16
+// CHECK:STDOUT:   %.loc35_5 = load double, ptr %m.var, align 8, !dbg !17
+// CHECK:STDOUT:   %F.call.loc35 = call double @_CF.Main.3836ccc537683c19(double %.loc35_5, i32 0), !dbg !18
+// CHECK:STDOUT:   %.loc36_5 = load ptr, ptr %ptr_i32.var, align 8, !dbg !19
+// CHECK:STDOUT:   %F.call.loc36 = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %.loc36_5, i32 0), !dbg !20
+// CHECK:STDOUT:   %.loc37_5 = load ptr, ptr %ptr_f64.var, align 8, !dbg !21
+// CHECK:STDOUT:   %F.call.loc37 = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %.loc37_5, i32 0), !dbg !22
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !13
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %.loc40_9.5.temp), !dbg !14
+// CHECK:STDOUT:   call void @_CF.Main.936d996ea935415c(ptr %.loc40_9.5.temp, ptr %c.var, i32 0), !dbg !14
+// CHECK:STDOUT:   ret void, !dbg !23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
@@ -83,50 +85,65 @@ fn M() {
 // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
 // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #1
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr i32 @_CF.Main.de631560529e9861(i32 %x, i32 %count) !dbg !22 {
+// CHECK:STDOUT: define linkonce_odr i32 @_CF.Main.de631560529e9861(i32 %x, i32 %count) !dbg !24 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !25
+// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !26
+// CHECK:STDOUT:
+// CHECK:STDOUT: if.then:                                          ; preds = %entry
+// CHECK:STDOUT:   ret i32 %x, !dbg !27
+// CHECK:STDOUT:
+// CHECK:STDOUT: if.else:                                          ; preds = %entry
+// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !28
+// CHECK:STDOUT:   %F.call = call i32 @_CF.Main.de631560529e9861(i32 %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !29
+// CHECK:STDOUT:   ret i32 %F.call, !dbg !30
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr double @_CF.Main.3836ccc537683c19(double %x, i32 %count) !dbg !31 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !23
-// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !24
+// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !32
+// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !33
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.then:                                          ; preds = %entry
-// CHECK:STDOUT:   ret i32 %x, !dbg !25
+// CHECK:STDOUT:   ret double %x, !dbg !34
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
-// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !26
-// CHECK:STDOUT:   %F.call = call i32 @_CF.Main.de631560529e9861(i32 %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !27
-// CHECK:STDOUT:   ret i32 %F.call, !dbg !28
+// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !35
+// CHECK:STDOUT:   %F.call = call double @_CF.Main.3836ccc537683c19(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !36
+// CHECK:STDOUT:   ret double %F.call, !dbg !37
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr double @_CF.Main.3836ccc537683c19(double %x, i32 %count) !dbg !29 {
+// CHECK:STDOUT: define linkonce_odr ptr @_CF.Main.a194de4a3b8dbd0c(ptr %x, i32 %count) !dbg !38 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !30
-// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !31
+// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !39
+// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !40
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.then:                                          ; preds = %entry
-// CHECK:STDOUT:   ret double %x, !dbg !32
+// CHECK:STDOUT:   ret ptr %x, !dbg !41
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
-// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !33
-// CHECK:STDOUT:   %F.call = call double @_CF.Main.3836ccc537683c19(double %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !34
-// CHECK:STDOUT:   ret double %F.call, !dbg !35
+// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !42
+// CHECK:STDOUT:   %F.call = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !43
+// CHECK:STDOUT:   ret ptr %F.call, !dbg !44
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: define linkonce_odr ptr @_CF.Main.a194de4a3b8dbd0c(ptr %x, i32 %count) !dbg !36 {
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.936d996ea935415c(ptr sret({}) %return, ptr %x, i32 %count) !dbg !45 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !37
-// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !38
+// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Greater.call = icmp sgt i32 %count, 0, !dbg !46
+// CHECK:STDOUT:   br i1 %Int.as.OrderedWith.impl.Greater.call, label %if.then, label %if.else, !dbg !47
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.then:                                          ; preds = %entry
-// CHECK:STDOUT:   ret ptr %x, !dbg !39
+// CHECK:STDOUT:   call void @"_COp.C.Main:Copy.Core"(ptr %return, ptr %x), !dbg !48
+// CHECK:STDOUT:   ret void, !dbg !49
 // CHECK:STDOUT:
 // CHECK:STDOUT: if.else:                                          ; preds = %entry
-// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !40
-// CHECK:STDOUT:   %F.call = call ptr @_CF.Main.a194de4a3b8dbd0c(ptr %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !41
-// CHECK:STDOUT:   ret ptr %F.call, !dbg !42
+// CHECK:STDOUT:   %Int.as.AddWith.impl.Op.call = add i32 %count, 1, !dbg !50
+// CHECK:STDOUT:   call void @_CF.Main.936d996ea935415c(ptr %return, ptr %x, i32 %Int.as.AddWith.impl.Op.call), !dbg !51
+// CHECK:STDOUT:   ret void, !dbg !52
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: ; uselistorder directives
-// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 3, 2, 1, 0 }
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 5, 4, 3, 2, 1, 0 }
 // CHECK:STDOUT: uselistorder ptr @_CF.Main.a194de4a3b8dbd0c, { 1, 2, 0 }
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
@@ -148,33 +165,43 @@ fn M() {
 // CHECK:STDOUT: !10 = !DILocation(line: 30, column: 3, scope: !8)
 // CHECK:STDOUT: !11 = !DILocation(line: 31, column: 3, scope: !8)
 // CHECK:STDOUT: !12 = !DILocation(line: 32, column: 3, scope: !8)
-// CHECK:STDOUT: !13 = !DILocation(line: 34, column: 5, scope: !8)
-// CHECK:STDOUT: !14 = !DILocation(line: 34, column: 3, scope: !8)
-// CHECK:STDOUT: !15 = !DILocation(line: 35, column: 5, scope: !8)
-// CHECK:STDOUT: !16 = !DILocation(line: 35, column: 3, scope: !8)
-// CHECK:STDOUT: !17 = !DILocation(line: 36, column: 5, scope: !8)
-// CHECK:STDOUT: !18 = !DILocation(line: 36, column: 3, scope: !8)
-// CHECK:STDOUT: !19 = !DILocation(line: 37, column: 5, scope: !8)
-// CHECK:STDOUT: !20 = !DILocation(line: 37, column: 3, scope: !8)
-// CHECK:STDOUT: !21 = !DILocation(line: 28, column: 1, scope: !8)
-// CHECK:STDOUT: !22 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.de631560529e9861", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !23 = !DILocation(line: 22, column: 7, scope: !22)
-// CHECK:STDOUT: !24 = !DILocation(line: 22, column: 6, scope: !22)
-// CHECK:STDOUT: !25 = !DILocation(line: 23, column: 5, scope: !22)
-// CHECK:STDOUT: !26 = !DILocation(line: 25, column: 15, scope: !22)
-// CHECK:STDOUT: !27 = !DILocation(line: 25, column: 10, scope: !22)
-// CHECK:STDOUT: !28 = !DILocation(line: 25, column: 3, scope: !22)
-// CHECK:STDOUT: !29 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.3836ccc537683c19", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !30 = !DILocation(line: 22, column: 7, scope: !29)
-// CHECK:STDOUT: !31 = !DILocation(line: 22, column: 6, scope: !29)
-// CHECK:STDOUT: !32 = !DILocation(line: 23, column: 5, scope: !29)
-// CHECK:STDOUT: !33 = !DILocation(line: 25, column: 15, scope: !29)
-// CHECK:STDOUT: !34 = !DILocation(line: 25, column: 10, scope: !29)
-// CHECK:STDOUT: !35 = !DILocation(line: 25, column: 3, scope: !29)
-// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.a194de4a3b8dbd0c", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
-// CHECK:STDOUT: !37 = !DILocation(line: 22, column: 7, scope: !36)
-// CHECK:STDOUT: !38 = !DILocation(line: 22, column: 6, scope: !36)
-// CHECK:STDOUT: !39 = !DILocation(line: 23, column: 5, scope: !36)
-// CHECK:STDOUT: !40 = !DILocation(line: 25, column: 15, scope: !36)
-// CHECK:STDOUT: !41 = !DILocation(line: 25, column: 10, scope: !36)
-// CHECK:STDOUT: !42 = !DILocation(line: 25, column: 3, scope: !36)
+// CHECK:STDOUT: !13 = !DILocation(line: 39, column: 3, scope: !8)
+// CHECK:STDOUT: !14 = !DILocation(line: 40, column: 3, scope: !8)
+// CHECK:STDOUT: !15 = !DILocation(line: 34, column: 5, scope: !8)
+// CHECK:STDOUT: !16 = !DILocation(line: 34, column: 3, scope: !8)
+// CHECK:STDOUT: !17 = !DILocation(line: 35, column: 5, scope: !8)
+// CHECK:STDOUT: !18 = !DILocation(line: 35, column: 3, scope: !8)
+// CHECK:STDOUT: !19 = !DILocation(line: 36, column: 5, scope: !8)
+// CHECK:STDOUT: !20 = !DILocation(line: 36, column: 3, scope: !8)
+// CHECK:STDOUT: !21 = !DILocation(line: 37, column: 5, scope: !8)
+// CHECK:STDOUT: !22 = !DILocation(line: 37, column: 3, scope: !8)
+// CHECK:STDOUT: !23 = !DILocation(line: 28, column: 1, scope: !8)
+// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.de631560529e9861", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !25 = !DILocation(line: 22, column: 7, scope: !24)
+// CHECK:STDOUT: !26 = !DILocation(line: 22, column: 6, scope: !24)
+// CHECK:STDOUT: !27 = !DILocation(line: 23, column: 5, scope: !24)
+// CHECK:STDOUT: !28 = !DILocation(line: 25, column: 15, scope: !24)
+// CHECK:STDOUT: !29 = !DILocation(line: 25, column: 10, scope: !24)
+// CHECK:STDOUT: !30 = !DILocation(line: 25, column: 3, scope: !24)
+// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.3836ccc537683c19", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !32 = !DILocation(line: 22, column: 7, scope: !31)
+// CHECK:STDOUT: !33 = !DILocation(line: 22, column: 6, scope: !31)
+// CHECK:STDOUT: !34 = !DILocation(line: 23, column: 5, scope: !31)
+// CHECK:STDOUT: !35 = !DILocation(line: 25, column: 15, scope: !31)
+// CHECK:STDOUT: !36 = !DILocation(line: 25, column: 10, scope: !31)
+// CHECK:STDOUT: !37 = !DILocation(line: 25, column: 3, scope: !31)
+// CHECK:STDOUT: !38 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.a194de4a3b8dbd0c", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !39 = !DILocation(line: 22, column: 7, scope: !38)
+// CHECK:STDOUT: !40 = !DILocation(line: 22, column: 6, scope: !38)
+// CHECK:STDOUT: !41 = !DILocation(line: 23, column: 5, scope: !38)
+// CHECK:STDOUT: !42 = !DILocation(line: 25, column: 15, scope: !38)
+// CHECK:STDOUT: !43 = !DILocation(line: 25, column: 10, scope: !38)
+// CHECK:STDOUT: !44 = !DILocation(line: 25, column: 3, scope: !38)
+// CHECK:STDOUT: !45 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.936d996ea935415c", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !46 = !DILocation(line: 22, column: 7, scope: !45)
+// CHECK:STDOUT: !47 = !DILocation(line: 22, column: 6, scope: !45)
+// CHECK:STDOUT: !48 = !DILocation(line: 23, column: 12, scope: !45)
+// CHECK:STDOUT: !49 = !DILocation(line: 23, column: 5, scope: !45)
+// CHECK:STDOUT: !50 = !DILocation(line: 25, column: 15, scope: !45)
+// CHECK:STDOUT: !51 = !DILocation(line: 25, column: 10, scope: !45)
+// CHECK:STDOUT: !52 = !DILocation(line: 25, column: 3, scope: !45)

+ 278 - 0
toolchain/lower/testdata/function/generic/type_representation.carbon

@@ -0,0 +1,278 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon
+//
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/function/generic/type_representation.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/function/generic/type_representation.carbon
+
+interface Copy {
+  fn Op[self: Self]() -> Self;
+}
+
+fn F[T:! Copy](a: T) -> T {
+  var v: T = a.Op();
+  return a.Op();
+}
+
+impl i32 as Copy {
+  fn Op[self: i32]() -> i32 {
+    return self;
+  }
+}
+
+fn F_i32(a: i32) -> i32 {
+  return F(a);
+}
+
+class X {
+  var a: i32;
+  var b: i32;
+
+  impl as Copy {
+    fn Op[self: X]() -> X {
+      return {.a = self.a, .b = self.b};
+    }
+  }
+}
+
+fn F_X(a: X) -> X {
+  return F(a);
+}
+
+impl () as Copy {
+  fn Op[self: ()]() -> () {
+    return ();
+  }
+}
+
+fn F_empty_tuple(a: ()) -> () {
+  return F(a);
+}
+
+impl (i32, i32) as Copy {
+  fn Op[self: (i32, i32)]() -> (i32, i32) {
+    return self;
+  }
+}
+
+fn F_two_tuple(a: (i32, i32)) -> (i32, i32) {
+  return F(a);
+}
+
+impl ((i32, i32), X) as Copy {
+  fn Op[self: ((i32, i32), X)]() -> ((i32, i32), X) {
+    return (self.0.(Copy.Op)(), self.1.(Copy.Op)());
+  }
+}
+
+fn F_nested_tuple(a: ((i32, i32), X)) -> ((i32, i32), X) {
+  return F(a);
+}
+
+// CHECK:STDOUT: ; ModuleID = 'type_representation.carbon'
+// CHECK:STDOUT: source_filename = "type_representation.carbon"
+// CHECK:STDOUT:
+// CHECK:STDOUT: define i32 @"_COp.Int.Core:Copy.Main"(i32 %self) !dbg !4 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   ret i32 %self, !dbg !7
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define i32 @_CF_i32.Main(i32 %a) !dbg !8 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %F.call = call i32 @_CF.Main.c51f5dcf0e081157(i32 %a), !dbg !9
+// CHECK:STDOUT:   ret i32 %F.call, !dbg !10
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @"_COp.X.Main:Copy.Main"(ptr sret({ i32, i32 }) %return, ptr %self) !dbg !11 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %.loc38_24.1.a = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 0, !dbg !12
+// CHECK:STDOUT:   %.loc38_24.2 = load i32, ptr %.loc38_24.1.a, align 4, !dbg !12
+// CHECK:STDOUT:   %.loc38_37.1.b = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 1, !dbg !13
+// CHECK:STDOUT:   %.loc38_37.2 = load i32, ptr %.loc38_37.1.b, align 4, !dbg !13
+// CHECK:STDOUT:   %.loc38_39.2.a = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !14
+// CHECK:STDOUT:   store i32 %.loc38_24.2, ptr %.loc38_39.2.a, align 4, !dbg !14
+// CHECK:STDOUT:   %.loc38_39.4.b = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !14
+// CHECK:STDOUT:   store i32 %.loc38_37.2, ptr %.loc38_39.4.b, align 4, !dbg !14
+// CHECK:STDOUT:   ret void, !dbg !15
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CF_X.Main(ptr sret({ i32, i32 }) %return, ptr %a) !dbg !16 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @_CF.Main.b1d03582403d0f2e(ptr %return, ptr %a), !dbg !17
+// CHECK:STDOUT:   ret void, !dbg !18
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @"_COp.61ea2aba74ab3bf1:Copy.Main"() !dbg !19 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   ret void, !dbg !20
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CF_empty_tuple.Main() !dbg !21 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @_CF.Main.f0b2e3523ff3fa17(), !dbg !22
+// CHECK:STDOUT:   ret void, !dbg !23
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @"_COp.d07e2731f1087d49:Copy.Main"(ptr sret({ i32, i32 }) %return, ptr %self) !dbg !24 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %tuple.elem0.loc59_12.1.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 0, !dbg !25
+// CHECK:STDOUT:   %tuple.elem0.loc59_12.1.tuple.elem.load = load i32, ptr %tuple.elem0.loc59_12.1.tuple.elem, align 4, !dbg !25
+// CHECK:STDOUT:   %tuple.elem0.loc59_12.2.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 0, !dbg !25
+// CHECK:STDOUT:   store i32 %tuple.elem0.loc59_12.1.tuple.elem.load, ptr %tuple.elem0.loc59_12.2.tuple.elem, align 4, !dbg !25
+// CHECK:STDOUT:   %tuple.elem1.loc59_12.1.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %self, i32 0, i32 1, !dbg !25
+// CHECK:STDOUT:   %tuple.elem1.loc59_12.1.tuple.elem.load = load i32, ptr %tuple.elem1.loc59_12.1.tuple.elem, align 4, !dbg !25
+// CHECK:STDOUT:   %tuple.elem1.loc59_12.2.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %return, i32 0, i32 1, !dbg !25
+// CHECK:STDOUT:   store i32 %tuple.elem1.loc59_12.1.tuple.elem.load, ptr %tuple.elem1.loc59_12.2.tuple.elem, align 4, !dbg !25
+// CHECK:STDOUT:   ret void, !dbg !26
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CF_two_tuple.Main(ptr sret({ i32, i32 }) %return, ptr %a) !dbg !27 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @_CF.Main.09ed05d6841b72fa(ptr %return, ptr %a), !dbg !28
+// CHECK:STDOUT:   ret void, !dbg !29
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @"_COp.4af564822fd0c29a:Copy.Main"(ptr sret({ { i32, i32 }, { i32, i32 } }) %return, ptr %self) !dbg !30 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %tuple.elem0.loc69_17.tuple.elem = getelementptr inbounds nuw { ptr, ptr }, ptr %self, i32 0, i32 0, !dbg !31
+// CHECK:STDOUT:   %tuple.elem0.loc69_17.tuple.elem.load = load ptr, ptr %tuple.elem0.loc69_17.tuple.elem, align 8, !dbg !31
+// CHECK:STDOUT:   %tuple.elem0.loc69_51.tuple.elem = getelementptr inbounds nuw { { i32, i32 }, { i32, i32 } }, ptr %return, i32 0, i32 0, !dbg !32
+// CHECK:STDOUT:   call void @"_COp.d07e2731f1087d49:Copy.Main"(ptr %tuple.elem0.loc69_51.tuple.elem, ptr %tuple.elem0.loc69_17.tuple.elem.load), !dbg !31
+// CHECK:STDOUT:   %tuple.elem1.loc69_37.tuple.elem = getelementptr inbounds nuw { ptr, ptr }, ptr %self, i32 0, i32 1, !dbg !33
+// CHECK:STDOUT:   %tuple.elem1.loc69_37.tuple.elem.load = load ptr, ptr %tuple.elem1.loc69_37.tuple.elem, align 8, !dbg !33
+// CHECK:STDOUT:   %tuple.elem1.loc69_51.tuple.elem = getelementptr inbounds nuw { { i32, i32 }, { i32, i32 } }, ptr %return, i32 0, i32 1, !dbg !32
+// CHECK:STDOUT:   call void @"_COp.X.Main:Copy.Main"(ptr %tuple.elem1.loc69_51.tuple.elem, ptr %tuple.elem1.loc69_37.tuple.elem.load), !dbg !33
+// CHECK:STDOUT:   ret void, !dbg !34
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define void @_CF_nested_tuple.Main(ptr sret({ { i32, i32 }, { i32, i32 } }) %return, ptr %a) !dbg !35 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   call void @_CF.Main.6513c914c89dac0d(ptr %return, ptr %a), !dbg !36
+// CHECK:STDOUT:   ret void, !dbg !37
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr i32 @_CF.Main.c51f5dcf0e081157(i32 %a) !dbg !38 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %v.var = alloca i32, align 4, !dbg !39
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %v.var), !dbg !39
+// CHECK:STDOUT:   %.loc18_19 = call i32 @"_COp.Int.Core:Copy.Main"(i32 %a), !dbg !40
+// CHECK:STDOUT:   store i32 %.loc18_19, ptr %v.var, align 4, !dbg !39
+// CHECK:STDOUT:   %.loc19_15 = call i32 @"_COp.Int.Core:Copy.Main"(i32 %a), !dbg !41
+// CHECK:STDOUT:   ret i32 %.loc19_15, !dbg !42
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.b1d03582403d0f2e(ptr sret({ i32, i32 }) %return, ptr %a) !dbg !43 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %v.var = alloca { i32, i32 }, align 8, !dbg !44
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %v.var), !dbg !44
+// CHECK:STDOUT:   call void @"_COp.X.Main:Copy.Main"(ptr %v.var, ptr %a), !dbg !45
+// CHECK:STDOUT:   call void @"_COp.X.Main:Copy.Main"(ptr %return, ptr %a), !dbg !46
+// CHECK:STDOUT:   ret void, !dbg !47
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.f0b2e3523ff3fa17() !dbg !48 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %v.var = alloca {}, align 8, !dbg !49
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %v.var), !dbg !49
+// CHECK:STDOUT:   call void @"_COp.61ea2aba74ab3bf1:Copy.Main"(), !dbg !50
+// CHECK:STDOUT:   call void @"_COp.61ea2aba74ab3bf1:Copy.Main"(), !dbg !51
+// CHECK:STDOUT:   ret void, !dbg !52
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.09ed05d6841b72fa(ptr sret({ i32, i32 }) %return, ptr %a) !dbg !53 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %v.var = alloca { i32, i32 }, align 8, !dbg !54
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %v.var), !dbg !54
+// CHECK:STDOUT:   call void @"_COp.d07e2731f1087d49:Copy.Main"(ptr %v.var, ptr %a), !dbg !55
+// CHECK:STDOUT:   call void @"_COp.d07e2731f1087d49:Copy.Main"(ptr %return, ptr %a), !dbg !56
+// CHECK:STDOUT:   ret void, !dbg !57
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: define linkonce_odr void @_CF.Main.6513c914c89dac0d(ptr sret({ { i32, i32 }, { i32, i32 } }) %return, ptr %a) !dbg !58 {
+// CHECK:STDOUT: entry:
+// CHECK:STDOUT:   %v.var = alloca { { i32, i32 }, { i32, i32 } }, align 8, !dbg !59
+// CHECK:STDOUT:   call void @llvm.lifetime.start.p0(ptr %v.var), !dbg !59
+// CHECK:STDOUT:   call void @"_COp.4af564822fd0c29a:Copy.Main"(ptr %v.var, ptr %a), !dbg !60
+// CHECK:STDOUT:   call void @"_COp.4af564822fd0c29a:Copy.Main"(ptr %return, ptr %a), !dbg !61
+// CHECK:STDOUT:   ret void, !dbg !62
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0
+// CHECK:STDOUT:
+// CHECK:STDOUT: ; uselistorder directives
+// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 4, 3, 2, 1, 0 }
+// CHECK:STDOUT:
+// CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+// CHECK:STDOUT:
+// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
+// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
+// CHECK:STDOUT:
+// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
+// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+// CHECK:STDOUT: !3 = !DIFile(filename: "type_representation.carbon", directory: "")
+// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Op", linkageName: "_COp.Int.Core:Copy.Main", scope: null, file: !3, line: 23, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
+// CHECK:STDOUT: !6 = !{}
+// CHECK:STDOUT: !7 = !DILocation(line: 24, column: 5, scope: !4)
+// CHECK:STDOUT: !8 = distinct !DISubprogram(name: "F_i32", linkageName: "_CF_i32.Main", scope: null, file: !3, line: 28, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !9 = !DILocation(line: 29, column: 10, scope: !8)
+// CHECK:STDOUT: !10 = !DILocation(line: 29, column: 3, scope: !8)
+// CHECK:STDOUT: !11 = distinct !DISubprogram(name: "Op", linkageName: "_COp.X.Main:Copy.Main", scope: null, file: !3, line: 37, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !12 = !DILocation(line: 38, column: 20, scope: !11)
+// CHECK:STDOUT: !13 = !DILocation(line: 38, column: 33, scope: !11)
+// CHECK:STDOUT: !14 = !DILocation(line: 38, column: 14, scope: !11)
+// CHECK:STDOUT: !15 = !DILocation(line: 38, column: 7, scope: !11)
+// CHECK:STDOUT: !16 = distinct !DISubprogram(name: "F_X", linkageName: "_CF_X.Main", scope: null, file: !3, line: 43, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !17 = !DILocation(line: 44, column: 10, scope: !16)
+// CHECK:STDOUT: !18 = !DILocation(line: 44, column: 3, scope: !16)
+// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "Op", linkageName: "_COp.61ea2aba74ab3bf1:Copy.Main", scope: null, file: !3, line: 48, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !20 = !DILocation(line: 49, column: 5, scope: !19)
+// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "F_empty_tuple", linkageName: "_CF_empty_tuple.Main", scope: null, file: !3, line: 53, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !22 = !DILocation(line: 54, column: 10, scope: !21)
+// CHECK:STDOUT: !23 = !DILocation(line: 54, column: 3, scope: !21)
+// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "Op", linkageName: "_COp.d07e2731f1087d49:Copy.Main", scope: null, file: !3, line: 58, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !25 = !DILocation(line: 59, column: 12, scope: !24)
+// CHECK:STDOUT: !26 = !DILocation(line: 59, column: 5, scope: !24)
+// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "F_two_tuple", linkageName: "_CF_two_tuple.Main", scope: null, file: !3, line: 63, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !28 = !DILocation(line: 64, column: 10, scope: !27)
+// CHECK:STDOUT: !29 = !DILocation(line: 64, column: 3, scope: !27)
+// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "Op", linkageName: "_COp.4af564822fd0c29a:Copy.Main", scope: null, file: !3, line: 68, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !31 = !DILocation(line: 69, column: 13, scope: !30)
+// CHECK:STDOUT: !32 = !DILocation(line: 69, column: 12, scope: !30)
+// CHECK:STDOUT: !33 = !DILocation(line: 69, column: 33, scope: !30)
+// CHECK:STDOUT: !34 = !DILocation(line: 69, column: 5, scope: !30)
+// CHECK:STDOUT: !35 = distinct !DISubprogram(name: "F_nested_tuple", linkageName: "_CF_nested_tuple.Main", scope: null, file: !3, line: 73, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !36 = !DILocation(line: 74, column: 10, scope: !35)
+// CHECK:STDOUT: !37 = !DILocation(line: 74, column: 3, scope: !35)
+// CHECK:STDOUT: !38 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.c51f5dcf0e081157", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !39 = !DILocation(line: 18, column: 3, scope: !38)
+// CHECK:STDOUT: !40 = !DILocation(line: 18, column: 14, scope: !38)
+// CHECK:STDOUT: !41 = !DILocation(line: 19, column: 10, scope: !38)
+// CHECK:STDOUT: !42 = !DILocation(line: 19, column: 3, scope: !38)
+// CHECK:STDOUT: !43 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.b1d03582403d0f2e", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !44 = !DILocation(line: 18, column: 3, scope: !43)
+// CHECK:STDOUT: !45 = !DILocation(line: 18, column: 14, scope: !43)
+// CHECK:STDOUT: !46 = !DILocation(line: 19, column: 10, scope: !43)
+// CHECK:STDOUT: !47 = !DILocation(line: 19, column: 3, scope: !43)
+// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.f0b2e3523ff3fa17", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !49 = !DILocation(line: 18, column: 3, scope: !48)
+// CHECK:STDOUT: !50 = !DILocation(line: 18, column: 14, scope: !48)
+// CHECK:STDOUT: !51 = !DILocation(line: 19, column: 10, scope: !48)
+// CHECK:STDOUT: !52 = !DILocation(line: 19, column: 3, scope: !48)
+// CHECK:STDOUT: !53 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.09ed05d6841b72fa", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !54 = !DILocation(line: 18, column: 3, scope: !53)
+// CHECK:STDOUT: !55 = !DILocation(line: 18, column: 14, scope: !53)
+// CHECK:STDOUT: !56 = !DILocation(line: 19, column: 10, scope: !53)
+// CHECK:STDOUT: !57 = !DILocation(line: 19, column: 3, scope: !53)
+// CHECK:STDOUT: !58 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main.6513c914c89dac0d", scope: null, file: !3, line: 17, type: !5, spFlags: DISPFlagDefinition, unit: !2)
+// CHECK:STDOUT: !59 = !DILocation(line: 18, column: 3, scope: !58)
+// CHECK:STDOUT: !60 = !DILocation(line: 18, column: 14, scope: !58)
+// CHECK:STDOUT: !61 = !DILocation(line: 19, column: 10, scope: !58)
+// CHECK:STDOUT: !62 = !DILocation(line: 19, column: 3, scope: !58)

+ 3 - 0
toolchain/sem_ir/expr_info.cpp

@@ -293,6 +293,9 @@ auto FindReturnSlotArgForInitializer(const File& sem_ir, InstId init_id)
         }
         return sem_ir.inst_blocks().Get(call.args_id).back();
       }
+      case CARBON_KIND(ErrorInst _): {
+        return InstId::None;
+      }
       default:
         CARBON_FATAL("Initialization from unexpected inst {0}", init_untyped);
     }

+ 6 - 0
toolchain/sem_ir/type_info.cpp

@@ -17,6 +17,9 @@ auto ValueRepr::Print(llvm::raw_ostream& out) const -> void {
     case Unknown:
       out << "unknown";
       break;
+    case Dependent:
+      out << "dependent";
+      break;
     case None:
       out << "none";
       break;
@@ -56,6 +59,9 @@ auto InitRepr::ForType(const File& file, TypeId type_id) -> InitRepr {
     case ValueRepr::None:
       return {.kind = InitRepr::None};
 
+    case ValueRepr::Dependent:
+      return {.kind = InitRepr::Dependent};
+
     case ValueRepr::Copy:
       // TODO: Use in-place initialization for types that have non-trivial
       // destructive move.

+ 21 - 1
toolchain/sem_ir/type_info.h

@@ -22,6 +22,8 @@ struct ValueRepr : public Printable<ValueRepr> {
     // The value representation is not yet known. This is used for incomplete
     // types.
     Unknown,
+    // The value representation is dependent because the type is symbolic.
+    Dependent,
     // The type has no value representation. This is used for empty types, such
     // as `()`, where there is no value.
     None,
@@ -93,6 +95,9 @@ struct InitRepr : Printable<InitRepr> {
     // The type has no initializing representation. This is used for empty
     // types, where no initialization is necessary.
     None,
+    // The initializing representation is dependent because the type is
+    // symbolic.
+    Dependent,
     // An initializing expression produces an object representation by value,
     // which is copied into the initialized object.
     ByCopy,
@@ -117,12 +122,27 @@ struct InitRepr : Printable<InitRepr> {
   // representation of the type. Provided for symmetry with `ValueRepr`.
   auto IsCopyOfObjectRepr() const -> bool { return kind == ByCopy; }
 
+  // Returns whether the initializing representation might be by-copy, and
+  // therefore might require a final destination store.
+  auto MightBeByCopy() const -> bool {
+    return kind == ByCopy || kind == Dependent;
+  }
+
+  // Returns whether the initializing representation might be in-place, and
+  // therefore might require a destination address to be provided as input.
+  auto MightBeInPlace() const -> bool {
+    return kind == InPlace || kind == Dependent;
+  }
+
   auto Print(llvm::raw_ostream& out) const -> void {
     out << "{kind: ";
     switch (kind) {
       case None:
         out << "None";
         break;
+      case Dependent:
+        out << "Dependent";
+        break;
       case ByCopy:
         out << "ByCopy";
         break;
@@ -161,7 +181,7 @@ struct ReturnTypeInfo : public Printable<ReturnTypeInfo> {
   // only be called for valid return info.
   auto has_return_slot() const -> bool {
     CARBON_CHECK(is_valid());
-    return init_repr.kind == InitRepr::InPlace;
+    return init_repr.MightBeInPlace();
   }
 
   auto Print(llvm::raw_ostream& out) const -> void {