Make Destroy.Op functions able to have a body (#6729)

This is iterating on how `Destroy.Op` generates, to start adding body
capabilities. This changes the way the signature is created, and adds a
`CoreWitness` function kind so that mangling can prevent name
collisions. The result is that what _was_ `DestroyOp` is now
`Core.Destroy.Op` or, as can be seen in
toolchain/lower/testdata/interop/cpp/nullptr.carbon,
`_COp.<hash>:core.Destroy.Core` where `:core` is indicating that it's a
core witness (taking a note from `:thunk`).

Assisted-by: Google Antigravity with Gemini 3 Flash
This commit is contained in:
Jon Ross-Perkins
2026-03-02 17:57:31 +00:00
committed by GitHub
parent 2389590230
commit b14015602b
163 changed files with 2472 additions and 2339 deletions
+71 -71
View File
@@ -500,8 +500,8 @@ fn F() {
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -543,12 +543,12 @@ fn F() {
// CHECK:STDOUT: %.loc11_11.2: ref %ptr = converted %p.ref, %.loc11_11.1
// CHECK:STDOUT: %.loc11_11.3: %ptr = acquire_value %.loc11_11.2
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc11_11.3)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %p.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %p.var, constants.%Destroy.Op
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%p.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: ref %const) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %const) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_double_non_nullable_pointer_param.carbon
// CHECK:STDOUT:
@@ -577,8 +577,8 @@ fn F() {
// CHECK:STDOUT: %ptr.dfe: type = ptr_type %ptr.5c7 [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
// CHECK:STDOUT: %S.cpp_destructor.type: type = fn_type @S.cpp_destructor [concrete]
// CHECK:STDOUT: %S.cpp_destructor: %S.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -640,14 +640,14 @@ fn F() {
// CHECK:STDOUT: %p.ref: ref %ptr.5c7 = name_ref p, %p
// CHECK:STDOUT: %addr.loc10: %ptr.dfe = addr_of %p.ref
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%addr.loc10)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %p.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %p.var, constants.%Destroy.Op
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%p.var)
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: ref %ptr.5c7) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %ptr.5c7) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_non_nullable_pointer_to_const_param_using_const.carbon
// CHECK:STDOUT:
@@ -663,8 +663,8 @@ fn F() {
// CHECK:STDOUT: %ptr.ff5: type = ptr_type %const [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -704,12 +704,12 @@ fn F() {
// CHECK:STDOUT: %s.ref: ref %const = name_ref s, %s
// CHECK:STDOUT: %addr: %ptr.ff5 = addr_of %s.ref
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%addr)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %s.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%s.var)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %s.var, constants.%Destroy.Op
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%s.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: ref %const) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %const) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_non_nullable_pointer_to_const_param_using_non_const.carbon
// CHECK:STDOUT:
@@ -787,8 +787,8 @@ fn F() {
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -830,12 +830,12 @@ fn F() {
// CHECK:STDOUT: %.loc11_11.2: ref %ptr = converted %p.ref, %.loc11_11.1
// CHECK:STDOUT: %.loc11_11.3: %ptr = acquire_value %.loc11_11.2
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc11_11.3)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %p.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %p.var, constants.%Destroy.Op
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%p.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: ref %const) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %const) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_const_non_nullable_pointer_param_using_non_const.carbon
// CHECK:STDOUT:
@@ -850,8 +850,8 @@ fn F() {
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -890,12 +890,12 @@ fn F() {
// CHECK:STDOUT: %p.ref: ref %ptr = name_ref p, %p
// CHECK:STDOUT: %.loc11: %ptr = acquire_value %p.ref
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc11)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %p.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %p.var, constants.%Destroy.Op
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%p.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: ref %ptr) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %ptr) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_const_nullable_pointer_param_using_const.carbon
// CHECK:STDOUT:
@@ -947,10 +947,10 @@ fn F() {
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.05e: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.065, %ImplicitAs.facet.1bd) [concrete]
// CHECK:STDOUT: %.b4e: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.05e, %ImplicitAs.facet.1bd [concrete]
// CHECK:STDOUT: %const.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %const.as.ImplicitAs.impl.Convert.af2, @const.as.ImplicitAs.impl.Convert(%Optional.065, %ImplicitAs.facet.77f) [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc11 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.3: type = fn_type @DestroyOp.loc10 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.3: %DestroyOp.type.3e79c2.3 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc11 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1017,16 +1017,16 @@ fn F() {
// CHECK:STDOUT: %.loc11_11.4: ref %Optional.065 = temporary %.loc11_11.3, %.loc11_11.2
// CHECK:STDOUT: %.loc11_11.5: %Optional.065 = acquire_value %.loc11_11.4
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc11_11.5)
// CHECK:STDOUT: %DestroyOp.bound.loc11: <bound method> = bound_method %.loc11_11.4, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call.loc11: init %empty_tuple.type = call %DestroyOp.bound.loc11(%.loc11_11.4)
// CHECK:STDOUT: %DestroyOp.bound.loc10: <bound method> = bound_method %p.var, constants.%DestroyOp.b0ebf8.3
// CHECK:STDOUT: %DestroyOp.call.loc10: init %empty_tuple.type = call %DestroyOp.bound.loc10(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_11.4, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_11.4)
// CHECK:STDOUT: %Destroy.Op.bound.loc10: <bound method> = bound_method %p.var, constants.%Destroy.Op.651ba6.3
// CHECK:STDOUT: %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%p.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc11(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc11(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc10(%self.param: ref %const.b9a) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc10(%self.param: ref %const.b9a) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_const_nullable_pointer_param_using_non_const.carbon
// CHECK:STDOUT:
@@ -1049,8 +1049,8 @@ fn F() {
// CHECK:STDOUT: %MaybeUnformed.2e9: type = class_type @MaybeUnformed, @MaybeUnformed(%Destroy.facet.617) [symbolic]
// CHECK:STDOUT: %ptr.as.OptionalStorage.impl.Some.type.c7a: type = fn_type @ptr.as.OptionalStorage.impl.Some, @ptr.as.OptionalStorage.impl(%T.67d) [symbolic]
// CHECK:STDOUT: %ptr.as.OptionalStorage.impl.Some.38a: %ptr.as.OptionalStorage.impl.Some.type.c7a = struct_value () [symbolic]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.1: type = fn_type @DestroyOp.1 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.1: %DestroyOp.type.3e79c2.1 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.1 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]
// CHECK:STDOUT: %OptionalStorage.impl_witness.ba1: <witness> = impl_witness imports.%OptionalStorage.impl_witness_table.bee, @ptr.as.OptionalStorage.impl(%S) [concrete]
// CHECK:STDOUT: %OptionalStorage.facet.872: %OptionalStorage.type = facet_value %ptr.5c7, (%OptionalStorage.impl_witness.ba1) [concrete]
// CHECK:STDOUT: %Optional.065: type = class_type @Optional, @Optional(%OptionalStorage.facet.872) [concrete]
@@ -1073,8 +1073,8 @@ fn F() {
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.0a72: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.065, %ImplicitAs.facet.77f) [concrete]
// CHECK:STDOUT: %.9b3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.0a72, %ImplicitAs.facet.77f [concrete]
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.binding.as_type.as.ImplicitAs.impl.Convert.bd4, @U.binding.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.872, %OptionalAs.facet) [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc11 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc11 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1138,14 +1138,14 @@ fn F() {
// CHECK:STDOUT: %.loc11_11.4: ref %Optional.065 = temporary %.loc11_11.3, %.loc11_11.2
// CHECK:STDOUT: %.loc11_11.5: %Optional.065 = acquire_value %.loc11_11.4
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc11_11.5)
// CHECK:STDOUT: %DestroyOp.bound.loc11: <bound method> = bound_method %.loc11_11.4, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call.loc11: init %empty_tuple.type = call %DestroyOp.bound.loc11(%.loc11_11.4)
// CHECK:STDOUT: %DestroyOp.bound.loc10: <bound method> = bound_method %p.var, constants.%DestroyOp.b0ebf8.1
// CHECK:STDOUT: %DestroyOp.call.loc10: init %empty_tuple.type = call %DestroyOp.bound.loc10(%p.var)
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_11.4, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_11.4)
// CHECK:STDOUT: %Destroy.Op.bound.loc10: <bound method> = bound_method %p.var, constants.%Destroy.Op.651ba6.1
// CHECK:STDOUT: %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%p.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc11(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc11(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_non_nullable_pointer_return.carbon
// CHECK:STDOUT:
@@ -1325,8 +1325,8 @@ fn F() {
// CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.0a72: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Optional.065, %ImplicitAs.facet.77f) [concrete]
// CHECK:STDOUT: %.9b3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.0a72, %ImplicitAs.facet.77f [concrete]
// CHECK:STDOUT: %U.binding.as_type.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %U.binding.as_type.as.ImplicitAs.impl.Convert.bd4, @U.binding.as_type.as.ImplicitAs.impl.Convert.2(%OptionalStorage.facet.872, %OptionalAs.facet) [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc9 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc9 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: %S.cpp_destructor.type: type = fn_type @S.cpp_destructor [concrete]
// CHECK:STDOUT: %S.cpp_destructor: %S.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -1392,14 +1392,14 @@ fn F() {
// CHECK:STDOUT: %.loc9_11.3: ref %Optional.065 = temporary %.loc9_11.2, %.loc9_11.1
// CHECK:STDOUT: %.loc9_11.4: %Optional.065 = acquire_value %.loc9_11.3
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc9_11.4)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %.loc9_11.3, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc9_11.3)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc9_11.3, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc9_11.3)
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc9(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc9(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- null_pointer_arg_to_pointer_param.carbon
// CHECK:STDOUT:
@@ -1431,8 +1431,8 @@ fn F() {
// CHECK:STDOUT: %Optional.None.specific_fn: <specific function> = specific_function %Optional.None.c13, @Optional.None(%OptionalStorage.facet) [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc8 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc8 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1491,12 +1491,12 @@ fn F() {
// CHECK:STDOUT: %.loc8_38.2: ref %Optional.7f5 = temporary %.loc8_38.1, %Optional.None.call
// CHECK:STDOUT: %.loc8_38.3: %Optional.7f5 = acquire_value %.loc8_38.2
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc8_38.3)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %.loc8_38.2, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc8_38.2)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc8_38.2, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc8_38.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc8(%self.param: ref %Optional.7f5) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc8(%self.param: ref %Optional.7f5) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- nonnull_pointer_arg_to_pointer_param.carbon
// CHECK:STDOUT:
@@ -1532,8 +1532,8 @@ fn F() {
// CHECK:STDOUT: %Optional.Some.specific_fn: <specific function> = specific_function %Optional.Some.16d, @Optional.Some(%OptionalStorage.facet) [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc9 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc9 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: %S.cpp_destructor.type: type = fn_type @S.cpp_destructor [concrete]
// CHECK:STDOUT: %S.cpp_destructor: %S.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -1614,14 +1614,14 @@ fn F() {
// CHECK:STDOUT: %.loc9_40.4: ref %Optional.065 = temporary %.loc9_40.3, %Optional.Some.call
// CHECK:STDOUT: %.loc9_40.5: %Optional.065 = acquire_value %.loc9_40.4
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc9_40.5)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %.loc9_40.4, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc9_40.4)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc9_40.4, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc9_40.4)
// CHECK:STDOUT: %S.cpp_destructor.bound: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call: init %empty_tuple.type = call %S.cpp_destructor.bound(%s.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc9(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc9(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- forward_nullable_pointer.carbon
// CHECK:STDOUT:
@@ -1647,8 +1647,8 @@ fn F() {
// CHECK:STDOUT: %get: %get.type = struct_value () [concrete]
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc8 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc8 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -1697,12 +1697,12 @@ fn F() {
// CHECK:STDOUT: %.loc8_19.2: ref %Optional.ece = temporary %.loc8_19.1, %get.call
// CHECK:STDOUT: %.loc8_19.3: %Optional.ece = acquire_value %.loc8_19.2
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc8_19.3)
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %.loc8_19.2, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc8_19.2)
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.loc8_19.2, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc8_19.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc8(%self.param: ref %Optional.ece) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc8(%self.param: ref %Optional.ece) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- import_deduced_any_param_as_pointer.carbon
// CHECK:STDOUT:
@@ -1828,8 +1828,8 @@ fn F() {
// CHECK:STDOUT: %Indirect.cpp_overload_set.value: %Indirect.cpp_overload_set.type = cpp_overload_set_value @Indirect.cpp_overload_set [concrete]
// CHECK:STDOUT: %Indirect__carbon_thunk.type: type = fn_type @Indirect__carbon_thunk [concrete]
// CHECK:STDOUT: %Indirect__carbon_thunk: %Indirect__carbon_thunk.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type.3e79c2.2: type = fn_type @DestroyOp.loc13 [concrete]
// CHECK:STDOUT: %DestroyOp.b0ebf8.2: %DestroyOp.type.3e79c2.2 = struct_value () [concrete]
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc13 [concrete]
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
// CHECK:STDOUT: %S.cpp_destructor.type: type = fn_type @S.cpp_destructor [concrete]
// CHECK:STDOUT: %S.cpp_destructor: %S.cpp_destructor.type = struct_value () [concrete]
// CHECK:STDOUT: }
@@ -1948,16 +1948,16 @@ fn F() {
// CHECK:STDOUT: %.loc13_65.2: ref %Optional.065 = temporary %.loc13_65.1, %Indirect__carbon_thunk.call
// CHECK:STDOUT: %.loc13_65.3: %Optional.065 = acquire_value %.loc13_65.2
// CHECK:STDOUT: %a: %Optional.065 = value_binding a, %.loc13_65.3
// CHECK:STDOUT: %DestroyOp.bound.loc13: <bound method> = bound_method %.loc13_65.2, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call.loc13: init %empty_tuple.type = call %DestroyOp.bound.loc13(%.loc13_65.2)
// CHECK:STDOUT: %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_65.2, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_65.2)
// CHECK:STDOUT: %S.cpp_destructor.bound.loc13: <bound method> = bound_method %.loc13_55.4, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call.loc13: init %empty_tuple.type = call %S.cpp_destructor.bound.loc13(%.loc13_55.4)
// CHECK:STDOUT: %DestroyOp.bound.loc11: <bound method> = bound_method %.loc11_14.3, constants.%DestroyOp.b0ebf8.2
// CHECK:STDOUT: %DestroyOp.call.loc11: init %empty_tuple.type = call %DestroyOp.bound.loc11(%.loc11_14.3)
// CHECK:STDOUT: %Destroy.Op.bound.loc11: <bound method> = bound_method %.loc11_14.3, constants.%Destroy.Op.651ba6.2
// CHECK:STDOUT: %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%.loc11_14.3)
// CHECK:STDOUT: %S.cpp_destructor.bound.loc10: <bound method> = bound_method %s.var, constants.%S.cpp_destructor
// CHECK:STDOUT: %S.cpp_destructor.call.loc10: init %empty_tuple.type = call %S.cpp_destructor.bound.loc10(%s.var)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp.loc13(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: fn @Destroy.Op.loc13(%self.param: ref %Optional.065) = "no_op";
// CHECK:STDOUT: