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
+42 -80
View File
@@ -1898,13 +1898,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %C.Overload.cpp_overload_set.value: %C.Overload.cpp_overload_set.type = cpp_overload_set_value @C.Overload.cpp_overload_set [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type: type = fn_type @Overload__carbon_thunk [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk: %Overload__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value.136: %type_where = facet_value %PublicCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.136) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.52e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc = struct_value () [concrete]
// CHECK:STDOUT: %facet_value.b21: %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.b21) [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: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.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 {
@@ -1971,18 +1968,12 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc9_44.5: ref %PublicCall = value_as_ref %.loc9_44.4
// CHECK:STDOUT: %addr.loc9_45: %ptr.dfa = addr_of %.loc9_44.5
// CHECK:STDOUT: %Overload__carbon_thunk.call: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl(%addr.loc9_45)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc9: <bound method> = bound_method %.loc9_44.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc9: <bound method> = bound_method %.loc9_44.3, %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(%.loc9_44.3)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc8_38: <bound method> = bound_method %.loc8_38.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.15b
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8_38: <bound method> = bound_method %.loc8_38.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc8_38: init %empty_tuple.type = call %bound_method.loc8_38(%.loc8_38.3)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc8_37: <bound method> = bound_method %.loc8_37.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc8_37: <bound method> = bound_method %.loc8_37.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.3
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc8_37: init %empty_tuple.type = call %bound_method.loc8_37(%.loc8_37.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound.loc9: <bound method> = bound_method %.loc9_44.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call.loc9: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound.loc9(%.loc9_44.3)
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc8_38.3, constants.%C.cpp_destructor
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc8_38.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound.loc8: <bound method> = bound_method %.loc8_37.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call.loc8: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound.loc8(%.loc8_37.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2004,10 +1995,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
// CHECK:STDOUT: %C__carbon_thunk.type.65f120.1: type = fn_type @C__carbon_thunk.1 [concrete]
// CHECK:STDOUT: %C__carbon_thunk.d98342.1: %C__carbon_thunk.type.65f120.1 = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value.136: %type_where = facet_value %PublicCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.136) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.52e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall: type = class_type @ProtectedCall [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.type: type = cpp_overload_set_type @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
// CHECK:STDOUT: %ProtectedCall.ProtectedCall.cpp_overload_set.value: %ProtectedCall.ProtectedCall.cpp_overload_set.type = cpp_overload_set_value @ProtectedCall.ProtectedCall.cpp_overload_set [concrete]
@@ -2016,9 +2005,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %ProtectedCall__carbon_thunk: %ProtectedCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %C__carbon_thunk.type.65f120.2: type = fn_type @C__carbon_thunk.2 [concrete]
// CHECK:STDOUT: %C__carbon_thunk.d98342.2: %C__carbon_thunk.type.65f120.2 = struct_value () [concrete]
// CHECK:STDOUT: %facet_value.c53: %type_where = facet_value %ProtectedCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.c53) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.58f: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981 = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.type: type = fn_type @ProtectedCall.cpp_destructor [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor: %ProtectedCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %C.Overload.cpp_overload_set.type: type = cpp_overload_set_type @C.Overload.cpp_overload_set [concrete]
// CHECK:STDOUT: %C.Overload.cpp_overload_set.value: %C.Overload.cpp_overload_set.type = cpp_overload_set_value @C.Overload.cpp_overload_set [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type.9a101f.1: type = fn_type @Overload__carbon_thunk.1 [concrete]
@@ -2111,10 +2099,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc11_51.2: %struct_type.base.7c3 = struct_literal (%.loc11_50)
// CHECK:STDOUT: %.loc11_51.3: init %D = class_init (%.loc11_50), %return
// CHECK:STDOUT: %.loc11_52: init %D = converted %.loc11_51.2, %.loc11_51.3
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc11_49.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc11_49.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(%.loc11_49.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_49.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_49.3)
// CHECK:STDOUT: return %.loc11_52 to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2139,10 +2125,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc17_57.2: %struct_type.base.7c3 = struct_literal (%.loc17_56)
// CHECK:STDOUT: %.loc17_57.3: init %D = class_init (%.loc17_56), %return
// CHECK:STDOUT: %.loc17_58: init %D = converted %.loc17_57.2, %.loc17_57.3
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc17_55.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.58f
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc17_55.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(%.loc17_55.3)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc17_55.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc17_55.3)
// CHECK:STDOUT: return %.loc17_58 to %return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2161,10 +2145,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc23_40.5: ref %PublicCall = value_as_ref %.loc23_40.4
// CHECK:STDOUT: %addr.loc23_41: %ptr.dfa = addr_of %.loc23_40.5
// CHECK:STDOUT: %Overload__carbon_thunk.call: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.85994f.1(%addr.loc23_41)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc23_40.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc23_40.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(%.loc23_40.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc23_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc23_40.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2183,10 +2165,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc29_46.5: ref %ProtectedCall = value_as_ref %.loc29_46.4
// CHECK:STDOUT: %addr.loc29_47: %ptr.8e6 = addr_of %.loc29_46.5
// CHECK:STDOUT: %Overload__carbon_thunk.call: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.85994f.2(%addr.loc29_47)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc29_46.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.58f
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc29_46.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(%.loc29_46.3)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc29_46.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc29_46.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2205,10 +2185,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %PublicCall__carbon_thunk: %PublicCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type: type = fn_type @Overload__carbon_thunk [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk: %Overload__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 %PublicCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc: 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.52e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2250,10 +2228,8 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc8_49.5: ref %PublicCall = value_as_ref %.loc8_49.4
// CHECK:STDOUT: %addr.loc8_50: %ptr.dfa = addr_of %.loc8_49.5
// CHECK:STDOUT: %Overload__carbon_thunk.call: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl(%addr.loc8_50)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc8_49.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc8_49.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_49.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc8_49.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc8_49.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2281,13 +2257,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %ProtectedCall__carbon_thunk: %ProtectedCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type.9a101f.2: type = fn_type @Overload__carbon_thunk.2 [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.794c5b.2: %Overload__carbon_thunk.type.9a101f.2 = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value.c53: %type_where = facet_value %ProtectedCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.c53) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.58f: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981 = struct_value () [concrete]
// CHECK:STDOUT: %facet_value.136: %type_where = facet_value %PublicCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.136) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.52e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.type: type = fn_type @ProtectedCall.cpp_destructor [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor: %ProtectedCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2365,14 +2338,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc12_46.5: ref %ProtectedCall = value_as_ref %.loc12_46.4
// CHECK:STDOUT: %addr.loc12_47: %ptr.8e6 = addr_of %.loc12_46.5
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc12: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.85994f.2(%addr.loc12_47)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc12: <bound method> = bound_method %.loc12_46.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.58f
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc12: <bound method> = bound_method %.loc12_46.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc12: init %empty_tuple.type = call %bound_method.loc12(%.loc12_46.3)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc11: <bound method> = bound_method %.loc11_40.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc11: <bound method> = bound_method %.loc11_40.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc11: init %empty_tuple.type = call %bound_method.loc11(%.loc11_40.3)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc12_46.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc12_46.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2400,13 +2369,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %ProtectedCall__carbon_thunk: %ProtectedCall__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.type.9a101f.2: type = fn_type @Overload__carbon_thunk.2 [concrete]
// CHECK:STDOUT: %Overload__carbon_thunk.794c5b.2: %Overload__carbon_thunk.type.9a101f.2 = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value.c53: %type_where = facet_value %ProtectedCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.c53) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.58f: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.981 = struct_value () [concrete]
// CHECK:STDOUT: %facet_value.136: %type_where = facet_value %PublicCall, () [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.136) [concrete]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.52e: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.8dc = struct_value () [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.type: type = fn_type @ProtectedCall.cpp_destructor [concrete]
// CHECK:STDOUT: %ProtectedCall.cpp_destructor: %ProtectedCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor.type: type = fn_type @PublicCall.cpp_destructor [concrete]
// CHECK:STDOUT: %PublicCall.cpp_destructor: %PublicCall.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -2484,14 +2450,10 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %.loc12_46.5: ref %ProtectedCall = value_as_ref %.loc12_46.4
// CHECK:STDOUT: %addr.loc12_47: %ptr.8e6 = addr_of %.loc12_46.5
// CHECK:STDOUT: %Overload__carbon_thunk.call.loc12: init %empty_tuple.type = call imports.%Overload__carbon_thunk.decl.85994f.2(%addr.loc12_47)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc12: <bound method> = bound_method %.loc12_46.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.58f
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc12: <bound method> = bound_method %.loc12_46.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc12: init %empty_tuple.type = call %bound_method.loc12(%.loc12_46.3)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc11: <bound method> = bound_method %.loc11_40.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.52e
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method.loc11: <bound method> = bound_method %.loc11_40.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc11: init %empty_tuple.type = call %bound_method.loc11(%.loc11_40.3)
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.bound: <bound method> = bound_method %.loc12_46.3, constants.%ProtectedCall.cpp_destructor
// CHECK:STDOUT: %ProtectedCall.cpp_destructor.call: init %empty_tuple.type = call %ProtectedCall.cpp_destructor.bound(%.loc12_46.3)
// CHECK:STDOUT: %PublicCall.cpp_destructor.bound: <bound method> = bound_method %.loc11_40.3, constants.%PublicCall.cpp_destructor
// CHECK:STDOUT: %PublicCall.cpp_destructor.call: init %empty_tuple.type = call %PublicCall.cpp_destructor.bound(%.loc11_40.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: