Ver Fonte

Handle destruction for return statements (#5785)

This just catches uses equivalent to `return;` and `return <expr>;`.
Note it's just extending the current implicit return logic, not really
adding much unique here.

I'm still delaying break and continue because those require partial
destruction, which is more work and I want to be careful to get it
right.
Jon Ross-Perkins há 9 meses atrás
pai
commit
6a53947c5c
65 ficheiros alterados com 3313 adições e 684 exclusões
  1. 3 4
      toolchain/check/control_flow.cpp
  2. 17 5
      toolchain/check/control_flow.h
  3. 5 4
      toolchain/check/return.cpp
  4. 21 0
      toolchain/check/testdata/array/import.carbon
  5. 21 0
      toolchain/check/testdata/array/index_not_literal.carbon
  6. 20 0
      toolchain/check/testdata/basics/dump_sem_ir_ranges.carbon
  7. 164 10
      toolchain/check/testdata/class/adapter/adapt_copy.carbon
  8. 42 2
      toolchain/check/testdata/class/generic/import.carbon
  9. 52 10
      toolchain/check/testdata/class/generic/init.carbon
  10. 31 6
      toolchain/check/testdata/class/generic/member_access.carbon
  11. 58 8
      toolchain/check/testdata/class/generic/member_type.carbon
  12. 110 7
      toolchain/check/testdata/class/generic/method_deduce.carbon
  13. 22 0
      toolchain/check/testdata/class/inheritance_access.carbon
  14. 23 0
      toolchain/check/testdata/class/init_as.carbon
  15. 29 0
      toolchain/check/testdata/class/init_nested.carbon
  16. 23 0
      toolchain/check/testdata/class/local.carbon
  17. 48 8
      toolchain/check/testdata/class/method.carbon
  18. 23 0
      toolchain/check/testdata/class/static_method.carbon
  19. 139 0
      toolchain/check/testdata/deduce/array.carbon
  20. 151 21
      toolchain/check/testdata/deduce/generic_type.carbon
  21. 22 0
      toolchain/check/testdata/deduce/tuple.carbon
  22. 64 0
      toolchain/check/testdata/deduce/type_operator.carbon
  23. 121 22
      toolchain/check/testdata/for/actual.carbon
  24. 16 16
      toolchain/check/testdata/for/basic.carbon
  25. 154 154
      toolchain/check/testdata/for/pattern.carbon
  26. 50 6
      toolchain/check/testdata/function/generic/call.carbon
  27. 21 0
      toolchain/check/testdata/function/generic/deduce.carbon
  28. 29 16
      toolchain/check/testdata/generic/call_basic_depth.carbon
  29. 47 15
      toolchain/check/testdata/generic/template_dependence.carbon
  30. 27 4
      toolchain/check/testdata/if_expr/basic.carbon
  31. 74 27
      toolchain/check/testdata/if_expr/constant_condition.carbon
  32. 41 0
      toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon
  33. 23 2
      toolchain/check/testdata/impl/generic_redeclaration.carbon
  34. 71 9
      toolchain/check/testdata/impl/impl_thunk.carbon
  35. 43 21
      toolchain/check/testdata/impl/import_self.carbon
  36. 99 47
      toolchain/check/testdata/impl/import_thunk.carbon
  37. 41 13
      toolchain/check/testdata/impl/interface_args.carbon
  38. 72 50
      toolchain/check/testdata/impl/lookup/generic.carbon
  39. 57 35
      toolchain/check/testdata/impl/lookup/impl_forall.carbon
  40. 48 14
      toolchain/check/testdata/interface/generic_method.carbon
  41. 32 4
      toolchain/check/testdata/namespace/shadow.carbon
  42. 3 2
      toolchain/check/testdata/operators/overloaded/add.carbon
  43. 3 2
      toolchain/check/testdata/operators/overloaded/bit_and.carbon
  44. 3 2
      toolchain/check/testdata/operators/overloaded/bit_complement.carbon
  45. 3 2
      toolchain/check/testdata/operators/overloaded/bit_or.carbon
  46. 3 2
      toolchain/check/testdata/operators/overloaded/bit_xor.carbon
  47. 3 2
      toolchain/check/testdata/operators/overloaded/div.carbon
  48. 3 2
      toolchain/check/testdata/operators/overloaded/left_shift.carbon
  49. 3 13
      toolchain/check/testdata/operators/overloaded/mod.carbon
  50. 3 2
      toolchain/check/testdata/operators/overloaded/mul.carbon
  51. 3 2
      toolchain/check/testdata/operators/overloaded/negate.carbon
  52. 3 2
      toolchain/check/testdata/operators/overloaded/right_shift.carbon
  53. 3 2
      toolchain/check/testdata/operators/overloaded/sub.carbon
  54. 29 7
      toolchain/check/testdata/pointer/address_of_deref.carbon
  55. 49 14
      toolchain/check/testdata/pointer/basic.carbon
  56. 27 4
      toolchain/check/testdata/return/fail_return_with_returned_var.carbon
  57. 50 6
      toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon
  58. 57 16
      toolchain/check/testdata/return/fail_returned_var_shadow.carbon
  59. 23 0
      toolchain/check/testdata/return/fail_returned_var_type.carbon
  60. 714 42
      toolchain/check/testdata/return/import_convert_function.carbon
  61. 27 4
      toolchain/check/testdata/return/returned_var.carbon
  62. 63 16
      toolchain/check/testdata/return/returned_var_scope.carbon
  63. 23 0
      toolchain/check/testdata/struct/literal_member_access.carbon
  64. 21 0
      toolchain/check/testdata/tuple/element_access.carbon
  65. 40 0
      toolchain/check/testdata/tuple/in_place_tuple_init.carbon

+ 3 - 4
toolchain/check/control_flow.cpp

@@ -165,11 +165,10 @@ static auto AddCleanupBlock(Context& context) -> void {
   }
 }
 
-auto AddReturnCleanupBlock(
-    Context& context,
-    typename decltype(SemIR::Return::Kind)::TypedNodeId node_id) -> void {
+auto AddReturnCleanupBlock(Context& context,
+                           SemIR::LocIdAndInst loc_id_and_inst) -> void {
   AddCleanupBlock(context);
-  AddInst(context, node_id, SemIR::Return{});
+  AddInst(context, loc_id_and_inst);
 }
 
 }  // namespace Carbon::Check

+ 17 - 5
toolchain/check/control_flow.h

@@ -9,6 +9,7 @@
 #include "toolchain/check/inst.h"
 #include "toolchain/parse/typed_nodes.h"
 #include "toolchain/sem_ir/ids.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -89,6 +90,8 @@ auto AddInstWithCleanupInNoBlock(Context& context, LocT loc, InstT inst)
   return inst_id;
 }
 
+// Adds a return cleanup block, including the returning instruction.
+//
 // Cleanup blocks are an effort to share cleanup instructions across equivalent
 // scope-ending instructions (for example, all `return;` instructions are
 // equivalent). Structurally, they should first run non-shared cleanup, then
@@ -114,11 +117,20 @@ auto AddInstWithCleanupInNoBlock(Context& context, LocT loc, InstT inst)
 //     // Cleanup block 3: reuse cleanup block 2.
 //   }
 //
-// TODO: Add support for `return;`, `return <expr>;`, `break;`,and `continue;`;
-// also, add reuse (described above but not done).
-auto AddReturnCleanupBlock(
-    Context& context,
-    typename decltype(SemIR::Return::Kind)::TypedNodeId node_id) -> void;
+// TODO: Add support for `break;` and `continue;`.
+// TODO: Add reuse (described above but not done).
+auto AddReturnCleanupBlock(Context& context,
+                           SemIR::LocIdAndInst loc_id_and_inst) -> void;
+
+template <typename LocT>
+auto AddReturnCleanupBlock(Context& context, LocT loc) -> void {
+  AddReturnCleanupBlock(context, SemIR::LocIdAndInst(loc, SemIR::Return{}));
+}
+template <typename LocT>
+auto AddReturnCleanupBlockWithExpr(Context& context, LocT loc,
+                                   SemIR::ReturnExpr inst) -> void {
+  AddReturnCleanupBlock(context, SemIR::LocIdAndInst(loc, inst));
+}
 
 }  // namespace Carbon::Check
 

+ 5 - 4
toolchain/check/return.cpp

@@ -5,6 +5,7 @@
 #include "toolchain/check/return.h"
 
 #include "toolchain/check/context.h"
+#include "toolchain/check/control_flow.h"
 #include "toolchain/check/convert.h"
 #include "toolchain/check/inst.h"
 
@@ -125,7 +126,7 @@ auto BuildReturnWithNoExpr(Context& context, SemIR::LocId loc_id) -> void {
     diag.Emit();
   }
 
-  AddInst<SemIR::Return>(context, loc_id, {});
+  AddReturnCleanupBlock(context, loc_id);
 }
 
 auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id,
@@ -165,8 +166,8 @@ auto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id,
         ConvertToValueOfType(context, loc_id, expr_id, return_info.type_id);
   }
 
-  AddInst<SemIR::ReturnExpr>(context, loc_id,
-                             {.expr_id = expr_id, .dest_id = return_slot_id});
+  AddReturnCleanupBlockWithExpr(
+      context, loc_id, {.expr_id = expr_id, .dest_id = return_slot_id});
 }
 
 auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)
@@ -190,7 +191,7 @@ auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)
     return_slot_id = SemIR::InstId::None;
   }
 
-  AddInst<SemIR::ReturnExpr>(
+  AddReturnCleanupBlockWithExpr(
       context, node_id,
       {.expr_id = returned_var_id, .dest_id = return_slot_id});
 }

+ 21 - 0
toolchain/check/testdata/array/import.carbon

@@ -30,15 +30,30 @@ fn G(n: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete]
 // CHECK:STDOUT:   %array_type: type = array_type %int_42, %i32 [concrete]
+// CHECK:STDOUT:   %ptr.830: type = ptr_type %array_type [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.cc7: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.type.b8c: type = fn_type @Op.3, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.552: %Op.type.b8c = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type, (%Destroy.impl_witness.cc7) [concrete]
+// CHECK:STDOUT:   %.1ca: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.552, @Op.3(%array_type) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//library, F, loaded [concrete = constants.%F]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G(%n.param: %i32) -> %i32 {
@@ -52,6 +67,12 @@ fn G(n: i32) -> i32 {
 // CHECK:STDOUT:   %i32.loc6: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:   %.loc6_15.1: ref %i32 = array_index %.loc6_12.2, %n.ref
 // CHECK:STDOUT:   %.loc6_15.2: %i32 = bind_value %.loc6_15.1
+// CHECK:STDOUT:   %impl.elem0: %.1ca = impl_witness_access constants.%Destroy.impl_witness.cc7, element0 [concrete = constants.%Op.552]
+// CHECK:STDOUT:   %bound_method.loc6_12.1: <bound method> = bound_method %.loc6_12.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%array_type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_12.2: <bound method> = bound_method %.loc6_12.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.830 = addr_of %.loc6_12.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc6_12.2(%addr)
 // CHECK:STDOUT:   return %.loc6_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 0
toolchain/check/testdata/array/index_not_literal.carbon

@@ -50,11 +50,13 @@ fn F(a: array({}, 3)) -> {} {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.f01: type = ptr_type %array_type [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]
@@ -80,11 +82,24 @@ fn F(a: array({}, 3)) -> {} {
 // CHECK:STDOUT:   %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.14a: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.type.1e4: type = fn_type @Op.3, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.f0b: %Op.type.1e4 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type, (%Destroy.impl_witness.14a) [concrete]
+// CHECK:STDOUT:   %.9c9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.f0b, @Op.3(%array_type) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%arr.param: %array_type, %i.param: %i32) -> %i32 {
@@ -149,6 +164,12 @@ fn F(a: array({}, 3)) -> {} {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.ref(%.loc10_20.15, %.loc10_23.2)
 // CHECK:STDOUT:   %.loc10_25.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc10_25.2: %i32 = converted %F.call, %.loc10_25.1
+// CHECK:STDOUT:   %impl.elem0.loc10_20.4: %.9c9 = impl_witness_access constants.%Destroy.impl_witness.14a, element0 [concrete = constants.%Op.f0b]
+// CHECK:STDOUT:   %bound_method.loc10_20.7: <bound method> = bound_method %.loc10_20.3, %impl.elem0.loc10_20.4
+// CHECK:STDOUT:   %specific_fn.loc10_20.4: <specific function> = specific_function %impl.elem0.loc10_20.4, @Op.3(constants.%array_type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc10_20.8: <bound method> = bound_method %.loc10_20.3, %specific_fn.loc10_20.4
+// CHECK:STDOUT:   %addr: %ptr.f01 = addr_of %.loc10_20.3
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc10_20.8(%addr)
 // CHECK:STDOUT:   return %.loc10_25.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 20 - 0
toolchain/check/testdata/basics/dump_sem_ir_ranges.carbon

@@ -98,6 +98,18 @@ fn F();
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]
 // CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
@@ -106,6 +118,8 @@ fn F();
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -149,6 +163,12 @@ fn F();
 // CHECK:STDOUT:   %c.ref.loc20: ref %empty_tuple.type = name_ref c, %c
 // CHECK:STDOUT:   %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc20: %empty_tuple.type = converted %c.ref.loc20, %tuple [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:   %impl.elem0: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:   %bound_method.loc18_3.1: <bound method> = bound_method %c.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc18_3.2: <bound method> = bound_method %c.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %c.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc18_3.2(%addr)
 // CHECK:STDOUT:   return %.loc20
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 164 - 10
toolchain/check/testdata/class/adapter/adapt_copy.carbon

@@ -130,6 +130,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %AdaptCopyable: type = class_type @AdaptCopyable [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]
@@ -137,6 +138,18 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.cdf: type = pattern_type %AdaptCopyable [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.a93: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%AdaptCopyable) [concrete]
+// CHECK:STDOUT:   %Op.type.b65: type = fn_type @Op.2, @impl.49c(%AdaptCopyable) [concrete]
+// CHECK:STDOUT:   %Op.f60: %Op.type.b65 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.4c1: type = ptr_type %AdaptCopyable [concrete]
+// CHECK:STDOUT:   %Destroy.facet.279: %Destroy.type = facet_value %AdaptCopyable, (%Destroy.impl_witness.a93) [concrete]
+// CHECK:STDOUT:   %.6a3: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.279 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.e4c: <specific function> = specific_function %Op.f60, @Op.2(%AdaptCopyable) [concrete]
 // CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]
 // CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]
 // CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]
@@ -145,16 +158,27 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.813: type = pattern_type %tuple.type.2a3 [concrete]
 // CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]
 // CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.c30: type = ptr_type %tuple.type.2a3 [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.d22: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.2a3) [concrete]
+// CHECK:STDOUT:   %Op.type.f33: type = fn_type @Op.2, @impl.49c(%tuple.type.2a3) [concrete]
+// CHECK:STDOUT:   %Op.f7d: %Op.type.f33 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.ced: %Destroy.type = facet_value %tuple.type.2a3, (%Destroy.impl_witness.d22) [concrete]
+// CHECK:STDOUT:   %.c90: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.ced [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.2af: <specific function> = specific_function %Op.f7d, @Op.2(%tuple.type.2a3) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .UInt = %Core.UInt
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -229,6 +253,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %d: ref %AdaptCopyable = bind_name d, %d.var
 // CHECK:STDOUT:   %d.ref: ref %AdaptCopyable = name_ref d, %d
 // CHECK:STDOUT:   %.loc12: %AdaptCopyable = bind_value %d.ref
+// CHECK:STDOUT:   %impl.elem0: %.6a3 = impl_witness_access constants.%Destroy.impl_witness.a93, element0 [concrete = constants.%Op.f60]
+// CHECK:STDOUT:   %bound_method.loc11_3.1: <bound method> = bound_method %d.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%AdaptCopyable) [concrete = constants.%Op.specific_fn.e4c]
+// CHECK:STDOUT:   %bound_method.loc11_3.2: <bound method> = bound_method %d.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.4c1 = addr_of %d.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc11_3.2(%addr)
 // CHECK:STDOUT:   return %.loc12
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -268,6 +298,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc17_10.4: init %u32 = initialize_from %.loc17_10.3 to %tuple.elem1.loc17_10.2
 // CHECK:STDOUT:   %.loc17_10.5: init %tuple.type.2a3 = tuple_init (%.loc17_10.2, %.loc17_10.4) to %return
 // CHECK:STDOUT:   %.loc17_11: init %tuple.type.2a3 = converted %d.ref, %.loc17_10.5
+// CHECK:STDOUT:   %impl.elem0: %.c90 = impl_witness_access constants.%Destroy.impl_witness.d22, element0 [concrete = constants.%Op.f7d]
+// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %d.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%tuple.type.2a3) [concrete = constants.%Op.specific_fn.2af]
+// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %d.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.c30 = addr_of %d.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc16_3.2(%addr)
 // CHECK:STDOUT:   return %.loc17_11 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -277,6 +313,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %AdaptTuple: type = class_type @AdaptTuple [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]
@@ -285,6 +322,18 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.562: type = pattern_type %AdaptTuple [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.2ca: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%AdaptTuple) [concrete]
+// CHECK:STDOUT:   %Op.type.0f1: type = fn_type @Op.2, @impl.49c(%AdaptTuple) [concrete]
+// CHECK:STDOUT:   %Op.621: %Op.type.0f1 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.ca3: type = ptr_type %AdaptTuple [concrete]
+// CHECK:STDOUT:   %Destroy.facet.6e1: %Destroy.type = facet_value %AdaptTuple, (%Destroy.impl_witness.2ca) [concrete]
+// CHECK:STDOUT:   %.169: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.6e1 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.283: <specific function> = specific_function %Op.621, @Op.2(%AdaptTuple) [concrete]
 // CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]
 // CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]
 // CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]
@@ -292,16 +341,27 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.c9e: type = pattern_type %tuple.type.f69 [concrete]
 // CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]
 // CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.a18: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.f69) [concrete]
+// CHECK:STDOUT:   %Op.type.390: type = fn_type @Op.2, @impl.49c(%tuple.type.f69) [concrete]
+// CHECK:STDOUT:   %Op.d9f: %Op.type.390 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.ed5: type = ptr_type %tuple.type.f69 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.172: %Destroy.type = facet_value %tuple.type.f69, (%Destroy.impl_witness.a18) [concrete]
+// CHECK:STDOUT:   %.ee3: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.172 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.20d: <specific function> = specific_function %Op.d9f, @Op.2(%tuple.type.f69) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .UInt = %Core.UInt
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -403,6 +463,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc10_11.7: init %tuple.type.d07 = tuple_init (%.loc10_11.4, %.loc10_11.6) to %.loc10_11.3
 // CHECK:STDOUT:   %.loc10_11.8: init %AdaptTuple = as_compatible %.loc10_11.7
 // CHECK:STDOUT:   %.loc10_11.9: init %AdaptTuple = converted %d.ref, %.loc10_11.8
+// CHECK:STDOUT:   %impl.elem0: %.169 = impl_witness_access constants.%Destroy.impl_witness.2ca, element0 [concrete = constants.%Op.621]
+// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %d.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%AdaptTuple) [concrete = constants.%Op.specific_fn.283]
+// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %d.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.ca3 = addr_of %d.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr)
 // CHECK:STDOUT:   return %.loc10_11.9 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -463,6 +529,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc15_10.11: init %u32 = initialize_from %.loc15_10.10 to %tuple.elem1.loc15_10.4
 // CHECK:STDOUT:   %.loc15_10.12: init %tuple.type.f69 = tuple_init (%.loc15_10.9, %.loc15_10.11) to %return
 // CHECK:STDOUT:   %.loc15_11: init %tuple.type.f69 = converted %d.ref, %.loc15_10.12
+// CHECK:STDOUT:   %impl.elem0: %.ee3 = impl_witness_access constants.%Destroy.impl_witness.a18, element0 [concrete = constants.%Op.d9f]
+// CHECK:STDOUT:   %bound_method.loc14_3.1: <bound method> = bound_method %d.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%tuple.type.f69) [concrete = constants.%Op.specific_fn.20d]
+// CHECK:STDOUT:   %bound_method.loc14_3.2: <bound method> = bound_method %d.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.ed5 = addr_of %d.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc14_3.2(%addr)
 // CHECK:STDOUT:   return %.loc15_11 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -471,18 +543,35 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Noncopyable: type = class_type @Noncopyable [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %AdaptNoncopyable: type = class_type @AdaptNoncopyable [concrete]
-// CHECK:STDOUT:   %pattern_type: type = pattern_type %AdaptNoncopyable [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %pattern_type.8f9: type = pattern_type %AdaptNoncopyable [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.b01: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%AdaptNoncopyable) [concrete]
+// CHECK:STDOUT:   %Op.type.b79: type = fn_type @Op.2, @impl(%AdaptNoncopyable) [concrete]
+// CHECK:STDOUT:   %Op.77f: %Op.type.b79 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.ed9: type = ptr_type %AdaptNoncopyable [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %AdaptNoncopyable, (%Destroy.impl_witness.b01) [concrete]
+// CHECK:STDOUT:   %.1f7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.77f, @Op.2(%AdaptNoncopyable) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -496,10 +585,10 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %Noncopyable.decl: type = class_decl @Noncopyable [concrete = constants.%Noncopyable] {} {}
 // CHECK:STDOUT:   %AdaptNoncopyable.decl: type = class_decl @AdaptNoncopyable [concrete = constants.%AdaptNoncopyable] {} {}
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
-// CHECK:STDOUT:     %a.patt: %pattern_type = binding_pattern a [concrete]
-// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt, call_param0 [concrete]
-// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]
-// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt, call_param1 [concrete]
+// CHECK:STDOUT:     %a.patt: %pattern_type.8f9 = binding_pattern a [concrete]
+// CHECK:STDOUT:     %a.param_patt: %pattern_type.8f9 = value_param_pattern %a.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %return.patt: %pattern_type.8f9 = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: %pattern_type.8f9 = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %AdaptNoncopyable.ref.loc12_30: type = name_ref AdaptNoncopyable, file.%AdaptNoncopyable.decl [concrete = constants.%AdaptNoncopyable]
 // CHECK:STDOUT:     %a.param: %AdaptNoncopyable = value_param call_param0
@@ -512,7 +601,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Noncopyable {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -522,7 +611,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT: class @AdaptNoncopyable {
 // CHECK:STDOUT:   %Noncopyable.ref: type = name_ref Noncopyable, file.%Noncopyable.decl [concrete = constants.%Noncopyable]
 // CHECK:STDOUT:   adapt_decl %Noncopyable.ref [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -533,8 +622,8 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT: fn @G(%a.param: %AdaptNoncopyable) -> %return.param: %AdaptNoncopyable {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %b.patt: %pattern_type = binding_pattern b [concrete]
-// CHECK:STDOUT:     %b.var_patt: %pattern_type = var_pattern %b.patt [concrete]
+// CHECK:STDOUT:     %b.patt: %pattern_type.8f9 = binding_pattern b [concrete]
+// CHECK:STDOUT:     %b.var_patt: %pattern_type.8f9 = var_pattern %b.patt [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %b.var: ref %AdaptNoncopyable = var %b.var_patt
 // CHECK:STDOUT:   %a.ref: %AdaptNoncopyable = name_ref a, %a
@@ -543,6 +632,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %b: ref %AdaptNoncopyable = bind_name b, %b.var
 // CHECK:STDOUT:   %b.ref: ref %AdaptNoncopyable = name_ref b, %b
 // CHECK:STDOUT:   %.loc22: %AdaptNoncopyable = bind_value %b.ref
+// CHECK:STDOUT:   %impl.elem0: %.1f7 = impl_witness_access constants.%Destroy.impl_witness.b01, element0 [concrete = constants.%Op.77f]
+// CHECK:STDOUT:   %bound_method.loc17_3.1: <bound method> = bound_method %b.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%AdaptNoncopyable) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc17_3.2: <bound method> = bound_method %b.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.ed9 = addr_of %b.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc17_3.2(%addr)
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -555,6 +650,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %AdaptNoncopyableIndirect: type = class_type @AdaptNoncopyableIndirect [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]
@@ -563,15 +659,31 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.7e5: type = pattern_type %AdaptNoncopyableIndirect [concrete]
 // CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]
 // CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.a9c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%AdaptNoncopyableIndirect) [concrete]
+// CHECK:STDOUT:   %Op.type.b45: type = fn_type @Op.2, @impl(%AdaptNoncopyableIndirect) [concrete]
+// CHECK:STDOUT:   %Op.003: %Op.type.b45 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.921: type = ptr_type %AdaptNoncopyableIndirect [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %AdaptNoncopyableIndirect, (%Destroy.impl_witness.a9c) [concrete]
+// CHECK:STDOUT:   %.b9a: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.003, @Op.2(%AdaptNoncopyableIndirect) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -651,6 +763,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc28_11.4: init %i32 = initialize_from %.loc28_11.2 to %tuple.elem0.loc28_11.2
 // CHECK:STDOUT:   %tuple.elem1.loc28: ref %Noncopyable = tuple_access %.loc28_11.1, element1
 // CHECK:STDOUT:   %.loc28_11.5: %Noncopyable = bind_value %tuple.elem1.loc28
+// CHECK:STDOUT:   %impl.elem0: %.b9a = impl_witness_access constants.%Destroy.impl_witness.a9c, element0 [concrete = constants.%Op.003]
+// CHECK:STDOUT:   %bound_method.loc20_3.1: <bound method> = bound_method %b.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%AdaptNoncopyableIndirect) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc20_3.2: <bound method> = bound_method %b.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.921 = addr_of %b.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc20_3.2(%addr)
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -660,6 +778,7 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %AdaptStruct: type = class_type @AdaptStruct [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %struct_type.e.f: type = struct_type {.e: %i32, .f: %i32} [concrete]
@@ -667,6 +786,18 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.f45: type = pattern_type %AdaptStruct [concrete]
 // CHECK:STDOUT:   %I.type: type = fn_type @I [concrete]
 // CHECK:STDOUT:   %I: %I.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.da6: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%AdaptStruct) [concrete]
+// CHECK:STDOUT:   %Op.type.38c: type = fn_type @Op.2, @impl.49c(%AdaptStruct) [concrete]
+// CHECK:STDOUT:   %Op.d16: %Op.type.38c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.e10: type = ptr_type %AdaptStruct [concrete]
+// CHECK:STDOUT:   %Destroy.facet.94b: %Destroy.type = facet_value %AdaptStruct, (%Destroy.impl_witness.da6) [concrete]
+// CHECK:STDOUT:   %.cc4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.94b [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.ad6: <specific function> = specific_function %Op.d16, @Op.2(%AdaptStruct) [concrete]
 // CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]
 // CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]
 // CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]
@@ -675,16 +806,27 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %pattern_type.31d: type = pattern_type %tuple.type.80b [concrete]
 // CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]
 // CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.c31: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.80b) [concrete]
+// CHECK:STDOUT:   %Op.type.628: type = fn_type @Op.2, @impl.49c(%tuple.type.80b) [concrete]
+// CHECK:STDOUT:   %Op.8ff: %Op.type.628 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.b09: type = ptr_type %tuple.type.80b [concrete]
+// CHECK:STDOUT:   %Destroy.facet.df5: %Destroy.type = facet_value %tuple.type.80b, (%Destroy.impl_witness.c31) [concrete]
+// CHECK:STDOUT:   %.9ef: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.df5 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.301: <specific function> = specific_function %Op.8ff, @Op.2(%tuple.type.80b) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .UInt = %Core.UInt
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -785,6 +927,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc10_11.11: init %struct_type.e.f = struct_init (%.loc10_11.6, %.loc10_11.10) to %.loc10_11.4
 // CHECK:STDOUT:   %.loc10_11.12: init %AdaptStruct = as_compatible %.loc10_11.11
 // CHECK:STDOUT:   %.loc10_11.13: init %AdaptStruct = converted %h.ref, %.loc10_11.12
+// CHECK:STDOUT:   %impl.elem0: %.cc4 = impl_witness_access constants.%Destroy.impl_witness.da6, element0 [concrete = constants.%Op.d16]
+// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %h.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%AdaptStruct) [concrete = constants.%Op.specific_fn.ad6]
+// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %h.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e10 = addr_of %h.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr)
 // CHECK:STDOUT:   return %.loc10_11.13 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -845,6 +993,12 @@ fn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {
 // CHECK:STDOUT:   %.loc15_10.15: init %u32 = initialize_from %.loc15_10.14 to %tuple.elem1.loc15_10.2
 // CHECK:STDOUT:   %.loc15_10.16: init %tuple.type.80b = tuple_init (%.loc15_10.13, %.loc15_10.15) to %return
 // CHECK:STDOUT:   %.loc15_11: init %tuple.type.80b = converted %d.ref, %.loc15_10.16
+// CHECK:STDOUT:   %impl.elem0: %.9ef = impl_witness_access constants.%Destroy.impl_witness.c31, element0 [concrete = constants.%Op.8ff]
+// CHECK:STDOUT:   %bound_method.loc14_3.1: <bound method> = bound_method %d.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%tuple.type.80b) [concrete = constants.%Op.specific_fn.301]
+// CHECK:STDOUT:   %bound_method.loc14_3.2: <bound method> = bound_method %d.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.b09 = addr_of %d.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc14_3.2(%addr)
 // CHECK:STDOUT:   return %.loc15_11 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -452,6 +452,7 @@ class Class(U:! type) {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -474,6 +475,17 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %F.type.b25: type = fn_type @F.2 [concrete]
 // CHECK:STDOUT:   %F.c41: %F.type.b25 = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.f7c, @F.1(%i32) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.801: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%CompleteClass.e9e) [concrete]
+// CHECK:STDOUT:   %Op.type.9c5: type = fn_type @Op.3, @impl.49c(%CompleteClass.e9e) [concrete]
+// CHECK:STDOUT:   %Op.d10: %Op.type.9c5 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.a97: type = ptr_type %CompleteClass.e9e [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %CompleteClass.e9e, (%Destroy.impl_witness.801) [concrete]
+// CHECK:STDOUT:   %.2c0: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d10, @Op.3(%CompleteClass.e9e) [concrete]
 // CHECK:STDOUT:   %UseField.type: type = fn_type @UseField [concrete]
 // CHECK:STDOUT:   %UseField: %UseField.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -482,8 +494,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %Main.Class = import_ref Main//foo, Class, unloaded
 // CHECK:STDOUT:   %Main.CompleteClass: %CompleteClass.type = import_ref Main//foo, CompleteClass, loaded [concrete = constants.%CompleteClass.generic]
 // CHECK:STDOUT:   %Main.F: %F.type.b25 = import_ref Main//foo, F, loaded [concrete = constants.%F.c41]
-// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -494,6 +507,9 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %Main.import_ref.e76: @CompleteClass.%CompleteClass.elem (%CompleteClass.elem.28a) = import_ref Main//foo, loc7_8, loaded [concrete = %.364]
 // CHECK:STDOUT:   %Main.import_ref.a52: @CompleteClass.%F.type (%F.type.14f) = import_ref Main//foo, loc8_17, loaded [symbolic = @CompleteClass.%F (constants.%F.874)]
 // CHECK:STDOUT:   %Main.import_ref.5ab3ec.2: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %.364: @CompleteClass.%CompleteClass.elem (%CompleteClass.elem.28a) = field_decl n, element0 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -502,7 +518,7 @@ class Class(U:! type) {
 // CHECK:STDOUT:     .Class = imports.%Main.Class
 // CHECK:STDOUT:     .CompleteClass = imports.%Main.CompleteClass
 // CHECK:STDOUT:     .F = imports.%Main.F
-// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .Core = imports.%Core.ece
 // CHECK:STDOUT:     .UseMethod = %UseMethod.decl
 // CHECK:STDOUT:     .UseField = %UseField.decl
 // CHECK:STDOUT:   }
@@ -572,6 +588,18 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %F.call.loc7: init %i32 = call %F.specific_fn()
 // CHECK:STDOUT:   %.loc7_15.1: %i32 = value_of_initializer %F.call.loc7
 // CHECK:STDOUT:   %.loc7_15.2: %i32 = converted %F.call.loc7, %.loc7_15.1
+// CHECK:STDOUT:   %impl.elem0.loc6_3.1: %.2c0 = impl_witness_access constants.%Destroy.impl_witness.801, element0 [concrete = constants.%Op.d10]
+// CHECK:STDOUT:   %bound_method.loc6_3.1: <bound method> = bound_method %.loc6_3, %impl.elem0.loc6_3.1
+// CHECK:STDOUT:   %specific_fn.loc6_3.1: <specific function> = specific_function %impl.elem0.loc6_3.1, @Op.3(constants.%CompleteClass.e9e) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_3.2: <bound method> = bound_method %.loc6_3, %specific_fn.loc6_3.1
+// CHECK:STDOUT:   %addr.loc6_3.1: %ptr.a97 = addr_of %.loc6_3
+// CHECK:STDOUT:   %no_op.loc6_3.1: init %empty_tuple.type = call %bound_method.loc6_3.2(%addr.loc6_3.1)
+// CHECK:STDOUT:   %impl.elem0.loc6_3.2: %.2c0 = impl_witness_access constants.%Destroy.impl_witness.801, element0 [concrete = constants.%Op.d10]
+// CHECK:STDOUT:   %bound_method.loc6_3.3: <bound method> = bound_method %v.var, %impl.elem0.loc6_3.2
+// CHECK:STDOUT:   %specific_fn.loc6_3.2: <specific function> = specific_function %impl.elem0.loc6_3.2, @Op.3(constants.%CompleteClass.e9e) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc6_3.4: <bound method> = bound_method %v.var, %specific_fn.loc6_3.2
+// CHECK:STDOUT:   %addr.loc6_3.2: %ptr.a97 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc6_3.2: init %empty_tuple.type = call %bound_method.loc6_3.4(%addr.loc6_3.2)
 // CHECK:STDOUT:   return %.loc7_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -605,6 +633,18 @@ class Class(U:! type) {
 // CHECK:STDOUT:   %n.ref: %CompleteClass.elem.7fc = name_ref n, imports.%Main.import_ref.e76 [concrete = imports.%.364]
 // CHECK:STDOUT:   %.loc12_11.1: ref %i32 = class_element_access %v.ref, element0
 // CHECK:STDOUT:   %.loc12_11.2: %i32 = bind_value %.loc12_11.1
+// CHECK:STDOUT:   %impl.elem0.loc11_3.1: %.2c0 = impl_witness_access constants.%Destroy.impl_witness.801, element0 [concrete = constants.%Op.d10]
+// CHECK:STDOUT:   %bound_method.loc11_3.1: <bound method> = bound_method %.loc11_3, %impl.elem0.loc11_3.1
+// CHECK:STDOUT:   %specific_fn.loc11_3.1: <specific function> = specific_function %impl.elem0.loc11_3.1, @Op.3(constants.%CompleteClass.e9e) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_3.2: <bound method> = bound_method %.loc11_3, %specific_fn.loc11_3.1
+// CHECK:STDOUT:   %addr.loc11_3.1: %ptr.a97 = addr_of %.loc11_3
+// CHECK:STDOUT:   %no_op.loc11_3.1: init %empty_tuple.type = call %bound_method.loc11_3.2(%addr.loc11_3.1)
+// CHECK:STDOUT:   %impl.elem0.loc11_3.2: %.2c0 = impl_witness_access constants.%Destroy.impl_witness.801, element0 [concrete = constants.%Op.d10]
+// CHECK:STDOUT:   %bound_method.loc11_3.3: <bound method> = bound_method %v.var, %impl.elem0.loc11_3.2
+// CHECK:STDOUT:   %specific_fn.loc11_3.2: <specific function> = specific_function %impl.elem0.loc11_3.2, @Op.3(constants.%CompleteClass.e9e) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_3.4: <bound method> = bound_method %v.var, %specific_fn.loc11_3.2
+// CHECK:STDOUT:   %addr.loc11_3.2: %ptr.a97 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc11_3.2: init %empty_tuple.type = call %bound_method.loc11_3.4(%addr.loc11_3.2)
 // CHECK:STDOUT:   return %.loc12_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 52 - 10
toolchain/check/testdata/class/generic/init.carbon

@@ -52,17 +52,29 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Class.fe1: type = class_type @Class, @Class(%T) [symbolic]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %Class.elem.e26: type = unbound_element_type %Class.fe1, %T [symbolic]
 // CHECK:STDOUT:   %struct_type.k.b21: type = struct_type {.k: %T} [symbolic]
 // CHECK:STDOUT:   %complete_type.b9e: <witness> = complete_type_witness %struct_type.k.b21 [symbolic]
-// CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
+// CHECK:STDOUT:   %pattern_type.7dcd0a.1: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %InitFromStructGeneric.type: type = fn_type @InitFromStructGeneric [concrete]
 // CHECK:STDOUT:   %InitFromStructGeneric: %InitFromStructGeneric.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4f8: <witness> = require_complete_type %Class.fe1 [symbolic]
 // CHECK:STDOUT:   %pattern_type.3c1: type = pattern_type %Class.fe1 [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ptr.955: type = ptr_type %Class.fe1 [symbolic]
+// CHECK:STDOUT:   %require_complete.2ae: <witness> = require_complete_type %ptr.955 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.fe1, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.2d8: %Destroy.type = facet_value %Class.fe1, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.d76: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.2d8 [symbolic]
+// CHECK:STDOUT:   %impl.elem0.5b7: %.d76 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0.5b7, @Op.1(%Destroy.facet.2d8) [symbolic]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
@@ -77,14 +89,25 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   %struct_type.k.0bf: type = struct_type {.k: %i32} [concrete]
 // CHECK:STDOUT:   %complete_type.954: <witness> = complete_type_witness %struct_type.k.0bf [concrete]
 // CHECK:STDOUT:   %pattern_type.0fa: type = pattern_type %Class.247 [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.5f0: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Class.247) [concrete]
+// CHECK:STDOUT:   %Op.type.fdc: type = fn_type @Op.2, @impl.49c(%Class.247) [concrete]
+// CHECK:STDOUT:   %Op.af5: %Op.type.fdc = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.f7c: type = ptr_type %Class.247 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.c29: %Destroy.type = facet_value %Class.247, (%Destroy.impl_witness.5f0) [concrete]
+// CHECK:STDOUT:   %.9ad: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.c29 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.af5, @Op.2(%Class.247) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .Int = %Core.Int
 // 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:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -103,10 +126,10 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %InitFromStructGeneric.decl: %InitFromStructGeneric.type = fn_decl @InitFromStructGeneric [concrete = constants.%InitFromStructGeneric] {
 // CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]
-// CHECK:STDOUT:     %x.patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dc) = binding_pattern x [concrete]
-// CHECK:STDOUT:     %x.param_patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dc) = value_param_pattern %x.patt, call_param0 [concrete]
-// CHECK:STDOUT:     %return.patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dc) = return_slot_pattern [concrete]
-// CHECK:STDOUT:     %return.param_patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dc) = out_param_pattern %return.patt, call_param1 [concrete]
+// CHECK:STDOUT:     %x.patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dcd0a.1) = binding_pattern x [concrete]
+// CHECK:STDOUT:     %x.param_patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dcd0a.1) = value_param_pattern %x.patt, call_param0 [concrete]
+// CHECK:STDOUT:     %return.patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dcd0a.1) = return_slot_pattern [concrete]
+// CHECK:STDOUT:     %return.param_patt: @InitFromStructGeneric.%pattern_type.loc8 (%pattern_type.7dcd0a.1) = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref.loc8_45: type = name_ref T, %T.loc8_26.1 [symbolic = %T.loc8_26.2 (constants.%T)]
 // CHECK:STDOUT:     %T.loc8_26.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_26.2 (constants.%T)]
@@ -161,15 +184,22 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @InitFromStructGeneric(%T.loc8_26.1: type) {
 // CHECK:STDOUT:   %T.loc8_26.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_26.2 (constants.%T)]
-// CHECK:STDOUT:   %pattern_type.loc8: type = pattern_type %T.loc8_26.2 [symbolic = %pattern_type.loc8 (constants.%pattern_type.7dc)]
+// CHECK:STDOUT:   %pattern_type.loc8: type = pattern_type %T.loc8_26.2 [symbolic = %pattern_type.loc8 (constants.%pattern_type.7dcd0a.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.loc8: <witness> = require_complete_type %T.loc8_26.2 [symbolic = %require_complete.loc8 (constants.%require_complete.4ae)]
 // CHECK:STDOUT:   %Class.loc9_17.2: type = class_type @Class, @Class(%T.loc8_26.2) [symbolic = %Class.loc9_17.2 (constants.%Class.fe1)]
-// CHECK:STDOUT:   %require_complete.loc9: <witness> = require_complete_type %Class.loc9_17.2 [symbolic = %require_complete.loc9 (constants.%require_complete.4f8)]
+// CHECK:STDOUT:   %require_complete.loc9_17: <witness> = require_complete_type %Class.loc9_17.2 [symbolic = %require_complete.loc9_17 (constants.%require_complete.4f8)]
 // CHECK:STDOUT:   %pattern_type.loc9: type = pattern_type %Class.loc9_17.2 [symbolic = %pattern_type.loc9 (constants.%pattern_type.3c1)]
 // CHECK:STDOUT:   %struct_type.k: type = struct_type {.k: @InitFromStructGeneric.%T.loc8_26.2 (%T)} [symbolic = %struct_type.k (constants.%struct_type.k.b21)]
 // CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class.loc9_17.2, %T.loc8_26.2 [symbolic = %Class.elem (constants.%Class.elem.e26)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.loc9_17.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class.loc9_17.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.2d8)]
+// CHECK:STDOUT:   %.loc9_3.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc9_3.3 (constants.%.d76)]
+// CHECK:STDOUT:   %impl.elem0.loc9_3.2: @InitFromStructGeneric.%.loc9_3.3 (%.d76) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_3.2 (constants.%impl.elem0.5b7)]
+// CHECK:STDOUT:   %specific_impl_fn.loc9_3.2: <specific function> = specific_impl_function %impl.elem0.loc9_3.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc9_3.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %Class.loc9_17.2 [symbolic = %ptr (constants.%ptr.955)]
+// CHECK:STDOUT:   %require_complete.loc9_3: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc9_3 (constants.%require_complete.2ae)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%x.param: @InitFromStructGeneric.%T.loc8_26.2 (%T)) -> @InitFromStructGeneric.%T.loc8_26.2 (%T) {
 // CHECK:STDOUT:   !entry:
@@ -183,8 +213,8 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:     %.loc9_28.2: ref @InitFromStructGeneric.%T.loc8_26.2 (%T) = class_element_access %v.var, element0
 // CHECK:STDOUT:     %.loc9_28.3: init @InitFromStructGeneric.%T.loc8_26.2 (%T) = initialize_from %x.ref to %.loc9_28.2
 // CHECK:STDOUT:     %.loc9_28.4: init @InitFromStructGeneric.%Class.loc9_17.2 (%Class.fe1) = class_init (%.loc9_28.3), %v.var
-// CHECK:STDOUT:     %.loc9_3: init @InitFromStructGeneric.%Class.loc9_17.2 (%Class.fe1) = converted %.loc9_28.1, %.loc9_28.4
-// CHECK:STDOUT:     assign %v.var, %.loc9_3
+// CHECK:STDOUT:     %.loc9_3.1: init @InitFromStructGeneric.%Class.loc9_17.2 (%Class.fe1) = converted %.loc9_28.1, %.loc9_28.4
+// CHECK:STDOUT:     assign %v.var, %.loc9_3.1
 // CHECK:STDOUT:     %.loc9_17: type = splice_block %Class.loc9_17.1 [symbolic = %Class.loc9_17.2 (constants.%Class.fe1)] {
 // CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]
 // CHECK:STDOUT:       %T.ref.loc9: type = name_ref T, %T.loc8_26.1 [symbolic = %T.loc8_26.2 (constants.%T)]
@@ -195,6 +225,12 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:     %k.ref: @InitFromStructGeneric.%Class.elem (%Class.elem.e26) = name_ref k, @Class.%.loc5 [concrete = @Class.%.loc5]
 // CHECK:STDOUT:     %.loc10_11.1: ref @InitFromStructGeneric.%T.loc8_26.2 (%T) = class_element_access %v.ref, element0
 // CHECK:STDOUT:     %.loc10_11.2: @InitFromStructGeneric.%T.loc8_26.2 (%T) = bind_value %.loc10_11.1
+// CHECK:STDOUT:     %impl.elem0.loc9_3.1: @InitFromStructGeneric.%.loc9_3.3 (%.d76) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_3.2 (constants.%impl.elem0.5b7)]
+// CHECK:STDOUT:     %bound_method.loc9_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc9_3.1
+// CHECK:STDOUT:     %specific_impl_fn.loc9_3.1: <specific function> = specific_impl_function %impl.elem0.loc9_3.1, @Op.1(constants.%Destroy.facet.2d8) [symbolic = %specific_impl_fn.loc9_3.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc9_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc9_3.1
+// CHECK:STDOUT:     %addr: @InitFromStructGeneric.%ptr (%ptr.955) = addr_of %v.var
+// CHECK:STDOUT:     %.loc9_3.2: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr)
 // CHECK:STDOUT:     return %.loc10_11.2
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -224,6 +260,12 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:   %k.ref: %Class.elem.2d8 = name_ref k, @Class.%.loc5 [concrete = @Class.%.loc5]
 // CHECK:STDOUT:   %.loc15_11.1: ref %i32 = class_element_access %v.ref, element0
 // CHECK:STDOUT:   %.loc15_11.2: %i32 = bind_value %.loc15_11.1
+// CHECK:STDOUT:   %impl.elem0: %.9ad = impl_witness_access constants.%Destroy.impl_witness.5f0, element0 [concrete = constants.%Op.af5]
+// CHECK:STDOUT:   %bound_method.loc14_3.1: <bound method> = bound_method %v.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%Class.247) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc14_3.2: <bound method> = bound_method %v.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.f7c = addr_of %v.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc14_3.2(%addr)
 // CHECK:STDOUT:   return %.loc15_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -240,7 +282,7 @@ fn InitFromAdaptedSpecific(x: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @InitFromStructGeneric(constants.%T) {
 // CHECK:STDOUT:   %T.loc8_26.2 => constants.%T
-// CHECK:STDOUT:   %pattern_type.loc8 => constants.%pattern_type.7dc
+// CHECK:STDOUT:   %pattern_type.loc8 => constants.%pattern_type.7dcd0a.1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Class(constants.%i32) {

+ 31 - 6
toolchain/check/testdata/class/generic/member_access.carbon

@@ -418,6 +418,7 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic]
 // CHECK:STDOUT:   %pattern_type.3c1: type = pattern_type %Class [symbolic]
@@ -425,18 +426,29 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %Make: %Make.type = struct_value () [symbolic]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class [symbolic]
+// CHECK:STDOUT:   %require_complete.4f8: <witness> = require_complete_type %Class [symbolic]
 // CHECK:STDOUT:   %Class.val: %Class = struct_value () [symbolic]
 // CHECK:STDOUT:   %StaticMemberFunctionCall.type: type = fn_type @StaticMemberFunctionCall [concrete]
 // CHECK:STDOUT:   %StaticMemberFunctionCall: %StaticMemberFunctionCall.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Make.specific_fn: <specific function> = specific_function %Make, @Make(%T) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %ptr.955: type = ptr_type %Class [symbolic]
+// CHECK:STDOUT:   %require_complete.2ae: <witness> = require_complete_type %ptr.955 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.d76: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.d76 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%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 {
@@ -501,7 +513,7 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %Class.loc5_23.1 [symbolic = %pattern_type (constants.%pattern_type.3c1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc5_23.1 [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc5_23.1 [symbolic = %require_complete (constants.%require_complete.4f8)]
 // CHECK:STDOUT:   %Class.val: @Make.%Class.loc5_23.1 (%Class) = struct_value () [symbolic = %Class.val (constants.%Class.val)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> %return.param: @Make.%Class.loc5_23.1 (%Class) {
@@ -519,10 +531,17 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %Class.loc8_49.2 [symbolic = %pattern_type (constants.%pattern_type.3c1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc8_49.2 [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete.loc9: <witness> = require_complete_type %Class.loc8_49.2 [symbolic = %require_complete.loc9 (constants.%require_complete.4f8)]
 // CHECK:STDOUT:   %Make.type: type = fn_type @Make, @Class(%T.loc8_29.2) [symbolic = %Make.type (constants.%Make.type)]
 // CHECK:STDOUT:   %Make: @StaticMemberFunctionCall.%Make.type (%Make.type) = struct_value () [symbolic = %Make (constants.%Make)]
 // CHECK:STDOUT:   %Make.specific_fn.loc9_18.2: <specific function> = specific_function %Make, @Make(%T.loc8_29.2) [symbolic = %Make.specific_fn.loc9_18.2 (constants.%Make.specific_fn)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.loc8_49.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class.loc8_49.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]
+// CHECK:STDOUT:   %.loc8_39.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc8_39.3 (constants.%.d76)]
+// CHECK:STDOUT:   %impl.elem0.loc8_39.2: @StaticMemberFunctionCall.%.loc8_39.3 (%.d76) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc8_39.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.loc8_39.2: <specific function> = specific_impl_function %impl.elem0.loc8_39.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc8_39.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %Class.loc8_49.2 [symbolic = %ptr (constants.%ptr.955)]
+// CHECK:STDOUT:   %require_complete.loc8: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc8 (constants.%require_complete.2ae)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> %return.param: @StaticMemberFunctionCall.%Class.loc8_49.2 (%Class) {
 // CHECK:STDOUT:   !entry:
@@ -532,8 +551,14 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:     %.loc9: @StaticMemberFunctionCall.%Make.type (%Make.type) = specific_constant @Class.%Make.decl, @Class(constants.%T) [symbolic = %Make (constants.%Make)]
 // CHECK:STDOUT:     %Make.ref: @StaticMemberFunctionCall.%Make.type (%Make.type) = name_ref Make, %.loc9 [symbolic = %Make (constants.%Make)]
 // CHECK:STDOUT:     %Make.specific_fn.loc9_18.1: <specific function> = specific_function %Make.ref, @Make(constants.%T) [symbolic = %Make.specific_fn.loc9_18.2 (constants.%Make.specific_fn)]
-// CHECK:STDOUT:     %.loc8: ref @StaticMemberFunctionCall.%Class.loc8_49.2 (%Class) = splice_block %return {}
-// CHECK:STDOUT:     %Make.call: init @StaticMemberFunctionCall.%Class.loc8_49.2 (%Class) = call %Make.specific_fn.loc9_18.1() to %.loc8
+// CHECK:STDOUT:     %.loc8_39.1: ref @StaticMemberFunctionCall.%Class.loc8_49.2 (%Class) = splice_block %return {}
+// CHECK:STDOUT:     %Make.call: init @StaticMemberFunctionCall.%Class.loc8_49.2 (%Class) = call %Make.specific_fn.loc9_18.1() to %.loc8_39.1
+// CHECK:STDOUT:     %impl.elem0.loc8_39.1: @StaticMemberFunctionCall.%.loc8_39.3 (%.d76) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc8_39.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.loc8_39.1: <bound method> = bound_method %.loc8_39.1, %impl.elem0.loc8_39.1
+// CHECK:STDOUT:     %specific_impl_fn.loc8_39.1: <specific function> = specific_impl_function %impl.elem0.loc8_39.1, @Op.1(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc8_39.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc8_39.2: <bound method> = bound_method %.loc8_39.1, %specific_impl_fn.loc8_39.1
+// CHECK:STDOUT:     %addr: @StaticMemberFunctionCall.%ptr (%ptr.955) = addr_of %.loc8_39.1
+// CHECK:STDOUT:     %.loc8_39.2: init %empty_tuple.type = call %bound_method.loc8_39.2(%addr)
 // CHECK:STDOUT:     return %Make.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -552,7 +577,7 @@ fn StaticMemberFunctionCall(T:! type) -> Class(T) {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.3c1
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.4f8
 // CHECK:STDOUT:   %Class.val => constants.%Class.val
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 58 - 8
toolchain/check/testdata/class/generic/member_type.carbon

@@ -62,6 +62,7 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Outer.9d6: type = class_type @Outer, @Outer(%T) [symbolic]
 // CHECK:STDOUT:   %Inner.51b: type = class_type @Inner, @Inner(%T) [symbolic]
@@ -111,12 +112,24 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.480: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Inner.721) [concrete]
+// CHECK:STDOUT:   %Op.type.a38: type = fn_type @Op.3, @impl.49c(%Inner.721) [concrete]
+// CHECK:STDOUT:   %Op.27e: %Op.type.a38 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.416: type = ptr_type %Inner.721 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Inner.721, (%Destroy.impl_witness.480) [concrete]
+// CHECK:STDOUT:   %.cdb: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.27e, @Op.3(%Inner.721) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -124,6 +137,9 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -247,10 +263,10 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%i32) [concrete = constants.%F.specific_fn]
 // CHECK:STDOUT:   %.loc13_3: ref %Inner.721 = splice_block %c.var {}
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc13_42.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc13_42.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc13_42: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc13_42.1: <bound method> = bound_method %int_1, %impl.elem0.loc13_42 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc13_42: <specific function> = specific_function %impl.elem0.loc13_42, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_42.2: <bound method> = bound_method %int_1, %specific_fn.loc13_42 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc13_42.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc13_42.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc13_42.2: %i32 = converted %int_1, %.loc13_42.1 [concrete = constants.%int_1.5d2]
@@ -269,6 +285,18 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %n.ref: %Inner.elem.6c2 = name_ref n, @Inner.%.loc6 [concrete = @Inner.%.loc6]
 // CHECK:STDOUT:   %.loc14_11.1: ref %i32 = class_element_access %c.ref, element0
 // CHECK:STDOUT:   %.loc14_11.2: %i32 = bind_value %.loc14_11.1
+// CHECK:STDOUT:   %impl.elem0.loc13_3.1: %.cdb = impl_witness_access constants.%Destroy.impl_witness.480, element0 [concrete = constants.%Op.27e]
+// CHECK:STDOUT:   %bound_method.loc13_3.1: <bound method> = bound_method %.loc13_3, %impl.elem0.loc13_3.1
+// CHECK:STDOUT:   %specific_fn.loc13_3.1: <specific function> = specific_function %impl.elem0.loc13_3.1, @Op.3(constants.%Inner.721) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_3.2: <bound method> = bound_method %.loc13_3, %specific_fn.loc13_3.1
+// CHECK:STDOUT:   %addr.loc13_3.1: %ptr.416 = addr_of %.loc13_3
+// CHECK:STDOUT:   %no_op.loc13_3.1: init %empty_tuple.type = call %bound_method.loc13_3.2(%addr.loc13_3.1)
+// CHECK:STDOUT:   %impl.elem0.loc13_3.2: %.cdb = impl_witness_access constants.%Destroy.impl_witness.480, element0 [concrete = constants.%Op.27e]
+// CHECK:STDOUT:   %bound_method.loc13_3.3: <bound method> = bound_method %c.var, %impl.elem0.loc13_3.2
+// CHECK:STDOUT:   %specific_fn.loc13_3.2: <specific function> = specific_function %impl.elem0.loc13_3.2, @Op.3(constants.%Inner.721) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_3.4: <bound method> = bound_method %c.var, %specific_fn.loc13_3.2
+// CHECK:STDOUT:   %addr.loc13_3.2: %ptr.416 = addr_of %c.var
+// CHECK:STDOUT:   %no_op.loc13_3.2: init %empty_tuple.type = call %bound_method.loc13_3.4(%addr.loc13_3.2)
 // CHECK:STDOUT:   return %.loc14_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -335,6 +363,7 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Outer.9d6: type = class_type @Outer, @Outer(%T) [symbolic]
 // CHECK:STDOUT:   %Inner.type.392: type = facet_type <@Inner, @Inner(%T)> [symbolic]
@@ -394,15 +423,30 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %Inner.facet.840: %Inner.type.52d = facet_value %C.70f, (%Inner.impl_witness.47d) [concrete]
 // CHECK:STDOUT:   %.b10: type = fn_type_with_self_type %F.type.86e, %Inner.facet.840 [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.e75, @F.2(%i32) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.bad: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C.70f) [concrete]
+// CHECK:STDOUT:   %Op.type.b66: type = fn_type @Op.3, @impl.49c(%C.70f) [concrete]
+// CHECK:STDOUT:   %Op.369: %Op.type.b66 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.18f: type = ptr_type %C.70f [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C.70f, (%Destroy.impl_witness.bad) [concrete]
+// CHECK:STDOUT:   %.ecb: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.369, @Op.3(%C.70f) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -677,14 +721,20 @@ fn Test() -> i32 {
 // CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, %.loc24_23 [concrete = constants.%Inner.type.52d]
 // CHECK:STDOUT:   %.loc24_29: %Inner.assoc_type.215 = specific_constant @Inner.%assoc0.loc6_28.1, @Inner(constants.%i32) [concrete = constants.%assoc0.e80]
 // CHECK:STDOUT:   %F.ref: %Inner.assoc_type.215 = name_ref F, %.loc24_29 [concrete = constants.%assoc0.e80]
-// CHECK:STDOUT:   %impl.elem0: %.b10 = impl_witness_access constants.%Inner.impl_witness.47d, element0 [concrete = constants.%F.e75]
-// CHECK:STDOUT:   %bound_method.loc24_11: <bound method> = bound_method %c.ref, %impl.elem0
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @F.2(constants.%i32) [concrete = constants.%F.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc24_33: <bound method> = bound_method %c.ref, %specific_fn
+// CHECK:STDOUT:   %impl.elem0.loc24: %.b10 = impl_witness_access constants.%Inner.impl_witness.47d, element0 [concrete = constants.%F.e75]
+// CHECK:STDOUT:   %bound_method.loc24_11: <bound method> = bound_method %c.ref, %impl.elem0.loc24
+// CHECK:STDOUT:   %specific_fn.loc24: <specific function> = specific_function %impl.elem0.loc24, @F.2(constants.%i32) [concrete = constants.%F.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc24_33: <bound method> = bound_method %c.ref, %specific_fn.loc24
 // CHECK:STDOUT:   %.loc24_10: %C.70f = bind_value %c.ref
 // CHECK:STDOUT:   %F.call: init %i32 = call %bound_method.loc24_33(%.loc24_10)
 // CHECK:STDOUT:   %.loc24_34.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc24_34.2: %i32 = converted %F.call, %.loc24_34.1
+// CHECK:STDOUT:   %impl.elem0.loc23: %.ecb = impl_witness_access constants.%Destroy.impl_witness.bad, element0 [concrete = constants.%Op.369]
+// CHECK:STDOUT:   %bound_method.loc23_3.1: <bound method> = bound_method %c.var, %impl.elem0.loc23
+// CHECK:STDOUT:   %specific_fn.loc23: <specific function> = specific_function %impl.elem0.loc23, @Op.3(constants.%C.70f) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc23_3.2: <bound method> = bound_method %c.var, %specific_fn.loc23
+// CHECK:STDOUT:   %addr: %ptr.18f = addr_of %c.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc23_3.2(%addr)
 // CHECK:STDOUT:   return %.loc24_34.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 110 - 7
toolchain/check/testdata/class/generic/method_deduce.carbon

@@ -38,6 +38,7 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Class.fe1: type = class_type @Class, @Class(%T) [symbolic]
 // CHECK:STDOUT:   %U: type = bind_symbolic_name U, 1 [symbolic]
@@ -49,8 +50,19 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %GetNoDeduce.type.766: type = fn_type @GetNoDeduce, @Class(%T) [symbolic]
 // CHECK:STDOUT:   %GetNoDeduce.c9a: %GetNoDeduce.type.766 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ptr.937: type = ptr_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %require_complete.fe1: <witness> = require_complete_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %Get.specific_fn.f73: <specific function> = specific_function %Get.cf9, @Get(%T, %U) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %require_complete.8fa: <witness> = require_complete_type %ptr.937 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type.30b, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.1c6: %Destroy.type = facet_value %tuple.type.30b, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.1e9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.1c6 [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.1e9 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet.1c6) [symbolic]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %GetNoDeduce.specific_fn.536: <specific function> = specific_function %GetNoDeduce.c9a, @GetNoDeduce(%T, %U) [symbolic]
 // CHECK:STDOUT:   %Class.480: type = class_type @Class, @Class(%A) [concrete]
@@ -64,19 +76,38 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %GetNoDeduce.type.5d6: type = fn_type @GetNoDeduce, @Class(%A) [concrete]
 // CHECK:STDOUT:   %GetNoDeduce.162: %GetNoDeduce.type.5d6 = struct_value () [concrete]
 // CHECK:STDOUT:   %Get.specific_fn.213: <specific function> = specific_function %Get.f37, @Get(%A, %B) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.ae3: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%tuple.type.cc6) [concrete]
+// CHECK:STDOUT:   %Op.type.87c: type = fn_type @Op.2, @impl(%tuple.type.cc6) [concrete]
+// CHECK:STDOUT:   %Op.f13: %Op.type.87c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.3b5: type = ptr_type %tuple.type.cc6 [concrete]
+// CHECK:STDOUT:   %complete_type.a4a: <witness> = complete_type_witness %ptr.3b5 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.fae: %Destroy.type = facet_value %tuple.type.cc6, (%Destroy.impl_witness.ae3) [concrete]
+// CHECK:STDOUT:   %.c9f: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.fae [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.8d7: <specific function> = specific_function %Op.f13, @Op.2(%tuple.type.cc6) [concrete]
 // CHECK:STDOUT:   %CallGenericMethodWithNonDeducedParam.type: type = fn_type @CallGenericMethodWithNonDeducedParam [concrete]
 // CHECK:STDOUT:   %CallGenericMethodWithNonDeducedParam: %CallGenericMethodWithNonDeducedParam.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.c10: type = pattern_type %A [concrete]
 // CHECK:STDOUT:   %GetNoDeduce.specific_fn.438: <specific function> = specific_function %GetNoDeduce.162, @GetNoDeduce(%A, %B) [concrete]
 // CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.b6e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%A) [concrete]
+// CHECK:STDOUT:   %Op.type.b96: type = fn_type @Op.2, @impl(%A) [concrete]
+// CHECK:STDOUT:   %Op.885: %Op.type.b96 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.6db: type = ptr_type %A [concrete]
+// CHECK:STDOUT:   %Destroy.facet.4a1: %Destroy.type = facet_value %A, (%Destroy.impl_witness.b6e) [concrete]
+// CHECK:STDOUT:   %.af1: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.4a1 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.716: <specific function> = specific_function %Op.885, @Op.2(%A) [concrete]
 // CHECK:STDOUT:   %complete_type.56a: <witness> = complete_type_witness %tuple.type.cc6 [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -216,10 +247,17 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %tuple.type [symbolic = %pattern_type (constants.%pattern_type.65c)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete.fe1)]
+// CHECK:STDOUT:   %require_complete.loc19_20.1: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc19_20.1 (constants.%require_complete.fe1)]
 // CHECK:STDOUT:   %Get.type: type = fn_type @Get, @Class(%T) [symbolic = %Get.type (constants.%Get.type.fd9)]
 // CHECK:STDOUT:   %Get: @Get.%Get.type (%Get.type.fd9) = struct_value () [symbolic = %Get (constants.%Get.cf9)]
 // CHECK:STDOUT:   %Get.specific_fn.loc19_39.2: <specific function> = specific_function %Get, @Get(%T, %U.loc19_10.1) [symbolic = %Get.specific_fn.loc19_39.2 (constants.%Get.specific_fn.f73)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1c6)]
+// CHECK:STDOUT:   %.loc19_20.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc19_20.3 (constants.%.1e9)]
+// CHECK:STDOUT:   %impl.elem0.loc19_20.2: @Get.%.loc19_20.3 (%.1e9) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc19_20.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.loc19_20.2: <specific function> = specific_impl_function %impl.elem0.loc19_20.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc19_20.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %tuple.type [symbolic = %ptr (constants.%ptr.937)]
+// CHECK:STDOUT:   %require_complete.loc19_20.2: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc19_20.2 (constants.%require_complete.8fa)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> %return.param: @Get.%tuple.type (%tuple.type.30b) {
 // CHECK:STDOUT:   !entry:
@@ -227,8 +265,14 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:     %Get.ref: @Get.%Get.type (%Get.type.fd9) = name_ref Get, %.loc19_39 [symbolic = %Get (constants.%Get.cf9)]
 // CHECK:STDOUT:     %U.ref.loc19_43: type = name_ref U, %U.loc19_10.2 [symbolic = %U.loc19_10.1 (constants.%U)]
 // CHECK:STDOUT:     %Get.specific_fn.loc19_39.1: <specific function> = specific_function %Get.ref, @Get(constants.%T, constants.%U) [symbolic = %Get.specific_fn.loc19_39.2 (constants.%Get.specific_fn.f73)]
-// CHECK:STDOUT:     %.loc19_20: ref @Get.%tuple.type (%tuple.type.30b) = splice_block %return {}
-// CHECK:STDOUT:     %Get.call: init @Get.%tuple.type (%tuple.type.30b) = call %Get.specific_fn.loc19_39.1() to %.loc19_20
+// CHECK:STDOUT:     %.loc19_20.1: ref @Get.%tuple.type (%tuple.type.30b) = splice_block %return {}
+// CHECK:STDOUT:     %Get.call: init @Get.%tuple.type (%tuple.type.30b) = call %Get.specific_fn.loc19_39.1() to %.loc19_20.1
+// CHECK:STDOUT:     %impl.elem0.loc19_20.1: @Get.%.loc19_20.3 (%.1e9) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc19_20.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.loc19_20.1: <bound method> = bound_method %.loc19_20.1, %impl.elem0.loc19_20.1
+// CHECK:STDOUT:     %specific_impl_fn.loc19_20.1: <specific function> = specific_impl_function %impl.elem0.loc19_20.1, @Op.1(constants.%Destroy.facet.1c6) [symbolic = %specific_impl_fn.loc19_20.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc19_20.2: <bound method> = bound_method %.loc19_20.1, %specific_impl_fn.loc19_20.1
+// CHECK:STDOUT:     %addr: @Get.%ptr (%ptr.937) = addr_of %.loc19_20.1
+// CHECK:STDOUT:     %.loc19_20.2: init %empty_tuple.type = call %bound_method.loc19_20.2(%addr)
 // CHECK:STDOUT:     return %Get.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -246,6 +290,13 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %GetNoDeduce: @GetNoDeduce.%GetNoDeduce.type (%GetNoDeduce.type.766) = struct_value () [symbolic = %GetNoDeduce (constants.%GetNoDeduce.c9a)]
 // CHECK:STDOUT:   %GetNoDeduce.specific_fn.loc20_53.2: <specific function> = specific_function %GetNoDeduce, @GetNoDeduce(%T, %U.loc20_24.1) [symbolic = %GetNoDeduce.specific_fn.loc20_53.2 (constants.%GetNoDeduce.specific_fn.536)]
 // CHECK:STDOUT:   %require_complete.loc20_70: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc20_70 (constants.%require_complete.fe1)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1c6)]
+// CHECK:STDOUT:   %.loc20_34.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc20_34.3 (constants.%.1e9)]
+// CHECK:STDOUT:   %impl.elem0.loc20_34.2: @GetNoDeduce.%.loc20_34.3 (%.1e9) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc20_34.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.loc20_34.2: <specific function> = specific_impl_function %impl.elem0.loc20_34.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc20_34.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %tuple.type [symbolic = %ptr (constants.%ptr.937)]
+// CHECK:STDOUT:   %require_complete.loc20_34: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc20_34 (constants.%require_complete.8fa)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%x.param: @GetNoDeduce.%T (%T)) -> %return.param: @GetNoDeduce.%tuple.type (%tuple.type.30b) {
 // CHECK:STDOUT:   !entry:
@@ -254,8 +305,14 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:     %x.ref: @GetNoDeduce.%T (%T) = name_ref x, %x
 // CHECK:STDOUT:     %U.ref.loc20_68: type = name_ref U, %U.loc20_24.2 [symbolic = %U.loc20_24.1 (constants.%U)]
 // CHECK:STDOUT:     %GetNoDeduce.specific_fn.loc20_53.1: <specific function> = specific_function %GetNoDeduce.ref, @GetNoDeduce(constants.%T, constants.%U) [symbolic = %GetNoDeduce.specific_fn.loc20_53.2 (constants.%GetNoDeduce.specific_fn.536)]
-// CHECK:STDOUT:     %.loc20_34: ref @GetNoDeduce.%tuple.type (%tuple.type.30b) = splice_block %return {}
-// CHECK:STDOUT:     %GetNoDeduce.call: init @GetNoDeduce.%tuple.type (%tuple.type.30b) = call %GetNoDeduce.specific_fn.loc20_53.1(%x.ref) to %.loc20_34
+// CHECK:STDOUT:     %.loc20_34.1: ref @GetNoDeduce.%tuple.type (%tuple.type.30b) = splice_block %return {}
+// CHECK:STDOUT:     %GetNoDeduce.call: init @GetNoDeduce.%tuple.type (%tuple.type.30b) = call %GetNoDeduce.specific_fn.loc20_53.1(%x.ref) to %.loc20_34.1
+// CHECK:STDOUT:     %impl.elem0.loc20_34.1: @GetNoDeduce.%.loc20_34.3 (%.1e9) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc20_34.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.loc20_34.1: <bound method> = bound_method %.loc20_34.1, %impl.elem0.loc20_34.1
+// CHECK:STDOUT:     %specific_impl_fn.loc20_34.1: <specific function> = specific_impl_function %impl.elem0.loc20_34.1, @Op.1(constants.%Destroy.facet.1c6) [symbolic = %specific_impl_fn.loc20_34.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc20_34.2: <bound method> = bound_method %.loc20_34.1, %specific_impl_fn.loc20_34.1
+// CHECK:STDOUT:     %addr: @GetNoDeduce.%ptr (%ptr.937) = addr_of %.loc20_34.1
+// CHECK:STDOUT:     %.loc20_34.2: init %empty_tuple.type = call %bound_method.loc20_34.2(%addr)
 // CHECK:STDOUT:     return %GetNoDeduce.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -269,6 +326,12 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.ref, @Get(constants.%A, constants.%B) [concrete = constants.%Get.specific_fn.213]
 // CHECK:STDOUT:   %.loc23_35: ref %tuple.type.cc6 = splice_block %return {}
 // CHECK:STDOUT:   %Get.call: init %tuple.type.cc6 = call %Get.specific_fn() to %.loc23_35
+// CHECK:STDOUT:   %impl.elem0: %.c9f = impl_witness_access constants.%Destroy.impl_witness.ae3, element0 [concrete = constants.%Op.f13]
+// CHECK:STDOUT:   %bound_method.loc23_35.1: <bound method> = bound_method %.loc23_35, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%tuple.type.cc6) [concrete = constants.%Op.specific_fn.8d7]
+// CHECK:STDOUT:   %bound_method.loc23_35.2: <bound method> = bound_method %.loc23_35, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.3b5 = addr_of %.loc23_35
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc23_35.2(%addr)
 // CHECK:STDOUT:   return %Get.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -287,6 +350,18 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %.loc28_25.5: ref %A = converted %.loc28_25.1, %.loc28_25.4
 // CHECK:STDOUT:   %.loc28_25.6: %A = bind_value %.loc28_25.5
 // CHECK:STDOUT:   %GetNoDeduce.call: init %tuple.type.cc6 = call %GetNoDeduce.specific_fn(%.loc28_25.6) to %.loc27_54
+// CHECK:STDOUT:   %impl.elem0.loc28: %.af1 = impl_witness_access constants.%Destroy.impl_witness.b6e, element0 [concrete = constants.%Op.885]
+// CHECK:STDOUT:   %bound_method.loc28_25.1: <bound method> = bound_method %.loc28_25.2, %impl.elem0.loc28
+// CHECK:STDOUT:   %specific_fn.loc28: <specific function> = specific_function %impl.elem0.loc28, @Op.2(constants.%A) [concrete = constants.%Op.specific_fn.716]
+// CHECK:STDOUT:   %bound_method.loc28_25.2: <bound method> = bound_method %.loc28_25.2, %specific_fn.loc28
+// CHECK:STDOUT:   %addr.loc28: %ptr.6db = addr_of %.loc28_25.2
+// CHECK:STDOUT:   %no_op.loc28: init %empty_tuple.type = call %bound_method.loc28_25.2(%addr.loc28)
+// CHECK:STDOUT:   %impl.elem0.loc27: %.c9f = impl_witness_access constants.%Destroy.impl_witness.ae3, element0 [concrete = constants.%Op.f13]
+// CHECK:STDOUT:   %bound_method.loc27_54.1: <bound method> = bound_method %.loc27_54, %impl.elem0.loc27
+// CHECK:STDOUT:   %specific_fn.loc27: <specific function> = specific_function %impl.elem0.loc27, @Op.2(constants.%tuple.type.cc6) [concrete = constants.%Op.specific_fn.8d7]
+// CHECK:STDOUT:   %bound_method.loc27_54.2: <bound method> = bound_method %.loc27_54, %specific_fn.loc27
+// CHECK:STDOUT:   %addr.loc27: %ptr.3b5 = addr_of %.loc27_54
+// CHECK:STDOUT:   %no_op.loc27: init %empty_tuple.type = call %bound_method.loc27_54.2(%addr.loc27)
 // CHECK:STDOUT:   return %GetNoDeduce.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -307,10 +382,17 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.65c
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete.fe1
+// CHECK:STDOUT:   %require_complete.loc19_20.1 => constants.%require_complete.fe1
 // CHECK:STDOUT:   %Get.type => constants.%Get.type.fd9
 // CHECK:STDOUT:   %Get => constants.%Get.cf9
 // CHECK:STDOUT:   %Get.specific_fn.loc19_39.2 => constants.%Get.specific_fn.f73
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.1c6
+// CHECK:STDOUT:   %.loc19_20.3 => constants.%.1e9
+// CHECK:STDOUT:   %impl.elem0.loc19_20.2 => constants.%impl.elem0
+// CHECK:STDOUT:   %specific_impl_fn.loc19_20.2 => constants.%specific_impl_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.937
+// CHECK:STDOUT:   %require_complete.loc19_20.2 => constants.%require_complete.8fa
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @GetNoDeduce(constants.%T, constants.%U) {
@@ -326,6 +408,13 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %GetNoDeduce => constants.%GetNoDeduce.c9a
 // CHECK:STDOUT:   %GetNoDeduce.specific_fn.loc20_53.2 => constants.%GetNoDeduce.specific_fn.536
 // CHECK:STDOUT:   %require_complete.loc20_70 => constants.%require_complete.fe1
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.1c6
+// CHECK:STDOUT:   %.loc20_34.3 => constants.%.1e9
+// CHECK:STDOUT:   %impl.elem0.loc20_34.2 => constants.%impl.elem0
+// CHECK:STDOUT:   %specific_impl_fn.loc20_34.2 => constants.%specific_impl_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.937
+// CHECK:STDOUT:   %require_complete.loc20_34 => constants.%require_complete.8fa
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Class(constants.%A) {
@@ -345,10 +434,17 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.edc
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%complete_type.56a
+// CHECK:STDOUT:   %require_complete.loc19_20.1 => constants.%complete_type.56a
 // CHECK:STDOUT:   %Get.type => constants.%Get.type.501
 // CHECK:STDOUT:   %Get => constants.%Get.f37
 // CHECK:STDOUT:   %Get.specific_fn.loc19_39.2 => constants.%Get.specific_fn.213
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.impl_witness.ae3
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.fae
+// CHECK:STDOUT:   %.loc19_20.3 => constants.%.c9f
+// CHECK:STDOUT:   %impl.elem0.loc19_20.2 => constants.%Op.f13
+// CHECK:STDOUT:   %specific_impl_fn.loc19_20.2 => constants.%Op.specific_fn.8d7
+// CHECK:STDOUT:   %ptr => constants.%ptr.3b5
+// CHECK:STDOUT:   %require_complete.loc19_20.2 => constants.%complete_type.a4a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @GetNoDeduce(constants.%A, constants.%B) {
@@ -364,5 +460,12 @@ fn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {
 // CHECK:STDOUT:   %GetNoDeduce => constants.%GetNoDeduce.162
 // CHECK:STDOUT:   %GetNoDeduce.specific_fn.loc20_53.2 => constants.%GetNoDeduce.specific_fn.438
 // CHECK:STDOUT:   %require_complete.loc20_70 => constants.%complete_type.56a
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.impl_witness.ae3
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.fae
+// CHECK:STDOUT:   %.loc20_34.3 => constants.%.c9f
+// CHECK:STDOUT:   %impl.elem0.loc20_34.2 => constants.%Op.f13
+// CHECK:STDOUT:   %specific_impl_fn.loc20_34.2 => constants.%Op.specific_fn.8d7
+// CHECK:STDOUT:   %ptr => constants.%ptr.3b5
+// CHECK:STDOUT:   %require_complete.loc20_34 => constants.%complete_type.a4a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 22 - 0
toolchain/check/testdata/class/inheritance_access.carbon

@@ -379,15 +379,31 @@ class B {
 // CHECK:STDOUT:   %struct_type.base.0ff: type = struct_type {.base: %B} [concrete]
 // CHECK:STDOUT:   %complete_type.98e: <witness> = complete_type_witness %struct_type.base.0ff [concrete]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -481,6 +497,12 @@ class B {
 // CHECK:STDOUT:   %.loc15_44.2: ref %empty_tuple.type = temporary %.loc15_44.1, %F.call
 // CHECK:STDOUT:   %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc15_45: %empty_tuple.type = converted %F.call, %tuple [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:   %impl.elem0: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:   %bound_method.loc15_44.1: <bound method> = bound_method %.loc15_44.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_44.2: <bound method> = bound_method %.loc15_44.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %.loc15_44.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc15_44.2(%addr)
 // CHECK:STDOUT:   return %.loc15_45
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 0
toolchain/check/testdata/class/init_as.carbon

@@ -27,6 +27,7 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Class: type = class_type @Class [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]
@@ -58,12 +59,25 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %bound_method.b92: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]
 // CHECK:STDOUT:   %Class.val: %Class = struct_value (%int_1.5d2, %int_2.ef8) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.fef: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Class) [concrete]
+// CHECK:STDOUT:   %Op.type.7de: type = fn_type @Op.3, @impl.49c(%Class) [concrete]
+// CHECK:STDOUT:   %Op.d64: %Op.type.7de = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.e71: type = ptr_type %Class [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class, (%Destroy.impl_witness.fef) [concrete]
+// CHECK:STDOUT:   %.b9f: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d64, @Op.3(%Class) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -71,6 +85,9 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -138,6 +155,12 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %a.ref: %Class.elem = name_ref a, @Class.%.loc16 [concrete = @Class.%.loc16]
 // CHECK:STDOUT:   %.loc21_37.1: ref %i32 = class_element_access %.loc21_28, element0
 // CHECK:STDOUT:   %.loc21_37.2: %i32 = bind_value %.loc21_37.1
+// CHECK:STDOUT:   %impl.elem0.loc21_26.3: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc21_26.5: <bound method> = bound_method %.loc21_26.3, %impl.elem0.loc21_26.3
+// CHECK:STDOUT:   %specific_fn.loc21_26.3: <specific function> = specific_function %impl.elem0.loc21_26.3, @Op.3(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc21_26.6: <bound method> = bound_method %.loc21_26.3, %specific_fn.loc21_26.3
+// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %.loc21_26.3
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc21_26.6(%addr)
 // CHECK:STDOUT:   return %.loc21_37.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 29 - 0
toolchain/check/testdata/class/init_nested.carbon

@@ -34,6 +34,7 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT:   %Inner: type = class_type @Inner [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %Inner.elem: type = unbound_element_type %Inner, %i32 [concrete]
@@ -49,15 +50,31 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT:   %pattern_type.e74: type = pattern_type %Outer [concrete]
 // CHECK:STDOUT:   %MakeOuter.type: type = fn_type @MakeOuter [concrete]
 // CHECK:STDOUT:   %MakeOuter: %MakeOuter.type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.14c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%Inner) [concrete]
+// CHECK:STDOUT:   %Op.type.e24: type = fn_type @Op.2, @impl(%Inner) [concrete]
+// CHECK:STDOUT:   %Op.7b1: %Op.type.e24 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.78b: type = ptr_type %Inner [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Inner, (%Destroy.impl_witness.14c) [concrete]
+// CHECK:STDOUT:   %.f61: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.7b1, @Op.2(%Inner) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -135,6 +152,18 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT:   %.loc28_45.3: %struct_type.c.d.dce = struct_literal (%MakeInner.call.loc28_26, %MakeInner.call.loc28_44)
 // CHECK:STDOUT:   %.loc28_45.4: init %Outer = class_init (%MakeInner.call.loc28_26, %MakeInner.call.loc28_44), %return
 // CHECK:STDOUT:   %.loc28_46: init %Outer = converted %.loc28_45.3, %.loc28_45.4
+// CHECK:STDOUT:   %impl.elem0.loc28_45.1: %.f61 = impl_witness_access constants.%Destroy.impl_witness.14c, element0 [concrete = constants.%Op.7b1]
+// CHECK:STDOUT:   %bound_method.loc28_45.1: <bound method> = bound_method %.loc28_45.2, %impl.elem0.loc28_45.1
+// CHECK:STDOUT:   %specific_fn.loc28_45.1: <specific function> = specific_function %impl.elem0.loc28_45.1, @Op.2(constants.%Inner) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc28_45.2: <bound method> = bound_method %.loc28_45.2, %specific_fn.loc28_45.1
+// CHECK:STDOUT:   %addr.loc28_45.1: %ptr.78b = addr_of %.loc28_45.2
+// CHECK:STDOUT:   %no_op.loc28_45.1: init %empty_tuple.type = call %bound_method.loc28_45.2(%addr.loc28_45.1)
+// CHECK:STDOUT:   %impl.elem0.loc28_45.2: %.f61 = impl_witness_access constants.%Destroy.impl_witness.14c, element0 [concrete = constants.%Op.7b1]
+// CHECK:STDOUT:   %bound_method.loc28_45.3: <bound method> = bound_method %.loc28_45.1, %impl.elem0.loc28_45.2
+// CHECK:STDOUT:   %specific_fn.loc28_45.2: <specific function> = specific_function %impl.elem0.loc28_45.2, @Op.2(constants.%Inner) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc28_45.4: <bound method> = bound_method %.loc28_45.1, %specific_fn.loc28_45.2
+// CHECK:STDOUT:   %addr.loc28_45.2: %ptr.78b = addr_of %.loc28_45.1
+// CHECK:STDOUT:   %no_op.loc28_45.2: init %empty_tuple.type = call %bound_method.loc28_45.4(%addr.loc28_45.2)
 // CHECK:STDOUT:   return %.loc28_46 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 0
toolchain/check/testdata/class/local.carbon

@@ -33,6 +33,7 @@ class A {
 // CHECK:STDOUT:   %A: type = class_type @A [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -66,12 +67,25 @@ class A {
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
 // CHECK:STDOUT:   %B.val: %B = struct_value (%int_1.5d2) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.8a9: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.type.96c: type = fn_type @Op.3, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.c53: %Op.type.96c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.bac: type = ptr_type %B [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %B, (%Destroy.impl_witness.8a9) [concrete]
+// CHECK:STDOUT:   %.f0e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.c53, @Op.3(%B) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -79,6 +93,9 @@ class A {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -142,6 +159,12 @@ class A {
 // CHECK:STDOUT:   %n.ref: %B.elem = name_ref n, @B.%.loc23 [concrete = @B.%.loc23]
 // CHECK:STDOUT:   %.loc26_20.1: ref %i32 = class_element_access %.loc26_19.2, element0
 // CHECK:STDOUT:   %.loc26_20.2: %i32 = bind_value %.loc26_20.1
+// CHECK:STDOUT:   %impl.elem0: %.f0e = impl_witness_access constants.%Destroy.impl_witness.8a9, element0 [concrete = constants.%Op.c53]
+// CHECK:STDOUT:   %bound_method.loc26_19.1: <bound method> = bound_method %.loc26_19.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%B) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_19.2: <bound method> = bound_method %.loc26_19.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.bac = addr_of %.loc26_19.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc26_19.2(%addr)
 // CHECK:STDOUT:   return %.loc26_20.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 48 - 8
toolchain/check/testdata/class/method.carbon

@@ -69,6 +69,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %pattern_type.761: type = pattern_type %Class [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -107,6 +108,17 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
 // CHECK:STDOUT:   %Class.val: %Class = struct_value (%int_1.5d2) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.fef: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Class) [concrete]
+// CHECK:STDOUT:   %Op.type.7de: type = fn_type @Op.3, @impl.49c(%Class) [concrete]
+// CHECK:STDOUT:   %Op.d64: %Op.type.7de = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class, (%Destroy.impl_witness.fef) [concrete]
+// CHECK:STDOUT:   %.b9f: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d64, @Op.3(%Class) [concrete]
 // CHECK:STDOUT:   %CallWithAddr.type: type = fn_type @CallWithAddr [concrete]
 // CHECK:STDOUT:   %CallWithAddr: %CallWithAddr.type = struct_value () [concrete]
 // CHECK:STDOUT:   %CallFThroughPointer.type: type = fn_type @CallFThroughPointer [concrete]
@@ -125,6 +137,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -132,6 +145,9 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -360,10 +376,10 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %.loc39_18.1: %struct_type.k.240 = struct_literal (%int_1)
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc39_18.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc39_18.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc39_18.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc39_18.1: <bound method> = bound_method %int_1, %impl.elem0.loc39_18.1 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc39_18.1: <specific function> = specific_function %impl.elem0.loc39_18.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc39_18.2: <bound method> = bound_method %int_1, %specific_fn.loc39_18.1 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc39_18.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc39_18.2: init %i32 = converted %int_1, %int.convert_checked [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc39_18.3: ref %Class = temporary_storage
@@ -378,6 +394,12 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.bound(%.loc39_20.2)
 // CHECK:STDOUT:   %.loc39_33.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc39_33.2: %i32 = converted %F.call, %.loc39_33.1
+// CHECK:STDOUT:   %impl.elem0.loc39_18.2: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc39_18.3: <bound method> = bound_method %.loc39_18.3, %impl.elem0.loc39_18.2
+// CHECK:STDOUT:   %specific_fn.loc39_18.2: <specific function> = specific_function %impl.elem0.loc39_18.2, @Op.3(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc39_18.4: <bound method> = bound_method %.loc39_18.3, %specific_fn.loc39_18.2
+// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %.loc39_18.3
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc39_18.4(%addr)
 // CHECK:STDOUT:   return %.loc39_33.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -393,10 +415,16 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %c.ref: ref %Class = name_ref c, %c
 // CHECK:STDOUT:   %G.ref: %G.type = name_ref G, @Class.%G.decl [concrete = constants.%G]
 // CHECK:STDOUT:   %G.bound: <bound method> = bound_method %c.ref, %G.ref
-// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %c.ref
-// CHECK:STDOUT:   %G.call: init %i32 = call %G.bound(%addr)
+// CHECK:STDOUT:   %addr.loc44: %ptr.e71 = addr_of %c.ref
+// CHECK:STDOUT:   %G.call: init %i32 = call %G.bound(%addr.loc44)
 // CHECK:STDOUT:   %.loc44_15.1: %i32 = value_of_initializer %G.call
 // CHECK:STDOUT:   %.loc44_15.2: %i32 = converted %G.call, %.loc44_15.1
+// CHECK:STDOUT:   %impl.elem0: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc43_3.1: <bound method> = bound_method %c.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc43_3.2: <bound method> = bound_method %c.var, %specific_fn
+// CHECK:STDOUT:   %addr.loc43: %ptr.e71 = addr_of %c.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc43_3.2(%addr.loc43)
 // CHECK:STDOUT:   return %.loc44_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -440,6 +468,12 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.bound(%.loc58_15.3)
 // CHECK:STDOUT:   %.loc58_20.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc58_20.2: %i32 = converted %F.call, %.loc58_20.1
+// CHECK:STDOUT:   %impl.elem0: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc58_15.1: <bound method> = bound_method %.loc58_15.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc58_15.2: <bound method> = bound_method %.loc58_15.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %.loc58_15.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc58_15.2(%addr)
 // CHECK:STDOUT:   return %.loc58_20.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -451,10 +485,16 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   %.loc62_15.2: ref %Class = temporary %.loc62_15.1, %Make.call
 // CHECK:STDOUT:   %G.ref: %G.type = name_ref G, @Class.%G.decl [concrete = constants.%G]
 // CHECK:STDOUT:   %G.bound: <bound method> = bound_method %.loc62_15.2, %G.ref
-// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %.loc62_15.2
-// CHECK:STDOUT:   %G.call: init %i32 = call %G.bound(%addr)
+// CHECK:STDOUT:   %addr.loc62_15.1: %ptr.e71 = addr_of %.loc62_15.2
+// CHECK:STDOUT:   %G.call: init %i32 = call %G.bound(%addr.loc62_15.1)
 // CHECK:STDOUT:   %.loc62_20.1: %i32 = value_of_initializer %G.call
 // CHECK:STDOUT:   %.loc62_20.2: %i32 = converted %G.call, %.loc62_20.1
+// CHECK:STDOUT:   %impl.elem0: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc62_15.1: <bound method> = bound_method %.loc62_15.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc62_15.2: <bound method> = bound_method %.loc62_15.1, %specific_fn
+// CHECK:STDOUT:   %addr.loc62_15.2: %ptr.e71 = addr_of %.loc62_15.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc62_15.2(%addr.loc62_15.2)
 // CHECK:STDOUT:   return %.loc62_20.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 0
toolchain/check/testdata/class/static_method.carbon

@@ -27,6 +27,7 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %Class: type = class_type @Class [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -37,15 +38,31 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]
 // CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.761: type = pattern_type %Class [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.fef: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%Class) [concrete]
+// CHECK:STDOUT:   %Op.type.7de: type = fn_type @Op.2, @impl(%Class) [concrete]
+// CHECK:STDOUT:   %Op.d64: %Op.type.7de = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.e71: type = ptr_type %Class [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class, (%Destroy.impl_witness.fef) [concrete]
+// CHECK:STDOUT:   %.b9f: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d64, @Op.2(%Class) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -104,6 +121,12 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.ref()
 // CHECK:STDOUT:   %.loc21_15.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc21_15.2: %i32 = converted %F.call, %.loc21_15.1
+// CHECK:STDOUT:   %impl.elem0: %.b9f = impl_witness_access constants.%Destroy.impl_witness.fef, element0 [concrete = constants.%Op.d64]
+// CHECK:STDOUT:   %bound_method.loc20_3.1: <bound method> = bound_method %c.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%Class) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc20_3.2: <bound method> = bound_method %c.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e71 = addr_of %c.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc20_3.2(%addr)
 // CHECK:STDOUT:   return %.loc21_15.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 139 - 0
toolchain/check/testdata/deduce/array.carbon

@@ -138,6 +138,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.58b: type = pattern_type %array_type.743 [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dcd0a.1: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %require_complete.06f: <witness> = require_complete_type %array_type.743 [symbolic]
@@ -166,6 +167,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %array_type.002: type = array_type %int_3, %C [concrete]
+// CHECK:STDOUT:   %ptr.301: type = ptr_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %pattern_type.a63: type = pattern_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]
 // CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]
@@ -173,6 +175,23 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]
 // CHECK:STDOUT:   %array: %array_type.002 = tuple_value (%C.val, %C.val, %C.val) [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.3, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet.494: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.494 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.6eb: <specific function> = specific_function %Op.5d7, @Op.3(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.f2c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.type.85d: type = fn_type @Op.3, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.1f9: %Op.type.85d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.de0: %Destroy.type = facet_value %array_type.002, (%Destroy.impl_witness.f2c) [concrete]
+// CHECK:STDOUT:   %.4c4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.de0 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.f55: <specific function> = specific_function %Op.1f9, @Op.3(%array_type.002) [concrete]
 // CHECK:STDOUT:   %complete_type.dd1: <witness> = complete_type_witness %array_type.002 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -180,6 +199,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -187,6 +207,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -304,6 +327,18 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc8: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %.loc10: %array_type.002 = bind_value %a.ref
 // CHECK:STDOUT:   %F.call: init %C = call %F.specific_fn(%.loc10) to %.loc8
+// CHECK:STDOUT:   %impl.elem0.loc8: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc8_8.1: <bound method> = bound_method %.loc8, %impl.elem0.loc8
+// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Op.3(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:   %bound_method.loc8_8.2: <bound method> = bound_method %.loc8, %specific_fn.loc8
+// CHECK:STDOUT:   %addr.loc8: %ptr.019 = addr_of %.loc8
+// CHECK:STDOUT:   %no_op.loc8: init %empty_tuple.type = call %bound_method.loc8_8.2(%addr.loc8)
+// CHECK:STDOUT:   %impl.elem0.loc9: %.4c4 = impl_witness_access constants.%Destroy.impl_witness.f2c, element0 [concrete = constants.%Op.1f9]
+// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %a.var, %impl.elem0.loc9
+// CHECK:STDOUT:   %specific_fn.loc9: <specific function> = specific_function %impl.elem0.loc9, @Op.3(constants.%array_type.002) [concrete = constants.%Op.specific_fn.f55]
+// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %a.var, %specific_fn.loc9
+// CHECK:STDOUT:   %addr.loc9: %ptr.301 = addr_of %a.var
+// CHECK:STDOUT:   %no_op.loc9: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr.loc9)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -332,6 +367,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]
 // CHECK:STDOUT:   %N: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]
@@ -365,6 +401,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %array_type.002: type = array_type %int_3.1ba, %C [concrete]
+// CHECK:STDOUT:   %ptr.301: type = ptr_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %pattern_type.a63: type = pattern_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]
@@ -373,6 +410,17 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]
 // CHECK:STDOUT:   %array: %array_type.002 = tuple_value (%C.val, %C.val, %C.val) [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_3.1ba) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.f2c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.type.85d: type = fn_type @Op.3, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.1f9: %Op.type.85d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type.002, (%Destroy.impl_witness.f2c) [concrete]
+// CHECK:STDOUT:   %.4c4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.1f9, @Op.3(%array_type.002) [concrete]
 // CHECK:STDOUT:   %complete_type.dd1: <witness> = complete_type_witness %array_type.002 [concrete]
 // CHECK:STDOUT:   %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
@@ -384,6 +432,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -392,6 +441,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -514,6 +566,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%.loc10_12)
 // CHECK:STDOUT:   %.loc10_14.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc10_14.2: %i32 = converted %F.call, %.loc10_14.1
+// CHECK:STDOUT:   %impl.elem0: %.4c4 = impl_witness_access constants.%Destroy.impl_witness.f2c, element0 [concrete = constants.%Op.1f9]
+// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %a.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%array_type.002) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %a.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.301 = addr_of %a.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr)
 // CHECK:STDOUT:   return %.loc10_14.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -727,6 +785,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.a4c: type = pattern_type %array_type.9d4 [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dcd0a.1: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %require_complete.d11: <witness> = require_complete_type %array_type.9d4 [symbolic]
@@ -756,6 +815,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %array_type.002: type = array_type %int_3, %C [concrete]
+// CHECK:STDOUT:   %ptr.301: type = ptr_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %pattern_type.a63: type = pattern_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]
 // CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]
@@ -764,6 +824,23 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %array_type.15a: type = array_type %int_2, %C [concrete]
 // CHECK:STDOUT:   %pattern_type.114: type = pattern_type %array_type.15a [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.3, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet.494: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.494 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.6eb: <specific function> = specific_function %Op.5d7, @Op.3(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.f2c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.type.85d: type = fn_type @Op.3, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.1f9: %Op.type.85d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.de0: %Destroy.type = facet_value %array_type.002, (%Destroy.impl_witness.f2c) [concrete]
+// CHECK:STDOUT:   %.4c4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.de0 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.f55: <specific function> = specific_function %Op.1f9, @Op.3(%array_type.002) [concrete]
 // CHECK:STDOUT:   %complete_type.8eb: <witness> = complete_type_witness %array_type.15a [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -771,6 +848,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -778,6 +856,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -895,6 +976,18 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc8: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %.loc21: %array_type.15a = converted %a.ref, <error> [concrete = <error>]
 // CHECK:STDOUT:   %F.call: init %C = call %F.specific_fn(<error>) to %.loc8
+// CHECK:STDOUT:   %impl.elem0.loc8: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc8_8.1: <bound method> = bound_method %.loc8, %impl.elem0.loc8
+// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Op.3(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:   %bound_method.loc8_8.2: <bound method> = bound_method %.loc8, %specific_fn.loc8
+// CHECK:STDOUT:   %addr.loc8: %ptr.019 = addr_of %.loc8
+// CHECK:STDOUT:   %no_op.loc8: init %empty_tuple.type = call %bound_method.loc8_8.2(%addr.loc8)
+// CHECK:STDOUT:   %impl.elem0.loc10: %.4c4 = impl_witness_access constants.%Destroy.impl_witness.f2c, element0 [concrete = constants.%Op.1f9]
+// CHECK:STDOUT:   %bound_method.loc10_3.1: <bound method> = bound_method %a.var, %impl.elem0.loc10
+// CHECK:STDOUT:   %specific_fn.loc10: <specific function> = specific_function %impl.elem0.loc10, @Op.3(constants.%array_type.002) [concrete = constants.%Op.specific_fn.f55]
+// CHECK:STDOUT:   %bound_method.loc10_3.2: <bound method> = bound_method %a.var, %specific_fn.loc10
+// CHECK:STDOUT:   %addr.loc10: %ptr.301 = addr_of %a.var
+// CHECK:STDOUT:   %no_op.loc10: init %empty_tuple.type = call %bound_method.loc10_3.2(%addr.loc10)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -924,6 +1017,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %D: type = class_type @D [concrete]
 // CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]
 // CHECK:STDOUT:   %N: Core.IntLiteral = bind_symbolic_name N, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]
@@ -957,6 +1051,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %array_type.fe4: type = array_type %int_3.1ba, %D [concrete]
+// CHECK:STDOUT:   %ptr.af6: type = ptr_type %array_type.fe4 [concrete]
 // CHECK:STDOUT:   %pattern_type.f30: type = pattern_type %array_type.fe4 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]
@@ -967,6 +1062,17 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %array_type.002: type = array_type %int_3.1ba, %C [concrete]
 // CHECK:STDOUT:   %pattern_type.a63: type = pattern_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_3.1ba) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.51e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.fe4) [concrete]
+// CHECK:STDOUT:   %Op.type.419: type = fn_type @Op.3, @impl.49c(%array_type.fe4) [concrete]
+// CHECK:STDOUT:   %Op.11a: %Op.type.419 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type.fe4, (%Destroy.impl_witness.51e) [concrete]
+// CHECK:STDOUT:   %.761: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.11a, @Op.3(%array_type.fe4) [concrete]
 // CHECK:STDOUT:   %complete_type.dd1: <witness> = complete_type_witness %array_type.002 [concrete]
 // CHECK:STDOUT:   %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
@@ -978,6 +1084,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -986,6 +1093,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -1119,6 +1229,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(<error>)
 // CHECK:STDOUT:   %.loc22_14.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc22_14.2: %i32 = converted %F.call, %.loc22_14.1
+// CHECK:STDOUT:   %impl.elem0: %.761 = impl_witness_access constants.%Destroy.impl_witness.51e, element0 [concrete = constants.%Op.11a]
+// CHECK:STDOUT:   %bound_method.loc11_3.1: <bound method> = bound_method %a.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%array_type.fe4) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_3.2: <bound method> = bound_method %a.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.af6 = addr_of %a.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc11_3.2(%addr)
 // CHECK:STDOUT:   return %.loc22_14.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1148,6 +1264,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %N.51e: %i32 = bind_symbolic_name N, 0 [symbolic]
@@ -1177,6 +1294,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %array_type.002: type = array_type %int_3, %C [concrete]
+// CHECK:STDOUT:   %ptr.301: type = ptr_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %pattern_type.a63: type = pattern_type %array_type.002 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]
@@ -1184,12 +1302,24 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]
 // CHECK:STDOUT:   %array: %array_type.002 = tuple_value (%C.val, %C.val, %C.val) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.f2c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.type.85d: type = fn_type @Op.3, @impl.49c(%array_type.002) [concrete]
+// CHECK:STDOUT:   %Op.1f9: %Op.type.85d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type.002, (%Destroy.impl_witness.f2c) [concrete]
+// CHECK:STDOUT:   %.4c4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.1f9, @Op.3(%array_type.002) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -1197,6 +1327,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.85c: @impl.971.%Convert.type (%Convert.type.708) = import_ref Core//prelude/parts/int, loc20_44, loaded [symbolic = @impl.971.%Convert (constants.%Convert.c68)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.1d9 = impl_witness_table (%Core.import_ref.85c), @impl.971 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -1311,6 +1444,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %a: ref %array_type.002 = bind_name a, %a.var
 // CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:   %a.ref: ref %array_type.002 = name_ref a, %a
+// CHECK:STDOUT:   %impl.elem0: %.4c4 = impl_witness_access constants.%Destroy.impl_witness.f2c, element0 [concrete = constants.%Op.1f9]
+// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %a.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%array_type.002) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %a.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.301 = addr_of %a.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_3.2(%addr)
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 151 - 21
toolchain/check/testdata/deduce/generic_type.carbon

@@ -75,10 +75,11 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]
 // CHECK:STDOUT:   %C.f2e: type = class_type @C, @C(%T) [symbolic]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %D: type = class_type @D [concrete]
 // CHECK:STDOUT:   %pattern_type.e5e: type = pattern_type %C.f2e [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
@@ -93,13 +94,28 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.c4a: <specific function> = specific_function %F, @F(%D) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.45e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%D) [concrete]
+// CHECK:STDOUT:   %Op.type.548: type = fn_type @Op.2, @impl(%D) [concrete]
+// CHECK:STDOUT:   %Op.2d4: %Op.type.548 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.19c: type = ptr_type %D [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %D, (%Destroy.impl_witness.45e) [concrete]
+// CHECK:STDOUT:   %.64e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.2d4, @Op.2(%D) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -162,7 +178,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
 // CHECK:STDOUT:     %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:     complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT:   !members:
@@ -172,7 +188,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @D {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -209,6 +225,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%D) [concrete = constants.%F.specific_fn.c4a]
 // CHECK:STDOUT:   %.loc9_15: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %D = call %F.specific_fn(%p.ref) to %.loc9_15
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc9_15.1: <bound method> = bound_method %.loc9_15, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_15.2: <bound method> = bound_method %.loc9_15, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc9_15
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_15.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -243,8 +265,8 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.loc7_25 => constants.%pattern_type.510
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc7_25 => constants.%complete_type
-// CHECK:STDOUT:   %require_complete.loc7_17 => constants.%complete_type
+// CHECK:STDOUT:   %require_complete.loc7_25 => constants.%complete_type.357
+// CHECK:STDOUT:   %require_complete.loc7_17 => constants.%complete_type.357
 // CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.c4a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -254,17 +276,29 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %I.type: type = generic_class_type @I [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %I.generic: %I.type = struct_value () [concrete]
 // CHECK:STDOUT:   %I.ff1: type = class_type @I, @I(%T) [symbolic]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %pattern_type.576: type = pattern_type %I.ff1 [symbolic]
 // CHECK:STDOUT:   %pattern_type.c48: type = pattern_type %C [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.ff1 [symbolic]
+// CHECK:STDOUT:   %require_complete.1c8: <witness> = require_complete_type %I.ff1 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.ef1: <specific function> = specific_function %F, @F(%T) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // CHECK:STDOUT:   %I.ed8: type = class_type @I, @I(%C) [concrete]
 // CHECK:STDOUT:   %pattern_type.917: type = pattern_type %I.ed8 [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
@@ -274,9 +308,13 @@ fn G() -> i32 {
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -339,7 +377,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:   class {
 // CHECK:STDOUT:     %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:     complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT:   !members:
@@ -349,7 +387,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -362,7 +400,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %I.loc7_22.2 [symbolic = %pattern_type (constants.%pattern_type.576)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.loc7_22.2 [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.loc7_22.2 [symbolic = %require_complete (constants.%require_complete.1c8)]
 // CHECK:STDOUT:   %F.specific_fn.loc7_39.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.2) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.ef1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%p.param: @F.%I.loc7_22.2 (%I.ff1)) -> %return.param: %C {
@@ -372,6 +410,12 @@ fn G() -> i32 {
 // 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:     %.loc7_25: ref %C = splice_block %return {}
 // CHECK:STDOUT:     %F.call: init %C = call %F.specific_fn.loc7_39.1(%p.ref) to %.loc7_25
+// CHECK:STDOUT:     %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:     %bound_method.loc7_25.1: <bound method> = bound_method %.loc7_25, %impl.elem0
+// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:     %bound_method.loc7_25.2: <bound method> = bound_method %.loc7_25, %specific_fn
+// CHECK:STDOUT:     %addr: %ptr.019 = addr_of %.loc7_25
+// CHECK:STDOUT:     %no_op: init %empty_tuple.type = call %bound_method.loc7_25.2(%addr)
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -383,6 +427,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.04a]
 // CHECK:STDOUT:   %.loc9_15: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %C = call %F.specific_fn(%p.ref) to %.loc9_15
+// CHECK:STDOUT:   %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc9_15.1: <bound method> = bound_method %.loc9_15, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_15.2: <bound method> = bound_method %.loc9_15, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.019 = addr_of %.loc9_15
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_15.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -398,7 +448,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.576
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.1c8
 // CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.ef1
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -414,7 +464,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.917
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
 // CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.04a
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -424,6 +474,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Outer.9d6: type = class_type @Outer, @Outer(%T) [symbolic]
 // CHECK:STDOUT:   %U: type = bind_symbolic_name U, 1 [symbolic]
@@ -441,9 +492,20 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.65c: type = pattern_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.937: type = ptr_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %require_complete.fe1: <witness> = require_complete_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %require_complete.e7e: <witness> = require_complete_type %Inner.c71 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.dd9: <specific function> = specific_function %F, @F(%T, %U) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %require_complete.8fa: <witness> = require_complete_type %ptr.937 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type.30b, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.1c6: %Destroy.type = facet_value %tuple.type.30b, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.1e9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.1c6 [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.1e9 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet.1c6) [symbolic]
 // CHECK:STDOUT:   %Outer.7c4: type = class_type @Outer, @Outer(%C) [concrete]
 // CHECK:STDOUT:   %Inner.type.181: type = generic_class_type @Inner, @Outer(%C) [concrete]
 // CHECK:STDOUT:   %Inner.generic.205: %Inner.type.181 = struct_value () [concrete]
@@ -454,14 +516,26 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.4a7: <specific function> = specific_function %F, @F(%C, %D) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.2a9: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%tuple.type.e8a) [concrete]
+// CHECK:STDOUT:   %Op.type.290: type = fn_type @Op.2, @impl(%tuple.type.e8a) [concrete]
+// CHECK:STDOUT:   %Op.ce2: %Op.type.290 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.d45: type = ptr_type %tuple.type.e8a [concrete]
+// CHECK:STDOUT:   %complete_type.149: <witness> = complete_type_witness %ptr.d45 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5de: %Destroy.type = facet_value %tuple.type.e8a, (%Destroy.impl_witness.2a9) [concrete]
+// CHECK:STDOUT:   %.77c: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.5de [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ce2, @Op.2(%tuple.type.e8a) [concrete]
 // CHECK:STDOUT:   %complete_type.53b: <witness> = complete_type_witness %tuple.type.e8a [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -604,17 +678,30 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.loc13_48: type = pattern_type %tuple.type [symbolic = %pattern_type.loc13_48 (constants.%pattern_type.65c)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc13_48: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc13_48 (constants.%require_complete.fe1)]
+// CHECK:STDOUT:   %require_complete.loc13_48.1: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc13_48.1 (constants.%require_complete.fe1)]
 // CHECK:STDOUT:   %require_complete.loc13_27: <witness> = require_complete_type %Inner.loc13_45.2 [symbolic = %require_complete.loc13_27 (constants.%require_complete.e7e)]
 // CHECK:STDOUT:   %F.specific_fn.loc13_67.2: <specific function> = specific_function constants.%F, @F(%T.loc13_6.2, %U.loc13_16.2) [symbolic = %F.specific_fn.loc13_67.2 (constants.%F.specific_fn.dd9)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1c6)]
+// CHECK:STDOUT:   %.loc13_48.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc13_48.3 (constants.%.1e9)]
+// CHECK:STDOUT:   %impl.elem0.loc13_48.2: @F.%.loc13_48.3 (%.1e9) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_48.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.loc13_48.2: <specific function> = specific_impl_function %impl.elem0.loc13_48.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc13_48.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %tuple.type [symbolic = %ptr (constants.%ptr.937)]
+// CHECK:STDOUT:   %require_complete.loc13_48.2: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc13_48.2 (constants.%require_complete.8fa)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%p.param: @F.%Inner.loc13_45.2 (%Inner.c71)) -> %return.param: @F.%tuple.type (%tuple.type.30b) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:     %p.ref: @F.%Inner.loc13_45.2 (%Inner.c71) = name_ref p, %p
 // CHECK:STDOUT:     %F.specific_fn.loc13_67.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [symbolic = %F.specific_fn.loc13_67.2 (constants.%F.specific_fn.dd9)]
-// CHECK:STDOUT:     %.loc13_48: ref @F.%tuple.type (%tuple.type.30b) = splice_block %return {}
-// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.30b) = call %F.specific_fn.loc13_67.1(%p.ref) to %.loc13_48
+// CHECK:STDOUT:     %.loc13_48.1: ref @F.%tuple.type (%tuple.type.30b) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.30b) = call %F.specific_fn.loc13_67.1(%p.ref) to %.loc13_48.1
+// CHECK:STDOUT:     %impl.elem0.loc13_48.1: @F.%.loc13_48.3 (%.1e9) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc13_48.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.loc13_48.1: <bound method> = bound_method %.loc13_48.1, %impl.elem0.loc13_48.1
+// CHECK:STDOUT:     %specific_impl_fn.loc13_48.1: <specific function> = specific_impl_function %impl.elem0.loc13_48.1, @Op.1(constants.%Destroy.facet.1c6) [symbolic = %specific_impl_fn.loc13_48.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc13_48.2: <bound method> = bound_method %.loc13_48.1, %specific_impl_fn.loc13_48.1
+// CHECK:STDOUT:     %addr: @F.%ptr (%ptr.937) = addr_of %.loc13_48.1
+// CHECK:STDOUT:     %.loc13_48.2: init %empty_tuple.type = call %bound_method.loc13_48.2(%addr)
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -626,6 +713,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C, constants.%D) [concrete = constants.%F.specific_fn.4a7]
 // CHECK:STDOUT:   %.loc15_28: ref %tuple.type.e8a = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %tuple.type.e8a = call %F.specific_fn(%p.ref) to %.loc15_28
+// CHECK:STDOUT:   %impl.elem0: %.77c = impl_witness_access constants.%Destroy.impl_witness.2a9, element0 [concrete = constants.%Op.ce2]
+// CHECK:STDOUT:   %bound_method.loc15_28.1: <bound method> = bound_method %.loc15_28, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%tuple.type.e8a) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_28.2: <bound method> = bound_method %.loc15_28, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.d45 = addr_of %.loc15_28
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc15_28.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -656,9 +749,16 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.loc13_48 => constants.%pattern_type.65c
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc13_48 => constants.%require_complete.fe1
+// CHECK:STDOUT:   %require_complete.loc13_48.1 => constants.%require_complete.fe1
 // CHECK:STDOUT:   %require_complete.loc13_27 => constants.%require_complete.e7e
 // CHECK:STDOUT:   %F.specific_fn.loc13_67.2 => constants.%F.specific_fn.dd9
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.1c6
+// CHECK:STDOUT:   %.loc13_48.3 => constants.%.1e9
+// CHECK:STDOUT:   %impl.elem0.loc13_48.2 => constants.%impl.elem0
+// CHECK:STDOUT:   %specific_impl_fn.loc13_48.2 => constants.%specific_impl_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.937
+// CHECK:STDOUT:   %require_complete.loc13_48.2 => constants.%require_complete.8fa
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @Outer(constants.%C) {
@@ -688,9 +788,16 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %pattern_type.loc13_48 => constants.%pattern_type.9ec
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc13_48 => constants.%complete_type.53b
+// CHECK:STDOUT:   %require_complete.loc13_48.1 => constants.%complete_type.53b
 // CHECK:STDOUT:   %require_complete.loc13_27 => constants.%complete_type.357
 // CHECK:STDOUT:   %F.specific_fn.loc13_67.2 => constants.%F.specific_fn.4a7
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.impl_witness.2a9
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.5de
+// CHECK:STDOUT:   %.loc13_48.3 => constants.%.77c
+// CHECK:STDOUT:   %impl.elem0.loc13_48.2 => constants.%Op.ce2
+// CHECK:STDOUT:   %specific_impl_fn.loc13_48.2 => constants.%Op.specific_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.d45
+// CHECK:STDOUT:   %require_complete.loc13_48.2 => constants.%complete_type.149
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- nontype.carbon
@@ -698,6 +805,7 @@ fn G() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %N.51e: %i32 = bind_symbolic_name N, 0 [symbolic]
@@ -734,12 +842,25 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %WithNontype.val: %WithNontype.b82 = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.b66: type = pattern_type %WithNontype.b82 [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_0.6a9) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.a00: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%WithNontype.b82) [concrete]
+// CHECK:STDOUT:   %Op.type.68d: type = fn_type @Op.3, @impl.49c(%WithNontype.b82) [concrete]
+// CHECK:STDOUT:   %Op.6ee: %Op.type.68d = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.791: type = ptr_type %WithNontype.b82 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %WithNontype.b82, (%Destroy.impl_witness.a00) [concrete]
+// CHECK:STDOUT:   %.3b2: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.6ee, @Op.3(%WithNontype.b82) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -747,6 +868,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -837,10 +961,10 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc9_13.1: %empty_struct_type = struct_literal ()
 // CHECK:STDOUT:   %WithNontype.ref: %WithNontype.type = name_ref WithNontype, file.%WithNontype.decl [concrete = constants.%WithNontype.generic]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc9_31.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc9_31.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc9_31: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc9_31.1: <bound method> = bound_method %int_0, %impl.elem0.loc9_31 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc9_31: <specific function> = specific_function %impl.elem0.loc9_31, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_31.2: <bound method> = bound_method %int_0, %specific_fn.loc9_31 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc9_31.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc9_31.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc9_31.2: %i32 = converted %int_0, %.loc9_31.1 [concrete = constants.%int_0.6a9]
@@ -854,6 +978,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%.loc9_15.2)
 // CHECK:STDOUT:   %.loc9_33.1: %i32 = value_of_initializer %F.call
 // CHECK:STDOUT:   %.loc9_33.2: %i32 = converted %F.call, %.loc9_33.1
+// CHECK:STDOUT:   %impl.elem0.loc9_13: %.3b2 = impl_witness_access constants.%Destroy.impl_witness.a00, element0 [concrete = constants.%Op.6ee]
+// CHECK:STDOUT:   %bound_method.loc9_13.1: <bound method> = bound_method %.loc9_13.2, %impl.elem0.loc9_13
+// CHECK:STDOUT:   %specific_fn.loc9_13: <specific function> = specific_function %impl.elem0.loc9_13, @Op.3(constants.%WithNontype.b82) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_13.2: <bound method> = bound_method %.loc9_13.2, %specific_fn.loc9_13
+// CHECK:STDOUT:   %addr: %ptr.791 = addr_of %.loc9_13.2
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_13.2(%addr)
 // CHECK:STDOUT:   return %.loc9_33.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 22 - 0
toolchain/check/testdata/deduce/tuple.carbon

@@ -72,6 +72,7 @@ fn G(pair: (C, D)) -> D {
 // CHECK:STDOUT:   %pattern_type.65c: type = pattern_type %tuple.type.30b [symbolic]
 // CHECK:STDOUT:   %pattern_type.a32: type = pattern_type %U [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.b54: <witness> = require_complete_type %U [symbolic]
 // CHECK:STDOUT:   %require_complete.fe1: <witness> = require_complete_type %tuple.type.30b [symbolic]
@@ -82,14 +83,29 @@ fn G(pair: (C, D)) -> D {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.4a7: <specific function> = specific_function %F, @F(%C, %D) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.45e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%D) [concrete]
+// CHECK:STDOUT:   %Op.type.548: type = fn_type @Op.2, @impl(%D) [concrete]
+// CHECK:STDOUT:   %Op.2d4: %Op.type.548 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.19c: type = ptr_type %D [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %D, (%Destroy.impl_witness.45e) [concrete]
+// CHECK:STDOUT:   %.64e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.2d4, @Op.2(%D) [concrete]
 // CHECK:STDOUT:   %complete_type.53b: <witness> = complete_type_witness %tuple.type.e8a [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -194,6 +210,12 @@ fn G(pair: (C, D)) -> D {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C, constants.%D) [concrete = constants.%F.specific_fn.4a7]
 // CHECK:STDOUT:   %.loc9_20: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %D = call %F.specific_fn(%pair.ref) to %.loc9_20
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc9_20.1: <bound method> = bound_method %.loc9_20, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_20.2: <bound method> = bound_method %.loc9_20, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc9_20
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_20.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 64 - 0
toolchain/check/testdata/deduce/type_operator.carbon

@@ -79,6 +79,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %pattern_type.afe: type = pattern_type %ptr.79f [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %require_complete.6e5: <witness> = require_complete_type %ptr.79f [symbolic]
@@ -89,14 +90,28 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.04a: <specific function> = specific_function %F, @F(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
 // CHECK:STDOUT:   %complete_type.d05: <witness> = complete_type_witness %ptr.019 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -183,6 +198,12 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.04a]
 // CHECK:STDOUT:   %.loc8_13: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %C = call %F.specific_fn(%p.ref) to %.loc8_13
+// CHECK:STDOUT:   %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc8_13.1: <bound method> = bound_method %.loc8_13, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_13.2: <bound method> = bound_method %.loc8_13, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.019 = addr_of %.loc8_13
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc8_13.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -223,6 +244,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %pattern_type.fa5: type = pattern_type %ptr.6d4 [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %require_complete.20b: <witness> = require_complete_type %ptr.6d4 [symbolic]
@@ -234,14 +256,29 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.04a: <specific function> = specific_function %F, @F(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // CHECK:STDOUT:   %complete_type.247: <witness> = complete_type_witness %ptr.801 [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -331,6 +368,12 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.04a]
 // CHECK:STDOUT:   %.loc8_19: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %C = call %F.specific_fn(%p.ref) to %.loc8_19
+// CHECK:STDOUT:   %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc8_19.1: <bound method> = bound_method %.loc8_19, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_19.2: <bound method> = bound_method %.loc8_19, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.019 = addr_of %.loc8_19
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc8_19.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -372,6 +415,7 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %pattern_type.afe: type = pattern_type %ptr.79f [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %require_complete.6e5: <witness> = require_complete_type %ptr.79f [symbolic]
@@ -383,14 +427,28 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.specific_fn.486: <specific function> = specific_function %F, @F(%const) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.be1: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%const) [concrete]
+// CHECK:STDOUT:   %Op.type.dff: type = fn_type @Op.2, @impl(%const) [concrete]
+// CHECK:STDOUT:   %Op.206: %Op.type.dff = struct_value () [concrete]
 // CHECK:STDOUT:   %complete_type.247: <witness> = complete_type_witness %ptr.801 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %const, (%Destroy.impl_witness.be1) [concrete]
+// CHECK:STDOUT:   %.174: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.206, @Op.2(%const) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -479,6 +537,12 @@ fn G(p: C*) -> const C {
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%const) [concrete = constants.%F.specific_fn.486]
 // CHECK:STDOUT:   %.loc8_19: ref %const = splice_block %return {}
 // CHECK:STDOUT:   %F.call: init %const = call %F.specific_fn(%p.ref) to %.loc8_19
+// CHECK:STDOUT:   %impl.elem0: %.174 = impl_witness_access constants.%Destroy.impl_witness.be1, element0 [concrete = constants.%Op.206]
+// CHECK:STDOUT:   %bound_method.loc8_19.1: <bound method> = bound_method %.loc8_19, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%const) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_19.2: <bound method> = bound_method %.loc8_19, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.801 = addr_of %.loc8_19
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc8_19.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 121 - 22
toolchain/check/testdata/for/actual.carbon

@@ -141,6 +141,22 @@ fn Read() {
 // CHECK:STDOUT:   %impl.elem0.437: %.a0d = impl_witness_access %Inc.lookup_impl_witness, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.a5f: <specific function> = specific_impl_function %impl.elem0.437, @Op.95(%Inc.facet) [symbolic]
 // CHECK:STDOUT:   %Some.specific_fn: <specific function> = specific_function %Some.58a, @Some(%Int.49d0e6.1) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.96 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.97, @impl.49c(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ptr.2aa: type = ptr_type %Optional.708 [symbolic]
+// CHECK:STDOUT:   %require_complete.a5e: <witness> = require_complete_type %ptr.2aa [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.f9d: <witness> = lookup_impl_witness %Optional.708, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.be9: %Destroy.type = facet_value %Optional.708, (%Destroy.lookup_impl_witness.f9d) [symbolic]
+// CHECK:STDOUT:   %.1ee: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.be9 [symbolic]
+// CHECK:STDOUT:   %impl.elem0.5fd: %.1ee = impl_witness_access %Destroy.lookup_impl_witness.f9d, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.79e: <specific function> = specific_impl_function %impl.elem0.5fd, @Op.96(%Destroy.facet.be9) [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.34a: <witness> = lookup_impl_witness %Int.49d0e6.1, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.13d: %Destroy.type = facet_value %Int.49d0e6.1, (%Destroy.lookup_impl_witness.34a) [symbolic]
+// CHECK:STDOUT:   %.bbc: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.13d [symbolic]
+// CHECK:STDOUT:   %impl.elem0.fe8: %.bbc = impl_witness_access %Destroy.lookup_impl_witness.34a, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.f4e: <specific function> = specific_impl_function %impl.elem0.fe8, @Op.96(%Destroy.facet.13d) [symbolic]
 // CHECK:STDOUT:   %None.specific_fn: <specific function> = specific_function %None.83e, @None(%Int.49d0e6.1) [symbolic]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
@@ -169,6 +185,13 @@ fn Read() {
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%IntRange.365) [concrete]
+// CHECK:STDOUT:   %Op.type.2d1: type = fn_type @Op.97, @impl.49c(%IntRange.365) [concrete]
+// CHECK:STDOUT:   %Op.fa8: %Op.type.2d1 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.049: type = ptr_type %IntRange.365 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.507: %Destroy.type = facet_value %IntRange.365, (%Destroy.impl_witness.eb8) [concrete]
+// CHECK:STDOUT:   %.cb4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.507 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.df8: <specific function> = specific_function %Op.fa8, @Op.97(%IntRange.365) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -179,6 +202,7 @@ fn Read() {
 // CHECK:STDOUT:     .Optional = %Core.Optional
 // CHECK:STDOUT:     .OrderedWith = %Core.OrderedWith
 // CHECK:STDOUT:     .Inc = %Core.Inc
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
@@ -207,6 +231,9 @@ fn Read() {
 // CHECK:STDOUT:   %Core.import_ref.c4c = import_ref Core//prelude/types/int, loc54_61, unloaded
 // CHECK:STDOUT:   %OrderedWith.impl_witness_table.2b2 = impl_witness_table (%Core.import_ref.a5f, %Core.import_ref.a58, %Core.import_ref.a39, %Core.import_ref.c4c), @impl.db3 [concrete]
 // CHECK:STDOUT:   %Core.Inc: type = import_ref Core//prelude/operators/arithmetic, Inc, loaded [concrete = constants.%Inc.type]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/destroy, loc15_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -483,7 +510,7 @@ fn Read() {
 // CHECK:STDOUT:   %pattern_type.loc11_47: type = pattern_type %Optional.loc11_75.1 [symbolic = %pattern_type.loc11_47 (constants.%pattern_type.4b1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc11_47: <witness> = require_complete_type %Optional.loc11_75.1 [symbolic = %require_complete.loc11_47 (constants.%require_complete.b74)]
+// CHECK:STDOUT:   %require_complete.loc11_47.1: <witness> = require_complete_type %Optional.loc11_75.1 [symbolic = %require_complete.loc11_47.1 (constants.%require_complete.b74)]
 // CHECK:STDOUT:   %require_complete.loc11_17: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc11_17 (constants.%require_complete.524)]
 // CHECK:STDOUT:   %require_complete.loc11_31: <witness> = require_complete_type %ptr.loc11_44.1 [symbolic = %require_complete.loc11_31 (constants.%require_complete.0f5)]
 // CHECK:STDOUT:   %require_complete.loc12: <witness> = require_complete_type %Int.loc11_43.1 [symbolic = %require_complete.loc12 (constants.%require_complete.b4f426.1)]
@@ -508,6 +535,18 @@ fn Read() {
 // CHECK:STDOUT:   %Some.type: type = fn_type @Some, @Optional(%Int.loc11_43.1) [symbolic = %Some.type (constants.%Some.type.185)]
 // CHECK:STDOUT:   %Some: @Next.2.%Some.type (%Some.type.185) = struct_value () [symbolic = %Some (constants.%Some.58a)]
 // CHECK:STDOUT:   %Some.specific_fn.loc15_42.2: <specific function> = specific_function %Some, @Some(%Int.loc11_43.1) [symbolic = %Some.specific_fn.loc15_42.2 (constants.%Some.specific_fn)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.loc11: <witness> = lookup_impl_witness %Optional.loc11_75.1, @Destroy [symbolic = %Destroy.lookup_impl_witness.loc11 (constants.%Destroy.lookup_impl_witness.f9d)]
+// CHECK:STDOUT:   %Destroy.facet.loc11: %Destroy.type = facet_value %Optional.loc11_75.1, (%Destroy.lookup_impl_witness.loc11) [symbolic = %Destroy.facet.loc11 (constants.%Destroy.facet.be9)]
+// CHECK:STDOUT:   %.loc11_47.6: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet.loc11 [symbolic = %.loc11_47.6 (constants.%.1ee)]
+// CHECK:STDOUT:   %impl.elem0.loc11_47.4: @Next.2.%.loc11_47.6 (%.1ee) = impl_witness_access %Destroy.lookup_impl_witness.loc11, element0 [symbolic = %impl.elem0.loc11_47.4 (constants.%impl.elem0.5fd)]
+// CHECK:STDOUT:   %specific_impl_fn.loc11_47.4: <specific function> = specific_impl_function %impl.elem0.loc11_47.4, @Op.96(%Destroy.facet.loc11) [symbolic = %specific_impl_fn.loc11_47.4 (constants.%specific_impl_fn.79e)]
+// CHECK:STDOUT:   %ptr.loc11_47: type = ptr_type %Optional.loc11_75.1 [symbolic = %ptr.loc11_47 (constants.%ptr.2aa)]
+// CHECK:STDOUT:   %require_complete.loc11_47.2: <witness> = require_complete_type %ptr.loc11_47 [symbolic = %require_complete.loc11_47.2 (constants.%require_complete.a5e)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.loc12: <witness> = lookup_impl_witness %Int.loc11_43.1, @Destroy [symbolic = %Destroy.lookup_impl_witness.loc12 (constants.%Destroy.lookup_impl_witness.34a)]
+// CHECK:STDOUT:   %Destroy.facet.loc12: %Destroy.type = facet_value %Int.loc11_43.1, (%Destroy.lookup_impl_witness.loc12) [symbolic = %Destroy.facet.loc12 (constants.%Destroy.facet.13d)]
+// CHECK:STDOUT:   %.loc12_7.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet.loc12 [symbolic = %.loc12_7.3 (constants.%.bbc)]
+// CHECK:STDOUT:   %impl.elem0.loc12_7.3: @Next.2.%.loc12_7.3 (%.bbc) = impl_witness_access %Destroy.lookup_impl_witness.loc12, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.fe8)]
+// CHECK:STDOUT:   %specific_impl_fn.loc12_7.3: <specific function> = specific_impl_function %impl.elem0.loc12_7.3, @Op.96(%Destroy.facet.loc12) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.f4e)]
 // CHECK:STDOUT:   %None.type: type = fn_type @None, @Optional(%Int.loc11_43.1) [symbolic = %None.type (constants.%None.type.73a)]
 // CHECK:STDOUT:   %None: @Next.2.%None.type (%None.type.73a) = struct_value () [symbolic = %None (constants.%None.83e)]
 // CHECK:STDOUT:   %None.specific_fn.loc17_42.2: <specific function> = specific_function %None, @None(%Int.loc11_43.1) [symbolic = %None.specific_fn.loc17_42.2 (constants.%None.specific_fn)]
@@ -555,8 +594,8 @@ fn Read() {
 // CHECK:STDOUT:     %bound_method.loc14_9.1: <bound method> = bound_method %.loc14_11, %impl.elem0.loc14_9.1
 // CHECK:STDOUT:     %specific_impl_fn.loc14_9.1: <specific function> = specific_impl_function %impl.elem0.loc14_9.1, @Op.95(constants.%Inc.facet) [symbolic = %specific_impl_fn.loc14_9.2 (constants.%specific_impl_fn.a5f)]
 // CHECK:STDOUT:     %bound_method.loc14_9.2: <bound method> = bound_method %.loc14_11, %specific_impl_fn.loc14_9.1
-// CHECK:STDOUT:     %addr: @Next.2.%ptr.loc11_44.1 (%ptr.784) = addr_of %.loc14_11
-// CHECK:STDOUT:     %.loc14_9.1: init %empty_tuple.type = call %bound_method.loc14_9.2(%addr)
+// CHECK:STDOUT:     %addr.loc14: @Next.2.%ptr.loc11_44.1 (%ptr.784) = addr_of %.loc14_11
+// CHECK:STDOUT:     %.loc14_9.1: init %empty_tuple.type = call %bound_method.loc14_9.2(%addr.loc14)
 // CHECK:STDOUT:     %Core.ref.loc15_16: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
 // CHECK:STDOUT:     %Optional.ref.loc15: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic]
 // CHECK:STDOUT:     %Core.ref.loc15_30: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]
@@ -571,6 +610,18 @@ fn Read() {
 // CHECK:STDOUT:     %.loc11_47.1: ref @Next.2.%Optional.loc11_75.1 (%Optional.708) = splice_block %return {}
 // CHECK:STDOUT:     %.loc15_48: @Next.2.%Int.loc11_43.1 (%Int.49d0e6.1) = bind_value %value.ref.loc15
 // CHECK:STDOUT:     %Some.call: init @Next.2.%Optional.loc11_75.1 (%Optional.708) = call %Some.specific_fn.loc15_42.1(%.loc15_48) to %.loc11_47.1
+// CHECK:STDOUT:     %impl.elem0.loc11_47.1: @Next.2.%.loc11_47.6 (%.1ee) = impl_witness_access constants.%Destroy.lookup_impl_witness.f9d, element0 [symbolic = %impl.elem0.loc11_47.4 (constants.%impl.elem0.5fd)]
+// CHECK:STDOUT:     %bound_method.loc11_47.1: <bound method> = bound_method %.loc11_47.1, %impl.elem0.loc11_47.1
+// CHECK:STDOUT:     %specific_impl_fn.loc11_47.1: <specific function> = specific_impl_function %impl.elem0.loc11_47.1, @Op.96(constants.%Destroy.facet.be9) [symbolic = %specific_impl_fn.loc11_47.4 (constants.%specific_impl_fn.79e)]
+// CHECK:STDOUT:     %bound_method.loc11_47.2: <bound method> = bound_method %.loc11_47.1, %specific_impl_fn.loc11_47.1
+// CHECK:STDOUT:     %addr.loc11_47.1: @Next.2.%ptr.loc11_47 (%ptr.2aa) = addr_of %.loc11_47.1
+// CHECK:STDOUT:     %.loc11_47.2: init %empty_tuple.type = call %bound_method.loc11_47.2(%addr.loc11_47.1)
+// CHECK:STDOUT:     %impl.elem0.loc12_7.1: @Next.2.%.loc12_7.3 (%.bbc) = impl_witness_access constants.%Destroy.lookup_impl_witness.34a, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.fe8)]
+// CHECK:STDOUT:     %bound_method.loc12_7.1: <bound method> = bound_method %value.var, %impl.elem0.loc12_7.1
+// CHECK:STDOUT:     %specific_impl_fn.loc12_7.1: <specific function> = specific_impl_function %impl.elem0.loc12_7.1, @Op.96(constants.%Destroy.facet.13d) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.f4e)]
+// CHECK:STDOUT:     %bound_method.loc12_7.2: <bound method> = bound_method %value.var, %specific_impl_fn.loc12_7.1
+// CHECK:STDOUT:     %addr.loc12_7.1: @Next.2.%ptr.loc11_44.1 (%ptr.784) = addr_of %value.var
+// CHECK:STDOUT:     %.loc12_7.1: init %empty_tuple.type = call %bound_method.loc12_7.2(%addr.loc12_7.1)
 // CHECK:STDOUT:     return %Some.call to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT:   !if.else:
@@ -584,8 +635,26 @@ fn Read() {
 // CHECK:STDOUT:     %.loc17: @Next.2.%None.type (%None.type.73a) = specific_constant imports.%Core.import_ref.2b7, @Optional(constants.%Int.49d0e6.1) [symbolic = %None (constants.%None.83e)]
 // CHECK:STDOUT:     %None.ref: @Next.2.%None.type (%None.type.73a) = name_ref None, %.loc17 [symbolic = %None (constants.%None.83e)]
 // CHECK:STDOUT:     %None.specific_fn.loc17_42.1: <specific function> = specific_function %None.ref, @None(constants.%Int.49d0e6.1) [symbolic = %None.specific_fn.loc17_42.2 (constants.%None.specific_fn)]
-// CHECK:STDOUT:     %.loc11_47.2: ref @Next.2.%Optional.loc11_75.1 (%Optional.708) = splice_block %return {}
-// CHECK:STDOUT:     %None.call: init @Next.2.%Optional.loc11_75.1 (%Optional.708) = call %None.specific_fn.loc17_42.1() to %.loc11_47.2
+// CHECK:STDOUT:     %.loc11_47.3: ref @Next.2.%Optional.loc11_75.1 (%Optional.708) = splice_block %return {}
+// CHECK:STDOUT:     %None.call: init @Next.2.%Optional.loc11_75.1 (%Optional.708) = call %None.specific_fn.loc17_42.1() to %.loc11_47.3
+// CHECK:STDOUT:     %impl.elem0.loc11_47.2: @Next.2.%.loc11_47.6 (%.1ee) = impl_witness_access constants.%Destroy.lookup_impl_witness.f9d, element0 [symbolic = %impl.elem0.loc11_47.4 (constants.%impl.elem0.5fd)]
+// CHECK:STDOUT:     %bound_method.loc11_47.3: <bound method> = bound_method %.loc11_47.3, %impl.elem0.loc11_47.2
+// CHECK:STDOUT:     %specific_impl_fn.loc11_47.2: <specific function> = specific_impl_function %impl.elem0.loc11_47.2, @Op.96(constants.%Destroy.facet.be9) [symbolic = %specific_impl_fn.loc11_47.4 (constants.%specific_impl_fn.79e)]
+// CHECK:STDOUT:     %bound_method.loc11_47.4: <bound method> = bound_method %.loc11_47.3, %specific_impl_fn.loc11_47.2
+// CHECK:STDOUT:     %addr.loc11_47.2: @Next.2.%ptr.loc11_47 (%ptr.2aa) = addr_of %.loc11_47.3
+// CHECK:STDOUT:     %.loc11_47.4: init %empty_tuple.type = call %bound_method.loc11_47.4(%addr.loc11_47.2)
+// CHECK:STDOUT:     %impl.elem0.loc11_47.3: @Next.2.%.loc11_47.6 (%.1ee) = impl_witness_access constants.%Destroy.lookup_impl_witness.f9d, element0 [symbolic = %impl.elem0.loc11_47.4 (constants.%impl.elem0.5fd)]
+// CHECK:STDOUT:     %bound_method.loc11_47.5: <bound method> = bound_method %.loc11_47.1, %impl.elem0.loc11_47.3
+// CHECK:STDOUT:     %specific_impl_fn.loc11_47.3: <specific function> = specific_impl_function %impl.elem0.loc11_47.3, @Op.96(constants.%Destroy.facet.be9) [symbolic = %specific_impl_fn.loc11_47.4 (constants.%specific_impl_fn.79e)]
+// CHECK:STDOUT:     %bound_method.loc11_47.6: <bound method> = bound_method %.loc11_47.1, %specific_impl_fn.loc11_47.3
+// CHECK:STDOUT:     %addr.loc11_47.3: @Next.2.%ptr.loc11_47 (%ptr.2aa) = addr_of %.loc11_47.1
+// CHECK:STDOUT:     %.loc11_47.5: init %empty_tuple.type = call %bound_method.loc11_47.6(%addr.loc11_47.3)
+// CHECK:STDOUT:     %impl.elem0.loc12_7.2: @Next.2.%.loc12_7.3 (%.bbc) = impl_witness_access constants.%Destroy.lookup_impl_witness.34a, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.fe8)]
+// CHECK:STDOUT:     %bound_method.loc12_7.3: <bound method> = bound_method %value.var, %impl.elem0.loc12_7.2
+// CHECK:STDOUT:     %specific_impl_fn.loc12_7.2: <specific function> = specific_impl_function %impl.elem0.loc12_7.2, @Op.96(constants.%Destroy.facet.13d) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.f4e)]
+// CHECK:STDOUT:     %bound_method.loc12_7.4: <bound method> = bound_method %value.var, %specific_impl_fn.loc12_7.2
+// CHECK:STDOUT:     %addr.loc12_7.2: @Next.2.%ptr.loc11_44.1 (%ptr.784) = addr_of %value.var
+// CHECK:STDOUT:     %.loc12_7.2: init %empty_tuple.type = call %bound_method.loc12_7.4(%addr.loc12_7.2)
 // CHECK:STDOUT:     return %None.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -601,14 +670,20 @@ fn Read() {
 // CHECK:STDOUT:   %end.ref: %i32 = name_ref end, %end
 // CHECK:STDOUT:   %Make.specific_fn: <specific function> = specific_function %Make.ref, @Make(constants.%int_32) [concrete = constants.%Make.specific_fn]
 // CHECK:STDOUT:   %.loc26_20: ref %IntRange.365 = splice_block %return {}
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc27_28.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc27_28.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc27: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc27_28.1: <bound method> = bound_method %int_0, %impl.elem0.loc27 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc27: <specific function> = specific_function %impl.elem0.loc27, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc27_28.2: <bound method> = bound_method %int_0, %specific_fn.loc27 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc27_28.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc27_28.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc27_28.2: %i32 = converted %int_0, %.loc27_28.1 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %Make.call: init %IntRange.365 = call %Make.specific_fn(%.loc27_28.2, %end.ref) to %.loc26_20
+// CHECK:STDOUT:   %impl.elem0.loc26: %.cb4 = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.fa8]
+// CHECK:STDOUT:   %bound_method.loc26_20.1: <bound method> = bound_method %.loc26_20, %impl.elem0.loc26
+// CHECK:STDOUT:   %specific_fn.loc26: <specific function> = specific_function %impl.elem0.loc26, @Op.97(constants.%IntRange.365) [concrete = constants.%Op.specific_fn.df8]
+// CHECK:STDOUT:   %bound_method.loc26_20.2: <bound method> = bound_method %.loc26_20, %specific_fn.loc26
+// CHECK:STDOUT:   %addr: %ptr.049 = addr_of %.loc26_20
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc26_20.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -799,17 +874,29 @@ fn Read() {
 // CHECK:STDOUT:   %Some.type.fe1: type = fn_type @Some, @Optional(%Int.7ff11f.1) [symbolic]
 // CHECK:STDOUT:   %Some.aae: %Some.type.fe1 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Some.specific_fn: <specific function> = specific_function %Some.aae, @Some(%Int.7ff11f.1) [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.f0d: <witness> = lookup_impl_witness %Optional.e9f, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.82c: %Destroy.type = facet_value %Optional.e9f, (%Destroy.lookup_impl_witness.f0d) [symbolic]
+// CHECK:STDOUT:   %.485: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.82c [symbolic]
+// CHECK:STDOUT:   %impl.elem0.c7c: %.485 = impl_witness_access %Destroy.lookup_impl_witness.f0d, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.ebe: <specific function> = specific_impl_function %impl.elem0.c7c, @Op.95(%Destroy.facet.82c) [symbolic]
+// CHECK:STDOUT:   %ptr.d1d: type = ptr_type %Optional.e9f [symbolic]
+// CHECK:STDOUT:   %require_complete.c68: <witness> = require_complete_type %ptr.d1d [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.f03: <witness> = lookup_impl_witness %Int.7ff11f.1, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.96a: %Destroy.type = facet_value %Int.7ff11f.1, (%Destroy.lookup_impl_witness.f03) [symbolic]
+// CHECK:STDOUT:   %.f67: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.96a [symbolic]
+// CHECK:STDOUT:   %impl.elem0.4dc: %.f67 = impl_witness_access %Destroy.lookup_impl_witness.f03, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.f8f: <specific function> = specific_impl_function %impl.elem0.4dc, @Op.95(%Destroy.facet.96a) [symbolic]
 // CHECK:STDOUT:   %None.type.8c4: type = fn_type @None, @Optional(%Int.7ff11f.1) [symbolic]
 // CHECK:STDOUT:   %None.7a7: %None.type.8c4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %None.specific_fn: <specific function> = specific_function %None.7a7, @None(%Int.7ff11f.1) [symbolic]
 // CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.97, @impl.49c(%T.8b3) [symbolic]
 // CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%IntRange.365) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.6eb: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%IntRange.365) [concrete]
 // CHECK:STDOUT:   %Op.type.2d1: type = fn_type @Op.97, @impl.49c(%IntRange.365) [concrete]
 // CHECK:STDOUT:   %Op.fa8: %Op.type.2d1 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.049: type = ptr_type %IntRange.365 [concrete]
-// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %IntRange.365, (%Destroy.impl_witness.eb8) [concrete]
-// CHECK:STDOUT:   %.cb4: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Destroy.facet.c1a: %Destroy.type = facet_value %IntRange.365, (%Destroy.impl_witness.6eb) [concrete]
+// CHECK:STDOUT:   %.f02: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.c1a [concrete]
 // CHECK:STDOUT:   %Op.specific_fn.df8: <specific function> = specific_function %Op.fa8, @Op.97(%IntRange.365) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -852,8 +939,8 @@ fn Read() {
 // CHECK:STDOUT:   %Main.import_ref.f1e294.4: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N)]
 // CHECK:STDOUT:   %Main.import_ref.f1e294.5: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N)]
 // CHECK:STDOUT:   %Main.import_ref.014 = import_ref Main//lib, inst519 [indirect], unloaded
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/destroy, loc15_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
+// CHECK:STDOUT:   %Main.import_ref.3a7: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Main//lib, inst6835 [indirect], loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.3a7), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -949,13 +1036,13 @@ fn Read() {
 // CHECK:STDOUT:     %IntRange: type = class_type @IntRange, @IntRange(constants.%int_32) [concrete = constants.%IntRange.365]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %x: ref %IntRange.365 = bind_name x, %x.var
-// CHECK:STDOUT:   %impl.elem0.loc6_3.1: %.cb4 = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.fa8]
+// CHECK:STDOUT:   %impl.elem0.loc6_3.1: %.f02 = impl_witness_access constants.%Destroy.impl_witness.6eb, element0 [concrete = constants.%Op.fa8]
 // CHECK:STDOUT:   %bound_method.loc6_3.1: <bound method> = bound_method %.loc6_3, %impl.elem0.loc6_3.1
 // CHECK:STDOUT:   %specific_fn.loc6_3.1: <specific function> = specific_function %impl.elem0.loc6_3.1, @Op.97(constants.%IntRange.365) [concrete = constants.%Op.specific_fn.df8]
 // CHECK:STDOUT:   %bound_method.loc6_3.2: <bound method> = bound_method %.loc6_3, %specific_fn.loc6_3.1
 // CHECK:STDOUT:   %addr.loc6_3.1: %ptr.049 = addr_of %.loc6_3
 // CHECK:STDOUT:   %no_op.loc6_3.1: init %empty_tuple.type = call %bound_method.loc6_3.2(%addr.loc6_3.1)
-// CHECK:STDOUT:   %impl.elem0.loc6_3.2: %.cb4 = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.fa8]
+// CHECK:STDOUT:   %impl.elem0.loc6_3.2: %.f02 = impl_witness_access constants.%Destroy.impl_witness.6eb, element0 [concrete = constants.%Op.fa8]
 // CHECK:STDOUT:   %bound_method.loc6_3.3: <bound method> = bound_method %x.var, %impl.elem0.loc6_3.2
 // CHECK:STDOUT:   %specific_fn.loc6_3.2: <specific function> = specific_function %impl.elem0.loc6_3.2, @Op.97(constants.%IntRange.365) [concrete = constants.%Op.specific_fn.df8]
 // CHECK:STDOUT:   %bound_method.loc6_3.4: <bound method> = bound_method %x.var, %specific_fn.loc6_3.2
@@ -1001,15 +1088,15 @@ fn Read() {
 // CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.349)]
 // CHECK:STDOUT:   %pattern_type.1: type = pattern_type %IntRange [symbolic = %pattern_type.1 (constants.%pattern_type.dcd)]
 // CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic = %Int (constants.%Int.7ff11f.1)]
-// CHECK:STDOUT:   %ptr: type = ptr_type %Int [symbolic = %ptr (constants.%ptr.58a)]
-// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %ptr [symbolic = %pattern_type.2 (constants.%pattern_type.6d0)]
+// CHECK:STDOUT:   %ptr.1: type = ptr_type %Int [symbolic = %ptr.1 (constants.%ptr.58a)]
+// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %ptr.1 [symbolic = %pattern_type.2 (constants.%pattern_type.6d0)]
 // CHECK:STDOUT:   %Optional: type = class_type @Optional, @Optional(%Int) [symbolic = %Optional (constants.%Optional.e9f)]
 // CHECK:STDOUT:   %pattern_type.3: type = pattern_type %Optional [symbolic = %pattern_type.3 (constants.%pattern_type.fd8)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %require_complete.1: <witness> = require_complete_type %Optional [symbolic = %require_complete.1 (constants.%require_complete.5a1)]
 // CHECK:STDOUT:   %require_complete.2: <witness> = require_complete_type %IntRange [symbolic = %require_complete.2 (constants.%require_complete.524)]
-// CHECK:STDOUT:   %require_complete.3: <witness> = require_complete_type %ptr [symbolic = %require_complete.3 (constants.%require_complete.656)]
+// CHECK:STDOUT:   %require_complete.3: <witness> = require_complete_type %ptr.1 [symbolic = %require_complete.3 (constants.%require_complete.656)]
 // CHECK:STDOUT:   %require_complete.4: <witness> = require_complete_type %Int [symbolic = %require_complete.4 (constants.%require_complete.ffde5f.1)]
 // CHECK:STDOUT:   %pattern_type.4: type = pattern_type %Int [symbolic = %pattern_type.4 (constants.%pattern_type.0ede7b.1)]
 // CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int [symbolic = %IntRange.elem (constants.%IntRange.elem.ecb)]
@@ -1027,11 +1114,23 @@ fn Read() {
 // CHECK:STDOUT:   %Inc.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @Inc [symbolic = %Inc.lookup_impl_witness (constants.%Inc.lookup_impl_witness)]
 // CHECK:STDOUT:   %Inc.facet: %Inc.type = facet_value %Int, (%Inc.lookup_impl_witness) [symbolic = %Inc.facet (constants.%Inc.facet)]
 // CHECK:STDOUT:   %.2: type = fn_type_with_self_type constants.%Op.type.e3a, %Inc.facet [symbolic = %.2 (constants.%.15d)]
-// CHECK:STDOUT:   %impl.elem0: @Next.%.2 (%.15d) = impl_witness_access %Inc.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.181)]
-// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.96(%Inc.facet) [symbolic = %specific_impl_fn (constants.%specific_impl_fn.be7)]
+// CHECK:STDOUT:   %impl.elem0.1: @Next.%.2 (%.15d) = impl_witness_access %Inc.lookup_impl_witness, element0 [symbolic = %impl.elem0.1 (constants.%impl.elem0.181)]
+// CHECK:STDOUT:   %specific_impl_fn.1: <specific function> = specific_impl_function %impl.elem0.1, @Op.96(%Inc.facet) [symbolic = %specific_impl_fn.1 (constants.%specific_impl_fn.be7)]
 // CHECK:STDOUT:   %Some.type: type = fn_type @Some, @Optional(%Int) [symbolic = %Some.type (constants.%Some.type.fe1)]
 // CHECK:STDOUT:   %Some: @Next.%Some.type (%Some.type.fe1) = struct_value () [symbolic = %Some (constants.%Some.aae)]
 // CHECK:STDOUT:   %Some.specific_fn: <specific function> = specific_function %Some, @Some(%Int) [symbolic = %Some.specific_fn (constants.%Some.specific_fn)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.1: <witness> = lookup_impl_witness %Optional, @Destroy [symbolic = %Destroy.lookup_impl_witness.1 (constants.%Destroy.lookup_impl_witness.f0d)]
+// CHECK:STDOUT:   %Destroy.facet.1: %Destroy.type = facet_value %Optional, (%Destroy.lookup_impl_witness.1) [symbolic = %Destroy.facet.1 (constants.%Destroy.facet.82c)]
+// CHECK:STDOUT:   %.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet.1 [symbolic = %.3 (constants.%.485)]
+// CHECK:STDOUT:   %impl.elem0.2: @Next.%.3 (%.485) = impl_witness_access %Destroy.lookup_impl_witness.1, element0 [symbolic = %impl.elem0.2 (constants.%impl.elem0.c7c)]
+// CHECK:STDOUT:   %specific_impl_fn.2: <specific function> = specific_impl_function %impl.elem0.2, @Op.95(%Destroy.facet.1) [symbolic = %specific_impl_fn.2 (constants.%specific_impl_fn.ebe)]
+// CHECK:STDOUT:   %ptr.2: type = ptr_type %Optional [symbolic = %ptr.2 (constants.%ptr.d1d)]
+// CHECK:STDOUT:   %require_complete.6: <witness> = require_complete_type %ptr.2 [symbolic = %require_complete.6 (constants.%require_complete.c68)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.2: <witness> = lookup_impl_witness %Int, @Destroy [symbolic = %Destroy.lookup_impl_witness.2 (constants.%Destroy.lookup_impl_witness.f03)]
+// CHECK:STDOUT:   %Destroy.facet.2: %Destroy.type = facet_value %Int, (%Destroy.lookup_impl_witness.2) [symbolic = %Destroy.facet.2 (constants.%Destroy.facet.96a)]
+// CHECK:STDOUT:   %.4: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet.2 [symbolic = %.4 (constants.%.f67)]
+// CHECK:STDOUT:   %impl.elem0.3: @Next.%.4 (%.f67) = impl_witness_access %Destroy.lookup_impl_witness.2, element0 [symbolic = %impl.elem0.3 (constants.%impl.elem0.4dc)]
+// CHECK:STDOUT:   %specific_impl_fn.3: <specific function> = specific_impl_function %impl.elem0.3, @Op.95(%Destroy.facet.2) [symbolic = %specific_impl_fn.3 (constants.%specific_impl_fn.f8f)]
 // CHECK:STDOUT:   %None.type: type = fn_type @None, @Optional(%Int) [symbolic = %None.type (constants.%None.type.8c4)]
 // CHECK:STDOUT:   %None: @Next.%None.type (%None.type.8c4) = struct_value () [symbolic = %None (constants.%None.7a7)]
 // CHECK:STDOUT:   %None.specific_fn: <specific function> = specific_function %None, @None(%Int) [symbolic = %None.specific_fn (constants.%None.specific_fn)]
@@ -1103,7 +1202,7 @@ fn Read() {
 // CHECK:STDOUT:   %IntRange => constants.%IntRange.349
 // CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.dcd
 // CHECK:STDOUT:   %Int => constants.%Int.7ff11f.1
-// CHECK:STDOUT:   %ptr => constants.%ptr.58a
+// CHECK:STDOUT:   %ptr.1 => constants.%ptr.58a
 // CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.6d0
 // CHECK:STDOUT:   %Optional => constants.%Optional.e9f
 // CHECK:STDOUT:   %pattern_type.3 => constants.%pattern_type.fd8

+ 16 - 16
toolchain/check/testdata/for/basic.carbon

@@ -82,26 +82,10 @@ fn Run() {
 // CHECK:STDOUT:   %HasValue.ada: %HasValue.type.b7a = struct_value () [concrete]
 // CHECK:STDOUT:   %Get.type.130: type = fn_type @Get, @Optional(%empty_tuple.type) [concrete]
 // CHECK:STDOUT:   %Get.6e8: %Get.type.130 = struct_value () [concrete]
-// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
-// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]
-// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]
-// CHECK:STDOUT:   %AfterLoop.type: type = fn_type @AfterLoop [concrete]
-// CHECK:STDOUT:   %AfterLoop: %AfterLoop.type = struct_value () [concrete]
-// CHECK:STDOUT:   %TrivialRange.val: %TrivialRange = struct_value () [concrete]
-// CHECK:STDOUT:   %.510: type = fn_type_with_self_type %NewCursor.type.427, %Iterate.facet.d50 [concrete]
-// CHECK:STDOUT:   %.708: type = fn_type_with_self_type %Next.type.941, %Iterate.facet.d50 [concrete]
-// CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.ada, @HasValue(%empty_tuple.type) [concrete]
-// CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.6e8, @Get(%empty_tuple.type) [concrete]
 // CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
 // CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
 // CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
 // CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_tuple.type) [concrete]
-// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl.49c(%empty_tuple.type) [concrete]
-// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.926: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
-// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.926 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.393: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // CHECK:STDOUT:   %Destroy.impl_witness.003: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Optional.f9a) [concrete]
 // CHECK:STDOUT:   %Op.type.7e4: type = fn_type @Op.2, @impl.49c(%Optional.f9a) [concrete]
 // CHECK:STDOUT:   %Op.466: %Op.type.7e4 = struct_value () [concrete]
@@ -109,6 +93,22 @@ fn Run() {
 // CHECK:STDOUT:   %Destroy.facet.a27: %Destroy.type = facet_value %Optional.f9a, (%Destroy.impl_witness.003) [concrete]
 // CHECK:STDOUT:   %.3c9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.a27 [concrete]
 // CHECK:STDOUT:   %Op.specific_fn.733: <specific function> = specific_function %Op.466, @Op.2(%Optional.f9a) [concrete]
+// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.926: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.926 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.393: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]
+// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]
+// CHECK:STDOUT:   %AfterLoop.type: type = fn_type @AfterLoop [concrete]
+// CHECK:STDOUT:   %AfterLoop: %AfterLoop.type = struct_value () [concrete]
+// CHECK:STDOUT:   %TrivialRange.val: %TrivialRange = struct_value () [concrete]
+// CHECK:STDOUT:   %.510: type = fn_type_with_self_type %NewCursor.type.427, %Iterate.facet.d50 [concrete]
+// CHECK:STDOUT:   %.708: type = fn_type_with_self_type %Next.type.941, %Iterate.facet.d50 [concrete]
+// CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.ada, @HasValue(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.6e8, @Get(%empty_tuple.type) [concrete]
 // CHECK:STDOUT:   %Destroy.impl_witness.49d: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%TrivialRange) [concrete]
 // CHECK:STDOUT:   %Op.type.8d6: type = fn_type @Op.2, @impl.49c(%TrivialRange) [concrete]
 // CHECK:STDOUT:   %Op.90d: %Op.type.8d6 = struct_value () [concrete]

+ 154 - 154
toolchain/check/testdata/for/pattern.carbon

@@ -147,6 +147,10 @@ fn Run() {
 // CHECK:STDOUT:   %HasValue.6fd: %HasValue.type.f81 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Get.type.b8f: type = fn_type @Get, @Optional(%T) [symbolic]
 // CHECK:STDOUT:   %Get.9c8: %Get.type.b8f = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.989: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.ed4: type = fn_type @Op.2, @impl.d2b(%T) [symbolic]
+// CHECK:STDOUT:   %Op.486: %Op.type.ed4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Iterate.impl_witness.52a: <witness> = impl_witness imports.%Iterate.impl_witness_table, @impl.86e(%C) [concrete]
 // CHECK:STDOUT:   %NewCursor.type.951: type = fn_type @NewCursor.2, @impl.86e(%C) [concrete]
 // CHECK:STDOUT:   %NewCursor.535: %NewCursor.type.951 = struct_value () [concrete]
@@ -165,37 +169,33 @@ fn Run() {
 // CHECK:STDOUT:   %Get.9c1: %Get.type.115 = struct_value () [concrete]
 // CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.513, @HasValue(%C) [concrete]
 // CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.9c1, @Get(%C) [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C) [concrete]
-// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl.49c(%C) [concrete]
-// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.832: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.f77: type = fn_type @Op.2, @impl.d2b(%C) [concrete]
+// CHECK:STDOUT:   %Op.01c: %Op.type.f77 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
-// CHECK:STDOUT:   %Destroy.facet.494: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
-// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.494 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.6eb: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.b11: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Op.type.867: type = fn_type @Op.2, @impl.49c(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Op.3e8: %Op.type.867 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.25e: %Destroy.type = facet_value %C, (%Destroy.impl_witness.832) [concrete]
+// CHECK:STDOUT:   %.4cb: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.25e [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.abf: <specific function> = specific_function %Op.01c, @Op.2(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.b21: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Op.type.e93: type = fn_type @Op.2, @impl.d2b(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Op.a97: %Op.type.e93 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.8e6: type = ptr_type %Optional.cf0 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.530: %Destroy.type = facet_value %Optional.cf0, (%Destroy.impl_witness.b11) [concrete]
-// CHECK:STDOUT:   %.1f9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.530 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.273: <specific function> = specific_function %Op.3e8, @Op.2(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.e2f: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
-// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.e2f [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.652: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.506: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%EmptyRange.cc8) [concrete]
-// CHECK:STDOUT:   %Op.type.88d: type = fn_type @Op.2, @impl.49c(%EmptyRange.cc8) [concrete]
-// CHECK:STDOUT:   %Op.929: %Op.type.88d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.f84: %Destroy.type = facet_value %Optional.cf0, (%Destroy.impl_witness.b21) [concrete]
+// CHECK:STDOUT:   %.d26: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.f84 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.448: <specific function> = specific_function %Op.a97, @Op.2(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.67e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.8b2: type = fn_type @Op.2, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.ca6: %Op.type.8b2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2a8: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.67e) [concrete]
+// CHECK:STDOUT:   %.902: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.2a8 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.04c: <specific function> = specific_function %Op.ca6, @Op.2(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.805: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Op.type.699: type = fn_type @Op.2, @impl.d2b(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Op.d12: %Op.type.699 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.35d: type = ptr_type %EmptyRange.cc8 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.750: %Destroy.type = facet_value %EmptyRange.cc8, (%Destroy.impl_witness.506) [concrete]
-// CHECK:STDOUT:   %.053: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.750 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.a14: <specific function> = specific_function %Op.929, @Op.2(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5b2: %Destroy.type = facet_value %EmptyRange.cc8, (%Destroy.impl_witness.805) [concrete]
+// CHECK:STDOUT:   %.73c: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.5b2 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.cc4: <specific function> = specific_function %Op.d12, @Op.2(%EmptyRange.cc8) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -208,8 +208,8 @@ fn Run() {
 // CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.6ce, %Main.import_ref.999, %Main.import_ref.57b, %Main.import_ref.170), @impl.86e [concrete]
 // CHECK:STDOUT:   %Main.import_ref.7f9: @Optional.%HasValue.type (%HasValue.type.f81) = import_ref Main//empty_range, inst136 [indirect], loaded [symbolic = @Optional.%HasValue (constants.%HasValue.6fd)]
 // CHECK:STDOUT:   %Main.import_ref.d10: @Optional.%Get.type (%Get.type.b8f) = import_ref Main//empty_range, inst137 [indirect], loaded [symbolic = @Optional.%Get (constants.%Get.9c8)]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
+// CHECK:STDOUT:   %Main.import_ref.fcc: @impl.d2b.%Op.type (%Op.type.ed4) = import_ref Main//empty_range, inst373 [indirect], loaded [symbolic = @impl.d2b.%Op (constants.%Op.486)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.fcc), @impl.d2b [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
@@ -276,27 +276,27 @@ fn Run() {
 // CHECK:STDOUT:   br !for.next
 // CHECK:STDOUT:
 // CHECK:STDOUT: !for.done:
-// CHECK:STDOUT:   %impl.elem0.loc12_36.1: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %impl.elem0.loc12_36.1: %.4cb = impl_witness_access constants.%Destroy.impl_witness.832, element0 [concrete = constants.%Op.01c]
 // CHECK:STDOUT:   %bound_method.loc12_36.7: <bound method> = bound_method %.loc12_36.8, %impl.elem0.loc12_36.1
-// CHECK:STDOUT:   %specific_fn.loc12_36.3: <specific function> = specific_function %impl.elem0.loc12_36.1, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:   %specific_fn.loc12_36.3: <specific function> = specific_function %impl.elem0.loc12_36.1, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.abf]
 // CHECK:STDOUT:   %bound_method.loc12_36.8: <bound method> = bound_method %.loc12_36.8, %specific_fn.loc12_36.3
 // CHECK:STDOUT:   %addr.loc12_36.2: %ptr.019 = addr_of %.loc12_36.8
 // CHECK:STDOUT:   %no_op.loc12_36.1: init %empty_tuple.type = call %bound_method.loc12_36.8(%addr.loc12_36.2)
-// CHECK:STDOUT:   %impl.elem0.loc12_36.2: %.1f9 = impl_witness_access constants.%Destroy.impl_witness.b11, element0 [concrete = constants.%Op.3e8]
+// CHECK:STDOUT:   %impl.elem0.loc12_36.2: %.d26 = impl_witness_access constants.%Destroy.impl_witness.b21, element0 [concrete = constants.%Op.a97]
 // CHECK:STDOUT:   %bound_method.loc12_36.9: <bound method> = bound_method %.loc12_36.1, %impl.elem0.loc12_36.2
-// CHECK:STDOUT:   %specific_fn.loc12_36.4: <specific function> = specific_function %impl.elem0.loc12_36.2, @Op.2(constants.%Optional.cf0) [concrete = constants.%Op.specific_fn.273]
+// CHECK:STDOUT:   %specific_fn.loc12_36.4: <specific function> = specific_function %impl.elem0.loc12_36.2, @Op.2(constants.%Optional.cf0) [concrete = constants.%Op.specific_fn.448]
 // CHECK:STDOUT:   %bound_method.loc12_36.10: <bound method> = bound_method %.loc12_36.1, %specific_fn.loc12_36.4
 // CHECK:STDOUT:   %addr.loc12_36.3: %ptr.8e6 = addr_of %.loc12_36.1
 // CHECK:STDOUT:   %no_op.loc12_36.2: init %empty_tuple.type = call %bound_method.loc12_36.10(%addr.loc12_36.3)
-// CHECK:STDOUT:   %impl.elem0.loc12_36.3: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %impl.elem0.loc12_36.3: %.902 = impl_witness_access constants.%Destroy.impl_witness.67e, element0 [concrete = constants.%Op.ca6]
 // CHECK:STDOUT:   %bound_method.loc12_36.11: <bound method> = bound_method %var, %impl.elem0.loc12_36.3
-// CHECK:STDOUT:   %specific_fn.loc12_36.5: <specific function> = specific_function %impl.elem0.loc12_36.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.652]
+// CHECK:STDOUT:   %specific_fn.loc12_36.5: <specific function> = specific_function %impl.elem0.loc12_36.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.04c]
 // CHECK:STDOUT:   %bound_method.loc12_36.12: <bound method> = bound_method %var, %specific_fn.loc12_36.5
 // CHECK:STDOUT:   %addr.loc12_36.4: %ptr.c28 = addr_of %var
 // CHECK:STDOUT:   %no_op.loc12_36.3: init %empty_tuple.type = call %bound_method.loc12_36.12(%addr.loc12_36.4)
-// CHECK:STDOUT:   %impl.elem0.loc12_35: %.053 = impl_witness_access constants.%Destroy.impl_witness.506, element0 [concrete = constants.%Op.929]
+// CHECK:STDOUT:   %impl.elem0.loc12_35: %.73c = impl_witness_access constants.%Destroy.impl_witness.805, element0 [concrete = constants.%Op.d12]
 // CHECK:STDOUT:   %bound_method.loc12_35.1: <bound method> = bound_method %.loc12_35.1, %impl.elem0.loc12_35
-// CHECK:STDOUT:   %specific_fn.loc12_35: <specific function> = specific_function %impl.elem0.loc12_35, @Op.2(constants.%EmptyRange.cc8) [concrete = constants.%Op.specific_fn.a14]
+// CHECK:STDOUT:   %specific_fn.loc12_35: <specific function> = specific_function %impl.elem0.loc12_35, @Op.2(constants.%EmptyRange.cc8) [concrete = constants.%Op.specific_fn.cc4]
 // CHECK:STDOUT:   %bound_method.loc12_35.2: <bound method> = bound_method %.loc12_35.1, %specific_fn.loc12_35
 // CHECK:STDOUT:   %addr.loc12_35: %ptr.35d = addr_of %.loc12_35.1
 // CHECK:STDOUT:   %no_op.loc12_35: init %empty_tuple.type = call %bound_method.loc12_35.2(%addr.loc12_35)
@@ -333,6 +333,10 @@ fn Run() {
 // CHECK:STDOUT:   %HasValue.6fd: %HasValue.type.f81 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Get.type.b8f: type = fn_type @Get, @Optional(%T) [symbolic]
 // CHECK:STDOUT:   %Get.9c8: %Get.type.b8f = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.989: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.ed4: type = fn_type @Op.2, @impl.d2b(%T) [symbolic]
+// CHECK:STDOUT:   %Op.486: %Op.type.ed4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Iterate.impl_witness.52a: <witness> = impl_witness imports.%Iterate.impl_witness_table, @impl.86e(%C) [concrete]
 // CHECK:STDOUT:   %NewCursor.type.951: type = fn_type @NewCursor.2, @impl.86e(%C) [concrete]
 // CHECK:STDOUT:   %NewCursor.535: %NewCursor.type.951 = struct_value () [concrete]
@@ -351,36 +355,32 @@ fn Run() {
 // CHECK:STDOUT:   %Get.9c1: %Get.type.115 = struct_value () [concrete]
 // CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.513, @HasValue(%C) [concrete]
 // CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.9c1, @Get(%C) [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C) [concrete]
-// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl.49c(%C) [concrete]
-// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.494: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
-// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.494 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.6eb: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.b11: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Op.type.867: type = fn_type @Op.2, @impl.49c(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Op.3e8: %Op.type.867 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.832: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.f77: type = fn_type @Op.2, @impl.d2b(%C) [concrete]
+// CHECK:STDOUT:   %Op.01c: %Op.type.f77 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.25e: %Destroy.type = facet_value %C, (%Destroy.impl_witness.832) [concrete]
+// CHECK:STDOUT:   %.4cb: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.25e [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.abf: <specific function> = specific_function %Op.01c, @Op.2(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.b21: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Op.type.e93: type = fn_type @Op.2, @impl.d2b(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Op.a97: %Op.type.e93 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.8e6: type = ptr_type %Optional.cf0 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.530: %Destroy.type = facet_value %Optional.cf0, (%Destroy.impl_witness.b11) [concrete]
-// CHECK:STDOUT:   %.1f9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.530 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.273: <specific function> = specific_function %Op.3e8, @Op.2(%Optional.cf0) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.e2f: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
-// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.e2f [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.652: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.506: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%EmptyRange.cc8) [concrete]
-// CHECK:STDOUT:   %Op.type.88d: type = fn_type @Op.2, @impl.49c(%EmptyRange.cc8) [concrete]
-// CHECK:STDOUT:   %Op.929: %Op.type.88d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.f84: %Destroy.type = facet_value %Optional.cf0, (%Destroy.impl_witness.b21) [concrete]
+// CHECK:STDOUT:   %.d26: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.f84 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.448: <specific function> = specific_function %Op.a97, @Op.2(%Optional.cf0) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.67e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.8b2: type = fn_type @Op.2, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.ca6: %Op.type.8b2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2a8: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.67e) [concrete]
+// CHECK:STDOUT:   %.902: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.2a8 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.04c: <specific function> = specific_function %Op.ca6, @Op.2(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.805: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Op.type.699: type = fn_type @Op.2, @impl.d2b(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Op.d12: %Op.type.699 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.35d: type = ptr_type %EmptyRange.cc8 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.750: %Destroy.type = facet_value %EmptyRange.cc8, (%Destroy.impl_witness.506) [concrete]
-// CHECK:STDOUT:   %.053: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.750 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.a14: <specific function> = specific_function %Op.929, @Op.2(%EmptyRange.cc8) [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5b2: %Destroy.type = facet_value %EmptyRange.cc8, (%Destroy.impl_witness.805) [concrete]
+// CHECK:STDOUT:   %.73c: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.5b2 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.cc4: <specific function> = specific_function %Op.d12, @Op.2(%EmptyRange.cc8) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -393,8 +393,8 @@ fn Run() {
 // CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.6ce, %Main.import_ref.999, %Main.import_ref.57b, %Main.import_ref.170), @impl.86e [concrete]
 // CHECK:STDOUT:   %Main.import_ref.7f9: @Optional.%HasValue.type (%HasValue.type.f81) = import_ref Main//empty_range, inst136 [indirect], loaded [symbolic = @Optional.%HasValue (constants.%HasValue.6fd)]
 // CHECK:STDOUT:   %Main.import_ref.d10: @Optional.%Get.type (%Get.type.b8f) = import_ref Main//empty_range, inst137 [indirect], loaded [symbolic = @Optional.%Get (constants.%Get.9c8)]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
+// CHECK:STDOUT:   %Main.import_ref.fcc: @impl.d2b.%Op.type (%Op.type.ed4) = import_ref Main//empty_range, inst373 [indirect], loaded [symbolic = @impl.d2b.%Op (constants.%Op.486)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.fcc), @impl.d2b [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
@@ -463,33 +463,33 @@ fn Run() {
 // CHECK:STDOUT:   br !for.next
 // CHECK:STDOUT:
 // CHECK:STDOUT: !for.done:
-// CHECK:STDOUT:   %impl.elem0.loc12_8.1: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %impl.elem0.loc12_8.1: %.4cb = impl_witness_access constants.%Destroy.impl_witness.832, element0 [concrete = constants.%Op.01c]
 // CHECK:STDOUT:   %bound_method.loc12_8.1: <bound method> = bound_method %.loc12_8, %impl.elem0.loc12_8.1
-// CHECK:STDOUT:   %specific_fn.loc12_8.1: <specific function> = specific_function %impl.elem0.loc12_8.1, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:   %specific_fn.loc12_8.1: <specific function> = specific_function %impl.elem0.loc12_8.1, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.abf]
 // CHECK:STDOUT:   %bound_method.loc12_8.2: <bound method> = bound_method %.loc12_8, %specific_fn.loc12_8.1
 // CHECK:STDOUT:   %addr.loc12_8.1: %ptr.019 = addr_of %.loc12_8
 // CHECK:STDOUT:   %no_op.loc12_8.1: init %empty_tuple.type = call %bound_method.loc12_8.2(%addr.loc12_8.1)
-// CHECK:STDOUT:   %impl.elem0.loc12_8.2: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %impl.elem0.loc12_8.2: %.4cb = impl_witness_access constants.%Destroy.impl_witness.832, element0 [concrete = constants.%Op.01c]
 // CHECK:STDOUT:   %bound_method.loc12_8.3: <bound method> = bound_method %c.var, %impl.elem0.loc12_8.2
-// CHECK:STDOUT:   %specific_fn.loc12_8.2: <specific function> = specific_function %impl.elem0.loc12_8.2, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:   %specific_fn.loc12_8.2: <specific function> = specific_function %impl.elem0.loc12_8.2, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.abf]
 // CHECK:STDOUT:   %bound_method.loc12_8.4: <bound method> = bound_method %c.var, %specific_fn.loc12_8.2
 // CHECK:STDOUT:   %addr.loc12_8.2: %ptr.019 = addr_of %c.var
 // CHECK:STDOUT:   %no_op.loc12_8.2: init %empty_tuple.type = call %bound_method.loc12_8.4(%addr.loc12_8.2)
-// CHECK:STDOUT:   %impl.elem0.loc12_40.1: %.1f9 = impl_witness_access constants.%Destroy.impl_witness.b11, element0 [concrete = constants.%Op.3e8]
+// CHECK:STDOUT:   %impl.elem0.loc12_40.1: %.d26 = impl_witness_access constants.%Destroy.impl_witness.b21, element0 [concrete = constants.%Op.a97]
 // CHECK:STDOUT:   %bound_method.loc12_40.7: <bound method> = bound_method %.loc12_40.1, %impl.elem0.loc12_40.1
-// CHECK:STDOUT:   %specific_fn.loc12_40.3: <specific function> = specific_function %impl.elem0.loc12_40.1, @Op.2(constants.%Optional.cf0) [concrete = constants.%Op.specific_fn.273]
+// CHECK:STDOUT:   %specific_fn.loc12_40.3: <specific function> = specific_function %impl.elem0.loc12_40.1, @Op.2(constants.%Optional.cf0) [concrete = constants.%Op.specific_fn.448]
 // CHECK:STDOUT:   %bound_method.loc12_40.8: <bound method> = bound_method %.loc12_40.1, %specific_fn.loc12_40.3
 // CHECK:STDOUT:   %addr.loc12_40.2: %ptr.8e6 = addr_of %.loc12_40.1
 // CHECK:STDOUT:   %no_op.loc12_40.1: init %empty_tuple.type = call %bound_method.loc12_40.8(%addr.loc12_40.2)
-// CHECK:STDOUT:   %impl.elem0.loc12_40.2: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %impl.elem0.loc12_40.2: %.902 = impl_witness_access constants.%Destroy.impl_witness.67e, element0 [concrete = constants.%Op.ca6]
 // CHECK:STDOUT:   %bound_method.loc12_40.9: <bound method> = bound_method %var, %impl.elem0.loc12_40.2
-// CHECK:STDOUT:   %specific_fn.loc12_40.4: <specific function> = specific_function %impl.elem0.loc12_40.2, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.652]
+// CHECK:STDOUT:   %specific_fn.loc12_40.4: <specific function> = specific_function %impl.elem0.loc12_40.2, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.04c]
 // CHECK:STDOUT:   %bound_method.loc12_40.10: <bound method> = bound_method %var, %specific_fn.loc12_40.4
 // CHECK:STDOUT:   %addr.loc12_40.3: %ptr.c28 = addr_of %var
 // CHECK:STDOUT:   %no_op.loc12_40.2: init %empty_tuple.type = call %bound_method.loc12_40.10(%addr.loc12_40.3)
-// CHECK:STDOUT:   %impl.elem0.loc12_39: %.053 = impl_witness_access constants.%Destroy.impl_witness.506, element0 [concrete = constants.%Op.929]
+// CHECK:STDOUT:   %impl.elem0.loc12_39: %.73c = impl_witness_access constants.%Destroy.impl_witness.805, element0 [concrete = constants.%Op.d12]
 // CHECK:STDOUT:   %bound_method.loc12_39.1: <bound method> = bound_method %.loc12_39.1, %impl.elem0.loc12_39
-// CHECK:STDOUT:   %specific_fn.loc12_39: <specific function> = specific_function %impl.elem0.loc12_39, @Op.2(constants.%EmptyRange.cc8) [concrete = constants.%Op.specific_fn.a14]
+// CHECK:STDOUT:   %specific_fn.loc12_39: <specific function> = specific_function %impl.elem0.loc12_39, @Op.2(constants.%EmptyRange.cc8) [concrete = constants.%Op.specific_fn.cc4]
 // CHECK:STDOUT:   %bound_method.loc12_39.2: <bound method> = bound_method %.loc12_39.1, %specific_fn.loc12_39
 // CHECK:STDOUT:   %addr.loc12_39: %ptr.35d = addr_of %.loc12_39.1
 // CHECK:STDOUT:   %no_op.loc12_39: init %empty_tuple.type = call %bound_method.loc12_39.2(%addr.loc12_39)
@@ -529,6 +529,10 @@ fn Run() {
 // CHECK:STDOUT:   %HasValue.6fd: %HasValue.type.f81 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Get.type.b8f: type = fn_type @Get, @Optional(%T) [symbolic]
 // CHECK:STDOUT:   %Get.9c8: %Get.type.b8f = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.989: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.ed4: type = fn_type @Op.2, @impl.d2b(%T) [symbolic]
+// CHECK:STDOUT:   %Op.486: %Op.type.ed4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Iterate.impl_witness.6db: <witness> = impl_witness imports.%Iterate.impl_witness_table, @impl.86e(%tuple.type.784) [concrete]
 // CHECK:STDOUT:   %NewCursor.type.d32: type = fn_type @NewCursor.2, @impl.86e(%tuple.type.784) [concrete]
 // CHECK:STDOUT:   %NewCursor.763: %NewCursor.type.d32 = struct_value () [concrete]
@@ -548,36 +552,32 @@ fn Run() {
 // CHECK:STDOUT:   %ptr.b85: type = ptr_type %tuple.type.784 [concrete]
 // CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.4f9, @HasValue(%tuple.type.784) [concrete]
 // CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.d99, @Get(%tuple.type.784) [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.9fe: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.784) [concrete]
-// CHECK:STDOUT:   %Op.type.0fc: type = fn_type @Op.2, @impl.49c(%tuple.type.784) [concrete]
-// CHECK:STDOUT:   %Op.0a3: %Op.type.0fc = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.f73: %Destroy.type = facet_value %tuple.type.784, (%Destroy.impl_witness.9fe) [concrete]
-// CHECK:STDOUT:   %.e86: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.f73 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.10e: <specific function> = specific_function %Op.0a3, @Op.2(%tuple.type.784) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.4bb: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Optional.79e) [concrete]
-// CHECK:STDOUT:   %Op.type.e76: type = fn_type @Op.2, @impl.49c(%Optional.79e) [concrete]
-// CHECK:STDOUT:   %Op.d99: %Op.type.e76 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.356: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%tuple.type.784) [concrete]
+// CHECK:STDOUT:   %Op.type.973: type = fn_type @Op.2, @impl.d2b(%tuple.type.784) [concrete]
+// CHECK:STDOUT:   %Op.149: %Op.type.973 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.833: %Destroy.type = facet_value %tuple.type.784, (%Destroy.impl_witness.356) [concrete]
+// CHECK:STDOUT:   %.f45: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.833 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.14c: <specific function> = specific_function %Op.149, @Op.2(%tuple.type.784) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.4cb: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%Optional.79e) [concrete]
+// CHECK:STDOUT:   %Op.type.1cc: type = fn_type @Op.2, @impl.d2b(%Optional.79e) [concrete]
+// CHECK:STDOUT:   %Op.3ef: %Op.type.1cc = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.07d: type = ptr_type %Optional.79e [concrete]
-// CHECK:STDOUT:   %Destroy.facet.a9b: %Destroy.type = facet_value %Optional.79e, (%Destroy.impl_witness.4bb) [concrete]
-// CHECK:STDOUT:   %.447: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.a9b [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.e8f: <specific function> = specific_function %Op.d99, @Op.2(%Optional.79e) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.e2f: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
-// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.e2f [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.652: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.3df: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%EmptyRange.2f3) [concrete]
-// CHECK:STDOUT:   %Op.type.055: type = fn_type @Op.2, @impl.49c(%EmptyRange.2f3) [concrete]
-// CHECK:STDOUT:   %Op.74c: %Op.type.055 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.58b: %Destroy.type = facet_value %Optional.79e, (%Destroy.impl_witness.4cb) [concrete]
+// CHECK:STDOUT:   %.df3: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.58b [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.01c: <specific function> = specific_function %Op.3ef, @Op.2(%Optional.79e) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.67e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.8b2: type = fn_type @Op.2, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.ca6: %Op.type.8b2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2a8: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.67e) [concrete]
+// CHECK:STDOUT:   %.902: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.2a8 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.04c: <specific function> = specific_function %Op.ca6, @Op.2(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.e89: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%EmptyRange.2f3) [concrete]
+// CHECK:STDOUT:   %Op.type.f1e: type = fn_type @Op.2, @impl.d2b(%EmptyRange.2f3) [concrete]
+// CHECK:STDOUT:   %Op.155: %Op.type.f1e = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.5cf: type = ptr_type %EmptyRange.2f3 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.f26: %Destroy.type = facet_value %EmptyRange.2f3, (%Destroy.impl_witness.3df) [concrete]
-// CHECK:STDOUT:   %.222: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.f26 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.cd5: <specific function> = specific_function %Op.74c, @Op.2(%EmptyRange.2f3) [concrete]
+// CHECK:STDOUT:   %Destroy.facet.dcc: %Destroy.type = facet_value %EmptyRange.2f3, (%Destroy.impl_witness.e89) [concrete]
+// CHECK:STDOUT:   %.be5: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.dcc [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.e02: <specific function> = specific_function %Op.155, @Op.2(%EmptyRange.2f3) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -590,8 +590,8 @@ fn Run() {
 // CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.6ce, %Main.import_ref.999, %Main.import_ref.57b, %Main.import_ref.170), @impl.86e [concrete]
 // CHECK:STDOUT:   %Main.import_ref.7f9: @Optional.%HasValue.type (%HasValue.type.f81) = import_ref Main//empty_range, inst136 [indirect], loaded [symbolic = @Optional.%HasValue (constants.%HasValue.6fd)]
 // CHECK:STDOUT:   %Main.import_ref.d10: @Optional.%Get.type (%Get.type.b8f) = import_ref Main//empty_range, inst137 [indirect], loaded [symbolic = @Optional.%Get (constants.%Get.9c8)]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
+// CHECK:STDOUT:   %Main.import_ref.fcc: @impl.d2b.%Op.type (%Op.type.ed4) = import_ref Main//empty_range, inst373 [indirect], loaded [symbolic = @impl.d2b.%Op (constants.%Op.486)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.fcc), @impl.d2b [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
@@ -681,27 +681,27 @@ fn Run() {
 // CHECK:STDOUT:   br !for.next
 // CHECK:STDOUT:
 // CHECK:STDOUT: !for.done:
-// CHECK:STDOUT:   %impl.elem0.loc10_61.1: %.e86 = impl_witness_access constants.%Destroy.impl_witness.9fe, element0 [concrete = constants.%Op.0a3]
+// CHECK:STDOUT:   %impl.elem0.loc10_61.1: %.f45 = impl_witness_access constants.%Destroy.impl_witness.356, element0 [concrete = constants.%Op.149]
 // CHECK:STDOUT:   %bound_method.loc10_61.7: <bound method> = bound_method %.loc10_61.8, %impl.elem0.loc10_61.1
-// CHECK:STDOUT:   %specific_fn.loc10_61.3: <specific function> = specific_function %impl.elem0.loc10_61.1, @Op.2(constants.%tuple.type.784) [concrete = constants.%Op.specific_fn.10e]
+// CHECK:STDOUT:   %specific_fn.loc10_61.3: <specific function> = specific_function %impl.elem0.loc10_61.1, @Op.2(constants.%tuple.type.784) [concrete = constants.%Op.specific_fn.14c]
 // CHECK:STDOUT:   %bound_method.loc10_61.8: <bound method> = bound_method %.loc10_61.8, %specific_fn.loc10_61.3
 // CHECK:STDOUT:   %addr.loc10_61.2: %ptr.b85 = addr_of %.loc10_61.8
 // CHECK:STDOUT:   %no_op.loc10_61.1: init %empty_tuple.type = call %bound_method.loc10_61.8(%addr.loc10_61.2)
-// CHECK:STDOUT:   %impl.elem0.loc10_61.2: %.447 = impl_witness_access constants.%Destroy.impl_witness.4bb, element0 [concrete = constants.%Op.d99]
+// CHECK:STDOUT:   %impl.elem0.loc10_61.2: %.df3 = impl_witness_access constants.%Destroy.impl_witness.4cb, element0 [concrete = constants.%Op.3ef]
 // CHECK:STDOUT:   %bound_method.loc10_61.9: <bound method> = bound_method %.loc10_61.1, %impl.elem0.loc10_61.2
-// CHECK:STDOUT:   %specific_fn.loc10_61.4: <specific function> = specific_function %impl.elem0.loc10_61.2, @Op.2(constants.%Optional.79e) [concrete = constants.%Op.specific_fn.e8f]
+// CHECK:STDOUT:   %specific_fn.loc10_61.4: <specific function> = specific_function %impl.elem0.loc10_61.2, @Op.2(constants.%Optional.79e) [concrete = constants.%Op.specific_fn.01c]
 // CHECK:STDOUT:   %bound_method.loc10_61.10: <bound method> = bound_method %.loc10_61.1, %specific_fn.loc10_61.4
 // CHECK:STDOUT:   %addr.loc10_61.3: %ptr.07d = addr_of %.loc10_61.1
 // CHECK:STDOUT:   %no_op.loc10_61.2: init %empty_tuple.type = call %bound_method.loc10_61.10(%addr.loc10_61.3)
-// CHECK:STDOUT:   %impl.elem0.loc10_61.3: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %impl.elem0.loc10_61.3: %.902 = impl_witness_access constants.%Destroy.impl_witness.67e, element0 [concrete = constants.%Op.ca6]
 // CHECK:STDOUT:   %bound_method.loc10_61.11: <bound method> = bound_method %var, %impl.elem0.loc10_61.3
-// CHECK:STDOUT:   %specific_fn.loc10_61.5: <specific function> = specific_function %impl.elem0.loc10_61.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.652]
+// CHECK:STDOUT:   %specific_fn.loc10_61.5: <specific function> = specific_function %impl.elem0.loc10_61.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.04c]
 // CHECK:STDOUT:   %bound_method.loc10_61.12: <bound method> = bound_method %var, %specific_fn.loc10_61.5
 // CHECK:STDOUT:   %addr.loc10_61.4: %ptr.c28 = addr_of %var
 // CHECK:STDOUT:   %no_op.loc10_61.3: init %empty_tuple.type = call %bound_method.loc10_61.12(%addr.loc10_61.4)
-// CHECK:STDOUT:   %impl.elem0.loc10_60: %.222 = impl_witness_access constants.%Destroy.impl_witness.3df, element0 [concrete = constants.%Op.74c]
+// CHECK:STDOUT:   %impl.elem0.loc10_60: %.be5 = impl_witness_access constants.%Destroy.impl_witness.e89, element0 [concrete = constants.%Op.155]
 // CHECK:STDOUT:   %bound_method.loc10_60.1: <bound method> = bound_method %.loc10_60.1, %impl.elem0.loc10_60
-// CHECK:STDOUT:   %specific_fn.loc10_60: <specific function> = specific_function %impl.elem0.loc10_60, @Op.2(constants.%EmptyRange.2f3) [concrete = constants.%Op.specific_fn.cd5]
+// CHECK:STDOUT:   %specific_fn.loc10_60: <specific function> = specific_function %impl.elem0.loc10_60, @Op.2(constants.%EmptyRange.2f3) [concrete = constants.%Op.specific_fn.e02]
 // CHECK:STDOUT:   %bound_method.loc10_60.2: <bound method> = bound_method %.loc10_60.1, %specific_fn.loc10_60
 // CHECK:STDOUT:   %addr.loc10_60: %ptr.5cf = addr_of %.loc10_60.1
 // CHECK:STDOUT:   %no_op.loc10_60: init %empty_tuple.type = call %bound_method.loc10_60.2(%addr.loc10_60)
@@ -740,6 +740,10 @@ fn Run() {
 // CHECK:STDOUT:   %HasValue.6fd: %HasValue.type.f81 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Get.type.b8f: type = fn_type @Get, @Optional(%T) [symbolic]
 // CHECK:STDOUT:   %Get.9c8: %Get.type.b8f = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.989: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.ed4: type = fn_type @Op.2, @impl.d2b(%T) [symbolic]
+// CHECK:STDOUT:   %Op.486: %Op.type.ed4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Iterate.impl_witness.627: <witness> = impl_witness imports.%Iterate.impl_witness_table, @impl.86e(%tuple.type.56b) [concrete]
 // CHECK:STDOUT:   %NewCursor.type.59c: type = fn_type @NewCursor.2, @impl.86e(%tuple.type.56b) [concrete]
 // CHECK:STDOUT:   %NewCursor.263: %NewCursor.type.59c = struct_value () [concrete]
@@ -758,37 +762,33 @@ fn Run() {
 // CHECK:STDOUT:   %Get.8a7: %Get.type.4a4 = struct_value () [concrete]
 // CHECK:STDOUT:   %HasValue.specific_fn: <specific function> = specific_function %HasValue.bef, @HasValue(%tuple.type.56b) [concrete]
 // CHECK:STDOUT:   %Get.specific_fn: <specific function> = specific_function %Get.8a7, @Get(%tuple.type.56b) [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.7aa: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.56b) [concrete]
-// CHECK:STDOUT:   %Op.type.12e: type = fn_type @Op.2, @impl.49c(%tuple.type.56b) [concrete]
-// CHECK:STDOUT:   %Op.34b: %Op.type.12e = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.c9b: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%tuple.type.56b) [concrete]
+// CHECK:STDOUT:   %Op.type.65e: type = fn_type @Op.2, @impl.d2b(%tuple.type.56b) [concrete]
+// CHECK:STDOUT:   %Op.587: %Op.type.65e = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.9f0: type = ptr_type %tuple.type.56b [concrete]
-// CHECK:STDOUT:   %Destroy.facet.5ce: %Destroy.type = facet_value %tuple.type.56b, (%Destroy.impl_witness.7aa) [concrete]
-// CHECK:STDOUT:   %.874: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.5ce [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.50d: <specific function> = specific_function %Op.34b, @Op.2(%tuple.type.56b) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.d9c: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Optional.657) [concrete]
-// CHECK:STDOUT:   %Op.type.e9f: type = fn_type @Op.2, @impl.49c(%Optional.657) [concrete]
-// CHECK:STDOUT:   %Op.5c4: %Op.type.e9f = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.882: %Destroy.type = facet_value %tuple.type.56b, (%Destroy.impl_witness.c9b) [concrete]
+// CHECK:STDOUT:   %.d75: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.882 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.6b2: <specific function> = specific_function %Op.587, @Op.2(%tuple.type.56b) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.f8d: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%Optional.657) [concrete]
+// CHECK:STDOUT:   %Op.type.400: type = fn_type @Op.2, @impl.d2b(%Optional.657) [concrete]
+// CHECK:STDOUT:   %Op.5ec: %Op.type.400 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.036: type = ptr_type %Optional.657 [concrete]
-// CHECK:STDOUT:   %Destroy.facet.8a2: %Destroy.type = facet_value %Optional.657, (%Destroy.impl_witness.d9c) [concrete]
-// CHECK:STDOUT:   %.0d9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.8a2 [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.068: <specific function> = specific_function %Op.5c4, @Op.2(%Optional.657) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.facet.e2f: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
-// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.e2f [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.652: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %Destroy.impl_witness.7c5: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%EmptyRange.90a) [concrete]
-// CHECK:STDOUT:   %Op.type.8c3: type = fn_type @Op.2, @impl.49c(%EmptyRange.90a) [concrete]
-// CHECK:STDOUT:   %Op.85b: %Op.type.8c3 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.cb2: %Destroy.type = facet_value %Optional.657, (%Destroy.impl_witness.f8d) [concrete]
+// CHECK:STDOUT:   %.894: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.cb2 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.840: <specific function> = specific_function %Op.5ec, @Op.2(%Optional.657) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.67e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.8b2: type = fn_type @Op.2, @impl.d2b(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.ca6: %Op.type.8b2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2a8: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.67e) [concrete]
+// CHECK:STDOUT:   %.902: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.2a8 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.04c: <specific function> = specific_function %Op.ca6, @Op.2(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.f74: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%EmptyRange.90a) [concrete]
+// CHECK:STDOUT:   %Op.type.cee: type = fn_type @Op.2, @impl.d2b(%EmptyRange.90a) [concrete]
+// CHECK:STDOUT:   %Op.323: %Op.type.cee = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.f9b: type = ptr_type %EmptyRange.90a [concrete]
-// CHECK:STDOUT:   %Destroy.facet.06e: %Destroy.type = facet_value %EmptyRange.90a, (%Destroy.impl_witness.7c5) [concrete]
-// CHECK:STDOUT:   %.2da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.06e [concrete]
-// CHECK:STDOUT:   %Op.specific_fn.bc1: <specific function> = specific_function %Op.85b, @Op.2(%EmptyRange.90a) [concrete]
+// CHECK:STDOUT:   %Destroy.facet.31a: %Destroy.type = facet_value %EmptyRange.90a, (%Destroy.impl_witness.f74) [concrete]
+// CHECK:STDOUT:   %.3a2: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.31a [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.5d2: <specific function> = specific_function %Op.323, @Op.2(%EmptyRange.90a) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -801,8 +801,8 @@ fn Run() {
 // CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.6ce, %Main.import_ref.999, %Main.import_ref.57b, %Main.import_ref.170), @impl.86e [concrete]
 // CHECK:STDOUT:   %Main.import_ref.7f9: @Optional.%HasValue.type (%HasValue.type.f81) = import_ref Main//empty_range, inst136 [indirect], loaded [symbolic = @Optional.%HasValue (constants.%HasValue.6fd)]
 // CHECK:STDOUT:   %Main.import_ref.d10: @Optional.%Get.type (%Get.type.b8f) = import_ref Main//empty_range, inst137 [indirect], loaded [symbolic = @Optional.%Get (constants.%Get.9c8)]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
+// CHECK:STDOUT:   %Main.import_ref.fcc: @impl.d2b.%Op.type (%Op.type.ed4) = import_ref Main//empty_range, inst373 [indirect], loaded [symbolic = @impl.d2b.%Op (constants.%Op.486)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.fcc), @impl.d2b [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
@@ -880,27 +880,27 @@ fn Run() {
 // CHECK:STDOUT:   br !for.next
 // CHECK:STDOUT:
 // CHECK:STDOUT: !for.done:
-// CHECK:STDOUT:   %impl.elem0.loc12_49.1: %.874 = impl_witness_access constants.%Destroy.impl_witness.7aa, element0 [concrete = constants.%Op.34b]
+// CHECK:STDOUT:   %impl.elem0.loc12_49.1: %.d75 = impl_witness_access constants.%Destroy.impl_witness.c9b, element0 [concrete = constants.%Op.587]
 // CHECK:STDOUT:   %bound_method.loc12_49.7: <bound method> = bound_method %.loc12_49.8, %impl.elem0.loc12_49.1
-// CHECK:STDOUT:   %specific_fn.loc12_49.3: <specific function> = specific_function %impl.elem0.loc12_49.1, @Op.2(constants.%tuple.type.56b) [concrete = constants.%Op.specific_fn.50d]
+// CHECK:STDOUT:   %specific_fn.loc12_49.3: <specific function> = specific_function %impl.elem0.loc12_49.1, @Op.2(constants.%tuple.type.56b) [concrete = constants.%Op.specific_fn.6b2]
 // CHECK:STDOUT:   %bound_method.loc12_49.8: <bound method> = bound_method %.loc12_49.8, %specific_fn.loc12_49.3
 // CHECK:STDOUT:   %addr.loc12_49.2: %ptr.9f0 = addr_of %.loc12_49.8
 // CHECK:STDOUT:   %no_op.loc12_49.1: init %empty_tuple.type = call %bound_method.loc12_49.8(%addr.loc12_49.2)
-// CHECK:STDOUT:   %impl.elem0.loc12_49.2: %.0d9 = impl_witness_access constants.%Destroy.impl_witness.d9c, element0 [concrete = constants.%Op.5c4]
+// CHECK:STDOUT:   %impl.elem0.loc12_49.2: %.894 = impl_witness_access constants.%Destroy.impl_witness.f8d, element0 [concrete = constants.%Op.5ec]
 // CHECK:STDOUT:   %bound_method.loc12_49.9: <bound method> = bound_method %.loc12_49.1, %impl.elem0.loc12_49.2
-// CHECK:STDOUT:   %specific_fn.loc12_49.4: <specific function> = specific_function %impl.elem0.loc12_49.2, @Op.2(constants.%Optional.657) [concrete = constants.%Op.specific_fn.068]
+// CHECK:STDOUT:   %specific_fn.loc12_49.4: <specific function> = specific_function %impl.elem0.loc12_49.2, @Op.2(constants.%Optional.657) [concrete = constants.%Op.specific_fn.840]
 // CHECK:STDOUT:   %bound_method.loc12_49.10: <bound method> = bound_method %.loc12_49.1, %specific_fn.loc12_49.4
 // CHECK:STDOUT:   %addr.loc12_49.3: %ptr.036 = addr_of %.loc12_49.1
 // CHECK:STDOUT:   %no_op.loc12_49.2: init %empty_tuple.type = call %bound_method.loc12_49.10(%addr.loc12_49.3)
-// CHECK:STDOUT:   %impl.elem0.loc12_49.3: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %impl.elem0.loc12_49.3: %.902 = impl_witness_access constants.%Destroy.impl_witness.67e, element0 [concrete = constants.%Op.ca6]
 // CHECK:STDOUT:   %bound_method.loc12_49.11: <bound method> = bound_method %var, %impl.elem0.loc12_49.3
-// CHECK:STDOUT:   %specific_fn.loc12_49.5: <specific function> = specific_function %impl.elem0.loc12_49.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.652]
+// CHECK:STDOUT:   %specific_fn.loc12_49.5: <specific function> = specific_function %impl.elem0.loc12_49.3, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn.04c]
 // CHECK:STDOUT:   %bound_method.loc12_49.12: <bound method> = bound_method %var, %specific_fn.loc12_49.5
 // CHECK:STDOUT:   %addr.loc12_49.4: %ptr.c28 = addr_of %var
 // CHECK:STDOUT:   %no_op.loc12_49.3: init %empty_tuple.type = call %bound_method.loc12_49.12(%addr.loc12_49.4)
-// CHECK:STDOUT:   %impl.elem0.loc12_48: %.2da = impl_witness_access constants.%Destroy.impl_witness.7c5, element0 [concrete = constants.%Op.85b]
+// CHECK:STDOUT:   %impl.elem0.loc12_48: %.3a2 = impl_witness_access constants.%Destroy.impl_witness.f74, element0 [concrete = constants.%Op.323]
 // CHECK:STDOUT:   %bound_method.loc12_48.1: <bound method> = bound_method %.loc12_48.1, %impl.elem0.loc12_48
-// CHECK:STDOUT:   %specific_fn.loc12_48: <specific function> = specific_function %impl.elem0.loc12_48, @Op.2(constants.%EmptyRange.90a) [concrete = constants.%Op.specific_fn.bc1]
+// CHECK:STDOUT:   %specific_fn.loc12_48: <specific function> = specific_function %impl.elem0.loc12_48, @Op.2(constants.%EmptyRange.90a) [concrete = constants.%Op.specific_fn.5d2]
 // CHECK:STDOUT:   %bound_method.loc12_48.2: <bound method> = bound_method %.loc12_48.1, %specific_fn.loc12_48
 // CHECK:STDOUT:   %addr.loc12_48: %ptr.f9b = addr_of %.loc12_48.1
 // CHECK:STDOUT:   %no_op.loc12_48: init %empty_tuple.type = call %bound_method.loc12_48.2(%addr.loc12_48)

+ 50 - 6
toolchain/check/testdata/function/generic/call.carbon

@@ -63,6 +63,7 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %Function.type: type = fn_type @Function [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Function: %Function.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %CallGeneric.type: type = fn_type @CallGeneric [concrete]
@@ -76,18 +77,33 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %Function.specific_fn.4d7: <specific function> = specific_function %Function, @Function(%ptr.79f) [symbolic]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %pattern_type.c48: type = pattern_type %C [concrete]
 // CHECK:STDOUT:   %CallSpecific.type: type = fn_type @CallSpecific [concrete]
 // CHECK:STDOUT:   %CallSpecific: %CallSpecific.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Function.specific_fn.1b5: <specific function> = specific_function %Function, @Function(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -167,7 +183,7 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -240,6 +256,12 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %Function.specific_fn: <specific function> = specific_function %Function.ref, @Function(constants.%C) [concrete = constants.%Function.specific_fn.1b5]
 // CHECK:STDOUT:   %.loc18: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %Function.call: init %C = call %Function.specific_fn(%x.ref) to %.loc18
+// CHECK:STDOUT:   %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc18_23.1: <bound method> = bound_method %.loc18, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc18_23.2: <bound method> = bound_method %.loc18, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.019 = addr_of %.loc18
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc18_23.2(%addr)
 // CHECK:STDOUT:   return %Function.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -275,7 +297,7 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c48
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- deduced.carbon
@@ -285,6 +307,7 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
 // CHECK:STDOUT:   %Function.type: type = fn_type @Function [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Function: %Function.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %CallGeneric.type: type = fn_type @CallGeneric [concrete]
@@ -298,18 +321,33 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %Function.specific_fn.4d7: <specific function> = specific_function %Function, @Function(%ptr.79f) [symbolic]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %pattern_type.c48: type = pattern_type %C [concrete]
 // CHECK:STDOUT:   %CallSpecific.type: type = fn_type @CallSpecific [concrete]
 // CHECK:STDOUT:   %CallSpecific: %CallSpecific.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Function.specific_fn.1b5: <specific function> = specific_function %Function, @Function(%C) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -389,7 +427,7 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   complete_type_witness = %complete_type
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
@@ -458,6 +496,12 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %Function.specific_fn: <specific function> = specific_function %Function.ref, @Function(constants.%C) [concrete = constants.%Function.specific_fn.1b5]
 // CHECK:STDOUT:   %.loc18: ref %C = splice_block %return {}
 // CHECK:STDOUT:   %Function.call: init %C = call %Function.specific_fn(%x.ref) to %.loc18
+// CHECK:STDOUT:   %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:   %bound_method.loc18_23.1: <bound method> = bound_method %.loc18, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc18_23.2: <bound method> = bound_method %.loc18, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.019 = addr_of %.loc18
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc18_23.2(%addr)
 // CHECK:STDOUT:   return %Function.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -493,6 +537,6 @@ fn CallSpecific(x: C) -> C {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c48
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 0
toolchain/check/testdata/function/generic/deduce.carbon

@@ -517,6 +517,7 @@ fn F() {
 // CHECK:STDOUT:   %ptr.79f: type = ptr_type %T [symbolic]
 // CHECK:STDOUT:   %pattern_type.afe: type = pattern_type %ptr.79f [symbolic]
 // CHECK:STDOUT:   %ExplicitAndAlsoDeduced.type: type = fn_type @ExplicitAndAlsoDeduced [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %ExplicitAndAlsoDeduced: %ExplicitAndAlsoDeduced.type = struct_value () [concrete]
 // CHECK:STDOUT:   %require_complete.6e5: <witness> = require_complete_type %ptr.79f [symbolic]
 // CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
@@ -528,14 +529,28 @@ fn F() {
 // CHECK:STDOUT:   %pattern_type.c10: type = pattern_type %A [concrete]
 // CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.720: <specific function> = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%A) [concrete]
 // CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.b6e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%A) [concrete]
+// CHECK:STDOUT:   %Op.type.b96: type = fn_type @Op.2, @impl(%A) [concrete]
+// CHECK:STDOUT:   %Op.885: %Op.type.b96 = struct_value () [concrete]
 // CHECK:STDOUT:   %complete_type.7ea: <witness> = complete_type_witness %ptr.6db [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %A, (%Destroy.impl_witness.b6e) [concrete]
+// CHECK:STDOUT:   %.af1: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.885, @Op.2(%A) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -621,6 +636,12 @@ fn F() {
 // CHECK:STDOUT:   %ExplicitAndAlsoDeduced.call: init %ptr.6db = call %ExplicitAndAlsoDeduced.specific_fn(%.loc11_37.6)
 // CHECK:STDOUT:   %.loc11_39.1: %ptr.6db = value_of_initializer %ExplicitAndAlsoDeduced.call
 // CHECK:STDOUT:   %.loc11_39.2: %ptr.6db = converted %ExplicitAndAlsoDeduced.call, %.loc11_39.1
+// CHECK:STDOUT:   %impl.elem0: %.af1 = impl_witness_access constants.%Destroy.impl_witness.b6e, element0 [concrete = constants.%Op.885]
+// CHECK:STDOUT:   %bound_method.loc11_37.1: <bound method> = bound_method %.loc11_37.2, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%A) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_37.2: <bound method> = bound_method %.loc11_37.2, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.6db = addr_of %.loc11_37.2
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc11_37.2(%addr)
 // CHECK:STDOUT:   return %.loc11_39.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 29 - 16
toolchain/check/testdata/generic/call_basic_depth.carbon

@@ -66,6 +66,17 @@ fn M() {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %H.specific_fn.1ed: <specific function> = specific_function %H, @H(%T) [symbolic]
 // CHECK:STDOUT:   %Cfn.specific_fn.53f: <specific function> = specific_function %Cfn, @Cfn(%T) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.906: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.type.153: type = fn_type @Op.2, @impl.49c(%C) [concrete]
+// CHECK:STDOUT:   %Op.5d7: %Op.type.153 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.019: type = ptr_type %C [concrete]
+// CHECK:STDOUT:   %Destroy.facet.494: %Destroy.type = facet_value %C, (%Destroy.impl_witness.906) [concrete]
+// CHECK:STDOUT:   %.b80: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.494 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.6eb: <specific function> = specific_function %Op.5d7, @Op.2(%C) [concrete]
 // CHECK:STDOUT:   %M.type: type = fn_type @M [concrete]
 // CHECK:STDOUT:   %M: %M.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
@@ -94,36 +105,32 @@ fn M() {
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
 // CHECK:STDOUT:   %F.specific_fn.501: <specific function> = specific_function %F, @F(%i32) [concrete]
 // CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%i32) [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
-// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.2, @impl.49c(%i32) [concrete]
 // CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
-// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
-// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
-// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5f7: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.5f7 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.014: <specific function> = specific_function %Op.e6a, @Op.2(%i32) [concrete]
 // CHECK:STDOUT:   %H.specific_fn.aac: <specific function> = specific_function %H, @H(%i32) [concrete]
 // CHECK:STDOUT:   %Cfn.specific_fn.7b2: <specific function> = specific_function %Cfn, @Cfn(%i32) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
-// 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:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
-// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -282,10 +289,16 @@ fn M() {
 // CHECK:STDOUT:     %Cfn.bound: <bound method> = bound_method %c.ref, %Cfn.ref
 // CHECK:STDOUT:     %x.ref.loc34: @G.%T.loc29_6.2 (%T) = name_ref x, %x
 // CHECK:STDOUT:     %Cfn.specific_fn.loc34_4.1: <specific function> = specific_function %Cfn.ref, @Cfn(constants.%T) [symbolic = %Cfn.specific_fn.loc34_4.2 (constants.%Cfn.specific_fn.53f)]
-// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %c.ref, %Cfn.specific_fn.loc34_4.1
+// CHECK:STDOUT:     %bound_method.loc34: <bound method> = bound_method %c.ref, %Cfn.specific_fn.loc34_4.1
 // CHECK:STDOUT:     %.loc34: %C = bind_value %c.ref
-// CHECK:STDOUT:     %Cfn.call: init %empty_tuple.type = call %bound_method(%.loc34, %x.ref.loc34)
+// CHECK:STDOUT:     %Cfn.call: init %empty_tuple.type = call %bound_method.loc34(%.loc34, %x.ref.loc34)
 // CHECK:STDOUT:     %x.ref.loc35: @G.%T.loc29_6.2 (%T) = name_ref x, %x
+// CHECK:STDOUT:     %impl.elem0: %.b80 = impl_witness_access constants.%Destroy.impl_witness.906, element0 [concrete = constants.%Op.5d7]
+// CHECK:STDOUT:     %bound_method.loc33_3.1: <bound method> = bound_method %c.var, %impl.elem0
+// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%C) [concrete = constants.%Op.specific_fn.6eb]
+// CHECK:STDOUT:     %bound_method.loc33_3.2: <bound method> = bound_method %c.var, %specific_fn
+// CHECK:STDOUT:     %addr: %ptr.019 = addr_of %c.var
+// CHECK:STDOUT:     %no_op: init %empty_tuple.type = call %bound_method.loc33_3.2(%addr)
 // CHECK:STDOUT:     return %x.ref.loc35
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -334,13 +347,13 @@ fn M() {
 // CHECK:STDOUT:   assign %m.ref, %G.call
 // CHECK:STDOUT:   %impl.elem0.loc40: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
 // CHECK:STDOUT:   %bound_method.loc40_3.1: <bound method> = bound_method %m.var, %impl.elem0.loc40
-// CHECK:STDOUT:   %specific_fn.loc40: <specific function> = specific_function %impl.elem0.loc40, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %specific_fn.loc40: <specific function> = specific_function %impl.elem0.loc40, @Op.2(constants.%i32) [concrete = constants.%Op.specific_fn.014]
 // CHECK:STDOUT:   %bound_method.loc40_3.2: <bound method> = bound_method %m.var, %specific_fn.loc40
 // CHECK:STDOUT:   %addr.loc40: %ptr.235 = addr_of %m.var
 // CHECK:STDOUT:   %no_op.loc40: init %empty_tuple.type = call %bound_method.loc40_3.2(%addr.loc40)
 // CHECK:STDOUT:   %impl.elem0.loc39_3.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
 // CHECK:STDOUT:   %bound_method.loc39_3.3: <bound method> = bound_method %n.var, %impl.elem0.loc39_3.2
-// CHECK:STDOUT:   %specific_fn.loc39_3.2: <specific function> = specific_function %impl.elem0.loc39_3.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %specific_fn.loc39_3.2: <specific function> = specific_function %impl.elem0.loc39_3.2, @Op.2(constants.%i32) [concrete = constants.%Op.specific_fn.014]
 // CHECK:STDOUT:   %bound_method.loc39_3.4: <bound method> = bound_method %n.var, %specific_fn.loc39_3.2
 // CHECK:STDOUT:   %addr.loc39: %ptr.235 = addr_of %n.var
 // CHECK:STDOUT:   %no_op.loc39: init %empty_tuple.type = call %bound_method.loc39_3.4(%addr.loc39)

+ 47 - 15
toolchain/check/testdata/generic/template_dependence.carbon

@@ -109,23 +109,35 @@ fn F(template T:! type, U:! type) -> (T, U) {
 // CHECK:STDOUT: --- mixed.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0, template [template]
+// CHECK:STDOUT:   %T.8b3d5d.1: type = bind_symbolic_name T, 0, template [template]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %U: type = bind_symbolic_name U, 1 [symbolic]
 // CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]
-// CHECK:STDOUT:   %tuple.type.30b: type = tuple_type (%T, %U) [template]
+// CHECK:STDOUT:   %tuple.type.30b: type = tuple_type (%T.8b3d5d.1, %U) [template]
 // CHECK:STDOUT:   %pattern_type.65c: type = pattern_type %tuple.type.30b [template]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type.30b [template]
-// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T, %U) [template]
+// CHECK:STDOUT:   %ptr.937: type = ptr_type %tuple.type.30b [template]
+// CHECK:STDOUT:   %require_complete.fe1: <witness> = require_complete_type %tuple.type.30b [template]
+// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T.8b3d5d.1, %U) [template]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %require_complete.8fa: <witness> = require_complete_type %ptr.937 [template]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type.30b, @Destroy [template]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type.30b, (%Destroy.lookup_impl_witness) [template]
+// CHECK:STDOUT:   %.1e9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [template]
+// CHECK:STDOUT:   %impl.elem0: %.1e9 = impl_witness_access %Destroy.lookup_impl_witness, element0 [template]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet) [template]
 // 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 {
@@ -140,11 +152,11 @@ fn F(template T:! type, U:! type) -> (T, U) {
 // CHECK:STDOUT:     %return.patt: @F.%pattern_type (%pattern_type.65c) = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: @F.%pattern_type (%pattern_type.65c) = out_param_pattern %return.patt, call_param0 [concrete]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %T.ref.loc4: type = name_ref T, %T.loc4_15.1 [template = %T.loc4_15.2 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc4: type = name_ref T, %T.loc4_15.1 [template = %T.loc4_15.2 (constants.%T.8b3d5d.1)]
 // CHECK:STDOUT:     %U.ref.loc4: type = name_ref U, %U.loc4_25.1 [symbolic = %U.loc4_25.2 (constants.%U)]
 // CHECK:STDOUT:     %.loc4_43.1: %tuple.type.24b = tuple_literal (%T.ref.loc4, %U.ref.loc4)
 // CHECK:STDOUT:     %.loc4_43.2: type = converted %.loc4_43.1, constants.%tuple.type.30b [template = %tuple.type (constants.%tuple.type.30b)]
-// CHECK:STDOUT:     %T.loc4_15.1: type = bind_symbolic_name T, 0, template [template = %T.loc4_15.2 (constants.%T)]
+// CHECK:STDOUT:     %T.loc4_15.1: type = bind_symbolic_name T, 0, template [template = %T.loc4_15.2 (constants.%T.8b3d5d.1)]
 // CHECK:STDOUT:     %U.loc4_25.1: type = bind_symbolic_name U, 1 [symbolic = %U.loc4_25.2 (constants.%U)]
 // CHECK:STDOUT:     %return.param: ref @F.%tuple.type (%tuple.type.30b) = out_param call_param0
 // CHECK:STDOUT:     %return: ref @F.%tuple.type (%tuple.type.30b) = return_slot %return.param
@@ -152,35 +164,55 @@ fn F(template T:! type, U:! type) -> (T, U) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F(%T.loc4_15.1: type, %U.loc4_25.1: type) {
-// CHECK:STDOUT:   %T.loc4_15.2: type = bind_symbolic_name T, 0, template [template = %T.loc4_15.2 (constants.%T)]
+// CHECK:STDOUT:   %T.loc4_15.2: type = bind_symbolic_name T, 0, template [template = %T.loc4_15.2 (constants.%T.8b3d5d.1)]
 // CHECK:STDOUT:   %U.loc4_25.2: type = bind_symbolic_name U, 1 [symbolic = %U.loc4_25.2 (constants.%U)]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc4_15.2, %U.loc4_25.2) [template = %tuple.type (constants.%tuple.type.30b)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %tuple.type [template = %pattern_type (constants.%pattern_type.65c)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [template = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete.loc4_35.1: <witness> = require_complete_type %tuple.type [template = %require_complete.loc4_35.1 (constants.%require_complete.fe1)]
 // CHECK:STDOUT:   %F.specific_fn.loc5_10.2: <specific function> = specific_function constants.%F, @F(%T.loc4_15.2, %U.loc4_25.2) [template = %F.specific_fn.loc5_10.2 (constants.%F.specific_fn)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [template = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness) [template = %Destroy.facet (constants.%Destroy.facet)]
+// CHECK:STDOUT:   %.loc4_35.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [template = %.loc4_35.3 (constants.%.1e9)]
+// CHECK:STDOUT:   %impl.elem0.loc4_35.2: @F.%.loc4_35.3 (%.1e9) = impl_witness_access %Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc4_35.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.loc4_35.2: <specific function> = specific_impl_function %impl.elem0.loc4_35.2, @Op.1(%Destroy.facet) [template = %specific_impl_fn.loc4_35.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %tuple.type [template = %ptr (constants.%ptr.937)]
+// CHECK:STDOUT:   %require_complete.loc4_35.2: <witness> = require_complete_type %ptr [template = %require_complete.loc4_35.2 (constants.%require_complete.8fa)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn() -> %return.param: @F.%tuple.type (%tuple.type.30b) {
 // CHECK:STDOUT:   !entry:
 // CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
-// CHECK:STDOUT:     %T.ref.loc5: type = name_ref T, %T.loc4_15.1 [template = %T.loc4_15.2 (constants.%T)]
+// CHECK:STDOUT:     %T.ref.loc5: type = name_ref T, %T.loc4_15.1 [template = %T.loc4_15.2 (constants.%T.8b3d5d.1)]
 // CHECK:STDOUT:     %U.ref.loc5: type = name_ref U, %U.loc4_25.1 [symbolic = %U.loc4_25.2 (constants.%U)]
-// CHECK:STDOUT:     %F.specific_fn.loc5_10.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [template = %F.specific_fn.loc5_10.2 (constants.%F.specific_fn)]
-// CHECK:STDOUT:     %.loc4_35: ref @F.%tuple.type (%tuple.type.30b) = splice_block %return {}
-// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.30b) = call %F.specific_fn.loc5_10.1() to %.loc4_35
+// CHECK:STDOUT:     %F.specific_fn.loc5_10.1: <specific function> = specific_function %F.ref, @F(constants.%T.8b3d5d.1, constants.%U) [template = %F.specific_fn.loc5_10.2 (constants.%F.specific_fn)]
+// CHECK:STDOUT:     %.loc4_35.1: ref @F.%tuple.type (%tuple.type.30b) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.30b) = call %F.specific_fn.loc5_10.1() to %.loc4_35.1
+// CHECK:STDOUT:     %impl.elem0.loc4_35.1: @F.%.loc4_35.3 (%.1e9) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc4_35.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.loc4_35.1: <bound method> = bound_method %.loc4_35.1, %impl.elem0.loc4_35.1
+// CHECK:STDOUT:     %specific_impl_fn.loc4_35.1: <specific function> = specific_impl_function %impl.elem0.loc4_35.1, @Op.1(constants.%Destroy.facet) [template = %specific_impl_fn.loc4_35.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.loc4_35.2: <bound method> = bound_method %.loc4_35.1, %specific_impl_fn.loc4_35.1
+// CHECK:STDOUT:     %addr: @F.%ptr (%ptr.937) = addr_of %.loc4_35.1
+// CHECK:STDOUT:     %.loc4_35.2: init %empty_tuple.type = call %bound_method.loc4_35.2(%addr)
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F(constants.%T, constants.%U) {
-// CHECK:STDOUT:   %T.loc4_15.2 => constants.%T
+// CHECK:STDOUT: specific @F(constants.%T.8b3d5d.1, constants.%U) {
+// CHECK:STDOUT:   %T.loc4_15.2 => constants.%T.8b3d5d.1
 // CHECK:STDOUT:   %U.loc4_25.2 => constants.%U
 // CHECK:STDOUT:   %tuple.type => constants.%tuple.type.30b
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.65c
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete
+// CHECK:STDOUT:   %require_complete.loc4_35.1 => constants.%require_complete.fe1
 // CHECK:STDOUT:   %F.specific_fn.loc5_10.2 => constants.%F.specific_fn
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet
+// CHECK:STDOUT:   %.loc4_35.3 => constants.%.1e9
+// CHECK:STDOUT:   %impl.elem0.loc4_35.2 => constants.%impl.elem0
+// CHECK:STDOUT:   %specific_impl_fn.loc4_35.2 => constants.%specific_impl_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.937
+// CHECK:STDOUT:   %require_complete.loc4_35.2 => constants.%require_complete.8fa
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 27 - 4
toolchain/check/testdata/if_expr/basic.carbon

@@ -21,6 +21,7 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
@@ -32,6 +33,7 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %array_type: type = array_type %int_1, %i32 [concrete]
+// CHECK:STDOUT:   %ptr.260: type = ptr_type %array_type [concrete]
 // CHECK:STDOUT:   %pattern_type.a98: type = pattern_type %array_type [concrete]
 // CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (Core.IntLiteral) [concrete]
@@ -52,6 +54,17 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_0.6a9) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.bc9: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.type.fa9: type = fn_type @Op.3, @impl.49c(%array_type) [concrete]
+// CHECK:STDOUT:   %Op.606: %Op.type.fa9 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type, (%Destroy.impl_witness.bc9) [concrete]
+// CHECK:STDOUT:   %.050: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.606, @Op.3(%array_type) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -59,6 +72,7 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:     .Bool = %Core.Bool
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -67,6 +81,9 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -120,10 +137,10 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %x.var: ref %array_type = var %x.var_patt
 // CHECK:STDOUT:   %int_0.loc16_27: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
 // CHECK:STDOUT:   %.loc16_29.1: %tuple.type = tuple_literal (%int_0.loc16_27)
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc16_29.1: <bound method> = bound_method %int_0.loc16_27, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc16_29.2: <bound method> = bound_method %int_0.loc16_27, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc16_29: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc16_29.1: <bound method> = bound_method %int_0.loc16_27, %impl.elem0.loc16_29 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc16_29: <specific function> = specific_function %impl.elem0.loc16_29, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_29.2: <bound method> = bound_method %int_0.loc16_27, %specific_fn.loc16_29 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc16_29.2(%int_0.loc16_27) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc16_29.2: init %i32 = converted %int_0.loc16_27, %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %int_0.loc16_29: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
@@ -162,6 +179,12 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result:
 // CHECK:STDOUT:   %.loc17_10: %i32 = block_arg !if.expr.result
+// CHECK:STDOUT:   %impl.elem0.loc16_3: %.050 = impl_witness_access constants.%Destroy.impl_witness.bc9, element0 [concrete = constants.%Op.606]
+// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %x.var, %impl.elem0.loc16_3
+// CHECK:STDOUT:   %specific_fn.loc16_3: <specific function> = specific_function %impl.elem0.loc16_3, @Op.3(constants.%array_type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %x.var, %specific_fn.loc16_3
+// CHECK:STDOUT:   %addr: %ptr.260 = addr_of %x.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc16_3.2(%addr)
 // CHECK:STDOUT:   return %.loc17_10
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 74 - 27
toolchain/check/testdata/if_expr/constant_condition.carbon

@@ -40,6 +40,7 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -77,8 +78,26 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:   %false: bool = bool_literal false [concrete]
 // CHECK:STDOUT:   %Constant.type: type = fn_type @Constant [concrete]
 // CHECK:STDOUT:   %Constant: %Constant.type = struct_value () [concrete]
-// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]
-// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.711: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Op.type.ba2: type = fn_type @Op.3, @impl.49c(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Op.649: %Op.type.ba2 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.5d5: type = ptr_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2bf: %Destroy.type = facet_value %ptr.235, (%Destroy.impl_witness.711) [concrete]
+// CHECK:STDOUT:   %.a79: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.2bf [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.829: <specific function> = specific_function %Op.649, @Op.3(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5f7: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.5f7 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.014: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT:   %PartiallyConstant.type: type = fn_type @PartiallyConstant [concrete]
 // CHECK:STDOUT:   %PartiallyConstant: %PartiallyConstant.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -87,6 +106,7 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -94,6 +114,9 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -249,10 +272,10 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc27_3.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc27_3.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc27_3.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc27_3.1: <bound method> = bound_method %int_1, %impl.elem0.loc27_3.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc27_3.1: <specific function> = specific_function %impl.elem0.loc27_3.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc27_3.2: <bound method> = bound_method %int_1, %specific_fn.loc27_3.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc27_3.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc27_3: init %i32 = converted %int_1, %int.convert_checked [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %v.var, %.loc27_3
@@ -270,7 +293,7 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT: !if.expr.else.loc27:
 // CHECK:STDOUT:   %int_32.loc27_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32.loc27_32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:   %ptr.loc27: type = ptr_type %i32.loc27_32 [concrete = constants.%ptr]
+// CHECK:STDOUT:   %ptr.loc27: type = ptr_type %i32.loc27_32 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   br !if.expr.result.loc27(%ptr.loc27)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result.loc27:
@@ -283,10 +306,10 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:     %w.patt: %pattern_type.fe8 = binding_pattern w [concrete]
 // CHECK:STDOUT:     %w.var_patt: %pattern_type.fe8 = var_pattern %w.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %w.var: ref %ptr = var %w.var_patt
+// CHECK:STDOUT:   %w.var: ref %ptr.235 = var %w.var_patt
 // CHECK:STDOUT:   %v.ref: ref %i32 = name_ref v, %v
-// CHECK:STDOUT:   %addr: %ptr = addr_of %v.ref
-// CHECK:STDOUT:   assign %w.var, %addr
+// CHECK:STDOUT:   %addr.loc28_40: %ptr.235 = addr_of %v.ref
+// CHECK:STDOUT:   assign %w.var, %addr.loc28_40
 // CHECK:STDOUT:   br !.loc28_13
 // CHECK:STDOUT:
 // CHECK:STDOUT: !.loc28_13:
@@ -301,19 +324,31 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT: !if.expr.else.loc28:
 // CHECK:STDOUT:   %int_32.loc28_33: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32.loc28_33: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:   %ptr.loc28: type = ptr_type %i32.loc28_33 [concrete = constants.%ptr]
+// CHECK:STDOUT:   %ptr.loc28: type = ptr_type %i32.loc28_33 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   br !if.expr.result.loc28(%ptr.loc28)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result.loc28:
-// CHECK:STDOUT:   %.loc28: type = block_arg !if.expr.result.loc28 [concrete = constants.%ptr]
+// CHECK:STDOUT:   %.loc28: type = block_arg !if.expr.result.loc28 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   br !.loc28_7
 // CHECK:STDOUT:
 // CHECK:STDOUT: !.loc28_7:
-// CHECK:STDOUT:   %w: ref %ptr = bind_name w, %w.var
-// CHECK:STDOUT:   %w.ref: ref %ptr = name_ref w, %w
-// CHECK:STDOUT:   %.loc29_11: %ptr = bind_value %w.ref
+// CHECK:STDOUT:   %w: ref %ptr.235 = bind_name w, %w.var
+// CHECK:STDOUT:   %w.ref: ref %ptr.235 = name_ref w, %w
+// CHECK:STDOUT:   %.loc29_11: %ptr.235 = bind_value %w.ref
 // CHECK:STDOUT:   %.loc29_10.1: ref %i32 = deref %.loc29_11
 // CHECK:STDOUT:   %.loc29_10.2: %i32 = bind_value %.loc29_10.1
+// CHECK:STDOUT:   %impl.elem0.loc28: %.a79 = impl_witness_access constants.%Destroy.impl_witness.711, element0 [concrete = constants.%Op.649]
+// CHECK:STDOUT:   %bound_method.loc28_3.1: <bound method> = bound_method %w.var, %impl.elem0.loc28
+// CHECK:STDOUT:   %specific_fn.loc28: <specific function> = specific_function %impl.elem0.loc28, @Op.3(constants.%ptr.235) [concrete = constants.%Op.specific_fn.829]
+// CHECK:STDOUT:   %bound_method.loc28_3.2: <bound method> = bound_method %w.var, %specific_fn.loc28
+// CHECK:STDOUT:   %addr.loc28_3: %ptr.5d5 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc28: init %empty_tuple.type = call %bound_method.loc28_3.2(%addr.loc28_3)
+// CHECK:STDOUT:   %impl.elem0.loc27_3.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc27_3.3: <bound method> = bound_method %v.var, %impl.elem0.loc27_3.2
+// CHECK:STDOUT:   %specific_fn.loc27_3.2: <specific function> = specific_function %impl.elem0.loc27_3.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn.014]
+// CHECK:STDOUT:   %bound_method.loc27_3.4: <bound method> = bound_method %v.var, %specific_fn.loc27_3.2
+// CHECK:STDOUT:   %addr.loc27: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc27: init %empty_tuple.type = call %bound_method.loc27_3.4(%addr.loc27)
 // CHECK:STDOUT:   return %.loc29_10.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -325,10 +360,10 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc33_3.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc33_3.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc33_3.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc33_3.1: <bound method> = bound_method %int_1, %impl.elem0.loc33_3.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc33_3.1: <specific function> = specific_function %impl.elem0.loc33_3.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc33_3.2: <bound method> = bound_method %int_1, %specific_fn.loc33_3.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc33_3.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc33_3: init %i32 = converted %int_1, %int.convert_checked [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %v.var, %.loc33_3
@@ -357,10 +392,10 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT:     %w.patt: %pattern_type.fe8 = binding_pattern w [concrete]
 // CHECK:STDOUT:     %w.var_patt: %pattern_type.fe8 = var_pattern %w.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %w.var: ref %ptr = var %w.var_patt
+// CHECK:STDOUT:   %w.var: ref %ptr.235 = var %w.var_patt
 // CHECK:STDOUT:   %v.ref: ref %i32 = name_ref v, %v
-// CHECK:STDOUT:   %addr: %ptr = addr_of %v.ref
-// CHECK:STDOUT:   assign %w.var, %addr
+// CHECK:STDOUT:   %addr.loc34_38: %ptr.235 = addr_of %v.ref
+// CHECK:STDOUT:   assign %w.var, %addr.loc34_38
 // CHECK:STDOUT:   br !.loc34_13
 // CHECK:STDOUT:
 // CHECK:STDOUT: !.loc34_13:
@@ -374,19 +409,31 @@ fn PartiallyConstant(t: type) -> i32 {
 // CHECK:STDOUT: !if.expr.else.loc34:
 // CHECK:STDOUT:   %int_32.loc34: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32.loc34: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:   %ptr: type = ptr_type %i32.loc34 [concrete = constants.%ptr]
+// CHECK:STDOUT:   %ptr: type = ptr_type %i32.loc34 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   br !if.expr.result.loc34(%ptr)
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.expr.result.loc34:
-// CHECK:STDOUT:   %.loc34: type = block_arg !if.expr.result.loc34 [concrete = constants.%ptr]
+// CHECK:STDOUT:   %.loc34: type = block_arg !if.expr.result.loc34 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   br !.loc34_7
 // CHECK:STDOUT:
 // CHECK:STDOUT: !.loc34_7:
-// CHECK:STDOUT:   %w: ref %ptr = bind_name w, %w.var
-// CHECK:STDOUT:   %w.ref: ref %ptr = name_ref w, %w
-// CHECK:STDOUT:   %.loc35_11: %ptr = bind_value %w.ref
+// CHECK:STDOUT:   %w: ref %ptr.235 = bind_name w, %w.var
+// CHECK:STDOUT:   %w.ref: ref %ptr.235 = name_ref w, %w
+// CHECK:STDOUT:   %.loc35_11: %ptr.235 = bind_value %w.ref
 // CHECK:STDOUT:   %.loc35_10.1: ref %i32 = deref %.loc35_11
 // CHECK:STDOUT:   %.loc35_10.2: %i32 = bind_value %.loc35_10.1
+// CHECK:STDOUT:   %impl.elem0.loc34: %.a79 = impl_witness_access constants.%Destroy.impl_witness.711, element0 [concrete = constants.%Op.649]
+// CHECK:STDOUT:   %bound_method.loc34_3.1: <bound method> = bound_method %w.var, %impl.elem0.loc34
+// CHECK:STDOUT:   %specific_fn.loc34: <specific function> = specific_function %impl.elem0.loc34, @Op.3(constants.%ptr.235) [concrete = constants.%Op.specific_fn.829]
+// CHECK:STDOUT:   %bound_method.loc34_3.2: <bound method> = bound_method %w.var, %specific_fn.loc34
+// CHECK:STDOUT:   %addr.loc34_3: %ptr.5d5 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc34: init %empty_tuple.type = call %bound_method.loc34_3.2(%addr.loc34_3)
+// CHECK:STDOUT:   %impl.elem0.loc33_3.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc33_3.3: <bound method> = bound_method %v.var, %impl.elem0.loc33_3.2
+// CHECK:STDOUT:   %specific_fn.loc33_3.2: <specific function> = specific_function %impl.elem0.loc33_3.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn.014]
+// CHECK:STDOUT:   %bound_method.loc33_3.4: <bound method> = bound_method %v.var, %specific_fn.loc33_3.2
+// CHECK:STDOUT:   %addr.loc33: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc33: init %empty_tuple.type = call %bound_method.loc33_3.4(%addr.loc33)
 // CHECK:STDOUT:   return %.loc35_10.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 41 - 0
toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon

@@ -337,6 +337,18 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %J.facet.67f: %J.type = facet_value %FDifferentReturnType, (%J.impl_witness.bc1) [concrete]
 // CHECK:STDOUT:   %F.type.d3b58f.2: type = fn_type @F.19 [concrete]
 // CHECK:STDOUT:   %F.be86c9.2: %F.type.d3b58f.2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1f3: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%FDifferentReturnType) [concrete]
+// CHECK:STDOUT:   %Op.type.3d3: type = fn_type @Op.2, @impl.49c(%FDifferentReturnType) [concrete]
+// CHECK:STDOUT:   %Op.ddd: %Op.type.3d3 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.954: type = ptr_type %FDifferentReturnType [concrete]
+// CHECK:STDOUT:   %Destroy.facet.ada: %Destroy.type = facet_value %FDifferentReturnType, (%Destroy.impl_witness.1f3) [concrete]
+// CHECK:STDOUT:   %.04a: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.ada [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.b4b: <specific function> = specific_function %Op.ddd, @Op.2(%FDifferentReturnType) [concrete]
 // CHECK:STDOUT:   %SelfNested.type: type = facet_type <@SelfNested> [concrete]
 // CHECK:STDOUT:   %Self.2ff: %SelfNested.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %Self.as_type.e1e: type = facet_access_type %Self.2ff [symbolic]
@@ -372,6 +384,13 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %pattern_type.a5c: type = pattern_type %tuple.type.9c9 [concrete]
 // CHECK:STDOUT:   %F.type.f90165.2: type = fn_type @F.22 [concrete]
 // CHECK:STDOUT:   %F.fa8d04.2: %F.type.f90165.2 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.f40: type = ptr_type %array_type.a41 [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.de1: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%array_type.a41) [concrete]
+// CHECK:STDOUT:   %Op.type.ba3: type = fn_type @Op.2, @impl.49c(%array_type.a41) [concrete]
+// CHECK:STDOUT:   %Op.d25: %Op.type.ba3 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.158: %Destroy.type = facet_value %array_type.a41, (%Destroy.impl_witness.de1) [concrete]
+// CHECK:STDOUT:   %.bb0: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.158 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.235: <specific function> = specific_function %Op.d25, @Op.2(%array_type.a41) [concrete]
 // CHECK:STDOUT:   %SelfNestedBadReturnType: type = class_type @SelfNestedBadReturnType [concrete]
 // CHECK:STDOUT:   %SelfNested.impl_witness.d5e: <witness> = impl_witness @SelfNestedBadReturnType.%SelfNested.impl_witness_table [concrete]
 // CHECK:STDOUT:   %ptr.612: type = ptr_type %SelfNestedBadReturnType [concrete]
@@ -391,12 +410,16 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Bool = %Core.Bool
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1305,6 +1328,12 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %.loc200_38.1: ref %FDifferentReturnType = temporary_storage
 // CHECK:STDOUT:   %F.call: init %FDifferentReturnType = call %F.bound(%self.ref, %b.ref) to %.loc200_38.1
 // CHECK:STDOUT:   %.loc200_38.2: bool = converted %F.call, <error> [concrete = <error>]
+// CHECK:STDOUT:   %impl.elem0: %.04a = impl_witness_access constants.%Destroy.impl_witness.1f3, element0 [concrete = constants.%Op.ddd]
+// CHECK:STDOUT:   %bound_method.loc200_38.1: <bound method> = bound_method %.loc200_38.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%FDifferentReturnType) [concrete = constants.%Op.specific_fn.b4b]
+// CHECK:STDOUT:   %bound_method.loc200_38.2: <bound method> = bound_method %.loc200_38.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.954 = addr_of %.loc200_38.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc200_38.2(%addr)
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1334,6 +1363,12 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %.loc211_9.1: %SelfNestedBadParam = struct_access %tuple.elem1, element0
 // CHECK:STDOUT:   %.loc211_9.2: %i32 = converted %.loc211_9.1, <error> [concrete = <error>]
 // CHECK:STDOUT:   %F.call: init %array_type.a41 = call %F.ref(<error>) to %.loc211_41
+// CHECK:STDOUT:   %impl.elem0: %.bb0 = impl_witness_access constants.%Destroy.impl_witness.de1, element0 [concrete = constants.%Op.d25]
+// CHECK:STDOUT:   %bound_method.loc211_41.1: <bound method> = bound_method %.loc211_41, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%array_type.a41) [concrete = constants.%Op.specific_fn.235]
+// CHECK:STDOUT:   %bound_method.loc211_41.2: <bound method> = bound_method %.loc211_41, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.f40 = addr_of %.loc211_41
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc211_41.2(%addr)
 // CHECK:STDOUT:   return %F.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1347,6 +1382,12 @@ class SelfNestedBadReturnType {
 // CHECK:STDOUT:   %.loc239_112.1: ref %array_type.a41 = temporary_storage
 // CHECK:STDOUT:   %F.call: init %array_type.a41 = call %F.ref(%x.ref) to %.loc239_112.1
 // CHECK:STDOUT:   %.loc239_112.2: %array_type.126 = converted %F.call, <error> [concrete = <error>]
+// CHECK:STDOUT:   %impl.elem0: %.bb0 = impl_witness_access constants.%Destroy.impl_witness.de1, element0 [concrete = constants.%Op.d25]
+// CHECK:STDOUT:   %bound_method.loc239_112.1: <bound method> = bound_method %.loc239_112.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%array_type.a41) [concrete = constants.%Op.specific_fn.235]
+// CHECK:STDOUT:   %bound_method.loc239_112.2: <bound method> = bound_method %.loc239_112.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.f40 = addr_of %.loc239_112.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc239_112.2(%addr)
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 2
toolchain/check/testdata/impl/generic_redeclaration.carbon

@@ -555,7 +555,7 @@ impl forall [T:! type] T as I {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.826: %I.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl.2caff2.1(%T) [symbolic]
@@ -571,13 +571,28 @@ impl forall [T:! type] T as I {
 // CHECK:STDOUT:   %D: %D.type = struct_value () [symbolic]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
 // CHECK:STDOUT:   %C.specific_fn: <specific function> = specific_function %C, @C(%T) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -606,7 +621,7 @@ impl forall [T:! type] T as I {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @I {
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.826]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self
@@ -717,6 +732,12 @@ impl forall [T:! type] T as I {
 // CHECK:STDOUT:     %.loc21_14.2: ref %empty_tuple.type = temporary %.loc21_14.1, %C.call
 // CHECK:STDOUT:     %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:     %.loc21_15: %empty_tuple.type = converted %C.call, %tuple [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:     %impl.elem0: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:     %bound_method.loc21_14.1: <bound method> = bound_method %.loc21_14.1, %impl.elem0
+// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:     %bound_method.loc21_14.2: <bound method> = bound_method %.loc21_14.1, %specific_fn
+// CHECK:STDOUT:     %addr: %ptr.843 = addr_of %.loc21_14.1
+// CHECK:STDOUT:     %no_op: init %empty_tuple.type = call %bound_method.loc21_14.2(%addr)
 // CHECK:STDOUT:     return %.loc21_15
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }

+ 71 - 9
toolchain/check/testdata/impl/impl_thunk.carbon

@@ -329,12 +329,26 @@ impl () as I({}) {
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
 // CHECK:STDOUT:   %struct: %struct_type.c.d.15a = struct_value (%empty_tuple, %empty_struct) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.626: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%struct_type.d.c.b36) [concrete]
+// CHECK:STDOUT:   %Op.type.afe: type = fn_type @Op.2, @impl.49c(%struct_type.d.c.b36) [concrete]
+// CHECK:STDOUT:   %Op.742: %Op.type.afe = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.eab: type = ptr_type %struct_type.d.c.b36 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %struct_type.d.c.b36, (%Destroy.impl_witness.626) [concrete]
+// CHECK:STDOUT:   %.fa5: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.742, @Op.2(%struct_type.d.c.b36) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc8_7.2 as %I.ref {
+// CHECK:STDOUT: impl @impl.4ab: %.loc8_7.2 as %I.ref {
 // CHECK:STDOUT:   %F.decl.loc10_48.1: %F.type.39e918.1 = fn_decl @F.2 [concrete = constants.%F.c04b92.1] {
 // CHECK:STDOUT:     %y.patt: %pattern_type.231 = binding_pattern y [concrete]
 // CHECK:STDOUT:     %y.param_patt: %pattern_type.231 = value_param_pattern %y.patt, call_param0 [concrete]
@@ -371,9 +385,9 @@ impl () as I({}) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2(%y.param: %struct_type.b.a.40c) -> %return.param: %struct_type.d.c.b36;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.3(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a [thunk @impl.%F.decl.loc10_48.1] {
+// CHECK:STDOUT: fn @F.3(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a [thunk @impl.4ab.%F.decl.loc10_48.1] {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %F.ref: %F.type.39e918.1 = name_ref F, @impl.%F.decl.loc10_48.1 [concrete = constants.%F.c04b92.1]
+// CHECK:STDOUT:   %F.ref: %F.type.39e918.1 = name_ref F, @impl.4ab.%F.decl.loc10_48.1 [concrete = constants.%F.c04b92.1]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %.loc10_48.1: ref %struct_type.d.c.b36 = temporary_storage
 // CHECK:STDOUT:   <elided>
@@ -389,6 +403,12 @@ impl () as I({}) {
 // CHECK:STDOUT:   %.loc10_48.10: init %empty_struct_type = converted %.loc10_48.7, %.loc10_48.9 [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc10_48.11: init %struct_type.c.d.15a = struct_init (%.loc10_48.6, %.loc10_48.10) to %return [concrete = constants.%struct]
 // CHECK:STDOUT:   %.loc10_48.12: init %struct_type.c.d.15a = converted %F.call, %.loc10_48.11 [concrete = constants.%struct]
+// CHECK:STDOUT:   %impl.elem0: %.fa5 = impl_witness_access constants.%Destroy.impl_witness.626, element0 [concrete = constants.%Op.742]
+// CHECK:STDOUT:   %bound_method.loc10_48.1: <bound method> = bound_method %.loc10_48.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%struct_type.d.c.b36) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc10_48.2: <bound method> = bound_method %.loc10_48.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.eab = addr_of %.loc10_48.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc10_48.2(%addr)
 // CHECK:STDOUT:   return %.loc10_48.12 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -609,17 +629,32 @@ impl () as I({}) {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %A: type = class_type @A [concrete]
 // CHECK:STDOUT:   %B: type = class_type @B [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %pattern_type.049: type = pattern_type %B [concrete]
 // CHECK:STDOUT:   %F.type.b24d6f.1: type = fn_type @F.2 [concrete]
 // CHECK:STDOUT:   %F.77e9d5.1: %F.type.b24d6f.1 = struct_value () [concrete]
 // CHECK:STDOUT:   %F.type.b24d6f.2: type = fn_type @F.3 [concrete]
 // CHECK:STDOUT:   %F.77e9d5.2: %F.type.b24d6f.2 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.39d: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.type.1a6: type = fn_type @Op.2, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.3c2: %Op.type.1a6 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.e79: type = ptr_type %B [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %B, (%Destroy.impl_witness.39d) [concrete]
+// CHECK:STDOUT:   %.c16: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.3c2, @Op.2(%B) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %A.ref as %X.ref {
+// CHECK:STDOUT: impl @impl.3d2: %A.ref as %X.ref {
 // CHECK:STDOUT:   %F.decl.loc20_14.1: %F.type.b24d6f.1 = fn_decl @F.2 [concrete = constants.%F.77e9d5.1] {
 // CHECK:STDOUT:     %return.patt: %pattern_type.049 = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: %pattern_type.049 = out_param_pattern %return.patt, call_param0 [concrete]
@@ -642,9 +677,9 @@ impl () as I({}) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2() -> %return.param: %B;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.3() -> %return.param: %A [thunk @impl.%F.decl.loc20_14.1] {
+// CHECK:STDOUT: fn @F.3() -> %return.param: %A [thunk @impl.3d2.%F.decl.loc20_14.1] {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %F.ref: %F.type.b24d6f.1 = name_ref F, @impl.%F.decl.loc20_14.1 [concrete = constants.%F.77e9d5.1]
+// CHECK:STDOUT:   %F.ref: %F.type.b24d6f.1 = name_ref F, @impl.3d2.%F.decl.loc20_14.1 [concrete = constants.%F.77e9d5.1]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %.loc20_14.1: ref %B = temporary_storage
 // CHECK:STDOUT:   %F.call: init %B = call %F.ref() to %.loc20_14.1
@@ -652,6 +687,12 @@ impl () as I({}) {
 // CHECK:STDOUT:   %.loc20_14.3: ref %A = class_element_access %.loc20_14.2, element0
 // CHECK:STDOUT:   %.loc20_14.4: ref %A = converted %F.call, %.loc20_14.3
 // CHECK:STDOUT:   %.loc20_14.5: %A = bind_value %.loc20_14.4
+// CHECK:STDOUT:   %impl.elem0: %.c16 = impl_witness_access constants.%Destroy.impl_witness.39d, element0 [concrete = constants.%Op.3c2]
+// CHECK:STDOUT:   %bound_method.loc20_14.1: <bound method> = bound_method %.loc20_14.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%B) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc20_14.2: <bound method> = bound_method %.loc20_14.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e79 = addr_of %.loc20_14.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc20_14.2(%addr)
 // CHECK:STDOUT:   return <error> to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -852,6 +893,8 @@ impl () as I({}) {
 // CHECK:STDOUT: --- generic_interface.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %struct_type.b.a.1b0: type = struct_type {.b: %empty_struct_type, .a: %empty_struct_type} [concrete]
 // CHECK:STDOUT:   %pattern_type.914: type = pattern_type %struct_type.b.a.1b0 [concrete]
@@ -862,12 +905,25 @@ impl () as I({}) {
 // CHECK:STDOUT:   %F.975709.2: %F.type.29ab63.2 = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
 // CHECK:STDOUT:   %struct: %struct_type.a.b.f95 = struct_value (%empty_struct, %empty_struct) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.879: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%struct_type.b.a.1b0) [concrete]
+// CHECK:STDOUT:   %Op.type.f20: type = fn_type @Op.2, @impl.49c(%struct_type.b.a.1b0) [concrete]
+// CHECK:STDOUT:   %Op.eab: %Op.type.f20 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.30d: type = ptr_type %struct_type.b.a.1b0 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %struct_type.b.a.1b0, (%Destroy.impl_witness.879) [concrete]
+// CHECK:STDOUT:   %.49e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.eab, @Op.2(%struct_type.b.a.1b0) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc8_7.2 as %I.type {
+// CHECK:STDOUT: impl @impl.50b: %.loc8_7.2 as %I.type {
 // CHECK:STDOUT:   %F.decl.loc10_29.1: %F.type.29ab63.1 = fn_decl @F.2 [concrete = constants.%F.975709.1] {
 // CHECK:STDOUT:     %return.patt: %pattern_type.914 = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: %pattern_type.914 = out_param_pattern %return.patt, call_param0 [concrete]
@@ -893,9 +949,9 @@ impl () as I({}) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2() -> %return.param: %struct_type.b.a.1b0;
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.3() -> %return.param: %struct_type.a.b.f95 [thunk @impl.%F.decl.loc10_29.1] {
+// CHECK:STDOUT: fn @F.3() -> %return.param: %struct_type.a.b.f95 [thunk @impl.50b.%F.decl.loc10_29.1] {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %F.ref: %F.type.29ab63.1 = name_ref F, @impl.%F.decl.loc10_29.1 [concrete = constants.%F.975709.1]
+// CHECK:STDOUT:   %F.ref: %F.type.29ab63.1 = name_ref F, @impl.50b.%F.decl.loc10_29.1 [concrete = constants.%F.975709.1]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %.loc10_29.1: ref %struct_type.b.a.1b0 = temporary_storage
 // CHECK:STDOUT:   %F.call: init %struct_type.b.a.1b0 = call %F.ref() to %.loc10_29.1
@@ -910,6 +966,12 @@ impl () as I({}) {
 // CHECK:STDOUT:   %.loc10_29.10: init %empty_struct_type = converted %.loc10_29.7, %.loc10_29.9 [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc10_29.11: init %struct_type.a.b.f95 = struct_init (%.loc10_29.6, %.loc10_29.10) to %return [concrete = constants.%struct]
 // CHECK:STDOUT:   %.loc10_29.12: init %struct_type.a.b.f95 = converted %F.call, %.loc10_29.11 [concrete = constants.%struct]
+// CHECK:STDOUT:   %impl.elem0: %.49e = impl_witness_access constants.%Destroy.impl_witness.879, element0 [concrete = constants.%Op.eab]
+// CHECK:STDOUT:   %bound_method.loc10_29.1: <bound method> = bound_method %.loc10_29.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%struct_type.b.a.1b0) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc10_29.2: <bound method> = bound_method %.loc10_29.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.30d = addr_of %.loc10_29.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc10_29.2(%addr)
 // CHECK:STDOUT:   return %.loc10_29.12 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 43 - 21
toolchain/check/testdata/impl/import_self.carbon

@@ -120,11 +120,11 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Add.type: type = facet_type <@Add> [concrete]
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.b3d: %Add.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %Op.type.31b: type = fn_type @Op.1 [concrete]
 // CHECK:STDOUT:   %Op.d59: %Op.type.31b = struct_value () [concrete]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic]
-// CHECK:STDOUT:   %pattern_type.8f9: type = pattern_type %Self.as_type [symbolic]
+// CHECK:STDOUT:   %Self.as_type.f73: type = facet_access_type %Self.b3d [symbolic]
+// CHECK:STDOUT:   %pattern_type.8f9: type = pattern_type %Self.as_type.f73 [symbolic]
 // CHECK:STDOUT:   %Add.impl_witness: <witness> = impl_witness file.%Add.impl_witness_table [concrete]
 // CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]
 // CHECK:STDOUT:   %Op.type.adf: type = fn_type @Op.2 [concrete]
@@ -134,21 +134,37 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %Add.assoc_type: type = assoc_entity_type @Add [concrete]
-// CHECK:STDOUT:   %assoc0: %Add.assoc_type = assoc_entity element0, imports.%Main.import_ref.5a3 [concrete]
+// CHECK:STDOUT:   %assoc0.5ca: %Add.assoc_type = assoc_entity element0, imports.%Main.import_ref.5a3 [concrete]
 // CHECK:STDOUT:   %.59e: type = fn_type_with_self_type %Op.type.31b, %Add.facet [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.3 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.4, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.4, @impl.49c(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.4(%empty_tuple.type) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Main.Add: type = import_ref Main//a, Add, loaded [concrete = constants.%Add.type]
 // 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:   %Main.import_ref.07c = import_ref Main//a, inst19 [no loc], unloaded
-// CHECK:STDOUT:   %Main.import_ref.f99: %Add.assoc_type = import_ref Main//a, loc5_41, loaded [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %Main.import_ref.f99: %Add.assoc_type = import_ref Main//a, loc5_41, loaded [concrete = constants.%assoc0.5ca]
 // CHECK:STDOUT:   %Main.Op: %Op.type.31b = import_ref Main//a, Op, loaded [concrete = constants.%Op.d59]
-// CHECK:STDOUT:   %Main.import_ref.e5e: %Add.type = import_ref Main//a, inst19 [no loc], loaded [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Main.import_ref.e5e: %Add.type = import_ref Main//a, inst19 [no loc], loaded [symbolic = constants.%Self.b3d]
 // CHECK:STDOUT:   %Main.import_ref.5a3: %Op.type.31b = import_ref Main//a, loc5_41, loaded [concrete = constants.%Op.d59]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -159,12 +175,12 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %default.import = import <none>
-// CHECK:STDOUT:   impl_decl @impl [concrete] {} {
+// CHECK:STDOUT:   impl_decl @impl.d68 [concrete] {} {
 // CHECK:STDOUT:     %.loc6_7.1: %empty_tuple.type = tuple_literal ()
 // CHECK:STDOUT:     %.loc6_7.2: type = converted %.loc6_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %Add.ref: type = name_ref Add, imports.%Main.Add [concrete = constants.%Add.type]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %Add.impl_witness_table = impl_witness_table (@impl.%Op.decl), @impl [concrete]
+// CHECK:STDOUT:   %Add.impl_witness_table = impl_witness_table (@impl.d68.%Op.decl), @impl.d68 [concrete]
 // CHECK:STDOUT:   %Add.impl_witness: <witness> = impl_witness %Add.impl_witness_table [concrete = constants.%Add.impl_witness]
 // CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
 // CHECK:STDOUT:     %x.patt: %pattern_type.cb1 = binding_pattern x [concrete]
@@ -200,7 +216,7 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT:   witness = (imports.%Main.Op)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: %.loc6_7.2 as %Add.ref {
+// CHECK:STDOUT: impl @impl.d68: %.loc6_7.2 as %Add.ref {
 // CHECK:STDOUT:   %Op.decl: %Op.type.adf = fn_decl @Op.2 [concrete = constants.%Op.489] {
 // CHECK:STDOUT:     %self.patt: %pattern_type.cb1 = binding_pattern self [concrete]
 // CHECK:STDOUT:     %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt, call_param0 [concrete]
@@ -209,12 +225,12 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt, call_param2 [concrete]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref.loc7_37: type = name_ref Self, @impl.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %Self.ref.loc7_37: type = name_ref Self, @impl.d68.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %self.param: %empty_tuple.type = value_param call_param0
-// CHECK:STDOUT:     %Self.ref.loc7_15: type = name_ref Self, @impl.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %Self.ref.loc7_15: type = name_ref Self, @impl.d68.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %self: %empty_tuple.type = bind_name self, %self.param
 // CHECK:STDOUT:     %other.param: %empty_tuple.type = value_param call_param1
-// CHECK:STDOUT:     %Self.ref.loc7_28: type = name_ref Self, @impl.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
+// CHECK:STDOUT:     %Self.ref.loc7_28: type = name_ref Self, @impl.d68.%.loc6_7.2 [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:     %other: %empty_tuple.type = bind_name other, %other.param
 // CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param2
 // CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param
@@ -226,8 +242,8 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @Op.1(imports.%Main.import_ref.e5e: %Add.type) [from "a.carbon"] {
-// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type)]
+// CHECK:STDOUT:   %Self: %Add.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.b3d)]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type.f73)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.as_type [symbolic = %pattern_type (constants.%pattern_type.8f9)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn;
@@ -245,21 +261,27 @@ fn F(x: (), y: ()) -> () {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %x.ref: %empty_tuple.type = name_ref x, %x
 // CHECK:STDOUT:   %Add.ref: type = name_ref Add, imports.%Main.Add [concrete = constants.%Add.type]
-// CHECK:STDOUT:   %Op.ref: %Add.assoc_type = name_ref Op, imports.%Main.import_ref.f99 [concrete = constants.%assoc0]
-// CHECK:STDOUT:   %impl.elem0: %.59e = impl_witness_access constants.%Add.impl_witness, element0 [concrete = constants.%Op.489]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %x.ref, %impl.elem0
+// CHECK:STDOUT:   %Op.ref: %Add.assoc_type = name_ref Op, imports.%Main.import_ref.f99 [concrete = constants.%assoc0.5ca]
+// CHECK:STDOUT:   %impl.elem0.loc11_11: %.59e = impl_witness_access constants.%Add.impl_witness, element0 [concrete = constants.%Op.489]
+// CHECK:STDOUT:   %bound_method.loc11_11: <bound method> = bound_method %x.ref, %impl.elem0.loc11_11
 // CHECK:STDOUT:   %y.ref: %empty_tuple.type = name_ref y, %y
-// CHECK:STDOUT:   %Op.call: init %empty_tuple.type = call %bound_method(%x.ref, %y.ref)
+// CHECK:STDOUT:   %Op.call: init %empty_tuple.type = call %bound_method.loc11_11(%x.ref, %y.ref)
 // CHECK:STDOUT:   %.loc11_22.1: ref %empty_tuple.type = temporary_storage
 // CHECK:STDOUT:   %.loc11_22.2: ref %empty_tuple.type = temporary %.loc11_22.1, %Op.call
 // CHECK:STDOUT:   %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
 // CHECK:STDOUT:   %.loc11_23: %empty_tuple.type = converted %Op.call, %tuple [concrete = constants.%empty_tuple]
+// CHECK:STDOUT:   %impl.elem0.loc11_22: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:   %bound_method.loc11_22.1: <bound method> = bound_method %.loc11_22.1, %impl.elem0.loc11_22
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0.loc11_22, @Op.4(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_22.2: <bound method> = bound_method %.loc11_22.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %.loc11_22.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc11_22.2(%addr)
 // CHECK:STDOUT:   return %.loc11_23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Op.1(constants.%Self) {
-// CHECK:STDOUT:   %Self => constants.%Self
-// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type
+// CHECK:STDOUT: specific @Op.1(constants.%Self.b3d) {
+// CHECK:STDOUT:   %Self => constants.%Self.b3d
+// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type.f73
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.8f9
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 99 - 47
toolchain/check/testdata/impl/import_thunk.carbon

@@ -111,32 +111,48 @@ fn G() {
 // CHECK:STDOUT:   %Y: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic]
 // CHECK:STDOUT:   %C.13320f.2: type = class_type @C, @C(%Y) [symbolic]
 // CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]
-// CHECK:STDOUT:   %Self: %I.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.826: %I.type = bind_symbolic_name Self, 0 [symbolic]
 // CHECK:STDOUT:   %F.type.cf0: type = fn_type @F.1 [concrete]
 // CHECK:STDOUT:   %F.bc6: %F.type.cf0 = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]
-// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl(%Y) [symbolic]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl.22b(%Y) [symbolic]
 // CHECK:STDOUT:   %pattern_type.ccc: type = pattern_type %C.13320f.2 [symbolic]
-// CHECK:STDOUT:   %F.type.0daaa1.1: type = fn_type @F.2, @impl(%Y) [symbolic]
+// CHECK:STDOUT:   %F.type.0daaa1.1: type = fn_type @F.2, @impl.22b(%Y) [symbolic]
 // CHECK:STDOUT:   %F.49c1ac.1: %F.type.0daaa1.1 = struct_value () [symbolic]
 // CHECK:STDOUT:   %I.facet: %I.type = facet_value %C.13320f.2, (%I.impl_witness) [symbolic]
-// CHECK:STDOUT:   %F.type.0daaa1.2: type = fn_type @F.3, @impl(%Y) [symbolic]
+// CHECK:STDOUT:   %F.type.0daaa1.2: type = fn_type @F.3, @impl.22b(%Y) [symbolic]
 // CHECK:STDOUT:   %F.49c1ac.2: %F.type.0daaa1.2 = struct_value () [symbolic]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.13320f.2 [symbolic]
+// CHECK:STDOUT:   %require_complete.a35: <witness> = require_complete_type %C.13320f.2 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.49c1ac.1, @F.2(%Y) [symbolic]
 // CHECK:STDOUT:   %C.val: %C.13320f.2 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Destroy.assoc_type: type = assoc_entity_type @Destroy [concrete]
+// CHECK:STDOUT:   %assoc0: %Destroy.assoc_type = assoc_entity element0, imports.%Core.import_ref.725 [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.651: %Op.type.bae = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.40d: type = ptr_type %C.13320f.2 [symbolic]
+// CHECK:STDOUT:   %require_complete.0b0: <witness> = require_complete_type %ptr.40d [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C.13320f.2, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C.13320f.2, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %.97f: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.97f = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet) [symbolic]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Main.I: type = import_ref Main//a, I, loaded [concrete = constants.%I.type]
 // 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:   %Main.import_ref.e5d = import_ref Main//a, inst19 [no loc], unloaded
 // CHECK:STDOUT:   %Main.import_ref.507 = import_ref Main//a, loc5_14, unloaded
 // CHECK:STDOUT:   %Main.F: %F.type.cf0 = import_ref Main//a, F, loaded [concrete = constants.%F.bc6]
-// CHECK:STDOUT:   %Main.import_ref.5dd: %I.type = import_ref Main//a, inst19 [no loc], loaded [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Main.import_ref.5dd: %I.type = import_ref Main//a, inst19 [no loc], loaded [symbolic = constants.%Self.826]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.f99: %Destroy.assoc_type = import_ref Core//prelude/parts/destroy, loc5_28, loaded [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %Core.import_ref.725: %Op.type.bae = import_ref Core//prelude/parts/destroy, loc5_28, loaded [concrete = constants.%Op.651]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -156,7 +172,7 @@ fn G() {
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %X.loc5_9.1: %empty_tuple.type = bind_symbolic_name X, 0 [symbolic = %X.loc5_9.2 (constants.%X)]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:   impl_decl @impl.22b [concrete] {
 // CHECK:STDOUT:     %Y.patt: %pattern_type.cb1 = symbolic_binding_pattern Y, 0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
@@ -169,8 +185,8 @@ fn G() {
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:     %Y.loc7_14.1: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic = %Y.loc7_14.2 (constants.%Y)]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (@impl.%F.decl.loc8_17.2), @impl [concrete]
-// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table, @impl(constants.%Y) [symbolic = @impl.%I.impl_witness (constants.%I.impl_witness)]
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (@impl.22b.%F.decl.loc8_17.2), @impl.22b [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table, @impl.22b(constants.%Y) [symbolic = @impl.22b.%I.impl_witness (constants.%I.impl_witness)]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @I [from "a.carbon"] {
@@ -180,31 +196,31 @@ fn G() {
 // CHECK:STDOUT:   witness = (imports.%Main.F)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic impl @impl(%Y.loc7_14.1: %empty_tuple.type) {
+// CHECK:STDOUT: generic impl @impl.22b(%Y.loc7_14.1: %empty_tuple.type) {
 // CHECK:STDOUT:   %Y.loc7_14.2: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic = %Y.loc7_14.2 (constants.%Y)]
 // CHECK:STDOUT:   %C.loc7_25.2: type = class_type @C, @C(%Y.loc7_14.2) [symbolic = %C.loc7_25.2 (constants.%C.13320f.2)]
-// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl(%Y.loc7_14.2) [symbolic = %I.impl_witness (constants.%I.impl_witness)]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl.22b(%Y.loc7_14.2) [symbolic = %I.impl_witness (constants.%I.impl_witness)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %F.type.loc8_17.1: type = fn_type @F.2, @impl(%Y.loc7_14.2) [symbolic = %F.type.loc8_17.1 (constants.%F.type.0daaa1.1)]
-// CHECK:STDOUT:   %F.loc8_17.1: @impl.%F.type.loc8_17.1 (%F.type.0daaa1.1) = struct_value () [symbolic = %F.loc8_17.1 (constants.%F.49c1ac.1)]
-// CHECK:STDOUT:   %F.type.loc8_17.2: type = fn_type @F.3, @impl(%Y.loc7_14.2) [symbolic = %F.type.loc8_17.2 (constants.%F.type.0daaa1.2)]
-// CHECK:STDOUT:   %F.loc8_17.2: @impl.%F.type.loc8_17.2 (%F.type.0daaa1.2) = struct_value () [symbolic = %F.loc8_17.2 (constants.%F.49c1ac.2)]
+// CHECK:STDOUT:   %F.type.loc8_17.1: type = fn_type @F.2, @impl.22b(%Y.loc7_14.2) [symbolic = %F.type.loc8_17.1 (constants.%F.type.0daaa1.1)]
+// CHECK:STDOUT:   %F.loc8_17.1: @impl.22b.%F.type.loc8_17.1 (%F.type.0daaa1.1) = struct_value () [symbolic = %F.loc8_17.1 (constants.%F.49c1ac.1)]
+// CHECK:STDOUT:   %F.type.loc8_17.2: type = fn_type @F.3, @impl.22b(%Y.loc7_14.2) [symbolic = %F.type.loc8_17.2 (constants.%F.type.0daaa1.2)]
+// CHECK:STDOUT:   %F.loc8_17.2: @impl.22b.%F.type.loc8_17.2 (%F.type.0daaa1.2) = struct_value () [symbolic = %F.loc8_17.2 (constants.%F.49c1ac.2)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   impl: %C.loc7_25.1 as %I.ref {
-// CHECK:STDOUT:     %F.decl.loc8_17.1: @impl.%F.type.loc8_17.1 (%F.type.0daaa1.1) = fn_decl @F.2 [symbolic = @impl.%F.loc8_17.1 (constants.%F.49c1ac.1)] {
+// CHECK:STDOUT:     %F.decl.loc8_17.1: @impl.22b.%F.type.loc8_17.1 (%F.type.0daaa1.1) = fn_decl @F.2 [symbolic = @impl.22b.%F.loc8_17.1 (constants.%F.49c1ac.1)] {
 // CHECK:STDOUT:       %x.patt: @F.2.%pattern_type (%pattern_type.ccc) = binding_pattern x [concrete]
 // CHECK:STDOUT:       %x.param_patt: @F.2.%pattern_type (%pattern_type.ccc) = value_param_pattern %x.patt, call_param0 [concrete]
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %x.param: @F.2.%C.loc8_14.1 (%C.13320f.2) = value_param call_param0
 // CHECK:STDOUT:       %.loc8: type = splice_block %C.loc8_14.2 [symbolic = %C.loc8_14.1 (constants.%C.13320f.2)] {
 // CHECK:STDOUT:         %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]
-// CHECK:STDOUT:         %Y.ref: %empty_tuple.type = name_ref Y, @impl.%Y.loc7_14.1 [symbolic = %Y (constants.%Y)]
+// CHECK:STDOUT:         %Y.ref: %empty_tuple.type = name_ref Y, @impl.22b.%Y.loc7_14.1 [symbolic = %Y (constants.%Y)]
 // CHECK:STDOUT:         %C.loc8_14.2: type = class_type @C, @C(constants.%Y) [symbolic = %C.loc8_14.1 (constants.%C.13320f.2)]
 // CHECK:STDOUT:       }
 // CHECK:STDOUT:       %x: @F.2.%C.loc8_14.1 (%C.13320f.2) = bind_name x, %x.param
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %F.decl.loc8_17.2: @impl.%F.type.loc8_17.2 (%F.type.0daaa1.2) = fn_decl @F.3 [symbolic = @impl.%F.loc8_17.2 (constants.%F.49c1ac.2)] {
+// CHECK:STDOUT:     %F.decl.loc8_17.2: @impl.22b.%F.type.loc8_17.2 (%F.type.0daaa1.2) = fn_decl @F.3 [symbolic = @impl.22b.%F.loc8_17.2 (constants.%F.49c1ac.2)] {
 // CHECK:STDOUT:       %x.patt: %pattern_type.a96 = binding_pattern x [concrete]
 // CHECK:STDOUT:       %x.param_patt: %pattern_type.a96 = value_param_pattern %x.patt, call_param0 [concrete]
 // CHECK:STDOUT:     } {
@@ -239,13 +255,13 @@ fn G() {
 // CHECK:STDOUT:   fn;
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F.2(@impl.%Y.loc7_14.1: %empty_tuple.type) {
+// CHECK:STDOUT: generic fn @F.2(@impl.22b.%Y.loc7_14.1: %empty_tuple.type) {
 // CHECK:STDOUT:   %Y: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic = %Y (constants.%Y)]
 // CHECK:STDOUT:   %C.loc8_14.1: type = class_type @C, @C(%Y) [symbolic = %C.loc8_14.1 (constants.%C.13320f.2)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %C.loc8_14.1 [symbolic = %pattern_type (constants.%pattern_type.ccc)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.loc8_14.1 [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.loc8_14.1 [symbolic = %require_complete (constants.%require_complete.a35)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%x.param: @F.2.%C.loc8_14.1 (%C.13320f.2)) {
 // CHECK:STDOUT:   !entry:
@@ -253,19 +269,26 @@ fn G() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F.3(@impl.%Y.loc7_14.1: %empty_tuple.type) {
+// CHECK:STDOUT: generic fn @F.3(@impl.22b.%Y.loc7_14.1: %empty_tuple.type) {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT:   %Y: %empty_tuple.type = bind_symbolic_name Y, 0 [symbolic = %Y (constants.%Y)]
-// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl(%Y) [symbolic = %F.type (constants.%F.type.0daaa1.1)]
+// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl.22b(%Y) [symbolic = %F.type (constants.%F.type.0daaa1.1)]
 // CHECK:STDOUT:   %F: @F.3.%F.type (%F.type.0daaa1.1) = struct_value () [symbolic = %F (constants.%F.49c1ac.1)]
 // CHECK:STDOUT:   %F.specific_fn.loc8_17.2: <specific function> = specific_function %F, @F.2(%Y) [symbolic = %F.specific_fn.loc8_17.2 (constants.%F.specific_fn)]
 // CHECK:STDOUT:   %C: type = class_type @C, @C(%Y) [symbolic = %C (constants.%C.13320f.2)]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete.1: <witness> = require_complete_type %C [symbolic = %require_complete.1 (constants.%require_complete.a35)]
 // CHECK:STDOUT:   %C.val: @F.3.%C (%C.13320f.2) = struct_value () [symbolic = %C.val (constants.%C.val)]
-// CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%x.param: %empty_struct_type) [thunk @impl.%F.decl.loc8_17.1] {
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]
+// CHECK:STDOUT:   %.7: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.7 (constants.%.97f)]
+// CHECK:STDOUT:   %impl.elem0.2: @F.3.%.7 (%.97f) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn.2: <specific function> = specific_impl_function %impl.elem0.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %C [symbolic = %ptr (constants.%ptr.40d)]
+// CHECK:STDOUT:   %require_complete.2: <witness> = require_complete_type %ptr [symbolic = %require_complete.2 (constants.%require_complete.0b0)]
+// CHECK:STDOUT:
+// CHECK:STDOUT:   fn(%x.param: %empty_struct_type) [thunk @impl.22b.%F.decl.loc8_17.1] {
 // CHECK:STDOUT:   !entry:
-// CHECK:STDOUT:     %.loc8: @F.3.%F.type (%F.type.0daaa1.1) = specific_constant @impl.%F.decl.loc8_17.1, @impl(constants.%Y) [symbolic = %F (constants.%F.49c1ac.1)]
+// CHECK:STDOUT:     %.loc8: @F.3.%F.type (%F.type.0daaa1.1) = specific_constant @impl.22b.%F.decl.loc8_17.1, @impl.22b(constants.%Y) [symbolic = %F (constants.%F.49c1ac.1)]
 // CHECK:STDOUT:     %F.ref: @F.3.%F.type (%F.type.0daaa1.1) = name_ref F, %.loc8 [symbolic = %F (constants.%F.49c1ac.1)]
 // CHECK:STDOUT:     %x.ref: %empty_struct_type = name_ref x, %x.param
 // CHECK:STDOUT:     %F.specific_fn.loc8_17.1: <specific function> = specific_function %F.ref, @F.2(constants.%Y) [symbolic = %F.specific_fn.loc8_17.2 (constants.%F.specific_fn)]
@@ -275,6 +298,13 @@ fn G() {
 // CHECK:STDOUT:     %.4: ref @F.3.%C (%C.13320f.2) = converted %x.ref, %.3
 // CHECK:STDOUT:     %.5: @F.3.%C (%C.13320f.2) = bind_value %.4
 // CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc8_17.1(%.5)
+// CHECK:STDOUT:     %Op.ref: %Destroy.assoc_type = name_ref Op, imports.%Core.import_ref.f99 [concrete = constants.%assoc0]
+// CHECK:STDOUT:     %impl.elem0.1: @F.3.%.7 (%.97f) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.2 (constants.%impl.elem0)]
+// CHECK:STDOUT:     %bound_method.1: <bound method> = bound_method %.1, %impl.elem0.1
+// CHECK:STDOUT:     %specific_impl_fn.1: <specific function> = specific_impl_function %impl.elem0.1, @Op.1(constants.%Destroy.facet) [symbolic = %specific_impl_fn.2 (constants.%specific_impl_fn)]
+// CHECK:STDOUT:     %bound_method.2: <bound method> = bound_method %.1, %specific_impl_fn.1
+// CHECK:STDOUT:     %addr: @F.3.%ptr (%ptr.40d) = addr_of %.1
+// CHECK:STDOUT:     %.6: init %empty_tuple.type = call %bound_method.2(%addr)
 // CHECK:STDOUT:     return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -289,7 +319,7 @@ fn G() {
 // CHECK:STDOUT: !definition:
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%Y) {
+// CHECK:STDOUT: specific @impl.22b(constants.%Y) {
 // CHECK:STDOUT:   %Y.loc7_14.2 => constants.%Y
 // CHECK:STDOUT:   %C.loc7_25.2 => constants.%C.13320f.2
 // CHECK:STDOUT:   %I.impl_witness => constants.%I.impl_witness
@@ -301,7 +331,7 @@ fn G() {
 // CHECK:STDOUT:   %F.loc8_17.2 => constants.%F.49c1ac.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F.1(constants.%Self) {}
+// CHECK:STDOUT: specific @F.1(constants.%Self.826) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.2(constants.%Y) {
 // CHECK:STDOUT:   %Y => constants.%Y
@@ -309,7 +339,7 @@ fn G() {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.ccc
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%require_complete
+// CHECK:STDOUT:   %require_complete => constants.%require_complete.a35
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.1(constants.%I.facet) {}
@@ -346,6 +376,18 @@ fn G() {
 // CHECK:STDOUT:   %require_complete.a35: <witness> = require_complete_type %C.13320f.2 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.8d9: <specific function> = specific_function %F.49c1ac.1, @F.2(%Y) [symbolic]
 // CHECK:STDOUT:   %C.val.56a: %C.13320f.2 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C.13320f.2, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.666: %Destroy.type = facet_value %C.13320f.2, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %Op.type.989: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %.5fd: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.666 [symbolic]
+// CHECK:STDOUT:   %impl.elem0: %.5fd = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet.666) [symbolic]
+// CHECK:STDOUT:   %ptr.40d: type = ptr_type %C.13320f.2 [symbolic]
+// CHECK:STDOUT:   %require_complete.0b0: <witness> = require_complete_type %ptr.40d [symbolic]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.ed4: type = fn_type @Op.2, @impl.d2b(%T) [symbolic]
+// CHECK:STDOUT:   %Op.486: %Op.type.ed4 = struct_value () [symbolic]
 // CHECK:STDOUT:   %I.impl_witness.02b: <witness> = impl_witness imports.%I.impl_witness_table, @impl.22b(%empty_tuple) [concrete]
 // CHECK:STDOUT:   %F.type.af4856.1: type = fn_type @F.2, @impl.22b(%empty_tuple) [concrete]
 // CHECK:STDOUT:   %F.5fa954.1: %F.type.af4856.1 = struct_value () [concrete]
@@ -358,24 +400,20 @@ fn G() {
 // CHECK:STDOUT:   %pattern_type.186: type = pattern_type %C.607 [concrete]
 // CHECK:STDOUT:   %F.specific_fn.4832e8.2: <specific function> = specific_function %F.5fa954.1, @F.2(%empty_tuple) [concrete]
 // CHECK:STDOUT:   %C.val.12f: %C.607 = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
-// CHECK:STDOUT:   %Destroy.impl_witness.94b: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%C.607) [concrete]
-// CHECK:STDOUT:   %Op.type.961: type = fn_type @Op.2, @impl.49c(%C.607) [concrete]
-// CHECK:STDOUT:   %Op.7ef: %Op.type.961 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.ce0: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.d2b(%C.607) [concrete]
+// CHECK:STDOUT:   %Op.type.ea0: type = fn_type @Op.2, @impl.d2b(%C.607) [concrete]
+// CHECK:STDOUT:   %Op.ac0: %Op.type.ea0 = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.2ce: type = ptr_type %C.607 [concrete]
-// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C.607, (%Destroy.impl_witness.94b) [concrete]
-// CHECK:STDOUT:   %.bb3: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
-// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.7ef, @Op.2(%C.607) [concrete]
+// CHECK:STDOUT:   %complete_type.e2c: <witness> = complete_type_witness %ptr.2ce [concrete]
+// CHECK:STDOUT:   %Destroy.facet.c44: %Destroy.type = facet_value %C.607, (%Destroy.impl_witness.ce0) [concrete]
+// CHECK:STDOUT:   %.69e: type = fn_type_with_self_type %Op.type.989, %Destroy.facet.c44 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ac0, @Op.2(%C.607) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Main.I: type = import_ref Main//a, I, loaded [concrete = constants.%I.type]
 // CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//b, C, loaded [concrete = constants.%C.generic]
-// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
@@ -397,16 +435,16 @@ fn G() {
 // CHECK:STDOUT:   %Main.import_ref.eb1c17.3: %empty_tuple.type = import_ref Main//b, loc7_14, loaded [symbolic = @impl.22b.%Y (constants.%Y)]
 // CHECK:STDOUT:   %Main.import_ref.eb1c17.4: %empty_tuple.type = import_ref Main//b, loc7_14, loaded [symbolic = @impl.22b.%Y (constants.%Y)]
 // CHECK:STDOUT:   %Main.F.5a8: @impl.22b.%F.type.1 (%F.type.0daaa1.1) = import_ref Main//b, F, loaded [symbolic = @impl.22b.%F.1 (constants.%F.49c1ac.1)]
+// CHECK:STDOUT:   %Main.import_ref.fcc: @impl.d2b.%Op.type (%Op.type.ed4) = import_ref Main//b, inst153 [indirect], loaded [symbolic = @impl.d2b.%Op (constants.%Op.486)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Main.import_ref.fcc), @impl.d2b [concrete]
 // CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
-// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
-// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
 // CHECK:STDOUT:     .I = imports.%Main.I
 // CHECK:STDOUT:     .C = imports.%Main.C
-// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .Core = imports.%Core.ece
 // CHECK:STDOUT:     .G = %G.decl
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
@@ -478,7 +516,7 @@ fn G() {
 // CHECK:STDOUT:   %.loc7_16.6: ref %C.607 = converted %.loc7_16.2, %.loc7_16.5
 // CHECK:STDOUT:   %.loc7_16.7: %C.607 = bind_value %.loc7_16.6
 // CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc7_16.7)
-// CHECK:STDOUT:   %impl.elem0.loc7_16: %.bb3 = impl_witness_access constants.%Destroy.impl_witness.94b, element0 [concrete = constants.%Op.7ef]
+// CHECK:STDOUT:   %impl.elem0.loc7_16: %.69e = impl_witness_access constants.%Destroy.impl_witness.ce0, element0 [concrete = constants.%Op.ac0]
 // CHECK:STDOUT:   %bound_method.loc7_16.1: <bound method> = bound_method %.loc7_16.3, %impl.elem0.loc7_16
 // CHECK:STDOUT:   %specific_fn.loc7_16: <specific function> = specific_function %impl.elem0.loc7_16, @Op.2(constants.%C.607) [concrete = constants.%Op.specific_fn]
 // CHECK:STDOUT:   %bound_method.loc7_16.2: <bound method> = bound_method %.loc7_16.3, %specific_fn.loc7_16
@@ -509,8 +547,15 @@ fn G() {
 // CHECK:STDOUT:   %F: @F.3.%F.type (%F.type.0daaa1.1) = struct_value () [symbolic = %F (constants.%F.49c1ac.1)]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F.2(%Y) [symbolic = %F.specific_fn (constants.%F.specific_fn.8d9)]
 // CHECK:STDOUT:   %C: type = class_type @C, @C(%Y) [symbolic = %C (constants.%C.13320f.2)]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C [symbolic = %require_complete (constants.%require_complete.a35)]
+// CHECK:STDOUT:   %require_complete.1: <witness> = require_complete_type %C [symbolic = %require_complete.1 (constants.%require_complete.a35)]
 // CHECK:STDOUT:   %C.val: @F.3.%C (%C.13320f.2) = struct_value () [symbolic = %C.val (constants.%C.val.56a)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.666)]
+// CHECK:STDOUT:   %.1: type = fn_type_with_self_type constants.%Op.type.989, %Destroy.facet [symbolic = %.1 (constants.%.5fd)]
+// CHECK:STDOUT:   %impl.elem0: @F.3.%.1 (%.5fd) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0)]
+// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn (constants.%specific_impl_fn)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %C [symbolic = %ptr (constants.%ptr.40d)]
+// CHECK:STDOUT:   %require_complete.2: <witness> = require_complete_type %ptr [symbolic = %require_complete.2 (constants.%require_complete.0b0)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn [thunk imports.%Main.F.5a8];
 // CHECK:STDOUT: }
@@ -575,8 +620,15 @@ fn G() {
 // CHECK:STDOUT:   %F => constants.%F.5fa954.1
 // CHECK:STDOUT:   %F.specific_fn => constants.%F.specific_fn.4832e8.2
 // CHECK:STDOUT:   %C => constants.%C.607
-// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
+// CHECK:STDOUT:   %require_complete.1 => constants.%complete_type.357
 // CHECK:STDOUT:   %C.val => constants.%C.val.12f
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.impl_witness.ce0
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.c44
+// CHECK:STDOUT:   %.1 => constants.%.69e
+// CHECK:STDOUT:   %impl.elem0 => constants.%Op.ac0
+// CHECK:STDOUT:   %specific_impl_fn => constants.%Op.specific_fn
+// CHECK:STDOUT:   %ptr => constants.%ptr.2ce
+// CHECK:STDOUT:   %require_complete.2 => constants.%complete_type.e2c
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.2(constants.%empty_tuple) {

+ 41 - 13
toolchain/check/testdata/impl/interface_args.carbon

@@ -1042,8 +1042,9 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %B: type = class_type @B [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // CHECK:STDOUT:   %Factory.type.1a8: type = generic_interface_type @Factory [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Factory.generic: %Factory.type.1a8 = struct_value () [concrete]
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %Factory.type.c96: type = facet_type <@Factory, @Factory(%T)> [symbolic]
@@ -1057,8 +1058,8 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %assoc0.46d25f.1: %Factory.assoc_type.207 = assoc_entity element0, imports.%Main.import_ref.21018a.1 [symbolic]
 // CHECK:STDOUT:   %Method.type.7ee: type = fn_type @Method.1, @Factory(%T) [symbolic]
 // CHECK:STDOUT:   %Method.a71: %Method.type.7ee = struct_value () [symbolic]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self.9ba [symbolic]
-// CHECK:STDOUT:   %pattern_type.5ea: type = pattern_type %Self.as_type [symbolic]
+// CHECK:STDOUT:   %Self.as_type.56c: type = facet_access_type %Self.9ba [symbolic]
+// CHECK:STDOUT:   %pattern_type.5ea: type = pattern_type %Self.as_type.56c [symbolic]
 // CHECK:STDOUT:   %assoc1.16541d.1: %Factory.assoc_type.207 = assoc_entity element1, imports.%Main.import_ref.46fc3c.1 [symbolic]
 // CHECK:STDOUT:   %Self.187: %Factory.type.a5d = bind_symbolic_name Self, 1 [symbolic]
 // CHECK:STDOUT:   %Make.type.c59: type = fn_type @Make.1, @Factory(%B) [concrete]
@@ -1077,6 +1078,17 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %.711: type = fn_type_with_self_type %Make.type.c59, %Factory.facet [concrete]
 // CHECK:STDOUT:   %Make.type.ec4: type = fn_type @Make.2 [concrete]
 // CHECK:STDOUT:   %Make.377: %Make.type.ec4 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.39d: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.type.1a6: type = fn_type @Op.2, @impl.49c(%B) [concrete]
+// CHECK:STDOUT:   %Op.3c2: %Op.type.1a6 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.e79: type = ptr_type %B [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %B, (%Destroy.impl_witness.39d) [concrete]
+// CHECK:STDOUT:   %.c16: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.3c2, @Op.2(%B) [concrete]
 // CHECK:STDOUT:   %pattern_type.c10: type = pattern_type %A [concrete]
 // CHECK:STDOUT:   %InstanceB.type: type = fn_type @InstanceB [concrete]
 // CHECK:STDOUT:   %InstanceB: %InstanceB.type = struct_value () [concrete]
@@ -1091,10 +1103,11 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %Main.A: type = import_ref Main//factory, A, loaded [concrete = constants.%A]
 // CHECK:STDOUT:   %Main.B: type = import_ref Main//factory, B, loaded [concrete = constants.%B]
 // 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:   %Main.import_ref.8f24d3.1: <witness> = import_ref Main//factory, loc12_10, loaded [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %Main.import_ref.8f24d3.1: <witness> = import_ref Main//factory, loc12_10, loaded [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   %Main.import_ref.54a = import_ref Main//factory, inst86 [no loc], unloaded
 // CHECK:STDOUT:   %Main.import_ref.5ab3ec.1: type = import_ref Main//factory, loc4_19, loaded [symbolic = @Factory.%T (constants.%T)]
 // CHECK:STDOUT:   %Main.import_ref.fbb = import_ref Main//factory, inst27 [no loc], unloaded
@@ -1103,7 +1116,7 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %Main.Make = import_ref Main//factory, Make, unloaded
 // CHECK:STDOUT:   %Main.Method = import_ref Main//factory, Method, unloaded
 // CHECK:STDOUT:   %Main.import_ref.6fd: <witness> = import_ref Main//factory, loc14_22, loaded [concrete = constants.%Factory.impl_witness]
-// CHECK:STDOUT:   %Main.import_ref.8f24d3.2: <witness> = import_ref Main//factory, loc11_10, loaded [concrete = constants.%complete_type]
+// CHECK:STDOUT:   %Main.import_ref.8f24d3.2: <witness> = import_ref Main//factory, loc11_10, loaded [concrete = constants.%complete_type.357]
 // CHECK:STDOUT:   %Main.import_ref.da3 = import_ref Main//factory, inst80 [no loc], unloaded
 // CHECK:STDOUT:   %Main.import_ref.984: type = import_ref Main//factory, loc14_6, loaded [concrete = constants.%A]
 // CHECK:STDOUT:   %Main.import_ref.bd2: type = import_ref Main//factory, loc14_20, loaded [concrete = constants.%Factory.type.a5d]
@@ -1120,7 +1133,10 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %Main.import_ref.21018a.2 = import_ref Main//factory, loc6_17, unloaded
 // CHECK:STDOUT:   %Main.import_ref.9ec: %Make.type.ec4 = import_ref Main//factory, loc15_17, loaded [concrete = constants.%Make.377]
 // CHECK:STDOUT:   %Main.import_ref.7dd: %Method.type.af5 = import_ref Main//factory, loc16_31, loaded [concrete = constants.%Method.3d4]
-// CHECK:STDOUT:   %Factory.impl_witness_table = impl_witness_table (%Main.import_ref.9ec, %Main.import_ref.7dd), @impl [concrete]
+// CHECK:STDOUT:   %Factory.impl_witness_table = impl_witness_table (%Main.import_ref.9ec, %Main.import_ref.7dd), @impl.ba3 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Main.import_ref.46fc3c.2 = import_ref Main//factory, loc8_31, unloaded
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1182,7 +1198,7 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: impl @impl: imports.%Main.import_ref.984 as imports.%Main.import_ref.bd2 [from "factory.carbon"] {
+// CHECK:STDOUT: impl @impl.ba3: imports.%Main.import_ref.984 as imports.%Main.import_ref.bd2 [from "factory.carbon"] {
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Make = imports.%Main.import_ref.a27
 // CHECK:STDOUT:   .Method = imports.%Main.import_ref.163
@@ -1214,7 +1230,7 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %Factory.type: type = facet_type <@Factory, @Factory(%T)> [symbolic = %Factory.type (constants.%Factory.type.c96)]
 // CHECK:STDOUT:   %Self: @Method.1.%Factory.type (%Factory.type.c96) = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.9ba)]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type)]
+// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic = %Self.as_type (constants.%Self.as_type.56c)]
 // CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Self.as_type [symbolic = %pattern_type.1 (constants.%pattern_type.5ea)]
 // CHECK:STDOUT:   %pattern_type.2: type = pattern_type %T [symbolic = %pattern_type.2 (constants.%pattern_type.7dc)]
 // CHECK:STDOUT:
@@ -1231,9 +1247,15 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %Make.ref: %Factory.assoc_type.579 = name_ref Make, %.loc5_23 [concrete = constants.%assoc0.153]
 // CHECK:STDOUT:   %Factory.facet: %Factory.type.a5d = facet_value constants.%A, (constants.%Factory.impl_witness) [concrete = constants.%Factory.facet]
 // CHECK:STDOUT:   %.loc5_11: %Factory.type.a5d = converted %A.ref, %Factory.facet [concrete = constants.%Factory.facet]
-// CHECK:STDOUT:   %impl.elem0: %.711 = impl_witness_access constants.%Factory.impl_witness, element0 [concrete = constants.%Make.377]
+// CHECK:STDOUT:   %impl.elem0.loc5: %.711 = impl_witness_access constants.%Factory.impl_witness, element0 [concrete = constants.%Make.377]
 // CHECK:STDOUT:   %.loc4: ref %B = splice_block %return {}
-// CHECK:STDOUT:   %Make.call: init %B = call %impl.elem0() to %.loc4
+// CHECK:STDOUT:   %Make.call: init %B = call %impl.elem0.loc5() to %.loc4
+// CHECK:STDOUT:   %impl.elem0.loc4: %.c16 = impl_witness_access constants.%Destroy.impl_witness.39d, element0 [concrete = constants.%Op.3c2]
+// CHECK:STDOUT:   %bound_method.loc4_12.1: <bound method> = bound_method %.loc4, %impl.elem0.loc4
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0.loc4, @Op.2(constants.%B) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc4_12.2: <bound method> = bound_method %.loc4, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e79 = addr_of %.loc4
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc4_12.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1248,9 +1270,15 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %.loc8: %Factory.assoc_type.579 = specific_constant imports.%Main.import_ref.2e4, @Factory(constants.%B) [concrete = constants.%assoc1.a48]
 // CHECK:STDOUT:   %Method.ref: %Factory.assoc_type.579 = name_ref Method, %.loc8 [concrete = constants.%assoc1.a48]
 // CHECK:STDOUT:   %impl.elem1: %.fed = impl_witness_access constants.%Factory.impl_witness, element1 [concrete = constants.%Method.3d4]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc8: <bound method> = bound_method %a.ref, %impl.elem1
 // CHECK:STDOUT:   %.loc7: ref %B = splice_block %return {}
-// CHECK:STDOUT:   %Method.call: init %B = call %bound_method(%a.ref) to %.loc7
+// CHECK:STDOUT:   %Method.call: init %B = call %bound_method.loc8(%a.ref) to %.loc7
+// CHECK:STDOUT:   %impl.elem0: %.c16 = impl_witness_access constants.%Destroy.impl_witness.39d, element0 [concrete = constants.%Op.3c2]
+// CHECK:STDOUT:   %bound_method.loc7_20.1: <bound method> = bound_method %.loc7, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%B) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_20.2: <bound method> = bound_method %.loc7, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.e79 = addr_of %.loc7
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc7_20.2(%addr)
 // CHECK:STDOUT:   return %Method.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -1284,7 +1312,7 @@ fn InstanceC(a: A) -> C {
 // CHECK:STDOUT:   %T => constants.%T
 // CHECK:STDOUT:   %Factory.type => constants.%Factory.type.c96
 // CHECK:STDOUT:   %Self => constants.%Self.9ba
-// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type
+// CHECK:STDOUT:   %Self.as_type => constants.%Self.as_type.56c
 // CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.5ea
 // CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.7dc
 // CHECK:STDOUT: }

+ 72 - 50
toolchain/check/testdata/impl/lookup/generic.carbon

@@ -324,40 +324,56 @@ fn G(x: A) {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %HasF.type: type = facet_type <@HasF> [concrete]
-// CHECK:STDOUT:   %Self: %HasF.type = bind_symbolic_name Self, 0 [symbolic]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self [symbolic]
-// CHECK:STDOUT:   %pattern_type.28f: type = pattern_type %Self.as_type [symbolic]
+// CHECK:STDOUT:   %Self.f0c: %HasF.type = bind_symbolic_name Self, 0 [symbolic]
+// CHECK:STDOUT:   %Self.as_type.308: type = facet_access_type %Self.f0c [symbolic]
+// CHECK:STDOUT:   %pattern_type.28f: type = pattern_type %Self.as_type.308 [symbolic]
 // CHECK:STDOUT:   %F.type.b7b: type = fn_type @F.1 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %F.f50: %F.type.b7b = struct_value () [concrete]
 // CHECK:STDOUT:   %HasF.assoc_type: type = assoc_entity_type @HasF [concrete]
-// CHECK:STDOUT:   %assoc0: %HasF.assoc_type = assoc_entity element0, @HasF.%F.decl [concrete]
+// CHECK:STDOUT:   %assoc0.97a: %HasF.assoc_type = assoc_entity element0, @HasF.%F.decl [concrete]
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
-// CHECK:STDOUT:   %HasF.impl_witness.ec7: <witness> = impl_witness file.%HasF.impl_witness_table, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %HasF.impl_witness.ec7: <witness> = impl_witness file.%HasF.impl_witness_table, @impl.b7a(%T) [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dc: type = pattern_type %T [symbolic]
-// CHECK:STDOUT:   %F.type.3fd: type = fn_type @F.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %F.type.3fd: type = fn_type @F.2, @impl.b7a(%T) [symbolic]
 // CHECK:STDOUT:   %F.c98: %F.type.3fd = struct_value () [symbolic]
 // CHECK:STDOUT:   %HasF.facet.216: %HasF.type = facet_value %T, (%HasF.impl_witness.ec7) [symbolic]
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]
+// CHECK:STDOUT:   %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
-// CHECK:STDOUT:   %HasF.impl_witness.6e4: <witness> = impl_witness file.%HasF.impl_witness_table, @impl(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %F.type.2e4: type = fn_type @F.2, @impl(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %HasF.impl_witness.6e4: <witness> = impl_witness file.%HasF.impl_witness_table, @impl.b7a(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %F.type.2e4: type = fn_type @F.2, @impl.b7a(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %F.f13: %F.type.2e4 = struct_value () [concrete]
 // CHECK:STDOUT:   %HasF.facet.fa2: %HasF.type = facet_value %empty_struct_type, (%HasF.impl_witness.6e4) [concrete]
 // CHECK:STDOUT:   %.e02: type = fn_type_with_self_type %F.type.b7b, %HasF.facet.fa2 [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.f13, @F.2(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
-// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
+// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]
 // 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:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -368,15 +384,15 @@ fn G(x: A) {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.import = import Core
 // CHECK:STDOUT:   %HasF.decl: type = interface_decl @HasF [concrete = constants.%HasF.type] {} {}
-// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:   impl_decl @impl.b7a [concrete] {
 // CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc8_14.1 [symbolic = %T.loc8_14.2 (constants.%T)]
 // CHECK:STDOUT:     %HasF.ref: type = name_ref HasF, file.%HasF.decl [concrete = constants.%HasF.type]
 // CHECK:STDOUT:     %T.loc8_14.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %HasF.impl_witness_table = impl_witness_table (@impl.%F.decl), @impl [concrete]
-// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness %HasF.impl_witness_table, @impl(constants.%T) [symbolic = @impl.%HasF.impl_witness (constants.%HasF.impl_witness.ec7)]
+// CHECK:STDOUT:   %HasF.impl_witness_table = impl_witness_table (@impl.b7a.%F.decl), @impl.b7a [concrete]
+// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness %HasF.impl_witness_table, @impl.b7a(constants.%T) [symbolic = @impl.b7a.%HasF.impl_witness (constants.%HasF.impl_witness.ec7)]
 // CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {
 // CHECK:STDOUT:     %x.patt: %pattern_type.a96 = binding_pattern x [concrete]
 // CHECK:STDOUT:     %x.param_patt: %pattern_type.a96 = value_param_pattern %x.patt, call_param0 [concrete]
@@ -397,27 +413,27 @@ fn G(x: A) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: interface @HasF {
-// CHECK:STDOUT:   %Self: %HasF.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self]
+// CHECK:STDOUT:   %Self: %HasF.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.f0c]
 // CHECK:STDOUT:   %F.decl: %F.type.b7b = fn_decl @F.1 [concrete = constants.%F.f50] {
 // CHECK:STDOUT:     %self.patt: @F.1.%pattern_type (%pattern_type.28f) = binding_pattern self [concrete]
 // CHECK:STDOUT:     %self.param_patt: @F.1.%pattern_type (%pattern_type.28f) = value_param_pattern %self.patt, call_param0 [concrete]
 // CHECK:STDOUT:     %return.patt: @F.1.%pattern_type (%pattern_type.28f) = return_slot_pattern [concrete]
 // CHECK:STDOUT:     %return.param_patt: @F.1.%pattern_type (%pattern_type.28f) = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:   } {
-// CHECK:STDOUT:     %Self.ref.loc5_25: %HasF.type = name_ref Self, @HasF.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:     %Self.as_type.loc5_25: type = facet_access_type %Self.ref.loc5_25 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)]
-// CHECK:STDOUT:     %.loc5_25: type = converted %Self.ref.loc5_25, %Self.as_type.loc5_25 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)]
-// CHECK:STDOUT:     %self.param: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type) = value_param call_param0
-// CHECK:STDOUT:     %.loc5_14.1: type = splice_block %.loc5_14.2 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)] {
-// CHECK:STDOUT:       %Self.ref.loc5_14: %HasF.type = name_ref Self, @HasF.%Self [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:       %Self.as_type.loc5_14.2: type = facet_access_type %Self.ref.loc5_14 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)]
-// CHECK:STDOUT:       %.loc5_14.2: type = converted %Self.ref.loc5_14, %Self.as_type.loc5_14.2 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)]
+// CHECK:STDOUT:     %Self.ref.loc5_25: %HasF.type = name_ref Self, @HasF.%Self [symbolic = %Self (constants.%Self.f0c)]
+// CHECK:STDOUT:     %Self.as_type.loc5_25: type = facet_access_type %Self.ref.loc5_25 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)]
+// CHECK:STDOUT:     %.loc5_25: type = converted %Self.ref.loc5_25, %Self.as_type.loc5_25 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)]
+// CHECK:STDOUT:     %self.param: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308) = value_param call_param0
+// CHECK:STDOUT:     %.loc5_14.1: type = splice_block %.loc5_14.2 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)] {
+// CHECK:STDOUT:       %Self.ref.loc5_14: %HasF.type = name_ref Self, @HasF.%Self [symbolic = %Self (constants.%Self.f0c)]
+// CHECK:STDOUT:       %Self.as_type.loc5_14.2: type = facet_access_type %Self.ref.loc5_14 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)]
+// CHECK:STDOUT:       %.loc5_14.2: type = converted %Self.ref.loc5_14, %Self.as_type.loc5_14.2 [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)]
 // CHECK:STDOUT:     }
-// CHECK:STDOUT:     %self: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type) = bind_name self, %self.param
-// CHECK:STDOUT:     %return.param: ref @F.1.%Self.as_type.loc5_14.1 (%Self.as_type) = out_param call_param1
-// CHECK:STDOUT:     %return: ref @F.1.%Self.as_type.loc5_14.1 (%Self.as_type) = return_slot %return.param
+// CHECK:STDOUT:     %self: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308) = bind_name self, %self.param
+// CHECK:STDOUT:     %return.param: ref @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308) = out_param call_param1
+// CHECK:STDOUT:     %return: ref @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308) = return_slot %return.param
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %assoc0: %HasF.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0]
+// CHECK:STDOUT:   %assoc0: %HasF.assoc_type = assoc_entity element0, %F.decl [concrete = constants.%assoc0.97a]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Self = %Self
@@ -425,24 +441,24 @@ fn G(x: A) {
 // CHECK:STDOUT:   witness = (%F.decl)
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic impl @impl(%T.loc8_14.1: type) {
+// CHECK:STDOUT: generic impl @impl.b7a(%T.loc8_14.1: type) {
 // CHECK:STDOUT:   %T.loc8_14.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]
-// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness file.%HasF.impl_witness_table, @impl(%T.loc8_14.2) [symbolic = %HasF.impl_witness (constants.%HasF.impl_witness.ec7)]
+// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness file.%HasF.impl_witness_table, @impl.b7a(%T.loc8_14.2) [symbolic = %HasF.impl_witness (constants.%HasF.impl_witness.ec7)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl(%T.loc8_14.2) [symbolic = %F.type (constants.%F.type.3fd)]
-// CHECK:STDOUT:   %F: @impl.%F.type (%F.type.3fd) = struct_value () [symbolic = %F (constants.%F.c98)]
+// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl.b7a(%T.loc8_14.2) [symbolic = %F.type (constants.%F.type.3fd)]
+// CHECK:STDOUT:   %F: @impl.b7a.%F.type (%F.type.3fd) = struct_value () [symbolic = %F (constants.%F.c98)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   impl: %T.ref as %HasF.ref {
-// CHECK:STDOUT:     %F.decl: @impl.%F.type (%F.type.3fd) = fn_decl @F.2 [symbolic = @impl.%F (constants.%F.c98)] {
+// CHECK:STDOUT:     %F.decl: @impl.b7a.%F.type (%F.type.3fd) = fn_decl @F.2 [symbolic = @impl.b7a.%F (constants.%F.c98)] {
 // CHECK:STDOUT:       %self.patt: @F.2.%pattern_type (%pattern_type.7dc) = binding_pattern self [concrete]
 // CHECK:STDOUT:       %self.param_patt: @F.2.%pattern_type (%pattern_type.7dc) = value_param_pattern %self.patt, call_param0 [concrete]
 // CHECK:STDOUT:       %return.patt: @F.2.%pattern_type (%pattern_type.7dc) = return_slot_pattern [concrete]
 // CHECK:STDOUT:       %return.param_patt: @F.2.%pattern_type (%pattern_type.7dc) = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:     } {
-// CHECK:STDOUT:       %T.ref: type = name_ref T, @impl.%T.loc8_14.1 [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %T.ref: type = name_ref T, @impl.b7a.%T.loc8_14.1 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:       %self.param: @F.2.%T (%T) = value_param call_param0
-// CHECK:STDOUT:       %Self.ref: type = name_ref Self, @impl.%T.ref [symbolic = %T (constants.%T)]
+// CHECK:STDOUT:       %Self.ref: type = name_ref Self, @impl.b7a.%T.ref [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:       %self: @F.2.%T (%T) = bind_name self, %self.param
 // CHECK:STDOUT:       %return.param: ref @F.2.%T (%T) = out_param call_param1
 // CHECK:STDOUT:       %return: ref @F.2.%T (%T) = return_slot %return.param
@@ -456,19 +472,19 @@ fn G(x: A) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: generic fn @F.1(@HasF.%Self: %HasF.type) {
-// CHECK:STDOUT:   %Self: %HasF.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self)]
-// CHECK:STDOUT:   %Self.as_type.loc5_14.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type)]
+// CHECK:STDOUT:   %Self: %HasF.type = bind_symbolic_name Self, 0 [symbolic = %Self (constants.%Self.f0c)]
+// CHECK:STDOUT:   %Self.as_type.loc5_14.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc5_14.1 (constants.%Self.as_type.308)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.as_type.loc5_14.1 [symbolic = %pattern_type (constants.%pattern_type.28f)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type)) -> @F.1.%Self.as_type.loc5_14.1 (%Self.as_type);
+// CHECK:STDOUT:   fn(%self.param: @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308)) -> @F.1.%Self.as_type.loc5_14.1 (%Self.as_type.308);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F.2(@impl.%T.loc8_14.1: type) {
+// CHECK:STDOUT: generic fn @F.2(@impl.b7a.%T.loc8_14.1: type) {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)]
 // CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.7dc)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete)]
+// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.4ae)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%self.param: @F.2.%T (%T)) -> @F.2.%T (%T) {
 // CHECK:STDOUT:   !entry:
@@ -481,26 +497,32 @@ fn G(x: A) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %x.ref: %empty_struct_type = name_ref x, %x
 // CHECK:STDOUT:   %HasF.ref: type = name_ref HasF, file.%HasF.decl [concrete = constants.%HasF.type]
-// CHECK:STDOUT:   %F.ref: %HasF.assoc_type = name_ref F, @HasF.%assoc0 [concrete = constants.%assoc0]
-// CHECK:STDOUT:   %impl.elem0: %.e02 = impl_witness_access constants.%HasF.impl_witness.6e4, element0 [concrete = constants.%F.f13]
-// CHECK:STDOUT:   %bound_method.loc13_11: <bound method> = bound_method %x.ref, %impl.elem0
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @F.2(constants.%empty_struct_type) [concrete = constants.%F.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc13_21: <bound method> = bound_method %x.ref, %specific_fn
-// CHECK:STDOUT:   %F.call: init %empty_struct_type = call %bound_method.loc13_21(%x.ref)
+// CHECK:STDOUT:   %F.ref: %HasF.assoc_type = name_ref F, @HasF.%assoc0 [concrete = constants.%assoc0.97a]
+// CHECK:STDOUT:   %impl.elem0.loc13_11: %.e02 = impl_witness_access constants.%HasF.impl_witness.6e4, element0 [concrete = constants.%F.f13]
+// CHECK:STDOUT:   %bound_method.loc13_11: <bound method> = bound_method %x.ref, %impl.elem0.loc13_11
+// CHECK:STDOUT:   %specific_fn.loc13_11: <specific function> = specific_function %impl.elem0.loc13_11, @F.2(constants.%empty_struct_type) [concrete = constants.%F.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_21.1: <bound method> = bound_method %x.ref, %specific_fn.loc13_11
+// CHECK:STDOUT:   %F.call: init %empty_struct_type = call %bound_method.loc13_21.1(%x.ref)
 // CHECK:STDOUT:   %.loc13_21.1: ref %empty_struct_type = temporary_storage
 // CHECK:STDOUT:   %.loc13_21.2: ref %empty_struct_type = temporary %.loc13_21.1, %F.call
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc13_22: %empty_struct_type = converted %F.call, %empty_struct [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %impl.elem0.loc13_21: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %bound_method.loc13_21.2: <bound method> = bound_method %.loc13_21.1, %impl.elem0.loc13_21
+// CHECK:STDOUT:   %specific_fn.loc13_21: <specific function> = specific_function %impl.elem0.loc13_21, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_21.3: <bound method> = bound_method %.loc13_21.1, %specific_fn.loc13_21
+// CHECK:STDOUT:   %addr: %ptr.c28 = addr_of %.loc13_21.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc13_21.3(%addr)
 // CHECK:STDOUT:   return %.loc13_22
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @F.1(constants.%Self) {
-// CHECK:STDOUT:   %Self => constants.%Self
-// CHECK:STDOUT:   %Self.as_type.loc5_14.1 => constants.%Self.as_type
+// CHECK:STDOUT: specific @F.1(constants.%Self.f0c) {
+// CHECK:STDOUT:   %Self => constants.%Self.f0c
+// CHECK:STDOUT:   %Self.as_type.loc5_14.1 => constants.%Self.as_type.308
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.28f
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%T) {
+// CHECK:STDOUT: specific @impl.b7a(constants.%T) {
 // CHECK:STDOUT:   %T.loc8_14.2 => constants.%T
 // CHECK:STDOUT:   %HasF.impl_witness => constants.%HasF.impl_witness.ec7
 // CHECK:STDOUT:
@@ -520,7 +542,7 @@ fn G(x: A) {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7dc
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%empty_struct_type) {
+// CHECK:STDOUT: specific @impl.b7a(constants.%empty_struct_type) {
 // CHECK:STDOUT:   %T.loc8_14.2 => constants.%empty_struct_type
 // CHECK:STDOUT:   %HasF.impl_witness => constants.%HasF.impl_witness.6e4
 // CHECK:STDOUT:
@@ -534,7 +556,7 @@ fn G(x: A) {
 // CHECK:STDOUT:   %pattern_type => constants.%pattern_type.a96
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete => constants.%complete_type
+// CHECK:STDOUT:   %require_complete => constants.%complete_type.357
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- deduced_type_argument.carbon

+ 57 - 35
toolchain/check/testdata/impl/lookup/impl_forall.carbon

@@ -43,6 +43,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
 // CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]
 // CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]
 // CHECK:STDOUT:   %A.13025a.1: type = class_type @A, @A(%T) [symbolic]
 // CHECK:STDOUT:   %require_complete.4aeca8.1: <witness> = require_complete_type %T [symbolic]
@@ -54,8 +55,8 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %I.generic: %I.type.dac = struct_value () [concrete]
 // CHECK:STDOUT:   %I.type.325e65.1: type = facet_type <@I, @I(%U)> [symbolic]
 // CHECK:STDOUT:   %Self.209206.1: %I.type.325e65.1 = bind_symbolic_name Self, 1 [symbolic]
-// CHECK:STDOUT:   %Self.as_type: type = facet_access_type %Self.209206.1 [symbolic]
-// CHECK:STDOUT:   %pattern_type.4be: type = pattern_type %Self.as_type [symbolic]
+// CHECK:STDOUT:   %Self.as_type.928: type = facet_access_type %Self.209206.1 [symbolic]
+// CHECK:STDOUT:   %pattern_type.4be: type = pattern_type %Self.as_type.928 [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dcd0a.1: type = pattern_type %U [symbolic]
 // CHECK:STDOUT:   %F.type.2aef59.1: type = fn_type @F.1, @I(%U) [symbolic]
 // CHECK:STDOUT:   %F.bb2dd4.1: %F.type.2aef59.1 = struct_value () [symbolic]
@@ -70,10 +71,10 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %I.assoc_type.1e5078.2: type = assoc_entity_type @I, @I(%V) [symbolic]
 // CHECK:STDOUT:   %assoc0.8f0422.2: %I.assoc_type.1e5078.2 = assoc_entity element0, @I.%F.decl [symbolic]
 // CHECK:STDOUT:   %require_complete.cfebb2.1: <witness> = require_complete_type %I.type.325e65.2 [symbolic]
-// CHECK:STDOUT:   %I.impl_witness.40ab31.1: <witness> = impl_witness file.%I.impl_witness_table, @impl(%V) [symbolic]
+// CHECK:STDOUT:   %I.impl_witness.40ab31.1: <witness> = impl_witness file.%I.impl_witness_table, @impl.27e(%V) [symbolic]
 // CHECK:STDOUT:   %pattern_type.68d8d3.1: type = pattern_type %A.13025a.2 [symbolic]
 // CHECK:STDOUT:   %pattern_type.7dcd0a.2: type = pattern_type %V [symbolic]
-// CHECK:STDOUT:   %F.type.0fea45.1: type = fn_type @F.2, @impl(%V) [symbolic]
+// CHECK:STDOUT:   %F.type.0fea45.1: type = fn_type @F.2, @impl.27e(%V) [symbolic]
 // CHECK:STDOUT:   %F.d6ae34.1: %F.type.0fea45.1 = struct_value () [symbolic]
 // CHECK:STDOUT:   %I.facet.de3: %I.type.325e65.2 = facet_value %A.13025a.2, (%I.impl_witness.40ab31.1) [symbolic]
 // CHECK:STDOUT:   %require_complete.4aeca8.2: <witness> = require_complete_type %V [symbolic]
@@ -99,8 +100,8 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %I.assoc_type.1e5078.3: type = assoc_entity_type @I, @I(%W) [symbolic]
 // CHECK:STDOUT:   %assoc0.8f0422.3: %I.assoc_type.1e5078.3 = assoc_entity element0, @I.%F.decl [symbolic]
 // CHECK:STDOUT:   %require_complete.cfebb2.2: <witness> = require_complete_type %I.type.325e65.3 [symbolic]
-// CHECK:STDOUT:   %I.impl_witness.40ab31.2: <witness> = impl_witness file.%I.impl_witness_table, @impl(%W) [symbolic]
-// CHECK:STDOUT:   %F.type.0fea45.2: type = fn_type @F.2, @impl(%W) [symbolic]
+// CHECK:STDOUT:   %I.impl_witness.40ab31.2: <witness> = impl_witness file.%I.impl_witness_table, @impl.27e(%W) [symbolic]
+// CHECK:STDOUT:   %F.type.0fea45.2: type = fn_type @F.2, @impl.27e(%W) [symbolic]
 // CHECK:STDOUT:   %F.d6ae34.2: %F.type.0fea45.2 = struct_value () [symbolic]
 // CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %A.13025a.3, @I, @I(%W) [symbolic]
 // CHECK:STDOUT:   %I.facet.6d2: %I.type.325e65.3 = facet_value %A.13025a.3, (%I.lookup_impl_witness) [symbolic]
@@ -124,20 +125,35 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %I.assoc_type.22c: type = assoc_entity_type @I, @I(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %assoc0.722: %I.assoc_type.22c = assoc_entity element0, @I.%F.decl [concrete]
 // CHECK:STDOUT:   %complete_type.788: <witness> = complete_type_witness %I.type.885 [concrete]
-// CHECK:STDOUT:   %I.impl_witness.0f2: <witness> = impl_witness file.%I.impl_witness_table, @impl(%empty_struct_type) [concrete]
-// CHECK:STDOUT:   %F.type.875: type = fn_type @F.2, @impl(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %I.impl_witness.0f2: <witness> = impl_witness file.%I.impl_witness_table, @impl.27e(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %F.type.875: type = fn_type @F.2, @impl.27e(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %F.158: %F.type.875 = struct_value () [concrete]
 // CHECK:STDOUT:   %I.facet.bd5: %I.type.885 = facet_value %A.235, (%I.impl_witness.0f2) [concrete]
 // CHECK:STDOUT:   %.8fd: type = fn_type_with_self_type %F.type.684, %I.facet.bd5 [concrete]
 // CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.158, @F.2(%empty_struct_type) [concrete]
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.eb8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.type.069: type = fn_type @Op.2, @impl.49c(%empty_struct_type) [concrete]
+// CHECK:STDOUT:   %Op.d5a: %Op.type.069 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_struct_type, (%Destroy.impl_witness.eb8) [concrete]
+// CHECK:STDOUT:   %.9da: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.d5a, @Op.2(%empty_struct_type) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -159,7 +175,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %U.loc7_13.1: type = bind_symbolic_name U, 0 [symbolic = %U.loc7_13.2 (constants.%U)]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   impl_decl @impl [concrete] {
+// CHECK:STDOUT:   impl_decl @impl.27e [concrete] {
 // CHECK:STDOUT:     %V.patt: %pattern_type.98f = symbolic_binding_pattern V, 0 [concrete]
 // CHECK:STDOUT:   } {
 // CHECK:STDOUT:     %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A.generic]
@@ -170,8 +186,8 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:     %I.type.loc11_35.1: type = facet_type <@I, @I(constants.%V)> [symbolic = %I.type.loc11_35.2 (constants.%I.type.325e65.2)]
 // CHECK:STDOUT:     %V.loc11_14.1: type = bind_symbolic_name V, 0 [symbolic = %V.loc11_14.2 (constants.%V)]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (@impl.%F.decl), @impl [concrete]
-// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table, @impl(constants.%V) [symbolic = @impl.%I.impl_witness (constants.%I.impl_witness.40ab31.1)]
+// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (@impl.27e.%F.decl), @impl.27e [concrete]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table, @impl.27e(constants.%V) [symbolic = @impl.27e.%I.impl_witness (constants.%I.impl_witness.40ab31.1)]
 // CHECK:STDOUT:   %TestGeneric.decl: %TestGeneric.type = fn_decl @TestGeneric [concrete = constants.%TestGeneric] {
 // CHECK:STDOUT:     %W.patt: %pattern_type.98f = symbolic_binding_pattern W, 0 [concrete]
 // CHECK:STDOUT:     %a.patt: @TestGeneric.%pattern_type.loc17_26 (%pattern_type.68d8d3.2) = binding_pattern a [concrete]
@@ -232,14 +248,14 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:       %return.param_patt: @F.1.%pattern_type.loc8_22 (%pattern_type.7dcd0a.1) = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:     } {
 // CHECK:STDOUT:       %U.ref: type = name_ref U, @I.%U.loc7_13.1 [symbolic = %U (constants.%U)]
-// CHECK:STDOUT:       %self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = value_param call_param0
-// CHECK:STDOUT:       %.loc8_14.1: type = splice_block %.loc8_14.3 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)] {
+// CHECK:STDOUT:       %self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type.928) = value_param call_param0
+// CHECK:STDOUT:       %.loc8_14.1: type = splice_block %.loc8_14.3 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type.928)] {
 // CHECK:STDOUT:         %.loc8_14.2: @F.1.%I.type (%I.type.325e65.1) = specific_constant @I.%Self.1, @I(constants.%U) [symbolic = %Self (constants.%Self.209206.1)]
 // CHECK:STDOUT:         %Self.ref: @F.1.%I.type (%I.type.325e65.1) = name_ref Self, %.loc8_14.2 [symbolic = %Self (constants.%Self.209206.1)]
-// CHECK:STDOUT:         %Self.as_type.loc8_14.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)]
-// CHECK:STDOUT:         %.loc8_14.3: type = converted %Self.ref, %Self.as_type.loc8_14.2 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)]
+// CHECK:STDOUT:         %Self.as_type.loc8_14.2: type = facet_access_type %Self.ref [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type.928)]
+// CHECK:STDOUT:         %.loc8_14.3: type = converted %Self.ref, %Self.as_type.loc8_14.2 [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type.928)]
 // CHECK:STDOUT:       }
-// CHECK:STDOUT:       %self: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type) = bind_name self, %self.param
+// CHECK:STDOUT:       %self: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type.928) = bind_name self, %self.param
 // CHECK:STDOUT:       %return.param: ref @F.1.%U (%U) = out_param call_param1
 // CHECK:STDOUT:       %return: ref @F.1.%U (%U) = return_slot %return.param
 // CHECK:STDOUT:     }
@@ -253,27 +269,27 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic impl @impl(%V.loc11_14.1: type) {
+// CHECK:STDOUT: generic impl @impl.27e(%V.loc11_14.1: type) {
 // CHECK:STDOUT:   %V.loc11_14.2: type = bind_symbolic_name V, 0 [symbolic = %V.loc11_14.2 (constants.%V)]
 // CHECK:STDOUT:   %A.loc11_27.2: type = class_type @A, @A(%V.loc11_14.2) [symbolic = %A.loc11_27.2 (constants.%A.13025a.2)]
 // CHECK:STDOUT:   %I.type.loc11_35.2: type = facet_type <@I, @I(%V.loc11_14.2)> [symbolic = %I.type.loc11_35.2 (constants.%I.type.325e65.2)]
 // CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc11_35.2 [symbolic = %require_complete (constants.%require_complete.cfebb2.1)]
-// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl(%V.loc11_14.2) [symbolic = %I.impl_witness (constants.%I.impl_witness.40ab31.1)]
+// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness file.%I.impl_witness_table, @impl.27e(%V.loc11_14.2) [symbolic = %I.impl_witness (constants.%I.impl_witness.40ab31.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl(%V.loc11_14.2) [symbolic = %F.type (constants.%F.type.0fea45.1)]
-// CHECK:STDOUT:   %F: @impl.%F.type (%F.type.0fea45.1) = struct_value () [symbolic = %F (constants.%F.d6ae34.1)]
+// CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl.27e(%V.loc11_14.2) [symbolic = %F.type (constants.%F.type.0fea45.1)]
+// CHECK:STDOUT:   %F: @impl.27e.%F.type (%F.type.0fea45.1) = struct_value () [symbolic = %F (constants.%F.d6ae34.1)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   impl: %A.loc11_27.1 as %I.type.loc11_35.1 {
-// CHECK:STDOUT:     %F.decl: @impl.%F.type (%F.type.0fea45.1) = fn_decl @F.2 [symbolic = @impl.%F (constants.%F.d6ae34.1)] {
+// CHECK:STDOUT:     %F.decl: @impl.27e.%F.type (%F.type.0fea45.1) = fn_decl @F.2 [symbolic = @impl.27e.%F (constants.%F.d6ae34.1)] {
 // CHECK:STDOUT:       %self.patt: @F.2.%pattern_type.loc12_8 (%pattern_type.68d8d3.1) = binding_pattern self [concrete]
 // CHECK:STDOUT:       %self.param_patt: @F.2.%pattern_type.loc12_8 (%pattern_type.68d8d3.1) = value_param_pattern %self.patt, call_param0 [concrete]
 // CHECK:STDOUT:       %return.patt: @F.2.%pattern_type.loc12_22 (%pattern_type.7dcd0a.2) = return_slot_pattern [concrete]
 // CHECK:STDOUT:       %return.param_patt: @F.2.%pattern_type.loc12_22 (%pattern_type.7dcd0a.2) = out_param_pattern %return.patt, call_param1 [concrete]
 // CHECK:STDOUT:     } {
-// CHECK:STDOUT:       %V.ref: type = name_ref V, @impl.%V.loc11_14.1 [symbolic = %V (constants.%V)]
+// CHECK:STDOUT:       %V.ref: type = name_ref V, @impl.27e.%V.loc11_14.1 [symbolic = %V (constants.%V)]
 // CHECK:STDOUT:       %self.param: @F.2.%A (%A.13025a.2) = value_param call_param0
-// CHECK:STDOUT:       %Self.ref: type = name_ref Self, @impl.%A.loc11_27.1 [symbolic = %A (constants.%A.13025a.2)]
+// CHECK:STDOUT:       %Self.ref: type = name_ref Self, @impl.27e.%A.loc11_27.1 [symbolic = %A (constants.%A.13025a.2)]
 // CHECK:STDOUT:       %self: @F.2.%A (%A.13025a.2) = bind_name self, %self.param
 // CHECK:STDOUT:       %return.param: ref @F.2.%V (%V) = out_param call_param1
 // CHECK:STDOUT:       %return: ref @F.2.%V (%V) = return_slot %return.param
@@ -314,14 +330,14 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %U: type = bind_symbolic_name U, 0 [symbolic = %U (constants.%U)]
 // CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%U)> [symbolic = %I.type (constants.%I.type.325e65.1)]
 // CHECK:STDOUT:   %Self: @F.1.%I.type (%I.type.325e65.1) = bind_symbolic_name Self, 1 [symbolic = %Self (constants.%Self.209206.1)]
-// CHECK:STDOUT:   %Self.as_type.loc8_14.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type)]
+// CHECK:STDOUT:   %Self.as_type.loc8_14.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc8_14.1 (constants.%Self.as_type.928)]
 // CHECK:STDOUT:   %pattern_type.loc8_8: type = pattern_type %Self.as_type.loc8_14.1 [symbolic = %pattern_type.loc8_8 (constants.%pattern_type.4be)]
 // CHECK:STDOUT:   %pattern_type.loc8_22: type = pattern_type %U [symbolic = %pattern_type.loc8_22 (constants.%pattern_type.7dcd0a.1)]
 // CHECK:STDOUT:
-// CHECK:STDOUT:   fn(%self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type)) -> @F.1.%U (%U);
+// CHECK:STDOUT:   fn(%self.param: @F.1.%Self.as_type.loc8_14.1 (%Self.as_type.928)) -> @F.1.%U (%U);
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: generic fn @F.2(@impl.%V.loc11_14.1: type) {
+// CHECK:STDOUT: generic fn @F.2(@impl.27e.%V.loc11_14.1: type) {
 // CHECK:STDOUT:   %V: type = bind_symbolic_name V, 0 [symbolic = %V (constants.%V)]
 // CHECK:STDOUT:   %A: type = class_type @A, @A(%V) [symbolic = %A (constants.%A.13025a.2)]
 // CHECK:STDOUT:   %pattern_type.loc12_8: type = pattern_type %A [symbolic = %pattern_type.loc12_8 (constants.%pattern_type.68d8d3.1)]
@@ -390,15 +406,21 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(constants.%empty_struct_type)> [concrete = constants.%I.type.885]
 // CHECK:STDOUT:   %.loc22_18: %I.assoc_type.22c = specific_constant @I.%assoc0.loc8_26.1, @I(constants.%empty_struct_type) [concrete = constants.%assoc0.722]
 // CHECK:STDOUT:   %F.ref: %I.assoc_type.22c = name_ref F, %.loc22_18 [concrete = constants.%assoc0.722]
-// CHECK:STDOUT:   %impl.elem0: %.8fd = impl_witness_access constants.%I.impl_witness.0f2, element0 [concrete = constants.%F.158]
-// CHECK:STDOUT:   %bound_method.loc22_11: <bound method> = bound_method %a.ref, %impl.elem0
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @F.2(constants.%empty_struct_type) [concrete = constants.%F.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc22_22: <bound method> = bound_method %a.ref, %specific_fn
-// CHECK:STDOUT:   %F.call: init %empty_struct_type = call %bound_method.loc22_22(%a.ref)
+// CHECK:STDOUT:   %impl.elem0.loc22_11: %.8fd = impl_witness_access constants.%I.impl_witness.0f2, element0 [concrete = constants.%F.158]
+// CHECK:STDOUT:   %bound_method.loc22_11: <bound method> = bound_method %a.ref, %impl.elem0.loc22_11
+// CHECK:STDOUT:   %specific_fn.loc22_11: <specific function> = specific_function %impl.elem0.loc22_11, @F.2(constants.%empty_struct_type) [concrete = constants.%F.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc22_22.1: <bound method> = bound_method %a.ref, %specific_fn.loc22_11
+// CHECK:STDOUT:   %F.call: init %empty_struct_type = call %bound_method.loc22_22.1(%a.ref)
 // CHECK:STDOUT:   %.loc22_22.1: ref %empty_struct_type = temporary_storage
 // CHECK:STDOUT:   %.loc22_22.2: ref %empty_struct_type = temporary %.loc22_22.1, %F.call
 // CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.loc22_23: %empty_struct_type = converted %F.call, %empty_struct [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %impl.elem0.loc22_22: %.9da = impl_witness_access constants.%Destroy.impl_witness.eb8, element0 [concrete = constants.%Op.d5a]
+// CHECK:STDOUT:   %bound_method.loc22_22.2: <bound method> = bound_method %.loc22_22.1, %impl.elem0.loc22_22
+// CHECK:STDOUT:   %specific_fn.loc22_22: <specific function> = specific_function %impl.elem0.loc22_22, @Op.2(constants.%empty_struct_type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc22_22.3: <bound method> = bound_method %.loc22_22.1, %specific_fn.loc22_22
+// CHECK:STDOUT:   %addr: %ptr.c28 = addr_of %.loc22_22.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc22_22.3(%addr)
 // CHECK:STDOUT:   return %.loc22_23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -414,7 +436,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %U => constants.%U
 // CHECK:STDOUT:   %I.type => constants.%I.type.325e65.1
 // CHECK:STDOUT:   %Self => constants.%Self.209206.1
-// CHECK:STDOUT:   %Self.as_type.loc8_14.1 => constants.%Self.as_type
+// CHECK:STDOUT:   %Self.as_type.loc8_14.1 => constants.%Self.as_type.928
 // CHECK:STDOUT:   %pattern_type.loc8_8 => constants.%pattern_type.4be
 // CHECK:STDOUT:   %pattern_type.loc8_22 => constants.%pattern_type.7dcd0a.1
 // CHECK:STDOUT: }
@@ -442,7 +464,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %assoc0.loc8_26.2 => constants.%assoc0.8f0422.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%V) {
+// CHECK:STDOUT: specific @impl.27e(constants.%V) {
 // CHECK:STDOUT:   %V.loc11_14.2 => constants.%V
 // CHECK:STDOUT:   %A.loc11_27.2 => constants.%A.13025a.2
 // CHECK:STDOUT:   %I.type.loc11_35.2 => constants.%I.type.325e65.2
@@ -500,7 +522,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %assoc0.loc8_26.2 => constants.%assoc0.8f0422.3
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%W) {
+// CHECK:STDOUT: specific @impl.27e(constants.%W) {
 // CHECK:STDOUT:   %V.loc11_14.2 => constants.%W
 // CHECK:STDOUT:   %A.loc11_27.2 => constants.%A.13025a.3
 // CHECK:STDOUT:   %I.type.loc11_35.2 => constants.%I.type.325e65.3
@@ -544,7 +566,7 @@ fn TestSpecific(a: A({})) -> {} {
 // CHECK:STDOUT:   %assoc0.loc8_26.2 => constants.%assoc0.722
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @impl(constants.%empty_struct_type) {
+// CHECK:STDOUT: specific @impl.27e(constants.%empty_struct_type) {
 // CHECK:STDOUT:   %V.loc11_14.2 => constants.%empty_struct_type
 // CHECK:STDOUT:   %A.loc11_27.2 => constants.%A.235
 // CHECK:STDOUT:   %I.type.loc11_35.2 => constants.%I.type.885

+ 48 - 14
toolchain/check/testdata/interface/generic_method.carbon

@@ -643,6 +643,17 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %require_complete.d4d: <witness> = require_complete_type %tuple.type.8ae [symbolic]
 // CHECK:STDOUT:   %require_complete.ed4: <witness> = require_complete_type %U.753 [symbolic]
 // CHECK:STDOUT:   %F.specific_fn.7d9: <specific function> = specific_function %F.d79, @F.2(%V1, %V2, %W, %U.753) [symbolic]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T.8b3) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %ptr.ab5: type = ptr_type %tuple.type.8ae [symbolic]
+// CHECK:STDOUT:   %require_complete.293: <witness> = require_complete_type %ptr.ab5 [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.0d1: <witness> = lookup_impl_witness %tuple.type.8ae, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.3f0: %Destroy.type = facet_value %tuple.type.8ae, (%Destroy.lookup_impl_witness.0d1) [symbolic]
+// CHECK:STDOUT:   %.a93: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.3f0 [symbolic]
+// CHECK:STDOUT:   %impl.elem0.9fc: %.a93 = impl_witness_access %Destroy.lookup_impl_witness.0d1, element0 [symbolic]
+// CHECK:STDOUT:   %specific_impl_fn.2c6: <specific function> = specific_impl_function %impl.elem0.9fc, @Op.1(%Destroy.facet.3f0) [symbolic]
 // CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]
 // CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]
 // CHECK:STDOUT:   %tuple.type.a46: type = tuple_type (%Y1, %Y2) [concrete]
@@ -663,10 +674,6 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %pattern_type.0b2: type = pattern_type %tuple.type.415 [concrete]
 // CHECK:STDOUT:   %F.specific_fn.79b: <specific function> = specific_function %F.93b, @F.2(%Y1, %Y2, %X, %Z) [concrete]
 // CHECK:STDOUT:   %Z.val: %Z = struct_value () [concrete]
-// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
-// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
-// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl.49c(%T.8b3) [symbolic]
-// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
 // CHECK:STDOUT:   %Destroy.impl_witness.347: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%Z) [concrete]
 // CHECK:STDOUT:   %Op.type.f73: type = fn_type @Op.2, @impl.49c(%Z) [concrete]
 // CHECK:STDOUT:   %Op.6e3: %Op.type.f73 = struct_value () [concrete]
@@ -698,10 +705,10 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %require_complete.500: <witness> = require_complete_type %tuple.type.e28 [symbolic]
 // CHECK:STDOUT:   %ptr.103: type = ptr_type %tuple.type.e28 [symbolic]
 // CHECK:STDOUT:   %require_complete.8d3: <witness> = require_complete_type %ptr.103 [symbolic]
-// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type.e28, @Destroy [symbolic]
-// CHECK:STDOUT:   %Destroy.facet.1a6: %Destroy.type = facet_value %tuple.type.e28, (%Destroy.lookup_impl_witness) [symbolic]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness.1a2: <witness> = lookup_impl_witness %tuple.type.e28, @Destroy [symbolic]
+// CHECK:STDOUT:   %Destroy.facet.1a6: %Destroy.type = facet_value %tuple.type.e28, (%Destroy.lookup_impl_witness.1a2) [symbolic]
 // CHECK:STDOUT:   %.efa: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.1a6 [symbolic]
-// CHECK:STDOUT:   %impl.elem0.305: %.efa = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
+// CHECK:STDOUT:   %impl.elem0.305: %.efa = impl_witness_access %Destroy.lookup_impl_witness.1a2, element0 [symbolic]
 // CHECK:STDOUT:   %specific_impl_fn.52a: <specific function> = specific_impl_function %impl.elem0.305, @Op.1(%Destroy.facet.1a6) [symbolic]
 // CHECK:STDOUT:   %CallIndirect.type: type = fn_type @CallIndirect [concrete]
 // CHECK:STDOUT:   %CallIndirect: %CallIndirect.type = struct_value () [concrete]
@@ -926,11 +933,18 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %pattern_type.loc17_24: type = pattern_type %tuple.type.loc17_42.2 [symbolic = %pattern_type.loc17_24 (constants.%pattern_type.d4a)]
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc17_24: <witness> = require_complete_type %tuple.type.loc17_42.2 [symbolic = %require_complete.loc17_24 (constants.%require_complete.d4d)]
+// CHECK:STDOUT:   %require_complete.loc17_24.1: <witness> = require_complete_type %tuple.type.loc17_42.2 [symbolic = %require_complete.loc17_24.1 (constants.%require_complete.d4d)]
 // CHECK:STDOUT:   %require_complete.loc17_19: <witness> = require_complete_type %U.loc17_8.1 [symbolic = %require_complete.loc17_19 (constants.%require_complete.ed4)]
 // CHECK:STDOUT:   %F.type: type = fn_type @F.2, @impl.220(%V1, %V2, %W) [symbolic = %F.type (constants.%F.type.b3e)]
 // CHECK:STDOUT:   %F: @F.2.%F.type (%F.type.b3e) = struct_value () [symbolic = %F (constants.%F.d79)]
 // CHECK:STDOUT:   %F.specific_fn.loc18_12.2: <specific function> = specific_function %F, @F.2(%V1, %V2, %W, %U.loc17_8.1) [symbolic = %F.specific_fn.loc18_12.2 (constants.%F.specific_fn.7d9)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type.loc17_42.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.0d1)]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type.loc17_42.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.3f0)]
+// CHECK:STDOUT:   %.loc17_24.3: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc17_24.3 (constants.%.a93)]
+// CHECK:STDOUT:   %impl.elem0.loc17_24.2: @F.2.%.loc17_24.3 (%.a93) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc17_24.2 (constants.%impl.elem0.9fc)]
+// CHECK:STDOUT:   %specific_impl_fn.loc17_24.2: <specific function> = specific_impl_function %impl.elem0.loc17_24.2, @Op.1(%Destroy.facet) [symbolic = %specific_impl_fn.loc17_24.2 (constants.%specific_impl_fn.2c6)]
+// CHECK:STDOUT:   %ptr: type = ptr_type %tuple.type.loc17_42.2 [symbolic = %ptr (constants.%ptr.ab5)]
+// CHECK:STDOUT:   %require_complete.loc17_24.2: <witness> = require_complete_type %ptr [symbolic = %require_complete.loc17_24.2 (constants.%require_complete.293)]
 // CHECK:STDOUT:
 // CHECK:STDOUT:   fn(%u.param: @F.2.%U.loc17_8.1 (%U.753)) -> %return.param: @F.2.%tuple.type.loc17_42.2 (%tuple.type.8ae) {
 // CHECK:STDOUT:   !entry:
@@ -939,8 +953,14 @@ fn CallIndirect() {
 // CHECK:STDOUT:     %U.ref.loc18: type = name_ref U, %U.loc17_8.2 [symbolic = %U.loc17_8.1 (constants.%U.753)]
 // CHECK:STDOUT:     %u.ref: @F.2.%U.loc17_8.1 (%U.753) = name_ref u, %u
 // CHECK:STDOUT:     %F.specific_fn.loc18_12.1: <specific function> = specific_function %F.ref, @F.2(constants.%V1, constants.%V2, constants.%W, constants.%U.753) [symbolic = %F.specific_fn.loc18_12.2 (constants.%F.specific_fn.7d9)]
-// CHECK:STDOUT:     %.loc17_24: ref @F.2.%tuple.type.loc17_42.2 (%tuple.type.8ae) = splice_block %return {}
-// CHECK:STDOUT:     %F.call: init @F.2.%tuple.type.loc17_42.2 (%tuple.type.8ae) = call %F.specific_fn.loc18_12.1(%u.ref) to %.loc17_24
+// CHECK:STDOUT:     %.loc17_24.1: ref @F.2.%tuple.type.loc17_42.2 (%tuple.type.8ae) = splice_block %return {}
+// CHECK:STDOUT:     %F.call: init @F.2.%tuple.type.loc17_42.2 (%tuple.type.8ae) = call %F.specific_fn.loc18_12.1(%u.ref) to %.loc17_24.1
+// CHECK:STDOUT:     %impl.elem0.loc17_24.1: @F.2.%.loc17_24.3 (%.a93) = impl_witness_access constants.%Destroy.lookup_impl_witness.0d1, element0 [symbolic = %impl.elem0.loc17_24.2 (constants.%impl.elem0.9fc)]
+// CHECK:STDOUT:     %bound_method.loc17_24.1: <bound method> = bound_method %.loc17_24.1, %impl.elem0.loc17_24.1
+// CHECK:STDOUT:     %specific_impl_fn.loc17_24.1: <specific function> = specific_impl_function %impl.elem0.loc17_24.1, @Op.1(constants.%Destroy.facet.3f0) [symbolic = %specific_impl_fn.loc17_24.2 (constants.%specific_impl_fn.2c6)]
+// CHECK:STDOUT:     %bound_method.loc17_24.2: <bound method> = bound_method %.loc17_24.1, %specific_impl_fn.loc17_24.1
+// CHECK:STDOUT:     %addr: @F.2.%ptr (%ptr.ab5) = addr_of %.loc17_24.1
+// CHECK:STDOUT:     %.loc17_24.2: init %empty_tuple.type = call %bound_method.loc17_24.2(%addr)
 // CHECK:STDOUT:     return %F.call to %return
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
@@ -999,7 +1019,7 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %specific_impl_fn.loc28_4.2: <specific function> = specific_impl_function %impl.elem0.loc28_4.2, @F.1(constants.%X, %A.facet, constants.%Z) [symbolic = %specific_impl_fn.loc28_4.2 (constants.%specific_impl_fn.e7e)]
 // CHECK:STDOUT:   %tuple.type: type = tuple_type (constants.%X, %T.as_type.loc28_4.2, constants.%Z) [symbolic = %tuple.type (constants.%tuple.type.e28)]
 // CHECK:STDOUT:   %require_complete.loc28_12.1: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc28_12.1 (constants.%require_complete.500)]
-// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.1a2)]
 // CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1a6)]
 // CHECK:STDOUT:   %.loc28_12.5: type = fn_type_with_self_type constants.%Op.type.bae, %Destroy.facet [symbolic = %.loc28_12.5 (constants.%.efa)]
 // CHECK:STDOUT:   %impl.elem0.loc28_12.2: @CallGeneric.%.loc28_12.5 (%.efa) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc28_12.2 (constants.%impl.elem0.305)]
@@ -1032,7 +1052,7 @@ fn CallIndirect() {
 // CHECK:STDOUT:     %bound_method.loc28_11.2: <bound method> = bound_method %.loc28_11.2, %specific_fn
 // CHECK:STDOUT:     %addr.loc28_11: %ptr.fb6 = addr_of %.loc28_11.2
 // CHECK:STDOUT:     %no_op: init %empty_tuple.type = call %bound_method.loc28_11.2(%addr.loc28_11)
-// CHECK:STDOUT:     %impl.elem0.loc28_12.1: @CallGeneric.%.loc28_12.5 (%.efa) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc28_12.2 (constants.%impl.elem0.305)]
+// CHECK:STDOUT:     %impl.elem0.loc28_12.1: @CallGeneric.%.loc28_12.5 (%.efa) = impl_witness_access constants.%Destroy.lookup_impl_witness.1a2, element0 [symbolic = %impl.elem0.loc28_12.2 (constants.%impl.elem0.305)]
 // CHECK:STDOUT:     %bound_method.loc28_12.1: <bound method> = bound_method %.loc28_12.1, %impl.elem0.loc28_12.1
 // CHECK:STDOUT:     %specific_impl_fn.loc28_12.1: <specific function> = specific_impl_function %impl.elem0.loc28_12.1, @Op.1(constants.%Destroy.facet.1a6) [symbolic = %specific_impl_fn.loc28_12.2 (constants.%specific_impl_fn.52a)]
 // CHECK:STDOUT:     %bound_method.loc28_12.2: <bound method> = bound_method %.loc28_12.1, %specific_impl_fn.loc28_12.1
@@ -1109,11 +1129,18 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %pattern_type.loc17_24 => constants.%pattern_type.d4a
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc17_24 => constants.%require_complete.d4d
+// CHECK:STDOUT:   %require_complete.loc17_24.1 => constants.%require_complete.d4d
 // CHECK:STDOUT:   %require_complete.loc17_19 => constants.%require_complete.ed4
 // CHECK:STDOUT:   %F.type => constants.%F.type.b3e
 // CHECK:STDOUT:   %F => constants.%F.d79
 // CHECK:STDOUT:   %F.specific_fn.loc18_12.2 => constants.%F.specific_fn.7d9
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness.0d1
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.3f0
+// CHECK:STDOUT:   %.loc17_24.3 => constants.%.a93
+// CHECK:STDOUT:   %impl.elem0.loc17_24.2 => constants.%impl.elem0.9fc
+// CHECK:STDOUT:   %specific_impl_fn.loc17_24.2 => constants.%specific_impl_fn.2c6
+// CHECK:STDOUT:   %ptr => constants.%ptr.ab5
+// CHECK:STDOUT:   %require_complete.loc17_24.2 => constants.%require_complete.293
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @F.1(constants.%W, constants.%A.facet.461, constants.%U.753) {
@@ -1165,11 +1192,18 @@ fn CallIndirect() {
 // CHECK:STDOUT:   %pattern_type.loc17_24 => constants.%pattern_type.0b2
 // CHECK:STDOUT:
 // CHECK:STDOUT: !definition:
-// CHECK:STDOUT:   %require_complete.loc17_24 => constants.%complete_type.aa8
+// CHECK:STDOUT:   %require_complete.loc17_24.1 => constants.%complete_type.aa8
 // CHECK:STDOUT:   %require_complete.loc17_19 => constants.%complete_type.357
 // CHECK:STDOUT:   %F.type => constants.%F.type.bf7
 // CHECK:STDOUT:   %F => constants.%F.93b
 // CHECK:STDOUT:   %F.specific_fn.loc18_12.2 => constants.%F.specific_fn.79b
+// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.impl_witness.c80
+// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.2b1
+// CHECK:STDOUT:   %.loc17_24.3 => constants.%.1b7
+// CHECK:STDOUT:   %impl.elem0.loc17_24.2 => constants.%Op.66e
+// CHECK:STDOUT:   %specific_impl_fn.loc17_24.2 => constants.%Op.specific_fn.ce9
+// CHECK:STDOUT:   %ptr => constants.%ptr.ad9
+// CHECK:STDOUT:   %require_complete.loc17_24.2 => constants.%complete_type.e23
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: specific @CallGeneric(constants.%T.9c2) {

+ 32 - 4
toolchain/check/testdata/namespace/shadow.carbon

@@ -64,12 +64,25 @@ fn N.M.B() -> i32 {
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -77,6 +90,9 @@ fn N.M.B() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -125,10 +141,10 @@ fn N.M.B() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %A.var: ref %i32 = var %A.var_patt
 // CHECK:STDOUT:   %int_0.loc26: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0.loc26: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc26_5.1: <bound method> = bound_method %int_0.loc26, %impl.elem0.loc26 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn.loc26: <specific function> = specific_function %impl.elem0.loc26, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc26_5.2: <bound method> = bound_method %int_0.loc26, %specific_fn.loc26 [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc26_5.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc26_5.1: <bound method> = bound_method %int_0.loc26, %impl.elem0.loc26_5.1 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc26_5.1: <specific function> = specific_function %impl.elem0.loc26_5.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_5.2: <bound method> = bound_method %int_0.loc26, %specific_fn.loc26_5.1 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked.loc26: init %i32 = call %bound_method.loc26_5.2(%int_0.loc26) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc26_5: init %i32 = converted %int_0.loc26, %int.convert_checked.loc26 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %A.var, %.loc26_5
@@ -139,6 +155,12 @@ fn N.M.B() -> i32 {
 // CHECK:STDOUT:   %A: ref %i32 = bind_name A, %A.var
 // CHECK:STDOUT:   %A.ref.loc29: ref %i32 = name_ref A, %A
 // CHECK:STDOUT:   %.loc29: %i32 = bind_value %A.ref.loc29
+// CHECK:STDOUT:   %impl.elem0.loc26_5.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc26_5.3: <bound method> = bound_method %A.var, %impl.elem0.loc26_5.2
+// CHECK:STDOUT:   %specific_fn.loc26_5.2: <specific function> = specific_function %impl.elem0.loc26_5.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_5.4: <bound method> = bound_method %A.var, %specific_fn.loc26_5.2
+// CHECK:STDOUT:   %addr.loc26_5.1: %ptr.235 = addr_of %A.var
+// CHECK:STDOUT:   %no_op.loc26_5.1: init %empty_tuple.type = call %bound_method.loc26_5.4(%addr.loc26_5.1)
 // CHECK:STDOUT:   return %.loc29
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else:
@@ -150,6 +172,12 @@ fn N.M.B() -> i32 {
 // CHECK:STDOUT:   %int.convert_checked.loc31: init %i32 = call %bound_method.loc31_11.2(%int_0.loc31) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc31_11.1: %i32 = value_of_initializer %int.convert_checked.loc31 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc31_11.2: %i32 = converted %int_0.loc31, %.loc31_11.1 [concrete = constants.%int_0.6a9]
+// CHECK:STDOUT:   %impl.elem0.loc26_5.3: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc26_5.5: <bound method> = bound_method %A.var, %impl.elem0.loc26_5.3
+// CHECK:STDOUT:   %specific_fn.loc26_5.3: <specific function> = specific_function %impl.elem0.loc26_5.3, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_5.6: <bound method> = bound_method %A.var, %specific_fn.loc26_5.3
+// CHECK:STDOUT:   %addr.loc26_5.2: %ptr.235 = addr_of %A.var
+// CHECK:STDOUT:   %no_op.loc26_5.2: init %empty_tuple.type = call %bound_method.loc26_5.6(%addr.loc26_5.2)
 // CHECK:STDOUT:   return %.loc31_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.268 = impl_witness_access constants.%AddWith.impl_witness, element1 [concrete = constants.%Op.276]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.04a = impl_witness_access constants.%BitAndWith.impl_witness, element1 [concrete = constants.%Op.c46]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -49,9 +49,10 @@ fn TestOp(a: C) -> C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %impl.elem1: %.18b = impl_witness_access constants.%BitComplement.impl_witness, element1 [concrete = constants.%Op.d4b]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc28: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc28(%a.ref) to %.loc26
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref) to %.loc26
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.b8d = impl_witness_access constants.%BitOrWith.impl_witness, element1 [concrete = constants.%Op.3e9]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.c60 = impl_witness_access constants.%BitXorWith.impl_witness, element1 [concrete = constants.%Op.ef1]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.bb6 = impl_witness_access constants.%DivWith.impl_witness, element1 [concrete = constants.%Op.5b4]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.cd9 = impl_witness_access constants.%LeftShiftWith.impl_witness, element1 [concrete = constants.%Op.4d9]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 13
toolchain/check/testdata/operators/overloaded/mod.carbon

@@ -43,15 +43,8 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
-// CHECK:STDOUT:   %Other: type = bind_symbolic_name Other, 0 [symbolic]
-// CHECK:STDOUT:   %ModWith.type.bcb: type = facet_type <@ModWith, @ModWith(%Other)> [symbolic]
-// CHECK:STDOUT:   %Self.9cc: %ModWith.type.bcb = bind_symbolic_name Self, 1 [symbolic]
 // CHECK:STDOUT:   %ModWith.type.4d0: type = facet_type <@ModWith, @ModWith(%C)> [concrete]
-// CHECK:STDOUT:   %.Self.d23: %ModWith.type.4d0 = bind_symbolic_name .Self [symbolic_self]
 // CHECK:STDOUT:   %Op.type.140: type = fn_type @Op.1, @ModWith(%C) [concrete]
-// CHECK:STDOUT:   %.Self.as_type: type = facet_access_type %.Self.d23 [symbolic_self]
-// CHECK:STDOUT:   %ModWith.lookup_impl_witness.e42: <witness> = lookup_impl_witness %.Self.d23, @ModWith, @ModWith(%C) [symbolic_self]
-// CHECK:STDOUT:   %ModWith.facet.d9a: %ModWith.type.4d0 = facet_value %.Self.as_type, (%ModWith.lookup_impl_witness.e42) [symbolic_self]
 // CHECK:STDOUT:   %ModWith.impl_witness: <witness> = impl_witness file.%ModWith.impl_witness_table [concrete]
 // CHECK:STDOUT:   %Op.type.0ad: type = fn_type @Op.6 [concrete]
 // CHECK:STDOUT:   %Op.d57: %Op.type.0ad = struct_value () [concrete]
@@ -75,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.f08 = impl_witness_access constants.%ModWith.impl_witness, element1 [concrete = constants.%Op.d57]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -93,7 +87,3 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: specific @Result(constants.%Other, constants.%Self.9cc) {}
-// CHECK:STDOUT:
-// CHECK:STDOUT: specific @Result(constants.%C, constants.%ModWith.facet.d9a) {}
-// CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.6ce = impl_witness_access constants.%MulWith.impl_witness, element1 [concrete = constants.%Op.7af]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -50,9 +50,10 @@ fn TestOp(a: C) -> C {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %impl.elem1: %.26d = impl_witness_access constants.%Negate.impl_witness, element1 [concrete = constants.%Op.045]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc29: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc29(%a.ref) to %.loc27
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref) to %.loc27
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.982 = impl_witness_access constants.%RightShiftWith.impl_witness, element1 [concrete = constants.%Op.909]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -68,9 +68,10 @@ fn TestAssign(a: C*, b: C) {
 // CHECK:STDOUT:   %a.ref: %C = name_ref a, %a
 // CHECK:STDOUT:   %b.ref: %C = name_ref b, %b
 // CHECK:STDOUT:   %impl.elem1: %.71c = impl_witness_access constants.%SubWith.impl_witness, element1 [concrete = constants.%Op.5e4]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   %bound_method.loc31: <bound method> = bound_method %a.ref, %impl.elem1
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %Op.call: init %C = call %bound_method.loc31(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %Op.call: init %C = call %bound_method(%a.ref, %b.ref) to %.loc29
 // CHECK:STDOUT:   return %Op.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 29 - 7
toolchain/check/testdata/pointer/address_of_deref.carbon

@@ -22,6 +22,7 @@ fn F() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -44,13 +45,25 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
-// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -58,6 +71,9 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -85,10 +101,10 @@ fn F() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %n.var: ref %i32 = var %n.var_patt
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc16_3.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %int_0, %impl.elem0.loc16_3.1 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc16_3.1: <specific function> = specific_function %impl.elem0.loc16_3.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %int_0, %specific_fn.loc16_3.1 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc16_3.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc16_3: init %i32 = converted %int_0, %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %n.var, %.loc16_3
@@ -98,11 +114,17 @@ fn F() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %n: ref %i32 = bind_name n, %n.var
 // CHECK:STDOUT:   %n.ref: ref %i32 = name_ref n, %n
-// CHECK:STDOUT:   %addr.loc17_13: %ptr = addr_of %n.ref
+// CHECK:STDOUT:   %addr.loc17_13: %ptr.235 = addr_of %n.ref
 // CHECK:STDOUT:   %.loc17_12: ref %i32 = deref %addr.loc17_13
-// CHECK:STDOUT:   %addr.loc17_11: %ptr = addr_of %.loc17_12
+// CHECK:STDOUT:   %addr.loc17_11: %ptr.235 = addr_of %.loc17_12
 // CHECK:STDOUT:   %.loc17_10.1: ref %i32 = deref %addr.loc17_11
 // CHECK:STDOUT:   %.loc17_10.2: %i32 = bind_value %.loc17_10.1
+// CHECK:STDOUT:   %impl.elem0.loc16_3.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc16_3.3: <bound method> = bound_method %n.var, %impl.elem0.loc16_3.2
+// CHECK:STDOUT:   %specific_fn.loc16_3.2: <specific function> = specific_function %impl.elem0.loc16_3.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_3.4: <bound method> = bound_method %n.var, %specific_fn.loc16_3.2
+// CHECK:STDOUT:   %addr.loc16: %ptr.235 = addr_of %n.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc16_3.4(%addr.loc16)
 // CHECK:STDOUT:   return %.loc17_10.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 49 - 14
toolchain/check/testdata/pointer/basic.carbon

@@ -24,6 +24,7 @@ fn F() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -46,14 +47,33 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
-// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]
-// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.711: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Op.type.ba2: type = fn_type @Op.3, @impl.49c(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Op.649: %Op.type.ba2 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.5d5: type = ptr_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2bf: %Destroy.type = facet_value %ptr.235, (%Destroy.impl_witness.711) [concrete]
+// CHECK:STDOUT:   %.a79: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.2bf [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.829: <specific function> = specific_function %Op.649, @Op.3(%ptr.235) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet.5f7: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet.5f7 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.014: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -61,6 +81,9 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -88,10 +111,10 @@ fn F() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %n.var: ref %i32 = var %n.var_patt
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %impl.elem0.loc16_3.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc16_3.1: <bound method> = bound_method %int_0, %impl.elem0.loc16_3.1 [concrete = constants.%Convert.bound]
+// CHECK:STDOUT:   %specific_fn.loc16_3.1: <specific function> = specific_function %impl.elem0.loc16_3.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_3.2: <bound method> = bound_method %int_0, %specific_fn.loc16_3.1 [concrete = constants.%bound_method]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc16_3.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc16_3: init %i32 = converted %int_0, %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %n.var, %.loc16_3
@@ -104,20 +127,32 @@ fn F() -> i32 {
 // CHECK:STDOUT:     %p.patt: %pattern_type.fe8 = binding_pattern p [concrete]
 // CHECK:STDOUT:     %p.var_patt: %pattern_type.fe8 = var_pattern %p.patt [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %p.var: ref %ptr = var %p.var_patt
+// CHECK:STDOUT:   %p.var: ref %ptr.235 = var %p.var_patt
 // CHECK:STDOUT:   %n.ref: ref %i32 = name_ref n, %n
-// CHECK:STDOUT:   %addr: %ptr = addr_of %n.ref
-// CHECK:STDOUT:   assign %p.var, %addr
-// CHECK:STDOUT:   %.loc17: type = splice_block %ptr [concrete = constants.%ptr] {
+// CHECK:STDOUT:   %addr.loc17_17: %ptr.235 = addr_of %n.ref
+// CHECK:STDOUT:   assign %p.var, %addr.loc17_17
+// CHECK:STDOUT:   %.loc17: type = splice_block %ptr [concrete = constants.%ptr.235] {
 // CHECK:STDOUT:     %int_32.loc17: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:     %i32.loc17: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
-// CHECK:STDOUT:     %ptr: type = ptr_type %i32.loc17 [concrete = constants.%ptr]
+// CHECK:STDOUT:     %ptr: type = ptr_type %i32.loc17 [concrete = constants.%ptr.235]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %p: ref %ptr = bind_name p, %p.var
-// CHECK:STDOUT:   %p.ref: ref %ptr = name_ref p, %p
-// CHECK:STDOUT:   %.loc19_11: %ptr = bind_value %p.ref
+// CHECK:STDOUT:   %p: ref %ptr.235 = bind_name p, %p.var
+// CHECK:STDOUT:   %p.ref: ref %ptr.235 = name_ref p, %p
+// CHECK:STDOUT:   %.loc19_11: %ptr.235 = bind_value %p.ref
 // CHECK:STDOUT:   %.loc19_10.1: ref %i32 = deref %.loc19_11
 // CHECK:STDOUT:   %.loc19_10.2: %i32 = bind_value %.loc19_10.1
+// CHECK:STDOUT:   %impl.elem0.loc17: %.a79 = impl_witness_access constants.%Destroy.impl_witness.711, element0 [concrete = constants.%Op.649]
+// CHECK:STDOUT:   %bound_method.loc17_3.1: <bound method> = bound_method %p.var, %impl.elem0.loc17
+// CHECK:STDOUT:   %specific_fn.loc17: <specific function> = specific_function %impl.elem0.loc17, @Op.3(constants.%ptr.235) [concrete = constants.%Op.specific_fn.829]
+// CHECK:STDOUT:   %bound_method.loc17_3.2: <bound method> = bound_method %p.var, %specific_fn.loc17
+// CHECK:STDOUT:   %addr.loc17_3: %ptr.5d5 = addr_of %p.var
+// CHECK:STDOUT:   %no_op.loc17: init %empty_tuple.type = call %bound_method.loc17_3.2(%addr.loc17_3)
+// CHECK:STDOUT:   %impl.elem0.loc16_3.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc16_3.3: <bound method> = bound_method %n.var, %impl.elem0.loc16_3.2
+// CHECK:STDOUT:   %specific_fn.loc16_3.2: <specific function> = specific_function %impl.elem0.loc16_3.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn.014]
+// CHECK:STDOUT:   %bound_method.loc16_3.4: <bound method> = bound_method %n.var, %specific_fn.loc16_3.2
+// CHECK:STDOUT:   %addr.loc16: %ptr.235 = addr_of %n.var
+// CHECK:STDOUT:   %no_op.loc16: init %empty_tuple.type = call %bound_method.loc16_3.4(%addr.loc16)
 // CHECK:STDOUT:   return %.loc19_10.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 27 - 4
toolchain/check/testdata/return/fail_return_with_returned_var.carbon

@@ -42,6 +42,7 @@ fn G() -> C {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -65,6 +66,18 @@ fn G() -> C {
 // CHECK:STDOUT:   %bound_method.b6e: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]
 // CHECK:STDOUT:   %struct_type.a.b.501: type = struct_type {.a: %i32, .b: %i32} [concrete]
@@ -87,6 +100,7 @@ fn G() -> C {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -94,6 +108,9 @@ fn G() -> C {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -149,10 +166,10 @@ fn G() -> C {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc16_12.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc16_12.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc16_12.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc16_12.1: <bound method> = bound_method %int_0, %impl.elem0.loc16_12.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc16_12.1: <specific function> = specific_function %impl.elem0.loc16_12.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_12.2: <bound method> = bound_method %int_0, %specific_fn.loc16_12.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc16_12.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc16_12: init %i32 = converted %int_0, %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %v.var, %.loc16_12
@@ -162,6 +179,12 @@ fn G() -> C {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v: ref %i32 = bind_name v, %v.var
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
+// CHECK:STDOUT:   %impl.elem0.loc16_12.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc16_12.3: <bound method> = bound_method %v.var, %impl.elem0.loc16_12.2
+// CHECK:STDOUT:   %specific_fn.loc16_12.2: <specific function> = specific_function %impl.elem0.loc16_12.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc16_12.4: <bound method> = bound_method %v.var, %specific_fn.loc16_12.2
+// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc16_12.4(%addr)
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 50 - 6
toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon

@@ -54,15 +54,31 @@ fn ForgotReturnType() {
 // CHECK:STDOUT:   %Procedure.type: type = fn_type @Procedure [concrete]
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Procedure: %Procedure.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -77,8 +93,8 @@ fn ForgotReturnType() {
 // CHECK:STDOUT: fn @Procedure() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %v.patt: %pattern_type = binding_pattern v [concrete]
-// CHECK:STDOUT:     %v.var_patt: %pattern_type = var_pattern %v.patt [concrete]
+// CHECK:STDOUT:     %v.patt: %pattern_type.cb1 = binding_pattern v [concrete]
+// CHECK:STDOUT:     %v.var_patt: %pattern_type.cb1 = var_pattern %v.patt [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %empty_tuple.type = var %v.var_patt
 // CHECK:STDOUT:   %.loc12_25.1: %empty_tuple.type = tuple_literal ()
@@ -90,6 +106,12 @@ fn ForgotReturnType() {
 // CHECK:STDOUT:     %.loc12_20.3: type = converted %.loc12_20.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v: ref %empty_tuple.type = bind_name v, %v.var
+// CHECK:STDOUT:   %impl.elem0: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:   %bound_method.loc12_12.1: <bound method> = bound_method %v.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc12_12.2: <bound method> = bound_method %v.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %v.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc12_12.2(%addr)
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -99,15 +121,31 @@ fn ForgotReturnType() {
 // CHECK:STDOUT:   %ForgotReturnType.type: type = fn_type @ForgotReturnType [concrete]
 // CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %ForgotReturnType: %ForgotReturnType.type = struct_value () [concrete]
-// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]
 // CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.1dc: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.type.a63: type = fn_type @Op.2, @impl(%empty_tuple.type) [concrete]
+// CHECK:STDOUT:   %Op.ea3: %Op.type.a63 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %empty_tuple.type, (%Destroy.impl_witness.1dc) [concrete]
+// CHECK:STDOUT:   %.346: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.ea3, @Op.2(%empty_tuple.type) [concrete]
 // 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:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -122,8 +160,8 @@ fn ForgotReturnType() {
 // CHECK:STDOUT: fn @ForgotReturnType() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   name_binding_decl {
-// CHECK:STDOUT:     %v.patt: %pattern_type = binding_pattern v [concrete]
-// CHECK:STDOUT:     %v.var_patt: %pattern_type = var_pattern %v.patt [concrete]
+// CHECK:STDOUT:     %v.patt: %pattern_type.cb1 = binding_pattern v [concrete]
+// CHECK:STDOUT:     %v.var_patt: %pattern_type.cb1 = var_pattern %v.patt [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %empty_tuple.type = var %v.var_patt
 // CHECK:STDOUT:   %.loc12_25.1: %empty_tuple.type = tuple_literal ()
@@ -135,6 +173,12 @@ fn ForgotReturnType() {
 // CHECK:STDOUT:     %.loc12_20.3: type = converted %.loc12_20.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v: ref %empty_tuple.type = bind_name v, %v.var
+// CHECK:STDOUT:   %impl.elem0: %.346 = impl_witness_access constants.%Destroy.impl_witness.1dc, element0 [concrete = constants.%Op.ea3]
+// CHECK:STDOUT:   %bound_method.loc12_12.1: <bound method> = bound_method %v.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%empty_tuple.type) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc12_12.2: <bound method> = bound_method %v.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %v.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc12_12.2(%addr)
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 57 - 16
toolchain/check/testdata/return/fail_returned_var_shadow.carbon

@@ -49,6 +49,7 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -76,6 +77,18 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT:   %DifferentScopes.type: type = fn_type @DifferentScopes [concrete]
 // CHECK:STDOUT:   %DifferentScopes: %DifferentScopes.type = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -84,6 +97,7 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -91,6 +105,9 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -132,10 +149,10 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_0.loc17: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0.loc17: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc17_14.1: <bound method> = bound_method %int_0.loc17, %impl.elem0.loc17 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn.loc17: <specific function> = specific_function %impl.elem0.loc17, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc17_14.2: <bound method> = bound_method %int_0.loc17, %specific_fn.loc17 [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc17_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc17_14.1: <bound method> = bound_method %int_0.loc17, %impl.elem0.loc17_14.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc17_14.1: <specific function> = specific_function %impl.elem0.loc17_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc17_14.2: <bound method> = bound_method %int_0.loc17, %specific_fn.loc17_14.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked.loc17: init %i32 = call %bound_method.loc17_14.2(%int_0.loc17) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc17_14: init %i32 = converted %int_0.loc17, %int.convert_checked.loc17 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %v.var, %.loc17_14
@@ -150,10 +167,10 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %w.var: ref %i32 = var %w.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0.loc25: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc25_14.1: <bound method> = bound_method %int_1, %impl.elem0.loc25 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn.loc25: <specific function> = specific_function %impl.elem0.loc25, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc25_14.2: <bound method> = bound_method %int_1, %specific_fn.loc25 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc25_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc25_14.1: <bound method> = bound_method %int_1, %impl.elem0.loc25_14.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc25_14.1: <specific function> = specific_function %impl.elem0.loc25_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc25_14.2: <bound method> = bound_method %int_1, %specific_fn.loc25_14.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked.loc25: init %i32 = call %bound_method.loc25_14.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc25_14: init %i32 = converted %int_1, %int.convert_checked.loc25 [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %w.var, %.loc25_14
@@ -173,6 +190,18 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   %int.convert_checked.loc27: init %i32 = call %bound_method.loc27_11.2(%int_0.loc27) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc27_11.1: %i32 = value_of_initializer %int.convert_checked.loc27 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc27_11.2: %i32 = converted %int_0.loc27, %.loc27_11.1 [concrete = constants.%int_0.6a9]
+// CHECK:STDOUT:   %impl.elem0.loc25_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc25_14.3: <bound method> = bound_method %w.var, %impl.elem0.loc25_14.2
+// CHECK:STDOUT:   %specific_fn.loc25_14.2: <specific function> = specific_function %impl.elem0.loc25_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc25_14.4: <bound method> = bound_method %w.var, %specific_fn.loc25_14.2
+// CHECK:STDOUT:   %addr.loc25: %ptr.235 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc25: init %empty_tuple.type = call %bound_method.loc25_14.4(%addr.loc25)
+// CHECK:STDOUT:   %impl.elem0.loc17_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc17_14.3: <bound method> = bound_method %v.var, %impl.elem0.loc17_14.2
+// CHECK:STDOUT:   %specific_fn.loc17_14.2: <specific function> = specific_function %impl.elem0.loc17_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc17_14.4: <bound method> = bound_method %v.var, %specific_fn.loc17_14.2
+// CHECK:STDOUT:   %addr.loc17: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc17: init %empty_tuple.type = call %bound_method.loc17_14.4(%addr.loc17)
 // CHECK:STDOUT:   return %.loc27_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -188,10 +217,10 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_0.loc32: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0.loc32: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc32_14.1: <bound method> = bound_method %int_0.loc32, %impl.elem0.loc32 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn.loc32: <specific function> = specific_function %impl.elem0.loc32, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc32_14.2: <bound method> = bound_method %int_0.loc32, %specific_fn.loc32 [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc32_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc32_14.1: <bound method> = bound_method %int_0.loc32, %impl.elem0.loc32_14.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc32_14.1: <specific function> = specific_function %impl.elem0.loc32_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc32_14.2: <bound method> = bound_method %int_0.loc32, %specific_fn.loc32_14.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked.loc32: init %i32 = call %bound_method.loc32_14.2(%int_0.loc32) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc32_14: init %i32 = converted %int_0.loc32, %int.convert_checked.loc32 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %v.var, %.loc32_14
@@ -210,10 +239,10 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %w.var: ref %i32 = var %w.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0.loc41: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc41_16.1: <bound method> = bound_method %int_1, %impl.elem0.loc41 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn.loc41: <specific function> = specific_function %impl.elem0.loc41, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc41_16.2: <bound method> = bound_method %int_1, %specific_fn.loc41 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc41_16.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc41_16.1: <bound method> = bound_method %int_1, %impl.elem0.loc41_16.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc41_16.1: <specific function> = specific_function %impl.elem0.loc41_16.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc41_16.2: <bound method> = bound_method %int_1, %specific_fn.loc41_16.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked.loc41: init %i32 = call %bound_method.loc41_16.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc41_16: init %i32 = converted %int_1, %int.convert_checked.loc41 [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %w.var, %.loc41_16
@@ -236,6 +265,18 @@ fn DifferentScopes() -> i32 {
 // CHECK:STDOUT:   %int.convert_checked.loc44: init %i32 = call %bound_method.loc44_11.2(%int_0.loc44) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc44_11.1: %i32 = value_of_initializer %int.convert_checked.loc44 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc44_11.2: %i32 = converted %int_0.loc44, %.loc44_11.1 [concrete = constants.%int_0.6a9]
+// CHECK:STDOUT:   %impl.elem0.loc41_16.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc41_16.3: <bound method> = bound_method %w.var, %impl.elem0.loc41_16.2
+// CHECK:STDOUT:   %specific_fn.loc41_16.2: <specific function> = specific_function %impl.elem0.loc41_16.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc41_16.4: <bound method> = bound_method %w.var, %specific_fn.loc41_16.2
+// CHECK:STDOUT:   %addr.loc41: %ptr.235 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc41: init %empty_tuple.type = call %bound_method.loc41_16.4(%addr.loc41)
+// CHECK:STDOUT:   %impl.elem0.loc32_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc32_14.3: <bound method> = bound_method %v.var, %impl.elem0.loc32_14.2
+// CHECK:STDOUT:   %specific_fn.loc32_14.2: <specific function> = specific_function %impl.elem0.loc32_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc32_14.4: <bound method> = bound_method %v.var, %specific_fn.loc32_14.2
+// CHECK:STDOUT:   %addr.loc32: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc32: init %empty_tuple.type = call %bound_method.loc32_14.4(%addr.loc32)
 // CHECK:STDOUT:   return %.loc44_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 0
toolchain/check/testdata/return/fail_returned_var_type.carbon

@@ -29,6 +29,7 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -39,17 +40,33 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.3de: type = pattern_type f64 [concrete]
 // CHECK:STDOUT:   %float: f64 = float_literal 0 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.add: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(f64) [concrete]
+// CHECK:STDOUT:   %Op.type.3ef: type = fn_type @Op.2, @impl(f64) [concrete]
+// CHECK:STDOUT:   %Op.868: %Op.type.3ef = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.ef1: type = ptr_type f64 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value f64, (%Destroy.impl_witness.add) [concrete]
+// CHECK:STDOUT:   %.e7e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.868, @Op.2(f64) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .Float = %Core.Float
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
 // CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -86,6 +103,12 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v: ref f64 = bind_name v, %v.var
 // CHECK:STDOUT:   %.loc23_16: f64 = bind_value %v
+// CHECK:STDOUT:   %impl.elem0: %.e7e = impl_witness_access constants.%Destroy.impl_witness.add, element0 [concrete = constants.%Op.868]
+// CHECK:STDOUT:   %bound_method.loc23_12.1: <bound method> = bound_method %v.var, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(f64) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc23_12.2: <bound method> = bound_method %v.var, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.ef1 = addr_of %v.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc23_12.2(%addr)
 // CHECK:STDOUT:   return %.loc23_16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 714 - 42
toolchain/check/testdata/return/import_convert_function.carbon

@@ -52,6 +52,7 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %N.51e: %i32 = bind_symbolic_name N, 0 [symbolic]
@@ -93,6 +94,18 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %pattern_type.f33: type = pattern_type %C.c8d [concrete]
 // CHECK:STDOUT:   %Convert.type.cd0: type = fn_type @Convert.7 [concrete]
 // CHECK:STDOUT:   %Convert.b95: %Convert.type.cd0 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.45e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%D) [concrete]
+// CHECK:STDOUT:   %Op.type.548: type = fn_type @Op.3, @impl.49c(%D) [concrete]
+// CHECK:STDOUT:   %Op.2d4: %Op.type.548 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.19c: type = ptr_type %D [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %D, (%Destroy.impl_witness.45e) [concrete]
+// CHECK:STDOUT:   %.64e: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.2d4, @Op.3(%D) [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
@@ -162,6 +175,7 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -169,6 +183,9 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -582,6 +599,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc8: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc8
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc8_60.1: <bound method> = bound_method %.loc8, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_60.2: <bound method> = bound_method %.loc8, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc8
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc8_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -590,6 +613,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc9: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc9
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc9_60.1: <bound method> = bound_method %.loc9, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_60.2: <bound method> = bound_method %.loc9, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc9
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc9_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -598,6 +627,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc10: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc10
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc10_60.1: <bound method> = bound_method %.loc10, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc10_60.2: <bound method> = bound_method %.loc10, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc10
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc10_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -606,6 +641,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc11: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc11
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc11_60.1: <bound method> = bound_method %.loc11, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_60.2: <bound method> = bound_method %.loc11, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc11
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc11_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -614,6 +655,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc12: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc12
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc12_60.1: <bound method> = bound_method %.loc12, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc12_60.2: <bound method> = bound_method %.loc12, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc12
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc12_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -622,6 +669,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc13: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc13
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc13_60.1: <bound method> = bound_method %.loc13, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_60.2: <bound method> = bound_method %.loc13, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc13
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc13_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -630,6 +683,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc14: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc14
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc14_60.1: <bound method> = bound_method %.loc14, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc14_60.2: <bound method> = bound_method %.loc14, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc14
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc14_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -638,6 +697,12 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc15: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc15
+// CHECK:STDOUT:   %impl.elem0: %.64e = impl_witness_access constants.%Destroy.impl_witness.45e, element0 [concrete = constants.%Op.2d4]
+// CHECK:STDOUT:   %bound_method.loc15_60.1: <bound method> = bound_method %.loc15, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%D) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_60.2: <bound method> = bound_method %.loc15, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.19c = addr_of %.loc15
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc15_60.2(%addr)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -698,6 +763,7 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -734,6 +800,10 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %C.val.452: %C.b00 = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.5f9: type = facet_type <@ImplicitAs, @ImplicitAs(%D)> [concrete]
 // CHECK:STDOUT:   %Convert.type.334: type = fn_type @Convert.1, @ImplicitAs(%D) [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.6ba: type = fn_type @Op.2, @impl.2b5(%T) [symbolic]
+// CHECK:STDOUT:   %Op.f4a: %Op.type.6ba = struct_value () [symbolic]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
 // CHECK:STDOUT:   %C.674: type = class_type @C, @C(%int_1.5d2) [concrete]
 // CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]
@@ -753,6 +823,21 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.a9c: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.014 [concrete]
 // CHECK:STDOUT:   %Convert.type.971: type = fn_type @Convert.7 [concrete]
 // CHECK:STDOUT:   %Convert.bf9: %Convert.type.971 = struct_value () [concrete]
+// CHECK:STDOUT:   %Op.type.625: type = fn_type @Op.3 [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.a3f: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%D) [concrete]
+// CHECK:STDOUT:   %Op.type.69c: type = fn_type @Op.2, @impl.2b5(%D) [concrete]
+// CHECK:STDOUT:   %Op.f5a: %Op.type.69c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.f29: type = ptr_type %D [concrete]
+// CHECK:STDOUT:   %Destroy.facet.2d4: %Destroy.type = facet_value %D, (%Destroy.impl_witness.a3f) [concrete]
+// CHECK:STDOUT:   %.d1e: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.2d4 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.bd1: <specific function> = specific_function %Op.f5a, @Op.2(%D) [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.ce3: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.b00) [concrete]
+// CHECK:STDOUT:   %Op.type.94c: type = fn_type @Op.2, @impl.2b5(%C.b00) [concrete]
+// CHECK:STDOUT:   %Op.ae6: %Op.type.94c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.697: type = ptr_type %C.b00 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.f7c: %Destroy.type = facet_value %C.b00, (%Destroy.impl_witness.ce3) [concrete]
+// CHECK:STDOUT:   %.cde: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.f7c [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.e42: <specific function> = specific_function %Op.ae6, @Op.2(%C.b00) [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
@@ -762,6 +847,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.7d6: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.b8a [concrete]
 // CHECK:STDOUT:   %Convert.type.bdd: type = fn_type @Convert.8 [concrete]
 // CHECK:STDOUT:   %Convert.c82: %Convert.type.bdd = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.af9: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.674) [concrete]
+// CHECK:STDOUT:   %Op.type.b6b: type = fn_type @Op.2, @impl.2b5(%C.674) [concrete]
+// CHECK:STDOUT:   %Op.ad8: %Op.type.b6b = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.625: type = ptr_type %C.674 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.b44: %Destroy.type = facet_value %C.674, (%Destroy.impl_witness.af9) [concrete]
+// CHECK:STDOUT:   %.42d: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.b44 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.6b6: <specific function> = specific_function %Op.ad8, @Op.2(%C.674) [concrete]
 // CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
 // CHECK:STDOUT:   %Convert.bound.ef9: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.b92: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
@@ -771,6 +863,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.987: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.d55 [concrete]
 // CHECK:STDOUT:   %Convert.type.4c1: type = fn_type @Convert.9 [concrete]
 // CHECK:STDOUT:   %Convert.08c: %Convert.type.4c1 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.3a3: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.681) [concrete]
+// CHECK:STDOUT:   %Op.type.a31: type = fn_type @Op.2, @impl.2b5(%C.681) [concrete]
+// CHECK:STDOUT:   %Op.404: %Op.type.a31 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.3bd: type = ptr_type %C.681 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.1fc: %Destroy.type = facet_value %C.681, (%Destroy.impl_witness.3a3) [concrete]
+// CHECK:STDOUT:   %.715: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.1fc [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.822: <specific function> = specific_function %Op.404, @Op.2(%C.681) [concrete]
 // CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
@@ -780,6 +879,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.efa: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.aa1 [concrete]
 // CHECK:STDOUT:   %Convert.type.f89: type = fn_type @Convert.10 [concrete]
 // CHECK:STDOUT:   %Convert.2dd: %Convert.type.f89 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.4d8: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.7ac) [concrete]
+// CHECK:STDOUT:   %Op.type.100: type = fn_type @Op.2, @impl.2b5(%C.7ac) [concrete]
+// CHECK:STDOUT:   %Op.9cf: %Op.type.100 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.2b1: type = ptr_type %C.7ac [concrete]
+// CHECK:STDOUT:   %Destroy.facet.8c9: %Destroy.type = facet_value %C.7ac, (%Destroy.impl_witness.4d8) [concrete]
+// CHECK:STDOUT:   %.f23: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.8c9 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.694: <specific function> = specific_function %Op.9cf, @Op.2(%C.7ac) [concrete]
 // CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]
 // CHECK:STDOUT:   %Convert.bound.ac3: <bound method> = bound_method %int_4.0c1, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.1da: <bound method> = bound_method %int_4.0c1, %Convert.specific_fn [concrete]
@@ -789,6 +895,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.26e: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.750 [concrete]
 // CHECK:STDOUT:   %Convert.type.2ce: type = fn_type @Convert.11 [concrete]
 // CHECK:STDOUT:   %Convert.009: %Convert.type.2ce = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.f66: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.89d) [concrete]
+// CHECK:STDOUT:   %Op.type.86c: type = fn_type @Op.2, @impl.2b5(%C.89d) [concrete]
+// CHECK:STDOUT:   %Op.6b4: %Op.type.86c = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.c28b: type = ptr_type %C.89d [concrete]
+// CHECK:STDOUT:   %Destroy.facet.fe4: %Destroy.type = facet_value %C.89d, (%Destroy.impl_witness.f66) [concrete]
+// CHECK:STDOUT:   %.6ca: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.fe4 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.357: <specific function> = specific_function %Op.6b4, @Op.2(%C.89d) [concrete]
 // CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]
 // CHECK:STDOUT:   %Convert.bound.4e6: <bound method> = bound_method %int_5.64b, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.a25: <bound method> = bound_method %int_5.64b, %Convert.specific_fn [concrete]
@@ -798,6 +911,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.eaf: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.8cc [concrete]
 // CHECK:STDOUT:   %Convert.type.e9d: type = fn_type @Convert.12 [concrete]
 // CHECK:STDOUT:   %Convert.b66: %Convert.type.e9d = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.818: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.f0a) [concrete]
+// CHECK:STDOUT:   %Op.type.4df: type = fn_type @Op.2, @impl.2b5(%C.f0a) [concrete]
+// CHECK:STDOUT:   %Op.985: %Op.type.4df = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.24c: type = ptr_type %C.f0a [concrete]
+// CHECK:STDOUT:   %Destroy.facet.7eb: %Destroy.type = facet_value %C.f0a, (%Destroy.impl_witness.818) [concrete]
+// CHECK:STDOUT:   %.89c: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.7eb [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.a66: <specific function> = specific_function %Op.985, @Op.2(%C.f0a) [concrete]
 // CHECK:STDOUT:   %int_6.462: Core.IntLiteral = int_value 6 [concrete]
 // CHECK:STDOUT:   %Convert.bound.ce9: <bound method> = bound_method %int_6.462, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.efa: <bound method> = bound_method %int_6.462, %Convert.specific_fn [concrete]
@@ -807,6 +927,13 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.874: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.a69 [concrete]
 // CHECK:STDOUT:   %Convert.type.4b8: type = fn_type @Convert.13 [concrete]
 // CHECK:STDOUT:   %Convert.f59: %Convert.type.4b8 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.1e4: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.c60) [concrete]
+// CHECK:STDOUT:   %Op.type.32d: type = fn_type @Op.2, @impl.2b5(%C.c60) [concrete]
+// CHECK:STDOUT:   %Op.ca5: %Op.type.32d = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.b5e: type = ptr_type %C.c60 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.83d: %Destroy.type = facet_value %C.c60, (%Destroy.impl_witness.1e4) [concrete]
+// CHECK:STDOUT:   %.3d7: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.83d [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.8d0: <specific function> = specific_function %Op.ca5, @Op.2(%C.c60) [concrete]
 // CHECK:STDOUT:   %int_7.29f: Core.IntLiteral = int_value 7 [concrete]
 // CHECK:STDOUT:   %Convert.bound.208: <bound method> = bound_method %int_7.29f, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.3bd: <bound method> = bound_method %int_7.29f, %Convert.specific_fn [concrete]
@@ -816,14 +943,22 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.79b: type = fn_type_with_self_type %Convert.type.334, %ImplicitAs.facet.cca [concrete]
 // CHECK:STDOUT:   %Convert.type.c7e: type = fn_type @Convert.14 [concrete]
 // CHECK:STDOUT:   %Convert.6c1: %Convert.type.c7e = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.impl_witness.cc5: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.2b5(%C.304) [concrete]
+// CHECK:STDOUT:   %Op.type.986: type = fn_type @Op.2, @impl.2b5(%C.304) [concrete]
+// CHECK:STDOUT:   %Op.6fc: %Op.type.986 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.dc3: type = ptr_type %C.304 [concrete]
+// CHECK:STDOUT:   %Destroy.facet.143: %Destroy.type = facet_value %C.304, (%Destroy.impl_witness.cc5) [concrete]
+// CHECK:STDOUT:   %.3a6: type = fn_type_with_self_type %Op.type.625, %Destroy.facet.143 [concrete]
+// CHECK:STDOUT:   %Op.specific_fn.a08: <specific function> = specific_function %Op.6fc, @Op.2(%C.304) [concrete]
 // CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]
 // CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
-// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
+// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -849,6 +984,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %P.import_ref.708: <witness> = import_ref P//library, loc8_33, loaded [concrete = constants.%ImplicitAs.impl_witness.f53]
 // CHECK:STDOUT:   %P.import_ref.d2c: type = import_ref P//library, loc8_9, loaded [concrete = constants.%C.b00]
 // CHECK:STDOUT:   %P.import_ref.b769fa.1: type = import_ref P//library, loc8_31, loaded [concrete = constants.%ImplicitAs.type.5f9]
+// CHECK:STDOUT:   %P.import_ref.544: @impl.2b5.%Op.type (%Op.type.6ba) = import_ref P//library, inst478 [indirect], loaded [symbolic = @impl.2b5.%Op (constants.%Op.f4a)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%P.import_ref.544), @impl.2b5 [concrete]
 // CHECK:STDOUT:   %P.import_ref.ae8: <witness> = import_ref P//library, loc9_33, loaded [concrete = constants.%ImplicitAs.impl_witness.fcb]
 // CHECK:STDOUT:   %P.import_ref.cf3: type = import_ref P//library, loc9_9, loaded [concrete = constants.%C.674]
 // CHECK:STDOUT:   %P.import_ref.b769fa.2: type = import_ref P//library, loc9_31, loaded [concrete = constants.%ImplicitAs.type.5f9]
@@ -872,6 +1009,7 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %P.import_ref.b769fa.8: type = import_ref P//library, loc15_31, loaded [concrete = constants.%ImplicitAs.type.5f9]
 // CHECK:STDOUT:   %P.import_ref.e36: %Convert.type.971 = import_ref P//library, loc8_65, loaded [concrete = constants.%Convert.bf9]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.f4b = impl_witness_table (%P.import_ref.e36), @impl.284 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
 // CHECK:STDOUT:   %P.import_ref.38e: %Convert.type.bdd = import_ref P//library, loc9_65, loaded [concrete = constants.%Convert.c82]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.297 = impl_witness_table (%P.import_ref.38e), @impl.628 [concrete]
 // CHECK:STDOUT:   %P.import_ref.5ab: %Convert.type.4c1 = import_ref P//library, loc10_65, loaded [concrete = constants.%Convert.08c]
@@ -891,7 +1029,7 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [concrete] {
-// CHECK:STDOUT:     .Core = imports.%Core
+// CHECK:STDOUT:     .Core = imports.%Core.ece
 // CHECK:STDOUT:     .P = imports.%P
 // CHECK:STDOUT:     .F0 = %F0.decl
 // CHECK:STDOUT:   }
@@ -990,8 +1128,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
 // CHECK:STDOUT:   %impl.elem0.loc7_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc7_34.1: <bound method> = bound_method %int_0, %impl.elem0.loc7_34 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc7_34.2: <bound method> = bound_method %int_0, %specific_fn.loc7 [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %specific_fn.loc7_34: <specific function> = specific_function %impl.elem0.loc7_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_34.2: <bound method> = bound_method %int_0, %specific_fn.loc7_34 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked.loc7: init %i32 = call %bound_method.loc7_34.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc7_34.1: %i32 = value_of_initializer %int.convert_checked.loc7 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc7_34.2: %i32 = converted %int_0, %.loc7_34.1 [concrete = constants.%int_0.6a9]
@@ -1000,12 +1138,24 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc7_24.3: init %C.b00 = class_init (), %.loc7_24.2 [concrete = constants.%C.val.452]
 // CHECK:STDOUT:   %.loc7_24.4: ref %C.b00 = temporary %.loc7_24.2, %.loc7_24.3
 // CHECK:STDOUT:   %.loc7_26.1: ref %C.b00 = converted %.loc7_24.1, %.loc7_24.4
-// CHECK:STDOUT:   %impl.elem0.loc7_35: %.a9c = impl_witness_access constants.%ImplicitAs.impl_witness.f53, element0 [concrete = constants.%Convert.bf9]
-// CHECK:STDOUT:   %bound_method.loc7_35: <bound method> = bound_method %.loc7_26.1, %impl.elem0.loc7_35
+// CHECK:STDOUT:   %impl.elem0.loc7_35.1: %.a9c = impl_witness_access constants.%ImplicitAs.impl_witness.f53, element0 [concrete = constants.%Convert.bf9]
+// CHECK:STDOUT:   %bound_method.loc7_35.1: <bound method> = bound_method %.loc7_26.1, %impl.elem0.loc7_35.1
 // CHECK:STDOUT:   %.loc7_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc7_26.2: %C.b00 = bind_value %.loc7_26.1
-// CHECK:STDOUT:   %Convert.call.loc7: init %D = call %bound_method.loc7_35(%.loc7_26.2) to %.loc7_35.1
+// CHECK:STDOUT:   %Convert.call.loc7: init %D = call %bound_method.loc7_35.1(%.loc7_26.2) to %.loc7_35.1
 // CHECK:STDOUT:   %.loc7_35.2: init %D = converted %.loc7_26.1, %Convert.call.loc7
+// CHECK:STDOUT:   %impl.elem0.loc7_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.2: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.2
+// CHECK:STDOUT:   %specific_fn.loc7_35.1: <specific function> = specific_function %impl.elem0.loc7_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.3: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.1
+// CHECK:STDOUT:   %addr.loc7_35.1: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.1: init %empty_tuple.type = call %bound_method.loc7_35.3(%addr.loc7_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.1: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.1: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.1
+// CHECK:STDOUT:   %specific_fn.loc7_24.1: <specific function> = specific_function %impl.elem0.loc7_24.1, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.2: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.1
+// CHECK:STDOUT:   %addr.loc7_24.1: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.1: init %empty_tuple.type = call %bound_method.loc7_24.2(%addr.loc7_24.1)
 // CHECK:STDOUT:   return %.loc7_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc7:
@@ -1019,8 +1169,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %impl.elem0.loc8_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc8_34.1: <bound method> = bound_method %int_1, %impl.elem0.loc8_34 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc8_34.2: <bound method> = bound_method %int_1, %specific_fn.loc8 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %specific_fn.loc8_34: <specific function> = specific_function %impl.elem0.loc8_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_34.2: <bound method> = bound_method %int_1, %specific_fn.loc8_34 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked.loc8: init %i32 = call %bound_method.loc8_34.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc8_34.1: %i32 = value_of_initializer %int.convert_checked.loc8 [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc8_34.2: %i32 = converted %int_1, %.loc8_34.1 [concrete = constants.%int_1.5d2]
@@ -1029,12 +1179,36 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc8_24.3: init %C.674 = class_init (), %.loc8_24.2 [concrete = constants.%C.val.678]
 // CHECK:STDOUT:   %.loc8_24.4: ref %C.674 = temporary %.loc8_24.2, %.loc8_24.3
 // CHECK:STDOUT:   %.loc8_26.1: ref %C.674 = converted %.loc8_24.1, %.loc8_24.4
-// CHECK:STDOUT:   %impl.elem0.loc8_35: %.7d6 = impl_witness_access constants.%ImplicitAs.impl_witness.fcb, element0 [concrete = constants.%Convert.c82]
-// CHECK:STDOUT:   %bound_method.loc8_35: <bound method> = bound_method %.loc8_26.1, %impl.elem0.loc8_35
+// CHECK:STDOUT:   %impl.elem0.loc8_35.1: %.7d6 = impl_witness_access constants.%ImplicitAs.impl_witness.fcb, element0 [concrete = constants.%Convert.c82]
+// CHECK:STDOUT:   %bound_method.loc8_35.1: <bound method> = bound_method %.loc8_26.1, %impl.elem0.loc8_35.1
 // CHECK:STDOUT:   %.loc8_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc8_26.2: %C.674 = bind_value %.loc8_26.1
-// CHECK:STDOUT:   %Convert.call.loc8: init %D = call %bound_method.loc8_35(%.loc8_26.2) to %.loc8_35.1
+// CHECK:STDOUT:   %Convert.call.loc8: init %D = call %bound_method.loc8_35.1(%.loc8_26.2) to %.loc8_35.1
 // CHECK:STDOUT:   %.loc8_35.2: init %D = converted %.loc8_26.1, %Convert.call.loc8
+// CHECK:STDOUT:   %impl.elem0.loc8_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.2: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.2
+// CHECK:STDOUT:   %specific_fn.loc8_35.1: <specific function> = specific_function %impl.elem0.loc8_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.3: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.1
+// CHECK:STDOUT:   %addr.loc8_35.1: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.1: init %empty_tuple.type = call %bound_method.loc8_35.3(%addr.loc8_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.1: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.1: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.1
+// CHECK:STDOUT:   %specific_fn.loc8_24.1: <specific function> = specific_function %impl.elem0.loc8_24.1, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.2: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.1
+// CHECK:STDOUT:   %addr.loc8_24.1: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.1: init %empty_tuple.type = call %bound_method.loc8_24.2(%addr.loc8_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.4: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.3
+// CHECK:STDOUT:   %specific_fn.loc7_35.2: <specific function> = specific_function %impl.elem0.loc7_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.5: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.2
+// CHECK:STDOUT:   %addr.loc7_35.2: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.2: init %empty_tuple.type = call %bound_method.loc7_35.5(%addr.loc7_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.2: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.3: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.2
+// CHECK:STDOUT:   %specific_fn.loc7_24.2: <specific function> = specific_function %impl.elem0.loc7_24.2, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.4: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.2
+// CHECK:STDOUT:   %addr.loc7_24.2: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.2: init %empty_tuple.type = call %bound_method.loc7_24.4(%addr.loc7_24.2)
 // CHECK:STDOUT:   return %.loc8_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc8:
@@ -1048,8 +1222,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
 // CHECK:STDOUT:   %impl.elem0.loc9_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc9_34.1: <bound method> = bound_method %int_2, %impl.elem0.loc9_34 [concrete = constants.%Convert.bound.ef9]
-// CHECK:STDOUT:   %specific_fn.loc9: <specific function> = specific_function %impl.elem0.loc9_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc9_34.2: <bound method> = bound_method %int_2, %specific_fn.loc9 [concrete = constants.%bound_method.b92]
+// CHECK:STDOUT:   %specific_fn.loc9_34: <specific function> = specific_function %impl.elem0.loc9_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc9_34.2: <bound method> = bound_method %int_2, %specific_fn.loc9_34 [concrete = constants.%bound_method.b92]
 // CHECK:STDOUT:   %int.convert_checked.loc9: init %i32 = call %bound_method.loc9_34.2(%int_2) [concrete = constants.%int_2.ef8]
 // CHECK:STDOUT:   %.loc9_34.1: %i32 = value_of_initializer %int.convert_checked.loc9 [concrete = constants.%int_2.ef8]
 // CHECK:STDOUT:   %.loc9_34.2: %i32 = converted %int_2, %.loc9_34.1 [concrete = constants.%int_2.ef8]
@@ -1058,12 +1232,48 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc9_24.3: init %C.681 = class_init (), %.loc9_24.2 [concrete = constants.%C.val.fb5]
 // CHECK:STDOUT:   %.loc9_24.4: ref %C.681 = temporary %.loc9_24.2, %.loc9_24.3
 // CHECK:STDOUT:   %.loc9_26.1: ref %C.681 = converted %.loc9_24.1, %.loc9_24.4
-// CHECK:STDOUT:   %impl.elem0.loc9_35: %.987 = impl_witness_access constants.%ImplicitAs.impl_witness.746, element0 [concrete = constants.%Convert.08c]
-// CHECK:STDOUT:   %bound_method.loc9_35: <bound method> = bound_method %.loc9_26.1, %impl.elem0.loc9_35
+// CHECK:STDOUT:   %impl.elem0.loc9_35.1: %.987 = impl_witness_access constants.%ImplicitAs.impl_witness.746, element0 [concrete = constants.%Convert.08c]
+// CHECK:STDOUT:   %bound_method.loc9_35.1: <bound method> = bound_method %.loc9_26.1, %impl.elem0.loc9_35.1
 // CHECK:STDOUT:   %.loc9_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc9_26.2: %C.681 = bind_value %.loc9_26.1
-// CHECK:STDOUT:   %Convert.call.loc9: init %D = call %bound_method.loc9_35(%.loc9_26.2) to %.loc9_35.1
+// CHECK:STDOUT:   %Convert.call.loc9: init %D = call %bound_method.loc9_35.1(%.loc9_26.2) to %.loc9_35.1
 // CHECK:STDOUT:   %.loc9_35.2: init %D = converted %.loc9_26.1, %Convert.call.loc9
+// CHECK:STDOUT:   %impl.elem0.loc9_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.2: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.2
+// CHECK:STDOUT:   %specific_fn.loc9_35.1: <specific function> = specific_function %impl.elem0.loc9_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.3: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.1
+// CHECK:STDOUT:   %addr.loc9_35.1: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.1: init %empty_tuple.type = call %bound_method.loc9_35.3(%addr.loc9_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.1: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.1: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.1
+// CHECK:STDOUT:   %specific_fn.loc9_24.1: <specific function> = specific_function %impl.elem0.loc9_24.1, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.2: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.1
+// CHECK:STDOUT:   %addr.loc9_24.1: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.1: init %empty_tuple.type = call %bound_method.loc9_24.2(%addr.loc9_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.4: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.3
+// CHECK:STDOUT:   %specific_fn.loc8_35.2: <specific function> = specific_function %impl.elem0.loc8_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.5: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.2
+// CHECK:STDOUT:   %addr.loc8_35.2: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.2: init %empty_tuple.type = call %bound_method.loc8_35.5(%addr.loc8_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.2: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.3: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.2
+// CHECK:STDOUT:   %specific_fn.loc8_24.2: <specific function> = specific_function %impl.elem0.loc8_24.2, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.4: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.2
+// CHECK:STDOUT:   %addr.loc8_24.2: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.2: init %empty_tuple.type = call %bound_method.loc8_24.4(%addr.loc8_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.6: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.4
+// CHECK:STDOUT:   %specific_fn.loc7_35.3: <specific function> = specific_function %impl.elem0.loc7_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.7: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.3
+// CHECK:STDOUT:   %addr.loc7_35.3: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.3: init %empty_tuple.type = call %bound_method.loc7_35.7(%addr.loc7_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.3: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.5: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.3
+// CHECK:STDOUT:   %specific_fn.loc7_24.3: <specific function> = specific_function %impl.elem0.loc7_24.3, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.6: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.3
+// CHECK:STDOUT:   %addr.loc7_24.3: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.3: init %empty_tuple.type = call %bound_method.loc7_24.6(%addr.loc7_24.3)
 // CHECK:STDOUT:   return %.loc9_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc9:
@@ -1077,8 +1287,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]
 // CHECK:STDOUT:   %impl.elem0.loc10_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc10_34.1: <bound method> = bound_method %int_3, %impl.elem0.loc10_34 [concrete = constants.%Convert.bound.b30]
-// CHECK:STDOUT:   %specific_fn.loc10: <specific function> = specific_function %impl.elem0.loc10_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc10_34.2: <bound method> = bound_method %int_3, %specific_fn.loc10 [concrete = constants.%bound_method.047]
+// CHECK:STDOUT:   %specific_fn.loc10_34: <specific function> = specific_function %impl.elem0.loc10_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc10_34.2: <bound method> = bound_method %int_3, %specific_fn.loc10_34 [concrete = constants.%bound_method.047]
 // CHECK:STDOUT:   %int.convert_checked.loc10: init %i32 = call %bound_method.loc10_34.2(%int_3) [concrete = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc10_34.1: %i32 = value_of_initializer %int.convert_checked.loc10 [concrete = constants.%int_3.822]
 // CHECK:STDOUT:   %.loc10_34.2: %i32 = converted %int_3, %.loc10_34.1 [concrete = constants.%int_3.822]
@@ -1087,12 +1297,60 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc10_24.3: init %C.7ac = class_init (), %.loc10_24.2 [concrete = constants.%C.val.fe7]
 // CHECK:STDOUT:   %.loc10_24.4: ref %C.7ac = temporary %.loc10_24.2, %.loc10_24.3
 // CHECK:STDOUT:   %.loc10_26.1: ref %C.7ac = converted %.loc10_24.1, %.loc10_24.4
-// CHECK:STDOUT:   %impl.elem0.loc10_35: %.efa = impl_witness_access constants.%ImplicitAs.impl_witness.f79, element0 [concrete = constants.%Convert.2dd]
-// CHECK:STDOUT:   %bound_method.loc10_35: <bound method> = bound_method %.loc10_26.1, %impl.elem0.loc10_35
+// CHECK:STDOUT:   %impl.elem0.loc10_35.1: %.efa = impl_witness_access constants.%ImplicitAs.impl_witness.f79, element0 [concrete = constants.%Convert.2dd]
+// CHECK:STDOUT:   %bound_method.loc10_35.1: <bound method> = bound_method %.loc10_26.1, %impl.elem0.loc10_35.1
 // CHECK:STDOUT:   %.loc10_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc10_26.2: %C.7ac = bind_value %.loc10_26.1
-// CHECK:STDOUT:   %Convert.call.loc10: init %D = call %bound_method.loc10_35(%.loc10_26.2) to %.loc10_35.1
+// CHECK:STDOUT:   %Convert.call.loc10: init %D = call %bound_method.loc10_35.1(%.loc10_26.2) to %.loc10_35.1
 // CHECK:STDOUT:   %.loc10_35.2: init %D = converted %.loc10_26.1, %Convert.call.loc10
+// CHECK:STDOUT:   %impl.elem0.loc10_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.2: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.2
+// CHECK:STDOUT:   %specific_fn.loc10_35.1: <specific function> = specific_function %impl.elem0.loc10_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.3: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.1
+// CHECK:STDOUT:   %addr.loc10_35.1: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.1: init %empty_tuple.type = call %bound_method.loc10_35.3(%addr.loc10_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.1: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.1: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.1
+// CHECK:STDOUT:   %specific_fn.loc10_24.1: <specific function> = specific_function %impl.elem0.loc10_24.1, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.2: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.1
+// CHECK:STDOUT:   %addr.loc10_24.1: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.1: init %empty_tuple.type = call %bound_method.loc10_24.2(%addr.loc10_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.4: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.3
+// CHECK:STDOUT:   %specific_fn.loc9_35.2: <specific function> = specific_function %impl.elem0.loc9_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.5: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.2
+// CHECK:STDOUT:   %addr.loc9_35.2: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.2: init %empty_tuple.type = call %bound_method.loc9_35.5(%addr.loc9_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.2: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.3: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.2
+// CHECK:STDOUT:   %specific_fn.loc9_24.2: <specific function> = specific_function %impl.elem0.loc9_24.2, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.4: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.2
+// CHECK:STDOUT:   %addr.loc9_24.2: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.2: init %empty_tuple.type = call %bound_method.loc9_24.4(%addr.loc9_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.6: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.4
+// CHECK:STDOUT:   %specific_fn.loc8_35.3: <specific function> = specific_function %impl.elem0.loc8_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.7: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.3
+// CHECK:STDOUT:   %addr.loc8_35.3: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.3: init %empty_tuple.type = call %bound_method.loc8_35.7(%addr.loc8_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.3: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.5: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.3
+// CHECK:STDOUT:   %specific_fn.loc8_24.3: <specific function> = specific_function %impl.elem0.loc8_24.3, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.6: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.3
+// CHECK:STDOUT:   %addr.loc8_24.3: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.3: init %empty_tuple.type = call %bound_method.loc8_24.6(%addr.loc8_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.8: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.5
+// CHECK:STDOUT:   %specific_fn.loc7_35.4: <specific function> = specific_function %impl.elem0.loc7_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.9: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.4
+// CHECK:STDOUT:   %addr.loc7_35.4: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.4: init %empty_tuple.type = call %bound_method.loc7_35.9(%addr.loc7_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.4: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.7: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.4
+// CHECK:STDOUT:   %specific_fn.loc7_24.4: <specific function> = specific_function %impl.elem0.loc7_24.4, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.8: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.4
+// CHECK:STDOUT:   %addr.loc7_24.4: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.4: init %empty_tuple.type = call %bound_method.loc7_24.8(%addr.loc7_24.4)
 // CHECK:STDOUT:   return %.loc10_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc10:
@@ -1106,8 +1364,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]
 // CHECK:STDOUT:   %impl.elem0.loc11_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc11_34.1: <bound method> = bound_method %int_4, %impl.elem0.loc11_34 [concrete = constants.%Convert.bound.ac3]
-// CHECK:STDOUT:   %specific_fn.loc11: <specific function> = specific_function %impl.elem0.loc11_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc11_34.2: <bound method> = bound_method %int_4, %specific_fn.loc11 [concrete = constants.%bound_method.1da]
+// CHECK:STDOUT:   %specific_fn.loc11_34: <specific function> = specific_function %impl.elem0.loc11_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc11_34.2: <bound method> = bound_method %int_4, %specific_fn.loc11_34 [concrete = constants.%bound_method.1da]
 // CHECK:STDOUT:   %int.convert_checked.loc11: init %i32 = call %bound_method.loc11_34.2(%int_4) [concrete = constants.%int_4.940]
 // CHECK:STDOUT:   %.loc11_34.1: %i32 = value_of_initializer %int.convert_checked.loc11 [concrete = constants.%int_4.940]
 // CHECK:STDOUT:   %.loc11_34.2: %i32 = converted %int_4, %.loc11_34.1 [concrete = constants.%int_4.940]
@@ -1116,12 +1374,72 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc11_24.3: init %C.89d = class_init (), %.loc11_24.2 [concrete = constants.%C.val.1dd]
 // CHECK:STDOUT:   %.loc11_24.4: ref %C.89d = temporary %.loc11_24.2, %.loc11_24.3
 // CHECK:STDOUT:   %.loc11_26.1: ref %C.89d = converted %.loc11_24.1, %.loc11_24.4
-// CHECK:STDOUT:   %impl.elem0.loc11_35: %.26e = impl_witness_access constants.%ImplicitAs.impl_witness.16c, element0 [concrete = constants.%Convert.009]
-// CHECK:STDOUT:   %bound_method.loc11_35: <bound method> = bound_method %.loc11_26.1, %impl.elem0.loc11_35
+// CHECK:STDOUT:   %impl.elem0.loc11_35.1: %.26e = impl_witness_access constants.%ImplicitAs.impl_witness.16c, element0 [concrete = constants.%Convert.009]
+// CHECK:STDOUT:   %bound_method.loc11_35.1: <bound method> = bound_method %.loc11_26.1, %impl.elem0.loc11_35.1
 // CHECK:STDOUT:   %.loc11_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc11_26.2: %C.89d = bind_value %.loc11_26.1
-// CHECK:STDOUT:   %Convert.call.loc11: init %D = call %bound_method.loc11_35(%.loc11_26.2) to %.loc11_35.1
+// CHECK:STDOUT:   %Convert.call.loc11: init %D = call %bound_method.loc11_35.1(%.loc11_26.2) to %.loc11_35.1
 // CHECK:STDOUT:   %.loc11_35.2: init %D = converted %.loc11_26.1, %Convert.call.loc11
+// CHECK:STDOUT:   %impl.elem0.loc11_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc11_35.2: <bound method> = bound_method %.loc11_35.1, %impl.elem0.loc11_35.2
+// CHECK:STDOUT:   %specific_fn.loc11_35.1: <specific function> = specific_function %impl.elem0.loc11_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc11_35.3: <bound method> = bound_method %.loc11_35.1, %specific_fn.loc11_35.1
+// CHECK:STDOUT:   %addr.loc11_35.1: %ptr.f29 = addr_of %.loc11_35.1
+// CHECK:STDOUT:   %no_op.loc11_35.1: init %empty_tuple.type = call %bound_method.loc11_35.3(%addr.loc11_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc11_24.1: %.6ca = impl_witness_access constants.%Destroy.impl_witness.f66, element0 [concrete = constants.%Op.6b4]
+// CHECK:STDOUT:   %bound_method.loc11_24.1: <bound method> = bound_method %.loc11_24.2, %impl.elem0.loc11_24.1
+// CHECK:STDOUT:   %specific_fn.loc11_24.1: <specific function> = specific_function %impl.elem0.loc11_24.1, @Op.2(constants.%C.89d) [concrete = constants.%Op.specific_fn.357]
+// CHECK:STDOUT:   %bound_method.loc11_24.2: <bound method> = bound_method %.loc11_24.2, %specific_fn.loc11_24.1
+// CHECK:STDOUT:   %addr.loc11_24.1: %ptr.c28b = addr_of %.loc11_24.2
+// CHECK:STDOUT:   %no_op.loc11_24.1: init %empty_tuple.type = call %bound_method.loc11_24.2(%addr.loc11_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc10_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.4: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.3
+// CHECK:STDOUT:   %specific_fn.loc10_35.2: <specific function> = specific_function %impl.elem0.loc10_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.5: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.2
+// CHECK:STDOUT:   %addr.loc10_35.2: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.2: init %empty_tuple.type = call %bound_method.loc10_35.5(%addr.loc10_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.2: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.3: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.2
+// CHECK:STDOUT:   %specific_fn.loc10_24.2: <specific function> = specific_function %impl.elem0.loc10_24.2, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.4: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.2
+// CHECK:STDOUT:   %addr.loc10_24.2: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.2: init %empty_tuple.type = call %bound_method.loc10_24.4(%addr.loc10_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.6: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.4
+// CHECK:STDOUT:   %specific_fn.loc9_35.3: <specific function> = specific_function %impl.elem0.loc9_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.7: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.3
+// CHECK:STDOUT:   %addr.loc9_35.3: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.3: init %empty_tuple.type = call %bound_method.loc9_35.7(%addr.loc9_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.3: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.5: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.3
+// CHECK:STDOUT:   %specific_fn.loc9_24.3: <specific function> = specific_function %impl.elem0.loc9_24.3, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.6: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.3
+// CHECK:STDOUT:   %addr.loc9_24.3: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.3: init %empty_tuple.type = call %bound_method.loc9_24.6(%addr.loc9_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.8: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.5
+// CHECK:STDOUT:   %specific_fn.loc8_35.4: <specific function> = specific_function %impl.elem0.loc8_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.9: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.4
+// CHECK:STDOUT:   %addr.loc8_35.4: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.4: init %empty_tuple.type = call %bound_method.loc8_35.9(%addr.loc8_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.4: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.7: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.4
+// CHECK:STDOUT:   %specific_fn.loc8_24.4: <specific function> = specific_function %impl.elem0.loc8_24.4, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.8: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.4
+// CHECK:STDOUT:   %addr.loc8_24.4: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.4: init %empty_tuple.type = call %bound_method.loc8_24.8(%addr.loc8_24.4)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.10: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.6
+// CHECK:STDOUT:   %specific_fn.loc7_35.5: <specific function> = specific_function %impl.elem0.loc7_35.6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.11: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.5
+// CHECK:STDOUT:   %addr.loc7_35.5: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.5: init %empty_tuple.type = call %bound_method.loc7_35.11(%addr.loc7_35.5)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.5: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.9: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.5
+// CHECK:STDOUT:   %specific_fn.loc7_24.5: <specific function> = specific_function %impl.elem0.loc7_24.5, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.10: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.5
+// CHECK:STDOUT:   %addr.loc7_24.5: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.5: init %empty_tuple.type = call %bound_method.loc7_24.10(%addr.loc7_24.5)
 // CHECK:STDOUT:   return %.loc11_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc11:
@@ -1135,8 +1453,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]
 // CHECK:STDOUT:   %impl.elem0.loc12_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc12_34.1: <bound method> = bound_method %int_5, %impl.elem0.loc12_34 [concrete = constants.%Convert.bound.4e6]
-// CHECK:STDOUT:   %specific_fn.loc12: <specific function> = specific_function %impl.elem0.loc12_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc12_34.2: <bound method> = bound_method %int_5, %specific_fn.loc12 [concrete = constants.%bound_method.a25]
+// CHECK:STDOUT:   %specific_fn.loc12_34: <specific function> = specific_function %impl.elem0.loc12_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc12_34.2: <bound method> = bound_method %int_5, %specific_fn.loc12_34 [concrete = constants.%bound_method.a25]
 // CHECK:STDOUT:   %int.convert_checked.loc12: init %i32 = call %bound_method.loc12_34.2(%int_5) [concrete = constants.%int_5.0f6]
 // CHECK:STDOUT:   %.loc12_34.1: %i32 = value_of_initializer %int.convert_checked.loc12 [concrete = constants.%int_5.0f6]
 // CHECK:STDOUT:   %.loc12_34.2: %i32 = converted %int_5, %.loc12_34.1 [concrete = constants.%int_5.0f6]
@@ -1145,12 +1463,84 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc12_24.3: init %C.f0a = class_init (), %.loc12_24.2 [concrete = constants.%C.val.a4a]
 // CHECK:STDOUT:   %.loc12_24.4: ref %C.f0a = temporary %.loc12_24.2, %.loc12_24.3
 // CHECK:STDOUT:   %.loc12_26.1: ref %C.f0a = converted %.loc12_24.1, %.loc12_24.4
-// CHECK:STDOUT:   %impl.elem0.loc12_35: %.eaf = impl_witness_access constants.%ImplicitAs.impl_witness.aa9, element0 [concrete = constants.%Convert.b66]
-// CHECK:STDOUT:   %bound_method.loc12_35: <bound method> = bound_method %.loc12_26.1, %impl.elem0.loc12_35
+// CHECK:STDOUT:   %impl.elem0.loc12_35.1: %.eaf = impl_witness_access constants.%ImplicitAs.impl_witness.aa9, element0 [concrete = constants.%Convert.b66]
+// CHECK:STDOUT:   %bound_method.loc12_35.1: <bound method> = bound_method %.loc12_26.1, %impl.elem0.loc12_35.1
 // CHECK:STDOUT:   %.loc12_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc12_26.2: %C.f0a = bind_value %.loc12_26.1
-// CHECK:STDOUT:   %Convert.call.loc12: init %D = call %bound_method.loc12_35(%.loc12_26.2) to %.loc12_35.1
+// CHECK:STDOUT:   %Convert.call.loc12: init %D = call %bound_method.loc12_35.1(%.loc12_26.2) to %.loc12_35.1
 // CHECK:STDOUT:   %.loc12_35.2: init %D = converted %.loc12_26.1, %Convert.call.loc12
+// CHECK:STDOUT:   %impl.elem0.loc12_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc12_35.2: <bound method> = bound_method %.loc12_35.1, %impl.elem0.loc12_35.2
+// CHECK:STDOUT:   %specific_fn.loc12_35.1: <specific function> = specific_function %impl.elem0.loc12_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc12_35.3: <bound method> = bound_method %.loc12_35.1, %specific_fn.loc12_35.1
+// CHECK:STDOUT:   %addr.loc12_35.1: %ptr.f29 = addr_of %.loc12_35.1
+// CHECK:STDOUT:   %no_op.loc12_35.1: init %empty_tuple.type = call %bound_method.loc12_35.3(%addr.loc12_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc12_24.1: %.89c = impl_witness_access constants.%Destroy.impl_witness.818, element0 [concrete = constants.%Op.985]
+// CHECK:STDOUT:   %bound_method.loc12_24.1: <bound method> = bound_method %.loc12_24.2, %impl.elem0.loc12_24.1
+// CHECK:STDOUT:   %specific_fn.loc12_24.1: <specific function> = specific_function %impl.elem0.loc12_24.1, @Op.2(constants.%C.f0a) [concrete = constants.%Op.specific_fn.a66]
+// CHECK:STDOUT:   %bound_method.loc12_24.2: <bound method> = bound_method %.loc12_24.2, %specific_fn.loc12_24.1
+// CHECK:STDOUT:   %addr.loc12_24.1: %ptr.24c = addr_of %.loc12_24.2
+// CHECK:STDOUT:   %no_op.loc12_24.1: init %empty_tuple.type = call %bound_method.loc12_24.2(%addr.loc12_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc11_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc11_35.4: <bound method> = bound_method %.loc11_35.1, %impl.elem0.loc11_35.3
+// CHECK:STDOUT:   %specific_fn.loc11_35.2: <specific function> = specific_function %impl.elem0.loc11_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc11_35.5: <bound method> = bound_method %.loc11_35.1, %specific_fn.loc11_35.2
+// CHECK:STDOUT:   %addr.loc11_35.2: %ptr.f29 = addr_of %.loc11_35.1
+// CHECK:STDOUT:   %no_op.loc11_35.2: init %empty_tuple.type = call %bound_method.loc11_35.5(%addr.loc11_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc11_24.2: %.6ca = impl_witness_access constants.%Destroy.impl_witness.f66, element0 [concrete = constants.%Op.6b4]
+// CHECK:STDOUT:   %bound_method.loc11_24.3: <bound method> = bound_method %.loc11_24.2, %impl.elem0.loc11_24.2
+// CHECK:STDOUT:   %specific_fn.loc11_24.2: <specific function> = specific_function %impl.elem0.loc11_24.2, @Op.2(constants.%C.89d) [concrete = constants.%Op.specific_fn.357]
+// CHECK:STDOUT:   %bound_method.loc11_24.4: <bound method> = bound_method %.loc11_24.2, %specific_fn.loc11_24.2
+// CHECK:STDOUT:   %addr.loc11_24.2: %ptr.c28b = addr_of %.loc11_24.2
+// CHECK:STDOUT:   %no_op.loc11_24.2: init %empty_tuple.type = call %bound_method.loc11_24.4(%addr.loc11_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc10_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.6: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.4
+// CHECK:STDOUT:   %specific_fn.loc10_35.3: <specific function> = specific_function %impl.elem0.loc10_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.7: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.3
+// CHECK:STDOUT:   %addr.loc10_35.3: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.3: init %empty_tuple.type = call %bound_method.loc10_35.7(%addr.loc10_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.3: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.5: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.3
+// CHECK:STDOUT:   %specific_fn.loc10_24.3: <specific function> = specific_function %impl.elem0.loc10_24.3, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.6: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.3
+// CHECK:STDOUT:   %addr.loc10_24.3: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.3: init %empty_tuple.type = call %bound_method.loc10_24.6(%addr.loc10_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.8: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.5
+// CHECK:STDOUT:   %specific_fn.loc9_35.4: <specific function> = specific_function %impl.elem0.loc9_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.9: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.4
+// CHECK:STDOUT:   %addr.loc9_35.4: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.4: init %empty_tuple.type = call %bound_method.loc9_35.9(%addr.loc9_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.4: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.7: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.4
+// CHECK:STDOUT:   %specific_fn.loc9_24.4: <specific function> = specific_function %impl.elem0.loc9_24.4, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.8: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.4
+// CHECK:STDOUT:   %addr.loc9_24.4: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.4: init %empty_tuple.type = call %bound_method.loc9_24.8(%addr.loc9_24.4)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.10: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.6
+// CHECK:STDOUT:   %specific_fn.loc8_35.5: <specific function> = specific_function %impl.elem0.loc8_35.6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.11: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.5
+// CHECK:STDOUT:   %addr.loc8_35.5: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.5: init %empty_tuple.type = call %bound_method.loc8_35.11(%addr.loc8_35.5)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.5: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.9: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.5
+// CHECK:STDOUT:   %specific_fn.loc8_24.5: <specific function> = specific_function %impl.elem0.loc8_24.5, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.10: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.5
+// CHECK:STDOUT:   %addr.loc8_24.5: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.5: init %empty_tuple.type = call %bound_method.loc8_24.10(%addr.loc8_24.5)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.7: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.12: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.7
+// CHECK:STDOUT:   %specific_fn.loc7_35.6: <specific function> = specific_function %impl.elem0.loc7_35.7, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.13: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.6
+// CHECK:STDOUT:   %addr.loc7_35.6: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.6: init %empty_tuple.type = call %bound_method.loc7_35.13(%addr.loc7_35.6)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.6: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.11: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.6
+// CHECK:STDOUT:   %specific_fn.loc7_24.6: <specific function> = specific_function %impl.elem0.loc7_24.6, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.12: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.6
+// CHECK:STDOUT:   %addr.loc7_24.6: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.6: init %empty_tuple.type = call %bound_method.loc7_24.12(%addr.loc7_24.6)
 // CHECK:STDOUT:   return %.loc12_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc12:
@@ -1164,8 +1554,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete = constants.%int_6.462]
 // CHECK:STDOUT:   %impl.elem0.loc13_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc13_34.1: <bound method> = bound_method %int_6, %impl.elem0.loc13_34 [concrete = constants.%Convert.bound.ce9]
-// CHECK:STDOUT:   %specific_fn.loc13: <specific function> = specific_function %impl.elem0.loc13_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc13_34.2: <bound method> = bound_method %int_6, %specific_fn.loc13 [concrete = constants.%bound_method.efa]
+// CHECK:STDOUT:   %specific_fn.loc13_34: <specific function> = specific_function %impl.elem0.loc13_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc13_34.2: <bound method> = bound_method %int_6, %specific_fn.loc13_34 [concrete = constants.%bound_method.efa]
 // CHECK:STDOUT:   %int.convert_checked.loc13: init %i32 = call %bound_method.loc13_34.2(%int_6) [concrete = constants.%int_6.e56]
 // CHECK:STDOUT:   %.loc13_34.1: %i32 = value_of_initializer %int.convert_checked.loc13 [concrete = constants.%int_6.e56]
 // CHECK:STDOUT:   %.loc13_34.2: %i32 = converted %int_6, %.loc13_34.1 [concrete = constants.%int_6.e56]
@@ -1174,12 +1564,96 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc13_24.3: init %C.c60 = class_init (), %.loc13_24.2 [concrete = constants.%C.val.a4b]
 // CHECK:STDOUT:   %.loc13_24.4: ref %C.c60 = temporary %.loc13_24.2, %.loc13_24.3
 // CHECK:STDOUT:   %.loc13_26.1: ref %C.c60 = converted %.loc13_24.1, %.loc13_24.4
-// CHECK:STDOUT:   %impl.elem0.loc13_35: %.874 = impl_witness_access constants.%ImplicitAs.impl_witness.e4d, element0 [concrete = constants.%Convert.f59]
-// CHECK:STDOUT:   %bound_method.loc13_35: <bound method> = bound_method %.loc13_26.1, %impl.elem0.loc13_35
+// CHECK:STDOUT:   %impl.elem0.loc13_35.1: %.874 = impl_witness_access constants.%ImplicitAs.impl_witness.e4d, element0 [concrete = constants.%Convert.f59]
+// CHECK:STDOUT:   %bound_method.loc13_35.1: <bound method> = bound_method %.loc13_26.1, %impl.elem0.loc13_35.1
 // CHECK:STDOUT:   %.loc13_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc13_26.2: %C.c60 = bind_value %.loc13_26.1
-// CHECK:STDOUT:   %Convert.call.loc13: init %D = call %bound_method.loc13_35(%.loc13_26.2) to %.loc13_35.1
+// CHECK:STDOUT:   %Convert.call.loc13: init %D = call %bound_method.loc13_35.1(%.loc13_26.2) to %.loc13_35.1
 // CHECK:STDOUT:   %.loc13_35.2: init %D = converted %.loc13_26.1, %Convert.call.loc13
+// CHECK:STDOUT:   %impl.elem0.loc13_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc13_35.2: <bound method> = bound_method %.loc13_35.1, %impl.elem0.loc13_35.2
+// CHECK:STDOUT:   %specific_fn.loc13_35.1: <specific function> = specific_function %impl.elem0.loc13_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc13_35.3: <bound method> = bound_method %.loc13_35.1, %specific_fn.loc13_35.1
+// CHECK:STDOUT:   %addr.loc13_35.1: %ptr.f29 = addr_of %.loc13_35.1
+// CHECK:STDOUT:   %no_op.loc13_35.1: init %empty_tuple.type = call %bound_method.loc13_35.3(%addr.loc13_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc13_24.1: %.3d7 = impl_witness_access constants.%Destroy.impl_witness.1e4, element0 [concrete = constants.%Op.ca5]
+// CHECK:STDOUT:   %bound_method.loc13_24.1: <bound method> = bound_method %.loc13_24.2, %impl.elem0.loc13_24.1
+// CHECK:STDOUT:   %specific_fn.loc13_24.1: <specific function> = specific_function %impl.elem0.loc13_24.1, @Op.2(constants.%C.c60) [concrete = constants.%Op.specific_fn.8d0]
+// CHECK:STDOUT:   %bound_method.loc13_24.2: <bound method> = bound_method %.loc13_24.2, %specific_fn.loc13_24.1
+// CHECK:STDOUT:   %addr.loc13_24.1: %ptr.b5e = addr_of %.loc13_24.2
+// CHECK:STDOUT:   %no_op.loc13_24.1: init %empty_tuple.type = call %bound_method.loc13_24.2(%addr.loc13_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc12_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc12_35.4: <bound method> = bound_method %.loc12_35.1, %impl.elem0.loc12_35.3
+// CHECK:STDOUT:   %specific_fn.loc12_35.2: <specific function> = specific_function %impl.elem0.loc12_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc12_35.5: <bound method> = bound_method %.loc12_35.1, %specific_fn.loc12_35.2
+// CHECK:STDOUT:   %addr.loc12_35.2: %ptr.f29 = addr_of %.loc12_35.1
+// CHECK:STDOUT:   %no_op.loc12_35.2: init %empty_tuple.type = call %bound_method.loc12_35.5(%addr.loc12_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc12_24.2: %.89c = impl_witness_access constants.%Destroy.impl_witness.818, element0 [concrete = constants.%Op.985]
+// CHECK:STDOUT:   %bound_method.loc12_24.3: <bound method> = bound_method %.loc12_24.2, %impl.elem0.loc12_24.2
+// CHECK:STDOUT:   %specific_fn.loc12_24.2: <specific function> = specific_function %impl.elem0.loc12_24.2, @Op.2(constants.%C.f0a) [concrete = constants.%Op.specific_fn.a66]
+// CHECK:STDOUT:   %bound_method.loc12_24.4: <bound method> = bound_method %.loc12_24.2, %specific_fn.loc12_24.2
+// CHECK:STDOUT:   %addr.loc12_24.2: %ptr.24c = addr_of %.loc12_24.2
+// CHECK:STDOUT:   %no_op.loc12_24.2: init %empty_tuple.type = call %bound_method.loc12_24.4(%addr.loc12_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc11_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc11_35.6: <bound method> = bound_method %.loc11_35.1, %impl.elem0.loc11_35.4
+// CHECK:STDOUT:   %specific_fn.loc11_35.3: <specific function> = specific_function %impl.elem0.loc11_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc11_35.7: <bound method> = bound_method %.loc11_35.1, %specific_fn.loc11_35.3
+// CHECK:STDOUT:   %addr.loc11_35.3: %ptr.f29 = addr_of %.loc11_35.1
+// CHECK:STDOUT:   %no_op.loc11_35.3: init %empty_tuple.type = call %bound_method.loc11_35.7(%addr.loc11_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc11_24.3: %.6ca = impl_witness_access constants.%Destroy.impl_witness.f66, element0 [concrete = constants.%Op.6b4]
+// CHECK:STDOUT:   %bound_method.loc11_24.5: <bound method> = bound_method %.loc11_24.2, %impl.elem0.loc11_24.3
+// CHECK:STDOUT:   %specific_fn.loc11_24.3: <specific function> = specific_function %impl.elem0.loc11_24.3, @Op.2(constants.%C.89d) [concrete = constants.%Op.specific_fn.357]
+// CHECK:STDOUT:   %bound_method.loc11_24.6: <bound method> = bound_method %.loc11_24.2, %specific_fn.loc11_24.3
+// CHECK:STDOUT:   %addr.loc11_24.3: %ptr.c28b = addr_of %.loc11_24.2
+// CHECK:STDOUT:   %no_op.loc11_24.3: init %empty_tuple.type = call %bound_method.loc11_24.6(%addr.loc11_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc10_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.8: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.5
+// CHECK:STDOUT:   %specific_fn.loc10_35.4: <specific function> = specific_function %impl.elem0.loc10_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.9: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.4
+// CHECK:STDOUT:   %addr.loc10_35.4: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.4: init %empty_tuple.type = call %bound_method.loc10_35.9(%addr.loc10_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.4: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.7: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.4
+// CHECK:STDOUT:   %specific_fn.loc10_24.4: <specific function> = specific_function %impl.elem0.loc10_24.4, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.8: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.4
+// CHECK:STDOUT:   %addr.loc10_24.4: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.4: init %empty_tuple.type = call %bound_method.loc10_24.8(%addr.loc10_24.4)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.10: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.6
+// CHECK:STDOUT:   %specific_fn.loc9_35.5: <specific function> = specific_function %impl.elem0.loc9_35.6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.11: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.5
+// CHECK:STDOUT:   %addr.loc9_35.5: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.5: init %empty_tuple.type = call %bound_method.loc9_35.11(%addr.loc9_35.5)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.5: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.9: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.5
+// CHECK:STDOUT:   %specific_fn.loc9_24.5: <specific function> = specific_function %impl.elem0.loc9_24.5, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.10: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.5
+// CHECK:STDOUT:   %addr.loc9_24.5: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.5: init %empty_tuple.type = call %bound_method.loc9_24.10(%addr.loc9_24.5)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.7: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.12: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.7
+// CHECK:STDOUT:   %specific_fn.loc8_35.6: <specific function> = specific_function %impl.elem0.loc8_35.7, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.13: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.6
+// CHECK:STDOUT:   %addr.loc8_35.6: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.6: init %empty_tuple.type = call %bound_method.loc8_35.13(%addr.loc8_35.6)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.6: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.11: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.6
+// CHECK:STDOUT:   %specific_fn.loc8_24.6: <specific function> = specific_function %impl.elem0.loc8_24.6, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.12: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.6
+// CHECK:STDOUT:   %addr.loc8_24.6: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.6: init %empty_tuple.type = call %bound_method.loc8_24.12(%addr.loc8_24.6)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.8: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.14: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.8
+// CHECK:STDOUT:   %specific_fn.loc7_35.7: <specific function> = specific_function %impl.elem0.loc7_35.8, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.15: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.7
+// CHECK:STDOUT:   %addr.loc7_35.7: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.7: init %empty_tuple.type = call %bound_method.loc7_35.15(%addr.loc7_35.7)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.7: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.13: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.7
+// CHECK:STDOUT:   %specific_fn.loc7_24.7: <specific function> = specific_function %impl.elem0.loc7_24.7, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.14: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.7
+// CHECK:STDOUT:   %addr.loc7_24.7: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.7: init %empty_tuple.type = call %bound_method.loc7_24.14(%addr.loc7_24.7)
 // CHECK:STDOUT:   return %.loc13_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc13:
@@ -1193,8 +1667,8 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7.29f]
 // CHECK:STDOUT:   %impl.elem0.loc14_34: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
 // CHECK:STDOUT:   %bound_method.loc14_34.1: <bound method> = bound_method %int_7, %impl.elem0.loc14_34 [concrete = constants.%Convert.bound.208]
-// CHECK:STDOUT:   %specific_fn.loc14: <specific function> = specific_function %impl.elem0.loc14_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc14_34.2: <bound method> = bound_method %int_7, %specific_fn.loc14 [concrete = constants.%bound_method.3bd]
+// CHECK:STDOUT:   %specific_fn.loc14_34: <specific function> = specific_function %impl.elem0.loc14_34, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc14_34.2: <bound method> = bound_method %int_7, %specific_fn.loc14_34 [concrete = constants.%bound_method.3bd]
 // CHECK:STDOUT:   %int.convert_checked.loc14: init %i32 = call %bound_method.loc14_34.2(%int_7) [concrete = constants.%int_7.0b1]
 // CHECK:STDOUT:   %.loc14_34.1: %i32 = value_of_initializer %int.convert_checked.loc14 [concrete = constants.%int_7.0b1]
 // CHECK:STDOUT:   %.loc14_34.2: %i32 = converted %int_7, %.loc14_34.1 [concrete = constants.%int_7.0b1]
@@ -1203,12 +1677,108 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %.loc14_24.3: init %C.304 = class_init (), %.loc14_24.2 [concrete = constants.%C.val.f9f]
 // CHECK:STDOUT:   %.loc14_24.4: ref %C.304 = temporary %.loc14_24.2, %.loc14_24.3
 // CHECK:STDOUT:   %.loc14_26.1: ref %C.304 = converted %.loc14_24.1, %.loc14_24.4
-// CHECK:STDOUT:   %impl.elem0.loc14_35: %.79b = impl_witness_access constants.%ImplicitAs.impl_witness.0ca, element0 [concrete = constants.%Convert.6c1]
-// CHECK:STDOUT:   %bound_method.loc14_35: <bound method> = bound_method %.loc14_26.1, %impl.elem0.loc14_35
+// CHECK:STDOUT:   %impl.elem0.loc14_35.1: %.79b = impl_witness_access constants.%ImplicitAs.impl_witness.0ca, element0 [concrete = constants.%Convert.6c1]
+// CHECK:STDOUT:   %bound_method.loc14_35.1: <bound method> = bound_method %.loc14_26.1, %impl.elem0.loc14_35.1
 // CHECK:STDOUT:   %.loc14_35.1: ref %D = temporary_storage
 // CHECK:STDOUT:   %.loc14_26.2: %C.304 = bind_value %.loc14_26.1
-// CHECK:STDOUT:   %Convert.call.loc14: init %D = call %bound_method.loc14_35(%.loc14_26.2) to %.loc14_35.1
+// CHECK:STDOUT:   %Convert.call.loc14: init %D = call %bound_method.loc14_35.1(%.loc14_26.2) to %.loc14_35.1
 // CHECK:STDOUT:   %.loc14_35.2: init %D = converted %.loc14_26.1, %Convert.call.loc14
+// CHECK:STDOUT:   %impl.elem0.loc14_35.2: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc14_35.2: <bound method> = bound_method %.loc14_35.1, %impl.elem0.loc14_35.2
+// CHECK:STDOUT:   %specific_fn.loc14_35.1: <specific function> = specific_function %impl.elem0.loc14_35.2, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc14_35.3: <bound method> = bound_method %.loc14_35.1, %specific_fn.loc14_35.1
+// CHECK:STDOUT:   %addr.loc14_35.1: %ptr.f29 = addr_of %.loc14_35.1
+// CHECK:STDOUT:   %no_op.loc14_35.1: init %empty_tuple.type = call %bound_method.loc14_35.3(%addr.loc14_35.1)
+// CHECK:STDOUT:   %impl.elem0.loc14_24.1: %.3a6 = impl_witness_access constants.%Destroy.impl_witness.cc5, element0 [concrete = constants.%Op.6fc]
+// CHECK:STDOUT:   %bound_method.loc14_24.1: <bound method> = bound_method %.loc14_24.2, %impl.elem0.loc14_24.1
+// CHECK:STDOUT:   %specific_fn.loc14_24.1: <specific function> = specific_function %impl.elem0.loc14_24.1, @Op.2(constants.%C.304) [concrete = constants.%Op.specific_fn.a08]
+// CHECK:STDOUT:   %bound_method.loc14_24.2: <bound method> = bound_method %.loc14_24.2, %specific_fn.loc14_24.1
+// CHECK:STDOUT:   %addr.loc14_24.1: %ptr.dc3 = addr_of %.loc14_24.2
+// CHECK:STDOUT:   %no_op.loc14_24.1: init %empty_tuple.type = call %bound_method.loc14_24.2(%addr.loc14_24.1)
+// CHECK:STDOUT:   %impl.elem0.loc13_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc13_35.4: <bound method> = bound_method %.loc13_35.1, %impl.elem0.loc13_35.3
+// CHECK:STDOUT:   %specific_fn.loc13_35.2: <specific function> = specific_function %impl.elem0.loc13_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc13_35.5: <bound method> = bound_method %.loc13_35.1, %specific_fn.loc13_35.2
+// CHECK:STDOUT:   %addr.loc13_35.2: %ptr.f29 = addr_of %.loc13_35.1
+// CHECK:STDOUT:   %no_op.loc13_35.2: init %empty_tuple.type = call %bound_method.loc13_35.5(%addr.loc13_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc13_24.2: %.3d7 = impl_witness_access constants.%Destroy.impl_witness.1e4, element0 [concrete = constants.%Op.ca5]
+// CHECK:STDOUT:   %bound_method.loc13_24.3: <bound method> = bound_method %.loc13_24.2, %impl.elem0.loc13_24.2
+// CHECK:STDOUT:   %specific_fn.loc13_24.2: <specific function> = specific_function %impl.elem0.loc13_24.2, @Op.2(constants.%C.c60) [concrete = constants.%Op.specific_fn.8d0]
+// CHECK:STDOUT:   %bound_method.loc13_24.4: <bound method> = bound_method %.loc13_24.2, %specific_fn.loc13_24.2
+// CHECK:STDOUT:   %addr.loc13_24.2: %ptr.b5e = addr_of %.loc13_24.2
+// CHECK:STDOUT:   %no_op.loc13_24.2: init %empty_tuple.type = call %bound_method.loc13_24.4(%addr.loc13_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc12_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc12_35.6: <bound method> = bound_method %.loc12_35.1, %impl.elem0.loc12_35.4
+// CHECK:STDOUT:   %specific_fn.loc12_35.3: <specific function> = specific_function %impl.elem0.loc12_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc12_35.7: <bound method> = bound_method %.loc12_35.1, %specific_fn.loc12_35.3
+// CHECK:STDOUT:   %addr.loc12_35.3: %ptr.f29 = addr_of %.loc12_35.1
+// CHECK:STDOUT:   %no_op.loc12_35.3: init %empty_tuple.type = call %bound_method.loc12_35.7(%addr.loc12_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc12_24.3: %.89c = impl_witness_access constants.%Destroy.impl_witness.818, element0 [concrete = constants.%Op.985]
+// CHECK:STDOUT:   %bound_method.loc12_24.5: <bound method> = bound_method %.loc12_24.2, %impl.elem0.loc12_24.3
+// CHECK:STDOUT:   %specific_fn.loc12_24.3: <specific function> = specific_function %impl.elem0.loc12_24.3, @Op.2(constants.%C.f0a) [concrete = constants.%Op.specific_fn.a66]
+// CHECK:STDOUT:   %bound_method.loc12_24.6: <bound method> = bound_method %.loc12_24.2, %specific_fn.loc12_24.3
+// CHECK:STDOUT:   %addr.loc12_24.3: %ptr.24c = addr_of %.loc12_24.2
+// CHECK:STDOUT:   %no_op.loc12_24.3: init %empty_tuple.type = call %bound_method.loc12_24.6(%addr.loc12_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc11_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc11_35.8: <bound method> = bound_method %.loc11_35.1, %impl.elem0.loc11_35.5
+// CHECK:STDOUT:   %specific_fn.loc11_35.4: <specific function> = specific_function %impl.elem0.loc11_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc11_35.9: <bound method> = bound_method %.loc11_35.1, %specific_fn.loc11_35.4
+// CHECK:STDOUT:   %addr.loc11_35.4: %ptr.f29 = addr_of %.loc11_35.1
+// CHECK:STDOUT:   %no_op.loc11_35.4: init %empty_tuple.type = call %bound_method.loc11_35.9(%addr.loc11_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc11_24.4: %.6ca = impl_witness_access constants.%Destroy.impl_witness.f66, element0 [concrete = constants.%Op.6b4]
+// CHECK:STDOUT:   %bound_method.loc11_24.7: <bound method> = bound_method %.loc11_24.2, %impl.elem0.loc11_24.4
+// CHECK:STDOUT:   %specific_fn.loc11_24.4: <specific function> = specific_function %impl.elem0.loc11_24.4, @Op.2(constants.%C.89d) [concrete = constants.%Op.specific_fn.357]
+// CHECK:STDOUT:   %bound_method.loc11_24.8: <bound method> = bound_method %.loc11_24.2, %specific_fn.loc11_24.4
+// CHECK:STDOUT:   %addr.loc11_24.4: %ptr.c28b = addr_of %.loc11_24.2
+// CHECK:STDOUT:   %no_op.loc11_24.4: init %empty_tuple.type = call %bound_method.loc11_24.8(%addr.loc11_24.4)
+// CHECK:STDOUT:   %impl.elem0.loc10_35.6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.10: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.6
+// CHECK:STDOUT:   %specific_fn.loc10_35.5: <specific function> = specific_function %impl.elem0.loc10_35.6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.11: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.5
+// CHECK:STDOUT:   %addr.loc10_35.5: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.5: init %empty_tuple.type = call %bound_method.loc10_35.11(%addr.loc10_35.5)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.5: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.9: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.5
+// CHECK:STDOUT:   %specific_fn.loc10_24.5: <specific function> = specific_function %impl.elem0.loc10_24.5, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.10: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.5
+// CHECK:STDOUT:   %addr.loc10_24.5: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.5: init %empty_tuple.type = call %bound_method.loc10_24.10(%addr.loc10_24.5)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.7: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.12: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.7
+// CHECK:STDOUT:   %specific_fn.loc9_35.6: <specific function> = specific_function %impl.elem0.loc9_35.7, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.13: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.6
+// CHECK:STDOUT:   %addr.loc9_35.6: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.6: init %empty_tuple.type = call %bound_method.loc9_35.13(%addr.loc9_35.6)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.6: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.11: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.6
+// CHECK:STDOUT:   %specific_fn.loc9_24.6: <specific function> = specific_function %impl.elem0.loc9_24.6, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.12: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.6
+// CHECK:STDOUT:   %addr.loc9_24.6: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.6: init %empty_tuple.type = call %bound_method.loc9_24.12(%addr.loc9_24.6)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.8: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.14: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.8
+// CHECK:STDOUT:   %specific_fn.loc8_35.7: <specific function> = specific_function %impl.elem0.loc8_35.8, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.15: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.7
+// CHECK:STDOUT:   %addr.loc8_35.7: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.7: init %empty_tuple.type = call %bound_method.loc8_35.15(%addr.loc8_35.7)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.7: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.13: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.7
+// CHECK:STDOUT:   %specific_fn.loc8_24.7: <specific function> = specific_function %impl.elem0.loc8_24.7, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.14: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.7
+// CHECK:STDOUT:   %addr.loc8_24.7: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.7: init %empty_tuple.type = call %bound_method.loc8_24.14(%addr.loc8_24.7)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.9: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.16: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.9
+// CHECK:STDOUT:   %specific_fn.loc7_35.8: <specific function> = specific_function %impl.elem0.loc7_35.9, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.17: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.8
+// CHECK:STDOUT:   %addr.loc7_35.8: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.8: init %empty_tuple.type = call %bound_method.loc7_35.17(%addr.loc7_35.8)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.8: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.15: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.8
+// CHECK:STDOUT:   %specific_fn.loc7_24.8: <specific function> = specific_function %impl.elem0.loc7_24.8, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.16: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.8
+// CHECK:STDOUT:   %addr.loc7_24.8: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.8: init %empty_tuple.type = call %bound_method.loc7_24.16(%addr.loc7_24.8)
 // CHECK:STDOUT:   return %.loc14_35.2 to %return
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else.loc14:
@@ -1216,6 +1786,108 @@ fn F0(n: i32) -> P.D {
 // CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, imports.%P.Make [concrete = constants.%Make]
 // CHECK:STDOUT:   %.loc6_15: ref %D = splice_block %return {}
 // CHECK:STDOUT:   %Make.call: init %D = call %Make.ref() to %.loc6_15
+// CHECK:STDOUT:   %impl.elem0.loc6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc6_15.1: <bound method> = bound_method %.loc6_15, %impl.elem0.loc6
+// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc6_15.2: <bound method> = bound_method %.loc6_15, %specific_fn.loc6
+// CHECK:STDOUT:   %addr.loc6: %ptr.f29 = addr_of %.loc6_15
+// CHECK:STDOUT:   %no_op.loc6: init %empty_tuple.type = call %bound_method.loc6_15.2(%addr.loc6)
+// CHECK:STDOUT:   %impl.elem0.loc14_35.3: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc14_35.4: <bound method> = bound_method %.loc14_35.1, %impl.elem0.loc14_35.3
+// CHECK:STDOUT:   %specific_fn.loc14_35.2: <specific function> = specific_function %impl.elem0.loc14_35.3, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc14_35.5: <bound method> = bound_method %.loc14_35.1, %specific_fn.loc14_35.2
+// CHECK:STDOUT:   %addr.loc14_35.2: %ptr.f29 = addr_of %.loc14_35.1
+// CHECK:STDOUT:   %no_op.loc14_35.2: init %empty_tuple.type = call %bound_method.loc14_35.5(%addr.loc14_35.2)
+// CHECK:STDOUT:   %impl.elem0.loc14_24.2: %.3a6 = impl_witness_access constants.%Destroy.impl_witness.cc5, element0 [concrete = constants.%Op.6fc]
+// CHECK:STDOUT:   %bound_method.loc14_24.3: <bound method> = bound_method %.loc14_24.2, %impl.elem0.loc14_24.2
+// CHECK:STDOUT:   %specific_fn.loc14_24.2: <specific function> = specific_function %impl.elem0.loc14_24.2, @Op.2(constants.%C.304) [concrete = constants.%Op.specific_fn.a08]
+// CHECK:STDOUT:   %bound_method.loc14_24.4: <bound method> = bound_method %.loc14_24.2, %specific_fn.loc14_24.2
+// CHECK:STDOUT:   %addr.loc14_24.2: %ptr.dc3 = addr_of %.loc14_24.2
+// CHECK:STDOUT:   %no_op.loc14_24.2: init %empty_tuple.type = call %bound_method.loc14_24.4(%addr.loc14_24.2)
+// CHECK:STDOUT:   %impl.elem0.loc13_35.4: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc13_35.6: <bound method> = bound_method %.loc13_35.1, %impl.elem0.loc13_35.4
+// CHECK:STDOUT:   %specific_fn.loc13_35.3: <specific function> = specific_function %impl.elem0.loc13_35.4, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc13_35.7: <bound method> = bound_method %.loc13_35.1, %specific_fn.loc13_35.3
+// CHECK:STDOUT:   %addr.loc13_35.3: %ptr.f29 = addr_of %.loc13_35.1
+// CHECK:STDOUT:   %no_op.loc13_35.3: init %empty_tuple.type = call %bound_method.loc13_35.7(%addr.loc13_35.3)
+// CHECK:STDOUT:   %impl.elem0.loc13_24.3: %.3d7 = impl_witness_access constants.%Destroy.impl_witness.1e4, element0 [concrete = constants.%Op.ca5]
+// CHECK:STDOUT:   %bound_method.loc13_24.5: <bound method> = bound_method %.loc13_24.2, %impl.elem0.loc13_24.3
+// CHECK:STDOUT:   %specific_fn.loc13_24.3: <specific function> = specific_function %impl.elem0.loc13_24.3, @Op.2(constants.%C.c60) [concrete = constants.%Op.specific_fn.8d0]
+// CHECK:STDOUT:   %bound_method.loc13_24.6: <bound method> = bound_method %.loc13_24.2, %specific_fn.loc13_24.3
+// CHECK:STDOUT:   %addr.loc13_24.3: %ptr.b5e = addr_of %.loc13_24.2
+// CHECK:STDOUT:   %no_op.loc13_24.3: init %empty_tuple.type = call %bound_method.loc13_24.6(%addr.loc13_24.3)
+// CHECK:STDOUT:   %impl.elem0.loc12_35.5: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc12_35.8: <bound method> = bound_method %.loc12_35.1, %impl.elem0.loc12_35.5
+// CHECK:STDOUT:   %specific_fn.loc12_35.4: <specific function> = specific_function %impl.elem0.loc12_35.5, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc12_35.9: <bound method> = bound_method %.loc12_35.1, %specific_fn.loc12_35.4
+// CHECK:STDOUT:   %addr.loc12_35.4: %ptr.f29 = addr_of %.loc12_35.1
+// CHECK:STDOUT:   %no_op.loc12_35.4: init %empty_tuple.type = call %bound_method.loc12_35.9(%addr.loc12_35.4)
+// CHECK:STDOUT:   %impl.elem0.loc12_24.4: %.89c = impl_witness_access constants.%Destroy.impl_witness.818, element0 [concrete = constants.%Op.985]
+// CHECK:STDOUT:   %bound_method.loc12_24.7: <bound method> = bound_method %.loc12_24.2, %impl.elem0.loc12_24.4
+// CHECK:STDOUT:   %specific_fn.loc12_24.4: <specific function> = specific_function %impl.elem0.loc12_24.4, @Op.2(constants.%C.f0a) [concrete = constants.%Op.specific_fn.a66]
+// CHECK:STDOUT:   %bound_method.loc12_24.8: <bound method> = bound_method %.loc12_24.2, %specific_fn.loc12_24.4
+// CHECK:STDOUT:   %addr.loc12_24.4: %ptr.24c = addr_of %.loc12_24.2
+// CHECK:STDOUT:   %no_op.loc12_24.4: init %empty_tuple.type = call %bound_method.loc12_24.8(%addr.loc12_24.4)
+// CHECK:STDOUT:   %impl.elem0.loc11_35.6: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc11_35.10: <bound method> = bound_method %.loc11_35.1, %impl.elem0.loc11_35.6
+// CHECK:STDOUT:   %specific_fn.loc11_35.5: <specific function> = specific_function %impl.elem0.loc11_35.6, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc11_35.11: <bound method> = bound_method %.loc11_35.1, %specific_fn.loc11_35.5
+// CHECK:STDOUT:   %addr.loc11_35.5: %ptr.f29 = addr_of %.loc11_35.1
+// CHECK:STDOUT:   %no_op.loc11_35.5: init %empty_tuple.type = call %bound_method.loc11_35.11(%addr.loc11_35.5)
+// CHECK:STDOUT:   %impl.elem0.loc11_24.5: %.6ca = impl_witness_access constants.%Destroy.impl_witness.f66, element0 [concrete = constants.%Op.6b4]
+// CHECK:STDOUT:   %bound_method.loc11_24.9: <bound method> = bound_method %.loc11_24.2, %impl.elem0.loc11_24.5
+// CHECK:STDOUT:   %specific_fn.loc11_24.5: <specific function> = specific_function %impl.elem0.loc11_24.5, @Op.2(constants.%C.89d) [concrete = constants.%Op.specific_fn.357]
+// CHECK:STDOUT:   %bound_method.loc11_24.10: <bound method> = bound_method %.loc11_24.2, %specific_fn.loc11_24.5
+// CHECK:STDOUT:   %addr.loc11_24.5: %ptr.c28b = addr_of %.loc11_24.2
+// CHECK:STDOUT:   %no_op.loc11_24.5: init %empty_tuple.type = call %bound_method.loc11_24.10(%addr.loc11_24.5)
+// CHECK:STDOUT:   %impl.elem0.loc10_35.7: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc10_35.12: <bound method> = bound_method %.loc10_35.1, %impl.elem0.loc10_35.7
+// CHECK:STDOUT:   %specific_fn.loc10_35.6: <specific function> = specific_function %impl.elem0.loc10_35.7, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc10_35.13: <bound method> = bound_method %.loc10_35.1, %specific_fn.loc10_35.6
+// CHECK:STDOUT:   %addr.loc10_35.6: %ptr.f29 = addr_of %.loc10_35.1
+// CHECK:STDOUT:   %no_op.loc10_35.6: init %empty_tuple.type = call %bound_method.loc10_35.13(%addr.loc10_35.6)
+// CHECK:STDOUT:   %impl.elem0.loc10_24.6: %.f23 = impl_witness_access constants.%Destroy.impl_witness.4d8, element0 [concrete = constants.%Op.9cf]
+// CHECK:STDOUT:   %bound_method.loc10_24.11: <bound method> = bound_method %.loc10_24.2, %impl.elem0.loc10_24.6
+// CHECK:STDOUT:   %specific_fn.loc10_24.6: <specific function> = specific_function %impl.elem0.loc10_24.6, @Op.2(constants.%C.7ac) [concrete = constants.%Op.specific_fn.694]
+// CHECK:STDOUT:   %bound_method.loc10_24.12: <bound method> = bound_method %.loc10_24.2, %specific_fn.loc10_24.6
+// CHECK:STDOUT:   %addr.loc10_24.6: %ptr.2b1 = addr_of %.loc10_24.2
+// CHECK:STDOUT:   %no_op.loc10_24.6: init %empty_tuple.type = call %bound_method.loc10_24.12(%addr.loc10_24.6)
+// CHECK:STDOUT:   %impl.elem0.loc9_35.8: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc9_35.14: <bound method> = bound_method %.loc9_35.1, %impl.elem0.loc9_35.8
+// CHECK:STDOUT:   %specific_fn.loc9_35.7: <specific function> = specific_function %impl.elem0.loc9_35.8, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc9_35.15: <bound method> = bound_method %.loc9_35.1, %specific_fn.loc9_35.7
+// CHECK:STDOUT:   %addr.loc9_35.7: %ptr.f29 = addr_of %.loc9_35.1
+// CHECK:STDOUT:   %no_op.loc9_35.7: init %empty_tuple.type = call %bound_method.loc9_35.15(%addr.loc9_35.7)
+// CHECK:STDOUT:   %impl.elem0.loc9_24.7: %.715 = impl_witness_access constants.%Destroy.impl_witness.3a3, element0 [concrete = constants.%Op.404]
+// CHECK:STDOUT:   %bound_method.loc9_24.13: <bound method> = bound_method %.loc9_24.2, %impl.elem0.loc9_24.7
+// CHECK:STDOUT:   %specific_fn.loc9_24.7: <specific function> = specific_function %impl.elem0.loc9_24.7, @Op.2(constants.%C.681) [concrete = constants.%Op.specific_fn.822]
+// CHECK:STDOUT:   %bound_method.loc9_24.14: <bound method> = bound_method %.loc9_24.2, %specific_fn.loc9_24.7
+// CHECK:STDOUT:   %addr.loc9_24.7: %ptr.3bd = addr_of %.loc9_24.2
+// CHECK:STDOUT:   %no_op.loc9_24.7: init %empty_tuple.type = call %bound_method.loc9_24.14(%addr.loc9_24.7)
+// CHECK:STDOUT:   %impl.elem0.loc8_35.9: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc8_35.16: <bound method> = bound_method %.loc8_35.1, %impl.elem0.loc8_35.9
+// CHECK:STDOUT:   %specific_fn.loc8_35.8: <specific function> = specific_function %impl.elem0.loc8_35.9, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc8_35.17: <bound method> = bound_method %.loc8_35.1, %specific_fn.loc8_35.8
+// CHECK:STDOUT:   %addr.loc8_35.8: %ptr.f29 = addr_of %.loc8_35.1
+// CHECK:STDOUT:   %no_op.loc8_35.8: init %empty_tuple.type = call %bound_method.loc8_35.17(%addr.loc8_35.8)
+// CHECK:STDOUT:   %impl.elem0.loc8_24.8: %.42d = impl_witness_access constants.%Destroy.impl_witness.af9, element0 [concrete = constants.%Op.ad8]
+// CHECK:STDOUT:   %bound_method.loc8_24.15: <bound method> = bound_method %.loc8_24.2, %impl.elem0.loc8_24.8
+// CHECK:STDOUT:   %specific_fn.loc8_24.8: <specific function> = specific_function %impl.elem0.loc8_24.8, @Op.2(constants.%C.674) [concrete = constants.%Op.specific_fn.6b6]
+// CHECK:STDOUT:   %bound_method.loc8_24.16: <bound method> = bound_method %.loc8_24.2, %specific_fn.loc8_24.8
+// CHECK:STDOUT:   %addr.loc8_24.8: %ptr.625 = addr_of %.loc8_24.2
+// CHECK:STDOUT:   %no_op.loc8_24.8: init %empty_tuple.type = call %bound_method.loc8_24.16(%addr.loc8_24.8)
+// CHECK:STDOUT:   %impl.elem0.loc7_35.10: %.d1e = impl_witness_access constants.%Destroy.impl_witness.a3f, element0 [concrete = constants.%Op.f5a]
+// CHECK:STDOUT:   %bound_method.loc7_35.18: <bound method> = bound_method %.loc7_35.1, %impl.elem0.loc7_35.10
+// CHECK:STDOUT:   %specific_fn.loc7_35.9: <specific function> = specific_function %impl.elem0.loc7_35.10, @Op.2(constants.%D) [concrete = constants.%Op.specific_fn.bd1]
+// CHECK:STDOUT:   %bound_method.loc7_35.19: <bound method> = bound_method %.loc7_35.1, %specific_fn.loc7_35.9
+// CHECK:STDOUT:   %addr.loc7_35.9: %ptr.f29 = addr_of %.loc7_35.1
+// CHECK:STDOUT:   %no_op.loc7_35.9: init %empty_tuple.type = call %bound_method.loc7_35.19(%addr.loc7_35.9)
+// CHECK:STDOUT:   %impl.elem0.loc7_24.9: %.cde = impl_witness_access constants.%Destroy.impl_witness.ce3, element0 [concrete = constants.%Op.ae6]
+// CHECK:STDOUT:   %bound_method.loc7_24.17: <bound method> = bound_method %.loc7_24.2, %impl.elem0.loc7_24.9
+// CHECK:STDOUT:   %specific_fn.loc7_24.9: <specific function> = specific_function %impl.elem0.loc7_24.9, @Op.2(constants.%C.b00) [concrete = constants.%Op.specific_fn.e42]
+// CHECK:STDOUT:   %bound_method.loc7_24.18: <bound method> = bound_method %.loc7_24.2, %specific_fn.loc7_24.9
+// CHECK:STDOUT:   %addr.loc7_24.9: %ptr.697 = addr_of %.loc7_24.2
+// CHECK:STDOUT:   %no_op.loc7_24.9: init %empty_tuple.type = call %bound_method.loc7_24.18(%addr.loc7_24.9)
 // CHECK:STDOUT:   return %Make.call to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 27 - 4
toolchain/check/testdata/return/returned_var.carbon

@@ -33,6 +33,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]
@@ -71,12 +72,25 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Convert.bound.d04: <bound method> = bound_method %int_0.5c6, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.b6e: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
@@ -84,6 +98,9 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -172,10 +189,10 @@ fn G() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %result.var: ref %i32 = var %result.var_patt
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc26_12.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc26_12.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc26_12.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc26_12.1: <bound method> = bound_method %int_0, %impl.elem0.loc26_12.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc26_12.1: <specific function> = specific_function %impl.elem0.loc26_12.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_12.2: <bound method> = bound_method %int_0, %specific_fn.loc26_12.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked: init %i32 = call %bound_method.loc26_12.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc26_12: init %i32 = converted %int_0, %int.convert_checked [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %result.var, %.loc26_12
@@ -185,6 +202,12 @@ fn G() -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %result: ref %i32 = bind_name result, %result.var
 // CHECK:STDOUT:   %.loc26_16: %i32 = bind_value %result
+// CHECK:STDOUT:   %impl.elem0.loc26_12.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc26_12.3: <bound method> = bound_method %result.var, %impl.elem0.loc26_12.2
+// CHECK:STDOUT:   %specific_fn.loc26_12.2: <specific function> = specific_function %impl.elem0.loc26_12.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc26_12.4: <bound method> = bound_method %result.var, %specific_fn.loc26_12.2
+// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %result.var
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc26_12.4(%addr)
 // CHECK:STDOUT:   return %.loc26_16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 63 - 16
toolchain/check/testdata/return/returned_var_scope.carbon

@@ -36,6 +36,7 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
@@ -63,6 +64,18 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
 // CHECK:STDOUT:   %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.64e: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.type.a17: type = fn_type @Op.3, @impl.49c(%i32) [concrete]
+// CHECK:STDOUT:   %Op.e6a: %Op.type.a17 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %i32, (%Destroy.impl_witness.64e) [concrete]
+// CHECK:STDOUT:   %.ab7: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.e6a, @Op.3(%i32) [concrete]
 // CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]
 // CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]
@@ -74,6 +87,7 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
 // CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     .Bool = %Core.Bool
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
@@ -82,6 +96,9 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
 // CHECK:STDOUT:   %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/parts/int, loc16_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
 // CHECK:STDOUT:   %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -133,10 +150,10 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_0.loc17: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0.loc17: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc17_14.1: <bound method> = bound_method %int_0.loc17, %impl.elem0.loc17 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn.loc17: <specific function> = specific_function %impl.elem0.loc17, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc17_14.2: <bound method> = bound_method %int_0.loc17, %specific_fn.loc17 [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc17_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc17_14.1: <bound method> = bound_method %int_0.loc17, %impl.elem0.loc17_14.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc17_14.1: <specific function> = specific_function %impl.elem0.loc17_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc17_14.2: <bound method> = bound_method %int_0.loc17, %specific_fn.loc17_14.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked.loc17: init %i32 = call %bound_method.loc17_14.2(%int_0.loc17) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc17_14: init %i32 = converted %int_0.loc17, %int.convert_checked.loc17 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %v.var, %.loc17_14
@@ -158,10 +175,10 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %w.var: ref %i32 = var %w.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0.loc20: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc20_14.1: <bound method> = bound_method %int_1, %impl.elem0.loc20 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn.loc20: <specific function> = specific_function %impl.elem0.loc20, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc20_14.2: <bound method> = bound_method %int_1, %specific_fn.loc20 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc20_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc20_14.1: <bound method> = bound_method %int_1, %impl.elem0.loc20_14.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc20_14.1: <specific function> = specific_function %impl.elem0.loc20_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc20_14.2: <bound method> = bound_method %int_1, %specific_fn.loc20_14.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked.loc20: init %i32 = call %bound_method.loc20_14.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc20_14: init %i32 = converted %int_1, %int.convert_checked.loc20 [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %w.var, %.loc20_14
@@ -181,6 +198,18 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   %int.convert_checked.loc22: init %i32 = call %bound_method.loc22_11.2(%int_0.loc22) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc22_11.1: %i32 = value_of_initializer %int.convert_checked.loc22 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc22_11.2: %i32 = converted %int_0.loc22, %.loc22_11.1 [concrete = constants.%int_0.6a9]
+// CHECK:STDOUT:   %impl.elem0.loc20_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc20_14.3: <bound method> = bound_method %w.var, %impl.elem0.loc20_14.2
+// CHECK:STDOUT:   %specific_fn.loc20_14.2: <specific function> = specific_function %impl.elem0.loc20_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc20_14.4: <bound method> = bound_method %w.var, %specific_fn.loc20_14.2
+// CHECK:STDOUT:   %addr.loc20: %ptr.235 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc20: init %empty_tuple.type = call %bound_method.loc20_14.4(%addr.loc20)
+// CHECK:STDOUT:   %impl.elem0.loc17_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc17_14.3: <bound method> = bound_method %v.var, %impl.elem0.loc17_14.2
+// CHECK:STDOUT:   %specific_fn.loc17_14.2: <specific function> = specific_function %impl.elem0.loc17_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc17_14.4: <bound method> = bound_method %v.var, %specific_fn.loc17_14.2
+// CHECK:STDOUT:   %addr.loc17: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc17: init %empty_tuple.type = call %bound_method.loc17_14.4(%addr.loc17)
 // CHECK:STDOUT:   return %.loc22_11.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -196,10 +225,10 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
-// CHECK:STDOUT:   %impl.elem0.loc27: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc27_14.1: <bound method> = bound_method %int_0, %impl.elem0.loc27 [concrete = constants.%Convert.bound.d04]
-// CHECK:STDOUT:   %specific_fn.loc27: <specific function> = specific_function %impl.elem0.loc27, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc27_14.2: <bound method> = bound_method %int_0, %specific_fn.loc27 [concrete = constants.%bound_method.b6e]
+// CHECK:STDOUT:   %impl.elem0.loc27_14.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc27_14.1: <bound method> = bound_method %int_0, %impl.elem0.loc27_14.1 [concrete = constants.%Convert.bound.d04]
+// CHECK:STDOUT:   %specific_fn.loc27_14.1: <specific function> = specific_function %impl.elem0.loc27_14.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc27_14.2: <bound method> = bound_method %int_0, %specific_fn.loc27_14.1 [concrete = constants.%bound_method.b6e]
 // CHECK:STDOUT:   %int.convert_checked.loc27: init %i32 = call %bound_method.loc27_14.2(%int_0) [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   %.loc27_14: init %i32 = converted %int_0, %int.convert_checked.loc27 [concrete = constants.%int_0.6a9]
 // CHECK:STDOUT:   assign %v.var, %.loc27_14
@@ -209,6 +238,12 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v: ref %i32 = bind_name v, %v.var
 // CHECK:STDOUT:   %.loc27_18: %i32 = bind_value %v
+// CHECK:STDOUT:   %impl.elem0.loc27_14.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc27_14.3: <bound method> = bound_method %v.var, %impl.elem0.loc27_14.2
+// CHECK:STDOUT:   %specific_fn.loc27_14.2: <specific function> = specific_function %impl.elem0.loc27_14.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc27_14.4: <bound method> = bound_method %v.var, %specific_fn.loc27_14.2
+// CHECK:STDOUT:   %addr.loc27_14.1: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc27_14.1: init %empty_tuple.type = call %bound_method.loc27_14.4(%addr.loc27_14.1)
 // CHECK:STDOUT:   return %.loc27_18
 // CHECK:STDOUT:
 // CHECK:STDOUT: !if.else:
@@ -218,10 +253,10 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %w.var: ref %i32 = var %w.var_patt
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
-// CHECK:STDOUT:   %impl.elem0.loc30: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
-// CHECK:STDOUT:   %bound_method.loc30_12.1: <bound method> = bound_method %int_1, %impl.elem0.loc30 [concrete = constants.%Convert.bound.ab5]
-// CHECK:STDOUT:   %specific_fn.loc30: <specific function> = specific_function %impl.elem0.loc30, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc30_12.2: <bound method> = bound_method %int_1, %specific_fn.loc30 [concrete = constants.%bound_method.9a1]
+// CHECK:STDOUT:   %impl.elem0.loc30_12.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
+// CHECK:STDOUT:   %bound_method.loc30_12.1: <bound method> = bound_method %int_1, %impl.elem0.loc30_12.1 [concrete = constants.%Convert.bound.ab5]
+// CHECK:STDOUT:   %specific_fn.loc30_12.1: <specific function> = specific_function %impl.elem0.loc30_12.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc30_12.2: <bound method> = bound_method %int_1, %specific_fn.loc30_12.1 [concrete = constants.%bound_method.9a1]
 // CHECK:STDOUT:   %int.convert_checked.loc30: init %i32 = call %bound_method.loc30_12.2(%int_1) [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   %.loc30_12: init %i32 = converted %int_1, %int.convert_checked.loc30 [concrete = constants.%int_1.5d2]
 // CHECK:STDOUT:   assign %w.var, %.loc30_12
@@ -231,6 +266,18 @@ fn EnclosingButAfter(b: bool) -> i32 {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %w: ref %i32 = bind_name w, %w.var
 // CHECK:STDOUT:   %.loc30_16: %i32 = bind_value %w
+// CHECK:STDOUT:   %impl.elem0.loc30_12.2: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc30_12.3: <bound method> = bound_method %w.var, %impl.elem0.loc30_12.2
+// CHECK:STDOUT:   %specific_fn.loc30_12.2: <specific function> = specific_function %impl.elem0.loc30_12.2, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc30_12.4: <bound method> = bound_method %w.var, %specific_fn.loc30_12.2
+// CHECK:STDOUT:   %addr.loc30: %ptr.235 = addr_of %w.var
+// CHECK:STDOUT:   %no_op.loc30: init %empty_tuple.type = call %bound_method.loc30_12.4(%addr.loc30)
+// CHECK:STDOUT:   %impl.elem0.loc27_14.3: %.ab7 = impl_witness_access constants.%Destroy.impl_witness.64e, element0 [concrete = constants.%Op.e6a]
+// CHECK:STDOUT:   %bound_method.loc27_14.5: <bound method> = bound_method %v.var, %impl.elem0.loc27_14.3
+// CHECK:STDOUT:   %specific_fn.loc27_14.3: <specific function> = specific_function %impl.elem0.loc27_14.3, @Op.3(constants.%i32) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc27_14.6: <bound method> = bound_method %v.var, %specific_fn.loc27_14.3
+// CHECK:STDOUT:   %addr.loc27_14.2: %ptr.235 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc27_14.2: init %empty_tuple.type = call %bound_method.loc27_14.6(%addr.loc27_14.2)
 // CHECK:STDOUT:   return %.loc30_16
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 23 - 0
toolchain/check/testdata/struct/literal_member_access.carbon

@@ -23,6 +23,7 @@ fn F() -> i32 {
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %struct_type.x.y.z: type = struct_type {.x: %i32, .y: %i32, .z: %i32} [concrete]
@@ -33,17 +34,33 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]
+// CHECK:STDOUT:   %ptr.6eb: type = ptr_type %struct_type.x.y.z [concrete]
 // CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]
 // CHECK:STDOUT:   %struct_type.a.b.c.4ca: type = struct_type {.a: Core.IntLiteral, .b: %struct_type.x.y.z, .c: Core.IntLiteral} [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.2, @impl(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.a8b: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl(%struct_type.x.y.z) [concrete]
+// CHECK:STDOUT:   %Op.type.f60: type = fn_type @Op.2, @impl(%struct_type.x.y.z) [concrete]
+// CHECK:STDOUT:   %Op.1a4: %Op.type.f60 = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %struct_type.x.y.z, (%Destroy.impl_witness.a8b) [concrete]
+// CHECK:STDOUT:   %.483: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.1a4, @Op.2(%struct_type.x.y.z) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {
 // CHECK:STDOUT:     .Int = %Core.Int
+// CHECK:STDOUT:     .Destroy = %Core.Destroy
 // CHECK:STDOUT:     import Core//prelude
 // CHECK:STDOUT:     import Core//prelude/...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]
+// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -101,6 +118,12 @@ fn F() -> i32 {
 // CHECK:STDOUT:   %.loc18_35.3: %struct_type.a.b.c.4ca = converted %.loc18_35.1, %struct.loc18_35
 // CHECK:STDOUT:   %.loc18_36: %struct_type.x.y.z = struct_access %.loc18_35.3, element1
 // CHECK:STDOUT:   %.loc18_38: %i32 = struct_access %.loc18_36, element1
+// CHECK:STDOUT:   %impl.elem0: %.483 = impl_witness_access constants.%Destroy.impl_witness.a8b, element0 [concrete = constants.%Op.1a4]
+// CHECK:STDOUT:   %bound_method.loc18_26.1: <bound method> = bound_method %.loc18_26.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.2(constants.%struct_type.x.y.z) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc18_26.2: <bound method> = bound_method %.loc18_26.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.6eb = addr_of %.loc18_26.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc18_26.2(%addr)
 // CHECK:STDOUT:   return %.loc18_38
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 0
toolchain/check/testdata/tuple/element_access.carbon

@@ -348,14 +348,29 @@ var b: i32 = a.({.index = 2}.index);
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.2 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.088: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.a1c) [concrete]
+// CHECK:STDOUT:   %Op.type.438: type = fn_type @Op.3, @impl.49c(%tuple.type.a1c) [concrete]
+// CHECK:STDOUT:   %Op.c8e: %Op.type.438 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.0b7: type = ptr_type %tuple.type.a1c [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type.a1c, (%Destroy.impl_witness.088) [concrete]
+// CHECK:STDOUT:   %.6a9: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.c8e, @Op.3(%tuple.type.a1c) [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() -> %i32 {
@@ -367,6 +382,12 @@ var b: i32 = a.({.index = 2}.index);
 // CHECK:STDOUT:   %.loc7_12.2: ref %tuple.type.a1c = temporary %.loc7_12.1, %F.call
 // CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %.loc7_12.2, element0
 // CHECK:STDOUT:   %.loc7_13: %i32 = bind_value %tuple.elem0
+// CHECK:STDOUT:   %impl.elem0: %.6a9 = impl_witness_access constants.%Destroy.impl_witness.088, element0 [concrete = constants.%Op.c8e]
+// CHECK:STDOUT:   %bound_method.loc7_12.1: <bound method> = bound_method %.loc7_12.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%tuple.type.a1c) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_12.2: <bound method> = bound_method %.loc7_12.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.0b7 = addr_of %.loc7_12.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc7_12.2(%addr)
 // CHECK:STDOUT:   return %.loc7_13
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 40 - 0
toolchain/check/testdata/tuple/in_place_tuple_init.carbon

@@ -50,6 +50,7 @@ fn H() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]
 // CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]
@@ -58,10 +59,24 @@ fn H() {
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
 // CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.261: type = ptr_type %tuple.type.d07 [concrete]
+// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]
+// CHECK:STDOUT:   %Op.type.bae: type = fn_type @Op.1 [concrete]
+// CHECK:STDOUT:   %T: type = bind_symbolic_name T, 0 [symbolic]
+// CHECK:STDOUT:   %Op.type.bc9: type = fn_type @Op.3, @impl.49c(%T) [symbolic]
+// CHECK:STDOUT:   %Op.46f: %Op.type.bc9 = struct_value () [symbolic]
+// CHECK:STDOUT:   %Destroy.impl_witness.5a7: <witness> = impl_witness imports.%Destroy.impl_witness_table, @impl.49c(%tuple.type.d07) [concrete]
+// CHECK:STDOUT:   %Op.type.a4a: type = fn_type @Op.3, @impl.49c(%tuple.type.d07) [concrete]
+// CHECK:STDOUT:   %Op.7c6: %Op.type.a4a = struct_value () [concrete]
+// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %tuple.type.d07, (%Destroy.impl_witness.5a7) [concrete]
+// CHECK:STDOUT:   %.b68: type = fn_type_with_self_type %Op.type.bae, %Destroy.facet [concrete]
+// CHECK:STDOUT:   %Op.specific_fn: <specific function> = specific_function %Op.7c6, @Op.3(%tuple.type.d07) [concrete]
 // CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Core.import_ref.0b9: @impl.49c.%Op.type (%Op.type.bc9) = import_ref Core//prelude/parts/destroy, loc8_29, loaded [symbolic = @impl.49c.%Op (constants.%Op.46f)]
+// CHECK:STDOUT:   %Destroy.impl_witness_table = impl_witness_table (%Core.import_ref.0b9), @impl.49c [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() -> %return.param: %tuple.type.d07 {
@@ -92,6 +107,25 @@ fn H() {
 // CHECK:STDOUT:   %F.ref.loc9: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   %F.call.loc9: init %tuple.type.d07 = call %F.ref.loc9() to %.loc5_8
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %impl.elem0.loc8: %.b68 = impl_witness_access constants.%Destroy.impl_witness.5a7, element0 [concrete = constants.%Op.7c6]
+// CHECK:STDOUT:   %bound_method.loc8_3.1: <bound method> = bound_method %.loc8, %impl.elem0.loc8
+// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Op.3(constants.%tuple.type.d07) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc8_3.2: <bound method> = bound_method %.loc8, %specific_fn.loc8
+// CHECK:STDOUT:   %addr.loc8: %ptr.261 = addr_of %.loc8
+// CHECK:STDOUT:   %no_op.loc8: init %empty_tuple.type = call %bound_method.loc8_3.2(%addr.loc8)
+// CHECK:STDOUT:   %impl.elem0.loc7_3.1: %.b68 = impl_witness_access constants.%Destroy.impl_witness.5a7, element0 [concrete = constants.%Op.7c6]
+// CHECK:STDOUT:   %bound_method.loc7_3.1: <bound method> = bound_method %.loc7_3, %impl.elem0.loc7_3.1
+// CHECK:STDOUT:   %specific_fn.loc7_3.1: <specific function> = specific_function %impl.elem0.loc7_3.1, @Op.3(constants.%tuple.type.d07) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_3.2: <bound method> = bound_method %.loc7_3, %specific_fn.loc7_3.1
+// CHECK:STDOUT:   %addr.loc7_3.1: %ptr.261 = addr_of %.loc7_3
+// CHECK:STDOUT:   %no_op.loc7_3.1: init %empty_tuple.type = call %bound_method.loc7_3.2(%addr.loc7_3.1)
+// CHECK:STDOUT:   %impl.elem0.loc7_3.2: %.b68 = impl_witness_access constants.%Destroy.impl_witness.5a7, element0 [concrete = constants.%Op.7c6]
+// CHECK:STDOUT:   %bound_method.loc7_3.3: <bound method> = bound_method %v.var, %impl.elem0.loc7_3.2
+// CHECK:STDOUT:   %specific_fn.loc7_3.2: <specific function> = specific_function %impl.elem0.loc7_3.2, @Op.3(constants.%tuple.type.d07) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc7_3.4: <bound method> = bound_method %v.var, %specific_fn.loc7_3.2
+// CHECK:STDOUT:   %addr.loc7_3.2: %ptr.261 = addr_of %v.var
+// CHECK:STDOUT:   %no_op.loc7_3.2: init %empty_tuple.type = call %bound_method.loc7_3.4(%addr.loc7_3.2)
 // CHECK:STDOUT:   return %F.call.loc9 to %return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -104,6 +138,12 @@ fn H() {
 // CHECK:STDOUT:   %.loc15_12.2: ref %tuple.type.d07 = temporary %.loc15_12.1, %G.call
 // CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %.loc15_12.2, element0
 // CHECK:STDOUT:   %.loc15_13: %i32 = bind_value %tuple.elem0
+// CHECK:STDOUT:   %impl.elem0: %.b68 = impl_witness_access constants.%Destroy.impl_witness.5a7, element0 [concrete = constants.%Op.7c6]
+// CHECK:STDOUT:   %bound_method.loc15_12.1: <bound method> = bound_method %.loc15_12.1, %impl.elem0
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Op.3(constants.%tuple.type.d07) [concrete = constants.%Op.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc15_12.2: <bound method> = bound_method %.loc15_12.1, %specific_fn
+// CHECK:STDOUT:   %addr: %ptr.261 = addr_of %.loc15_12.1
+// CHECK:STDOUT:   %no_op: init %empty_tuple.type = call %bound_method.loc15_12.2(%addr)
 // CHECK:STDOUT:   return %.loc15_13
 // CHECK:STDOUT: }
 // CHECK:STDOUT: