Support for calling C++ destructors. (#6453)

Synthesize an impl of `Destroy` for C++ classes in response to impl
lookup.
This commit is contained in:
Richard Smith
2025-12-09 21:03:27 +00:00
committed by GitHub
parent 2d38978756
commit c7cd24e1b2
28 changed files with 923 additions and 923 deletions
+38 -75
View File
@@ -538,10 +538,8 @@ fn F() {
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.15b: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -574,10 +572,8 @@ fn F() {
// CHECK:STDOUT: %.loc8_14.3: ref %C = value_as_ref %.loc8_14.2
// CHECK:STDOUT: %addr: %ptr.d9e = addr_of %.loc8_14.3
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc8_12.4)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -593,10 +589,8 @@ fn F() {
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.15b: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -627,10 +621,8 @@ fn F() {
// CHECK:STDOUT: %.loc24_14.1: ref %C = converted %.loc24_12.1, %.loc24_12.4
// CHECK:STDOUT: %.loc24_14.2: %C = acquire_value %.loc24_14.1
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc24_14.2)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc24_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc24_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc24_12.4)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc24_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc24_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -710,10 +702,8 @@ fn F() {
// CHECK:STDOUT: %ptr.838: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.422: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.e1c: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.422 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -762,14 +752,10 @@ fn F() {
// CHECK:STDOUT: %C.ref.loc10: type = name_ref C, imports.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: }
// CHECK:STDOUT: %x: ref %C = ref_binding x, %x.var
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc10: <bound method> = bound_method %x.var, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.e1c
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc10: <bound method> = bound_method %x.var, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc10: init %empty_tuple.type = call %bound_method.loc10(%x.var)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc8: <bound method> = bound_method %.loc8_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.e1c
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8: <bound method> = bound_method %.loc8_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8(%.loc8_12.4)
// CHECK:STDOUT: %C.cpp_destructor.bound.loc10: <bound method> = bound_method %x.var, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call.loc10: init %empty_tuple.type = call %C.cpp_destructor.bound.loc10(%x.var)
// CHECK:STDOUT: %C.cpp_destructor.bound.loc8: <bound method> = bound_method %.loc8_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call.loc8: init %empty_tuple.type = call %C.cpp_destructor.bound.loc8(%.loc8_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -786,10 +772,8 @@ fn F() {
// CHECK:STDOUT: %ptr.c0c: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.0f6: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.70e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.0f6 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -833,10 +817,8 @@ fn F() {
// CHECK:STDOUT: %.loc8_17.3: ref %C = value_as_ref %.loc8_17.2
// CHECK:STDOUT: %addr: %ptr.c0c = addr_of %.loc8_17.3
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_15.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.70e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_15.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc8_15.4)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_15.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_15.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -855,13 +837,10 @@ fn F() {
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %pattern_type.cff: type = pattern_type %O [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value.568: %type_where = facet_value %O, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.b7f: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.568) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.c77: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.b7f = struct_value () [concrete]
// CHECK:STDOUT: %facet_value.e34: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cf2: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.e34) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.449: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cf2 = struct_value () [concrete]
// CHECK:STDOUT: %O.cpp_destructor.type: type = fn_type @O.cpp_destructor [concrete]
// CHECK:STDOUT: %O.cpp_destructor: %O.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -906,14 +885,10 @@ fn F() {
// CHECK:STDOUT: %O.ref.loc9: type = name_ref O, imports.%O.decl [concrete = constants.%O]
// CHECK:STDOUT: }
// CHECK:STDOUT: %x: ref %O = ref_binding x, %x.var
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc9: <bound method> = bound_method %x.var, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.c77
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc9: <bound method> = bound_method %x.var, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc9: init %empty_tuple.type = call %bound_method.loc9(%x.var)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc8: <bound method> = bound_method %.loc8_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.449
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8: <bound method> = bound_method %.loc8_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8(%.loc8_12.4)
// CHECK:STDOUT: %O.cpp_destructor.bound: <bound method> = bound_method %x.var, constants.%O.cpp_destructor
// CHECK:STDOUT: %O.cpp_destructor.call: init %empty_tuple.type = call %O.cpp_destructor.bound(%x.var)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -934,10 +909,8 @@ fn F() {
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.15b: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -976,10 +949,8 @@ fn F() {
// CHECK:STDOUT: %.loc9_14.3: ref %C = value_as_ref %.loc9_14.2
// CHECK:STDOUT: %addr: %ptr.d9e = addr_of %.loc9_14.3
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc9_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc9_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc9_12.4)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc9_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc9_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -1000,10 +971,8 @@ fn F() {
// CHECK:STDOUT: %C.bar.cpp_overload_set.value: %C.bar.cpp_overload_set.type = cpp_overload_set_value @C.bar.cpp_overload_set [concrete]
// CHECK:STDOUT: %C.bar.type: type = fn_type @C.bar [concrete]
// CHECK:STDOUT: %C.bar: %C.bar.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.15b: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1042,10 +1011,8 @@ fn F() {
// CHECK:STDOUT: %C.ref.loc9: type = name_ref C, imports.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %bar.ref: %C.bar.cpp_overload_set.type = name_ref bar, imports.%C.bar.cpp_overload_set.value [concrete = constants.%C.bar.cpp_overload_set.value]
// CHECK:STDOUT: %C.bar.call: init %empty_tuple.type = call imports.%C.bar.decl()
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_12.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_12.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc8_12.4)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_12.4, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_12.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -1131,10 +1098,8 @@ fn F() {
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.15b: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.251 = struct_value () [concrete]
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1159,10 +1124,8 @@ fn F() {
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
// CHECK:STDOUT: %.loc8_11.2: init %C = in_place_init %foo__carbon_thunk.call, %.loc8_11.1
// CHECK:STDOUT: %.loc8_11.3: ref %C = temporary %.loc8_11.1, %.loc8_11.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_11.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_11.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%.loc8_11.3)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_11.3, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_11.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: