Add Destroy.SubobjectDestroy as a temporary replacement for Destroy.Op (#7773)

This change partially implements [PR #7362], which revises how objects
are destroyed. It is a partial implementation for two reasons:

1. This change moves `Destroy.Op`'s current behaviour into
`Destroy.SubobjectDestroy`, but it doesn't add support for objects with
non-trivial destruction.
2. `Destroy.SubobjectDestroy` is a workaround for `require impls
SubobjectDestroy`. We aren't able to use the latter until the dependents
add their requirements' implementations to their own witness tables.

[PR #7362]: https://github.com/carbon-language/carbon-lang/pulls/7362
This commit is contained in:
Christopher Di Bella
2026-09-24 00:06:28 +00:00
committed by GitHub
parent 03939a9223
commit f7cd39428e
309 changed files with 51760 additions and 15269 deletions
@@ -154,6 +154,7 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %X: type = class_type @X [concrete]
// CHECK:STDOUT: %pattern_type.88a: type = pattern_type %X [concrete]
// CHECK:STDOUT: %X.elem: type = unbound_element_type %X, %i32 [concrete]
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete]
// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]
@@ -165,8 +166,14 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Copy.WithSelf.Op.type.381: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]
// CHECK:STDOUT: %.737: type = fn_type_with_self_type %Copy.WithSelf.Op.type.381, %Copy.facet [concrete]
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete]
// CHECK:STDOUT: %self.param_patt.d52: %pattern_type.88a = ref_param_pattern [concrete]
// CHECK:STDOUT: %self.patt.b78: %pattern_type.88a = wrapper_binding_pattern self, %self.param_patt.d52 [concrete]
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc10 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.403: %Destroy.WithSelf.Op.type.ef0 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc10 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3: %Destroy.WithSelf.SelfDestruct.type.fbc = struct_value () [concrete]
// CHECK:STDOUT: %X.g.cpp_overload_set.type: type = cpp_overload_set_type @X.g.cpp_overload_set [concrete]
// CHECK:STDOUT: %X.g.cpp_overload_set.value: %X.g.cpp_overload_set.type = cpp_overload_set_value @X.g.cpp_overload_set [concrete]
// CHECK:STDOUT: %X.g.type: type = fn_type @X.g [concrete]
@@ -177,6 +184,11 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Main.F: %F.type = import_ref Main//direct_import, F, loaded [concrete = constants.%F]
// CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)]
// CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete]
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %X.g.cpp_overload_set.value: %X.g.cpp_overload_set.type = cpp_overload_set_value @X.g.cpp_overload_set [concrete = constants.%X.g.cpp_overload_set.value]
// CHECK:STDOUT: %X.g.decl: %X.g.type = fn_decl @X.g [concrete = constants.%X.g] {
// CHECK:STDOUT: <elided>
@@ -185,6 +197,16 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generated {
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc10 [concrete = constants.%Destroy.WithSelf.Op.403] {
// CHECK:STDOUT: %self.param_patt: %pattern_type.88a = ref_param_pattern [concrete = constants.%self.param_patt.d52]
// CHECK:STDOUT: %self.patt: %pattern_type.88a = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.b78]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Field() -> out %return.param: %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]
@@ -199,11 +221,20 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc10_13.2: <bound method> = bound_method %.loc10_13.2, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc10_13.2(%.loc10_13.2)
// CHECK:STDOUT: %X.cpp_destructor.bound: <bound method> = bound_method %.loc10_12.2, constants.%X.cpp_destructor
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call %X.cpp_destructor.bound(%.loc10_12.2)
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: <bound method> = bound_method %.loc10_12.2, constants.%Destroy.WithSelf.SelfDestruct.db3
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%.loc10_12.2)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc10(%self.param: ref %X) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc10(%self.param: ref %X) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl(%self.param)
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call imports.%X.cpp_destructor.decl(%self.param)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Function() -> out %return.param: %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]
@@ -214,8 +245,8 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc16_12.2, %g.ref
// CHECK:STDOUT: %.loc16_12.3: %X = acquire_value %.loc16_12.2
// CHECK:STDOUT: %X.g.call: init %i32 = call imports.%X.g.decl(%.loc16_12.3)
// CHECK:STDOUT: %X.cpp_destructor.bound: <bound method> = bound_method %.loc16_12.2, constants.%X.cpp_destructor
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call %X.cpp_destructor.bound(%.loc16_12.2)
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: <bound method> = bound_method %.loc16_12.2, constants.%Destroy.WithSelf.SelfDestruct.db3
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%.loc16_12.2)
// CHECK:STDOUT: return %X.g.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -253,6 +284,8 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %int_1.0c6: %i32 = int_value 1 [concrete]
// CHECK:STDOUT: %X.g.cpp_overload_set.type: type = cpp_overload_set_type @X.g.cpp_overload_set [concrete]
// CHECK:STDOUT: %X.g.cpp_overload_set.value: %X.g.cpp_overload_set.type = cpp_overload_set_value @X.g.cpp_overload_set [concrete]
// CHECK:STDOUT: %self.param_patt.d52: %pattern_type.88a = ref_param_pattern [concrete]
// CHECK:STDOUT: %self.patt.b78: %pattern_type.88a = wrapper_binding_pattern self, %self.param_patt.d52 [concrete]
// CHECK:STDOUT: %X.g.type: type = fn_type @X.g [concrete]
// CHECK:STDOUT: %X.g: %X.g.type = struct_value () [concrete]
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete]
@@ -267,6 +300,10 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete]
// CHECK:STDOUT: %X.cpp_destructor.type: type = fn_type @X.cpp_destructor [concrete]
// CHECK:STDOUT: %X.cpp_destructor: %X.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc9 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.403: %Destroy.WithSelf.Op.type.ef0 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc9 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3: %Destroy.WithSelf.SelfDestruct.type.fbc = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -286,6 +323,21 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)]
// CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete]
// CHECK:STDOUT: %X.cpp_destructor.decl: %X.cpp_destructor.type = fn_decl @X.cpp_destructor [concrete = constants.%X.cpp_destructor] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generated {
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc9 [concrete = constants.%Destroy.WithSelf.Op.403] {
// CHECK:STDOUT: %self.param_patt: %pattern_type.88a = ref_param_pattern [concrete = constants.%self.param_patt.d52]
// CHECK:STDOUT: %self.patt: %pattern_type.88a = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.b78]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %self.param: ref %X = ref_param call_param0
// CHECK:STDOUT: %self: ref %X = wrapper_binding self, %self.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Use() -> out %return.param: %tuple.type.e55 {
@@ -331,11 +383,20 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %.loc10_23.3: init %i32 to %tuple.elem1 = in_place_init %X.g.call
// CHECK:STDOUT: %.loc10_23.4: init %tuple.type.e55 to %return.param = tuple_init (%.loc10_23.2, %.loc10_23.3)
// CHECK:STDOUT: %.loc10_24: init %tuple.type.e55 = converted %.loc10_23.1, %.loc10_23.4
// CHECK:STDOUT: %X.cpp_destructor.bound: <bound method> = bound_method %ax.var, constants.%X.cpp_destructor
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call %X.cpp_destructor.bound(%ax.var)
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: <bound method> = bound_method %ax.var, constants.%Destroy.WithSelf.SelfDestruct.db3
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%ax.var)
// CHECK:STDOUT: return %.loc10_24 to %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc9(%self.param: ref %X) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc9(%self.param: ref %X) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl(%self.param)
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call imports.%X.cpp_destructor.decl(%self.param)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_template.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
@@ -347,6 +408,7 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %Y.90c: type = class_type @Y.1 [concrete]
// CHECK:STDOUT: %pattern_type.fa7: type = pattern_type %Y.90c [concrete]
// CHECK:STDOUT: %Y.elem.ab3: type = unbound_element_type %Y.90c, %i32 [concrete]
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete]
// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]
@@ -358,12 +420,19 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Copy.WithSelf.Op.type.381: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.1e1) [concrete]
// CHECK:STDOUT: %.737: type = fn_type_with_self_type %Copy.WithSelf.Op.type.381, %Copy.facet.1e1 [concrete]
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete]
// CHECK:STDOUT: %self.param_patt.770: %pattern_type.fa7 = ref_param_pattern [concrete]
// CHECK:STDOUT: %self.patt.4ee: %pattern_type.fa7 = wrapper_binding_pattern self, %self.param_patt.770 [concrete]
// CHECK:STDOUT: %Y.cpp_destructor.type.0df797.1: type = fn_type @Y.cpp_destructor.1 [concrete]
// CHECK:STDOUT: %Y.cpp_destructor.be1864.1: %Y.cpp_destructor.type.0df797.1 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.1: type = fn_type @Destroy.WithSelf.Op.loc9 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.403171.1: %Destroy.WithSelf.Op.type.ef016f.1 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.1: type = fn_type @Destroy.WithSelf.SelfDestruct.loc9 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3fdb.1: %Destroy.WithSelf.SelfDestruct.type.fbceb5.1 = struct_value () [concrete]
// CHECK:STDOUT: %Z: type = class_type @Z [concrete]
// CHECK:STDOUT: %H.type: type = fn_type @H [concrete]
// CHECK:STDOUT: %H: %H.type = struct_value () [concrete]
// CHECK:STDOUT: %Y.e8d: type = class_type @Y.2 [concrete]
// CHECK:STDOUT: %pattern_type.586: type = pattern_type %Y.e8d [concrete]
// CHECK:STDOUT: %Y.elem.9a6: type = unbound_element_type %Y.e8d, %Z [concrete]
// CHECK:STDOUT: %Z.Z.type: type = fn_type @Z.Z [concrete]
// CHECK:STDOUT: %Z.Z: %Z.Z.type = struct_value () [concrete]
@@ -378,8 +447,14 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Copy.facet.ca1: %Copy.type = facet_value %Z, (%custom_witness.f88) [concrete]
// CHECK:STDOUT: %Copy.WithSelf.Op.type.1ad: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.ca1) [concrete]
// CHECK:STDOUT: %.f96: type = fn_type_with_self_type %Copy.WithSelf.Op.type.1ad, %Copy.facet.ca1 [concrete]
// CHECK:STDOUT: %self.param_patt.c0b: %pattern_type.586 = ref_param_pattern [concrete]
// CHECK:STDOUT: %self.patt.d1c: %pattern_type.586 = wrapper_binding_pattern self, %self.param_patt.c0b [concrete]
// CHECK:STDOUT: %Y.cpp_destructor.type.0df797.2: type = fn_type @Y.cpp_destructor.2 [concrete]
// CHECK:STDOUT: %Y.cpp_destructor.be1864.2: %Y.cpp_destructor.type.0df797.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.2: type = fn_type @Destroy.WithSelf.Op.loc15 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.Op.403171.2: %Destroy.WithSelf.Op.type.ef016f.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.2: type = fn_type @Destroy.WithSelf.SelfDestruct.loc15 [concrete]
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3fdb.2: %Destroy.WithSelf.SelfDestruct.type.fbceb5.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -387,6 +462,11 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %Main.H: %H.type = import_ref Main//direct_import, H, loaded [concrete = constants.%H]
// CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)]
// CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete]
// CHECK:STDOUT: %Y.cpp_destructor.decl.ab2aab.1: %Y.cpp_destructor.type.0df797.1 = fn_decl @Y.cpp_destructor.1 [concrete = constants.%Y.cpp_destructor.be1864.1] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Z.Z.decl: %Z.Z.type = fn_decl @Z.Z [concrete = constants.%Z.Z] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
@@ -397,6 +477,28 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %Y.cpp_destructor.decl.ab2aab.2: %Y.cpp_destructor.type.0df797.2 = fn_decl @Y.cpp_destructor.2 [concrete = constants.%Y.cpp_destructor.be1864.2] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generated {
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.1: %Destroy.WithSelf.Op.type.ef016f.1 = fn_decl @Destroy.WithSelf.Op.loc9 [concrete = constants.%Destroy.WithSelf.Op.403171.1] {
// CHECK:STDOUT: %self.param_patt: %pattern_type.fa7 = ref_param_pattern [concrete = constants.%self.param_patt.770]
// CHECK:STDOUT: %self.patt: %pattern_type.fa7 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.4ee]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %self.param: ref %Y.90c = ref_param call_param0
// CHECK:STDOUT: %self: ref %Y.90c = wrapper_binding self, %self.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.2: %Destroy.WithSelf.Op.type.ef016f.2 = fn_decl @Destroy.WithSelf.Op.loc15 [concrete = constants.%Destroy.WithSelf.Op.403171.2] {
// CHECK:STDOUT: %self.param_patt: %pattern_type.586 = ref_param_pattern [concrete = constants.%self.param_patt.c0b]
// CHECK:STDOUT: %self.patt: %pattern_type.586 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.d1c]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %self.param: ref %Y.e8d = ref_param call_param0
// CHECK:STDOUT: %self: ref %Y.e8d = wrapper_binding self, %self.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Use() -> out %return.param: %i32 {
@@ -413,11 +515,20 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc9_13.2: <bound method> = bound_method %.loc9_13.2, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc9_13.2(%.loc9_13.2)
// CHECK:STDOUT: %Y.cpp_destructor.bound: <bound method> = bound_method %.loc9_12.2, constants.%Y.cpp_destructor.be1864.1
// CHECK:STDOUT: %Y.cpp_destructor.call: init %empty_tuple.type = call %Y.cpp_destructor.bound(%.loc9_12.2)
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: <bound method> = bound_method %.loc9_12.2, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.1
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%.loc9_12.2)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc9(%self.param: ref %Y.90c) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc9(%self.param: ref %Y.90c) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl.5f94cf.1(%self.param)
// CHECK:STDOUT: %Y.cpp_destructor.call: init %empty_tuple.type = call imports.%Y.cpp_destructor.decl.ab2aab.1(%self.param)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @UseZ() -> out %return.param: %Z {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %H.ref: %H.type = name_ref H, imports.%Main.H [concrete = constants.%H]
@@ -440,8 +551,17 @@ fn UseZ() -> Cpp.A.Z {
// CHECK:STDOUT: %addr.loc15_13.2: %ptr.df4 = addr_of %.loc13_19.1
// CHECK:STDOUT: %Z__carbon_thunk.call: init %empty_tuple.type = call imports.%Z__carbon_thunk.decl(%.loc15_13.6, %addr.loc15_13.2)
// CHECK:STDOUT: %.loc15_13.7: init %Z to %.loc13_19.1 = mark_in_place_init %Z__carbon_thunk.call
// CHECK:STDOUT: %Y.cpp_destructor.bound: <bound method> = bound_method %.loc15_12.2, constants.%Y.cpp_destructor.be1864.2
// CHECK:STDOUT: %Y.cpp_destructor.call: init %empty_tuple.type = call %Y.cpp_destructor.bound(%.loc15_12.2)
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: <bound method> = bound_method %.loc15_12.2, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2
// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%.loc15_12.2)
// CHECK:STDOUT: return %.loc15_13.7 to %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc15(%self.param: ref %Y.e8d) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc15(%self.param: ref %Y.e8d) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl.5f94cf.2(%self.param)
// CHECK:STDOUT: %Y.cpp_destructor.call: init %empty_tuple.type = call imports.%Y.cpp_destructor.decl.ab2aab.2(%self.param)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: