Change the Destroy blanket impls to be more specific (#6098)

The main direction of this change is the edits to `destroy.carbon`
(matching in both prelude and min_prelude).

Previously there was a no-op blanket impl for `Destroy`, which hid all
missing implementations of `Destroy`. This does a few things:

- Sets up builtin aggregate destruction for struct and tuple types as
before, but also adds C++ class types and array types to the same
handling. (all as a TODO for actual implementation)
- Also maybe-unformed destruction, for now at least. (there's a chance I
may try a different approach on this, but the impl lookup wasn't working
as I'd hope in order to write it in code)
- Adds handlers for simple things that are easy to do in code: `type`,
`bool`, pointers. (because these are no-op destruction)
- Redirect `const T` destruction to `T` destruction.

This leaves as future issues:

- `partial T` destruction. (this can't be done similar to `const`
because it only works for non-`final` class types; I think `class`
definitions should just generate what's needed)
- Destruction of other prelude-provided types. (will probably come up as
we implement class destruction, that the adapted builtin type doesn't
implement `Destroy` -- but may end up special-casing that in a way that
moots it)

This moves the `&` operator from `facet_types.carbon` to
`convert.carbon` because more things need to handle type and now that
we're getting separate copy and destroy interfaces. It should be
low-cost (an interface and builtin) so hopefully this is the right
balance for complexity and re-use.

A few tests are also edited in order to focus them more on what they
intend to test, and avoid a `Destroy` dependency.
This commit is contained in:
Jon Ross-Perkins
2025-09-18 22:10:50 +00:00
committed by GitHub
parent 868c4b768c
commit 9704dc670e
143 changed files with 3271 additions and 2413 deletions
+10 -10
View File
@@ -524,11 +524,11 @@ fn F() {
// CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %pattern_type.98f: type = pattern_type type [concrete]
// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic]
// CHECK:STDOUT: %ptr.79f: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %pattern_type.afe: type = pattern_type %ptr.79f [symbolic]
// CHECK:STDOUT: %ptr.79f131.1: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %pattern_type.afe: type = pattern_type %ptr.79f131.1 [symbolic]
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.type: type = fn_type @ExplicitAndAlsoDeduced [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.6e5: <witness> = require_complete_type %ptr.79f131.1 [symbolic]
// CHECK:STDOUT: %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.specific_fn.41d: <specific function> = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T) [symbolic]
// CHECK:STDOUT: %CallExplicitAndAlsoDeduced.type: type = fn_type @CallExplicitAndAlsoDeduced [concrete]
@@ -565,14 +565,14 @@ fn F() {
// CHECK:STDOUT: %return.param_patt: @ExplicitAndAlsoDeduced.%pattern_type.loc6_43 (%pattern_type.afe) = out_param_pattern %return.patt, call_param1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.ref.loc6_46: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]
// CHECK:STDOUT: %ptr.loc6_47.2: type = ptr_type %T.ref.loc6_46 [symbolic = %ptr.loc6_47.1 (constants.%ptr.79f)]
// CHECK:STDOUT: %ptr.loc6_47.2: type = ptr_type %T.ref.loc6_46 [symbolic = %ptr.loc6_47.1 (constants.%ptr.79f131.1)]
// CHECK:STDOUT: %.Self: %type = bind_symbolic_name .Self [symbolic_self = constants.%.Self]
// CHECK:STDOUT: %T.loc6_27.2: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_27.1 (constants.%T)]
// CHECK:STDOUT: %x.param: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = value_param call_param0
// CHECK:STDOUT: %T.ref.loc6_40: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]
// CHECK:STDOUT: %x: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = bind_name x, %x.param
// CHECK:STDOUT: %return.param: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f) = out_param call_param1
// CHECK:STDOUT: %return: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f) = return_slot %return.param
// CHECK:STDOUT: %return.param: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f131.1) = out_param call_param1
// CHECK:STDOUT: %return: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f131.1) = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %CallExplicitAndAlsoDeduced.decl: %CallExplicitAndAlsoDeduced.type = fn_decl @CallExplicitAndAlsoDeduced [concrete = constants.%CallExplicitAndAlsoDeduced] {
// CHECK:STDOUT: %return.patt: %pattern_type.5f8 = return_slot_pattern [concrete]
@@ -618,7 +618,7 @@ fn F() {
// CHECK:STDOUT: generic fn @ExplicitAndAlsoDeduced(%T.loc6_27.2: type) {
// CHECK:STDOUT: %T.loc6_27.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc6_27.1 (constants.%T)]
// CHECK:STDOUT: %pattern_type.loc6_37: type = pattern_type %T.loc6_27.1 [symbolic = %pattern_type.loc6_37 (constants.%pattern_type.7dc)]
// CHECK:STDOUT: %ptr.loc6_47.1: type = ptr_type %T.loc6_27.1 [symbolic = %ptr.loc6_47.1 (constants.%ptr.79f)]
// CHECK:STDOUT: %ptr.loc6_47.1: type = ptr_type %T.loc6_27.1 [symbolic = %ptr.loc6_47.1 (constants.%ptr.79f131.1)]
// CHECK:STDOUT: %pattern_type.loc6_43: type = pattern_type %ptr.loc6_47.1 [symbolic = %pattern_type.loc6_43 (constants.%pattern_type.afe)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
@@ -626,13 +626,13 @@ fn F() {
// CHECK:STDOUT: %require_complete.loc6_38: <witness> = require_complete_type %T.loc6_27.1 [symbolic = %require_complete.loc6_38 (constants.%require_complete.4ae)]
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2: <specific function> = specific_function constants.%ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T.loc6_27.1) [symbolic = %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 (constants.%ExplicitAndAlsoDeduced.specific_fn.41d)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%x.param: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T)) -> @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f) {
// CHECK:STDOUT: fn(%x.param: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T)) -> @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f131.1) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.ref: %ExplicitAndAlsoDeduced.type = name_ref ExplicitAndAlsoDeduced, file.%ExplicitAndAlsoDeduced.decl [concrete = constants.%ExplicitAndAlsoDeduced]
// CHECK:STDOUT: %T.ref.loc7: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]
// CHECK:STDOUT: %x.ref: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = name_ref x, %x
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.specific_fn.loc7_10.1: <specific function> = specific_function %ExplicitAndAlsoDeduced.ref, @ExplicitAndAlsoDeduced(constants.%T) [symbolic = %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 (constants.%ExplicitAndAlsoDeduced.specific_fn.41d)]
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.call: init @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f) = call %ExplicitAndAlsoDeduced.specific_fn.loc7_10.1(%x.ref)
// CHECK:STDOUT: %ExplicitAndAlsoDeduced.call: init @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.79f131.1) = call %ExplicitAndAlsoDeduced.specific_fn.loc7_10.1(%x.ref)
// CHECK:STDOUT: return %ExplicitAndAlsoDeduced.call to %return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -658,7 +658,7 @@ fn F() {
// CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(constants.%T) {
// CHECK:STDOUT: %T.loc6_27.1 => constants.%T
// CHECK:STDOUT: %pattern_type.loc6_37 => constants.%pattern_type.7dc
// CHECK:STDOUT: %ptr.loc6_47.1 => constants.%ptr.79f
// CHECK:STDOUT: %ptr.loc6_47.1 => constants.%ptr.79f131.1
// CHECK:STDOUT: %pattern_type.loc6_43 => constants.%pattern_type.afe
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
@@ -2,7 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/facet_types.carbon
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
//
@@ -105,8 +105,8 @@ fn F() {
// 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.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]
// CHECK:STDOUT: %Core.import_ref.636: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude, loc14_42, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]
// CHECK:STDOUT: %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]
// CHECK:STDOUT: %Core.import_ref.636: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc25_42, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]
// CHECK:STDOUT: %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.636), @type.as.BitAndWith.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -83,10 +83,12 @@ fn G() {
// CHECK:STDOUT: %Wrap.Make.type.708: type = fn_type @Wrap.Make, @Wrap(%C) [concrete]
// CHECK:STDOUT: %Wrap.Make.e4b: %Wrap.Make.type.708 = struct_value () [concrete]
// CHECK:STDOUT: %Wrap.Make.specific_fn.834: <specific function> = specific_function %Wrap.Make.e4b, @Wrap.Make(%C) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.08a: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%empty_tuple.type) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.daf: %T.as.Destroy.impl.Op.type.08a = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanAggregateDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %empty_tuple.type, () [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.4e0: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.c00: %AggregateT.as_type.as.Destroy.impl.Op.type.4e0 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.843: type = ptr_type %empty_tuple.type [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %T.as.Destroy.impl.Op.daf, @T.as.Destroy.impl.Op(%empty_tuple.type) [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %AggregateT.as_type.as.Destroy.impl.Op.c00, @AggregateT.as_type.as.Destroy.impl.Op(%facet_value) [concrete]
// CHECK:STDOUT: %Int.as.Destroy.impl.Op.type.4f9: type = fn_type @Int.as.Destroy.impl.Op, @Int.as.Destroy.impl(%int_32) [concrete]
// CHECK:STDOUT: %Int.as.Destroy.impl.Op.796: %Int.as.Destroy.impl.Op.type.4f9 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete]
@@ -309,11 +311,13 @@ fn G() {
// CHECK:STDOUT: %C.as.Destroy.impl.Op.bound: <bound method> = bound_method %c.var, constants.%C.as.Destroy.impl.Op
// CHECK:STDOUT: %addr.loc24: %ptr.019 = addr_of %c.var
// CHECK:STDOUT: %C.as.Destroy.impl.Op.call: init %empty_tuple.type = call %C.as.Destroy.impl.Op.bound(%addr.loc24)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %b.var, constants.%T.as.Destroy.impl.Op.daf
// CHECK:STDOUT: %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.Destroy.impl.Op.daf, @T.as.Destroy.impl.Op(constants.%empty_tuple.type) [concrete = constants.%T.as.Destroy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc23: <bound method> = bound_method %b.var, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%empty_tuple.type, () [concrete = constants.%facet_value]
// CHECK:STDOUT: %.loc23_3: %type_where = converted constants.%empty_tuple.type, %facet_value [concrete = constants.%facet_value]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %b.var, constants.%AggregateT.as_type.as.Destroy.impl.Op.c00
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%AggregateT.as_type.as.Destroy.impl.Op.c00, @AggregateT.as_type.as.Destroy.impl.Op(constants.%facet_value) [concrete = constants.%AggregateT.as_type.as.Destroy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc23: <bound method> = bound_method %b.var, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr.loc23: %ptr.843 = addr_of %b.var
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc23(%addr.loc23)
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc23(%addr.loc23)
// CHECK:STDOUT: %Int.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%Int.as.Destroy.impl.Op.796
// CHECK:STDOUT: %Int.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%Int.as.Destroy.impl.Op.796, @Int.as.Destroy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Destroy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc22: <bound method> = bound_method %a.var, %Int.as.Destroy.impl.Op.specific_fn
+26 -26
View File
@@ -27,20 +27,20 @@ fn F(T:! type) {
// 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: %ptr.79f: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %require_complete.6e5: <witness> = require_complete_type %ptr.79f [symbolic]
// CHECK:STDOUT: %pattern_type.afe: type = pattern_type %ptr.79f [symbolic]
// CHECK:STDOUT: %ptr.79f131.1: type = ptr_type %T [symbolic]
// CHECK:STDOUT: %require_complete.6e5: <witness> = require_complete_type %ptr.79f131.1 [symbolic]
// CHECK:STDOUT: %pattern_type.afe: type = pattern_type %ptr.79f131.1 [symbolic]
// CHECK:STDOUT: %require_complete.4ae: <witness> = require_complete_type %T [symbolic]
// CHECK:STDOUT: %pattern_type.7dc: type = pattern_type %T [symbolic]
// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete]
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
// CHECK:STDOUT: %ptr.a13: type = ptr_type %ptr.79f [symbolic]
// CHECK:STDOUT: %require_complete.132: <witness> = require_complete_type %ptr.a13 [symbolic]
// CHECK:STDOUT: %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.79f, @Destroy [symbolic]
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %ptr.79f, (%Destroy.lookup_impl_witness) [symbolic]
// CHECK:STDOUT: %.fc8: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet [symbolic]
// CHECK:STDOUT: %impl.elem0: %.fc8 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]
// CHECK:STDOUT: %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Destroy.Op(%Destroy.facet) [symbolic]
// CHECK:STDOUT: %ptr.a13abe.2: type = ptr_type %ptr.79f131.1 [symbolic]
// CHECK:STDOUT: %require_complete.1328e0.2: <witness> = require_complete_type %ptr.a13abe.2 [symbolic]
// CHECK:STDOUT: %Destroy.lookup_impl_witness.3af: <witness> = lookup_impl_witness %ptr.79f131.1, @Destroy [symbolic]
// CHECK:STDOUT: %Destroy.facet.64e: %Destroy.type = facet_value %ptr.79f131.1, (%Destroy.lookup_impl_witness.3af) [symbolic]
// CHECK:STDOUT: %.fc8: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet.64e [symbolic]
// CHECK:STDOUT: %impl.elem0.108: %.fc8 = impl_witness_access %Destroy.lookup_impl_witness.3af, element0 [symbolic]
// CHECK:STDOUT: %specific_impl_fn.a84: <specific function> = specific_impl_function %impl.elem0.108, @Destroy.Op(%Destroy.facet.64e) [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -70,18 +70,18 @@ fn F(T:! type) {
// CHECK:STDOUT: %T.loc15_6.1: type = bind_symbolic_name T, 0 [symbolic = %T.loc15_6.1 (constants.%T)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %ptr.loc16_11.2: type = ptr_type %T.loc15_6.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f)]
// CHECK:STDOUT: %ptr.loc16_11.2: type = ptr_type %T.loc15_6.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f131.1)]
// CHECK:STDOUT: %require_complete.loc16_11: <witness> = require_complete_type %ptr.loc16_11.2 [symbolic = %require_complete.loc16_11 (constants.%require_complete.6e5)]
// CHECK:STDOUT: %pattern_type.loc16: type = pattern_type %ptr.loc16_11.2 [symbolic = %pattern_type.loc16 (constants.%pattern_type.afe)]
// CHECK:STDOUT: %require_complete.loc17: <witness> = require_complete_type %T.loc15_6.1 [symbolic = %require_complete.loc17 (constants.%require_complete.4ae)]
// CHECK:STDOUT: %pattern_type.loc17: type = pattern_type %T.loc15_6.1 [symbolic = %pattern_type.loc17 (constants.%pattern_type.7dc)]
// CHECK:STDOUT: %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_11.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %ptr.loc16_11.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]
// CHECK:STDOUT: %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_11.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.3af)]
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %ptr.loc16_11.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.64e)]
// CHECK:STDOUT: %.loc16_3.2: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc16_3.2 (constants.%.fc8)]
// CHECK:STDOUT: %impl.elem0.loc16_3.2: @F.%.loc16_3.2 (%.fc8) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0)]
// CHECK:STDOUT: %specific_impl_fn.loc16_3.2: <specific function> = specific_impl_function %impl.elem0.loc16_3.2, @Destroy.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn)]
// CHECK:STDOUT: %ptr.loc16_3: type = ptr_type %ptr.loc16_11.2 [symbolic = %ptr.loc16_3 (constants.%ptr.a13)]
// CHECK:STDOUT: %require_complete.loc16_3: <witness> = require_complete_type %ptr.loc16_3 [symbolic = %require_complete.loc16_3 (constants.%require_complete.132)]
// CHECK:STDOUT: %impl.elem0.loc16_3.2: @F.%.loc16_3.2 (%.fc8) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0.108)]
// CHECK:STDOUT: %specific_impl_fn.loc16_3.2: <specific function> = specific_impl_function %impl.elem0.loc16_3.2, @Destroy.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn.a84)]
// CHECK:STDOUT: %ptr.loc16_3: type = ptr_type %ptr.loc16_11.2 [symbolic = %ptr.loc16_3 (constants.%ptr.a13abe.2)]
// CHECK:STDOUT: %require_complete.loc16_3: <witness> = require_complete_type %ptr.loc16_3 [symbolic = %require_complete.loc16_3 (constants.%require_complete.1328e0.2)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn() {
// CHECK:STDOUT: !entry:
@@ -89,26 +89,26 @@ fn F(T:! type) {
// CHECK:STDOUT: %p.patt: @F.%pattern_type.loc16 (%pattern_type.afe) = binding_pattern p [concrete]
// CHECK:STDOUT: %p.var_patt: @F.%pattern_type.loc16 (%pattern_type.afe) = var_pattern %p.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.var: ref @F.%ptr.loc16_11.2 (%ptr.79f) = var %p.var_patt
// CHECK:STDOUT: %.loc16_11: type = splice_block %ptr.loc16_11.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f)] {
// CHECK:STDOUT: %p.var: ref @F.%ptr.loc16_11.2 (%ptr.79f131.1) = var %p.var_patt
// CHECK:STDOUT: %.loc16_11: type = splice_block %ptr.loc16_11.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f131.1)] {
// CHECK:STDOUT: %T.ref.loc16: type = name_ref T, %T.loc15_6.2 [symbolic = %T.loc15_6.1 (constants.%T)]
// CHECK:STDOUT: %ptr.loc16_11.1: type = ptr_type %T.ref.loc16 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f)]
// CHECK:STDOUT: %ptr.loc16_11.1: type = ptr_type %T.ref.loc16 [symbolic = %ptr.loc16_11.2 (constants.%ptr.79f131.1)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p: ref @F.%ptr.loc16_11.2 (%ptr.79f) = bind_name p, %p.var
// CHECK:STDOUT: %p: ref @F.%ptr.loc16_11.2 (%ptr.79f131.1) = bind_name p, %p.var
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %n.patt: @F.%pattern_type.loc17 (%pattern_type.7dc) = binding_pattern n [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.ref: ref @F.%ptr.loc16_11.2 (%ptr.79f) = name_ref p, %p
// CHECK:STDOUT: %.loc17_15: @F.%ptr.loc16_11.2 (%ptr.79f) = bind_value %p.ref
// CHECK:STDOUT: %p.ref: ref @F.%ptr.loc16_11.2 (%ptr.79f131.1) = name_ref p, %p
// CHECK:STDOUT: %.loc17_15: @F.%ptr.loc16_11.2 (%ptr.79f131.1) = bind_value %p.ref
// CHECK:STDOUT: %.loc17_14.1: ref @F.%T.loc15_6.1 (%T) = deref %.loc17_15
// CHECK:STDOUT: %T.ref.loc17: type = name_ref T, %T.loc15_6.2 [symbolic = %T.loc15_6.1 (constants.%T)]
// CHECK:STDOUT: %.loc17_14.2: @F.%T.loc15_6.1 (%T) = bind_value %.loc17_14.1
// CHECK:STDOUT: %n: @F.%T.loc15_6.1 (%T) = bind_name n, %.loc17_14.2
// CHECK:STDOUT: %impl.elem0.loc16_3.1: @F.%.loc16_3.2 (%.fc8) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0)]
// CHECK:STDOUT: %impl.elem0.loc16_3.1: @F.%.loc16_3.2 (%.fc8) = impl_witness_access constants.%Destroy.lookup_impl_witness.3af, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0.108)]
// CHECK:STDOUT: %bound_method.loc16_3.1: <bound method> = bound_method %p.var, %impl.elem0.loc16_3.1
// CHECK:STDOUT: %specific_impl_fn.loc16_3.1: <specific function> = specific_impl_function %impl.elem0.loc16_3.1, @Destroy.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn)]
// CHECK:STDOUT: %specific_impl_fn.loc16_3.1: <specific function> = specific_impl_function %impl.elem0.loc16_3.1, @Destroy.Op(constants.%Destroy.facet.64e) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn.a84)]
// CHECK:STDOUT: %bound_method.loc16_3.2: <bound method> = bound_method %p.var, %specific_impl_fn.loc16_3.1
// CHECK:STDOUT: %addr: @F.%ptr.loc16_3 (%ptr.a13) = addr_of %p.var
// CHECK:STDOUT: %addr: @F.%ptr.loc16_3 (%ptr.a13abe.2) = addr_of %p.var
// CHECK:STDOUT: %.loc16_3.1: init %empty_tuple.type = call %bound_method.loc16_3.2(%addr)
// CHECK:STDOUT: return
// CHECK:STDOUT: }