Handle SpecificImplFunction in GetCallee (#6487)

I need this in a forthcoming PR, to reliably get the `Function` that was
originally used to build a `Call` inst, but even as a stand-alone
change, it seems to nicely improve the textual SemIR.
This commit is contained in:
Geoff Romer
2025-12-11 01:06:16 +00:00
committed by GitHub
parent ff8ce31e1b
commit a0d1e4b809
36 changed files with 370 additions and 366 deletions
+28 -28
View File
@@ -408,11 +408,11 @@ fn CallIndirect() {
// CHECK:STDOUT: %require_complete.loc16_37: <witness> = require_complete_type %tuple.type.loc16 [symbolic = %require_complete.loc16_37 (constants.%require_complete.7c8)]
// CHECK:STDOUT: %require_complete.loc16_19: <witness> = require_complete_type %ptr.loc16_22.1 [symbolic = %require_complete.loc16_19 (constants.%require_complete.ef162c.1)]
// CHECK:STDOUT: %tuple.type.loc17: type = tuple_type (constants.%empty_struct_type, constants.%empty_struct_type, %ptr.loc16_22.1) [symbolic = %tuple.type.loc17 (constants.%tuple.type.dd2)]
// CHECK:STDOUT: %.loc17_21.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc16_8.1) [symbolic = %.loc17_21.2 (constants.%.841)]
// CHECK:STDOUT: %.loc17_21.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%U.loc16_8.1) [symbolic = %.loc17_21.1 (constants.%.841)]
// CHECK:STDOUT: %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_22.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]
// CHECK:STDOUT: %Copy.facet: %Copy.type = facet_value %ptr.loc16_22.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.29b)]
// CHECK:STDOUT: %.loc17_21.3: type = fn_type_with_self_type constants.%Copy.Op.type, %Copy.facet [symbolic = %.loc17_21.3 (constants.%.cb5)]
// CHECK:STDOUT: %impl.elem0.loc17_21.2: @Y.as.A.impl.F.%.loc17_21.3 (%.cb5) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc17_21.2 (constants.%impl.elem0.771)]
// CHECK:STDOUT: %.loc17_21.2: type = fn_type_with_self_type constants.%Copy.Op.type, %Copy.facet [symbolic = %.loc17_21.2 (constants.%.cb5)]
// CHECK:STDOUT: %impl.elem0.loc17_21.2: @Y.as.A.impl.F.%.loc17_21.2 (%.cb5) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc17_21.2 (constants.%impl.elem0.771)]
// CHECK:STDOUT: %specific_impl_fn.loc17_21.2: <specific function> = specific_impl_function %impl.elem0.loc17_21.2, @Copy.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc17_21.2 (constants.%specific_impl_fn.b85)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn(%u.param: @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1)) -> %return.param: @Y.as.A.impl.F.%tuple.type.loc16 (%tuple.type.9bf) {
@@ -427,13 +427,13 @@ fn CallIndirect() {
// CHECK:STDOUT: %tuple.elem1: ref %Y = tuple_access %return, element1
// CHECK:STDOUT: %.loc17_18.2: init %Y = class_init (), %tuple.elem1 [concrete = constants.%Y.val]
// CHECK:STDOUT: %.loc17_22.3: init %Y = converted %.loc17_18.1, %.loc17_18.2 [concrete = constants.%Y.val]
// CHECK:STDOUT: %impl.elem0.loc17_21.1: @Y.as.A.impl.F.%.loc17_21.3 (%.cb5) = impl_witness_access constants.%Copy.lookup_impl_witness.2e6, element0 [symbolic = %impl.elem0.loc17_21.2 (constants.%impl.elem0.771)]
// CHECK:STDOUT: %impl.elem0.loc17_21.1: @Y.as.A.impl.F.%.loc17_21.2 (%.cb5) = impl_witness_access constants.%Copy.lookup_impl_witness.2e6, element0 [symbolic = %impl.elem0.loc17_21.2 (constants.%impl.elem0.771)]
// CHECK:STDOUT: %bound_method.loc17_21.1: <bound method> = bound_method %u.ref, %impl.elem0.loc17_21.1
// CHECK:STDOUT: %specific_impl_fn.loc17_21.1: <specific function> = specific_impl_function %impl.elem0.loc17_21.1, @Copy.Op(constants.%Copy.facet.29b) [symbolic = %specific_impl_fn.loc17_21.2 (constants.%specific_impl_fn.b85)]
// CHECK:STDOUT: %bound_method.loc17_21.2: <bound method> = bound_method %u.ref, %specific_impl_fn.loc17_21.1
// CHECK:STDOUT: %.loc17_21.1: init @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1) = call %bound_method.loc17_21.2(%u.ref)
// CHECK:STDOUT: %Copy.Op.call: init @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1) = call %bound_method.loc17_21.2(%u.ref)
// CHECK:STDOUT: %tuple.elem2: ref @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1) = tuple_access %return, element2
// CHECK:STDOUT: %.loc17_22.4: init @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1) = initialize_from %.loc17_21.1 to %tuple.elem2
// CHECK:STDOUT: %.loc17_22.4: init @Y.as.A.impl.F.%ptr.loc16_22.1 (%ptr.e8f8f9.1) = initialize_from %Copy.Op.call to %tuple.elem2
// CHECK:STDOUT: %.loc17_22.5: init @Y.as.A.impl.F.%tuple.type.loc16 (%tuple.type.9bf) = tuple_init (%.loc17_22.2, %.loc17_22.3, %.loc17_22.4) to %return
// CHECK:STDOUT: %.loc17_23: init @Y.as.A.impl.F.%tuple.type.loc16 (%tuple.type.9bf) = converted %.loc17_22.1, %.loc17_22.5
// CHECK:STDOUT: return %.loc17_23 to %return
@@ -490,10 +490,10 @@ fn CallIndirect() {
// CHECK:STDOUT: %tuple.type: type = tuple_type (constants.%X, %T.binding.as_type, constants.%ptr.fb6) [symbolic = %tuple.type (constants.%tuple.type.089)]
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete.e12)]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %tuple.type, () [symbolic = %facet_value (constants.%facet_value.8b2)]
// CHECK:STDOUT: %.loc28_12.4: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %.loc28_12.4 (constants.%.00b)]
// CHECK:STDOUT: %.loc28_12.3: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %.loc28_12.3 (constants.%.00b)]
// CHECK:STDOUT: %Destroy.impl_witness: <witness> = impl_witness imports.%Destroy.impl_witness_table, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %Destroy.impl_witness (constants.%Destroy.impl_witness.bd5)]
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.c2c)]
// CHECK:STDOUT: %.loc28_12.5: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc28_12.5 (constants.%.482)]
// CHECK:STDOUT: %.loc28_12.4: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc28_12.4 (constants.%.482)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.type (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.f36)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op: @CallGeneric.%DestroyT.binding.as_type.as.Destroy.impl.Op.type (%DestroyT.binding.as_type.as.Destroy.impl.Op.type.f36) = struct_value () [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.754)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28: <specific function> = specific_function %DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl.Op(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.4e3)]
@@ -518,13 +518,13 @@ fn CallIndirect() {
// CHECK:STDOUT: %addr: %ptr.fb6 = addr_of %u.ref
// CHECK:STDOUT: %specific_impl_fn.loc28_4.1: <specific function> = specific_impl_function %impl.elem0.loc28_4.1, @A.F(constants.%X, constants.%T.2e9, constants.%Z) [symbolic = %specific_impl_fn.loc28_4.2 (constants.%specific_impl_fn.727)]
// CHECK:STDOUT: %.loc28_12.1: ref @CallGeneric.%tuple.type (%tuple.type.089) = temporary_storage
// CHECK:STDOUT: %.loc28_12.2: init @CallGeneric.%tuple.type (%tuple.type.089) = call %specific_impl_fn.loc28_4.1(%addr) to %.loc28_12.1
// CHECK:STDOUT: %.loc28_12.3: ref @CallGeneric.%tuple.type (%tuple.type.089) = temporary %.loc28_12.1, %.loc28_12.2
// CHECK:STDOUT: %impl.elem0.loc28_12: @CallGeneric.%.loc28_12.5 (%.482) = impl_witness_access constants.%Destroy.impl_witness.bd5, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.754)]
// CHECK:STDOUT: %bound_method.loc28_12.1: <bound method> = bound_method %.loc28_12.3, %impl.elem0.loc28_12
// CHECK:STDOUT: %A.F.call: init @CallGeneric.%tuple.type (%tuple.type.089) = call %specific_impl_fn.loc28_4.1(%addr) to %.loc28_12.1
// CHECK:STDOUT: %.loc28_12.2: ref @CallGeneric.%tuple.type (%tuple.type.089) = temporary %.loc28_12.1, %A.F.call
// CHECK:STDOUT: %impl.elem0.loc28_12: @CallGeneric.%.loc28_12.4 (%.482) = impl_witness_access constants.%Destroy.impl_witness.bd5, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.754)]
// CHECK:STDOUT: %bound_method.loc28_12.1: <bound method> = bound_method %.loc28_12.2, %impl.elem0.loc28_12
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0.loc28_12, @DestroyT.binding.as_type.as.Destroy.impl.Op(constants.%facet_value.8b2) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.4e3)]
// CHECK:STDOUT: %bound_method.loc28_12.2: <bound method> = bound_method %.loc28_12.3, %specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc28: init %empty_tuple.type = call %bound_method.loc28_12.2(%.loc28_12.3)
// CHECK:STDOUT: %bound_method.loc28_12.2: <bound method> = bound_method %.loc28_12.2, %specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc28: init %empty_tuple.type = call %bound_method.loc28_12.2(%.loc28_12.2)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %u.var, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.afb
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1: <specific function> = specific_function constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.afb, @DestroyT.binding.as_type.as.Destroy.impl.Op(constants.%facet_value.4e3) [concrete = constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1eb]
// CHECK:STDOUT: %bound_method.loc27: <bound method> = bound_method %u.var, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
@@ -609,10 +609,10 @@ fn CallIndirect() {
// CHECK:STDOUT: %require_complete.loc16_37 => constants.%complete_type.05d
// CHECK:STDOUT: %require_complete.loc16_19 => constants.%complete_type.d3e
// CHECK:STDOUT: %tuple.type.loc17 => constants.%tuple.type.953
// CHECK:STDOUT: %.loc17_21.2 => constants.%.519
// CHECK:STDOUT: %.loc17_21.1 => constants.%.519
// CHECK:STDOUT: %Copy.lookup_impl_witness => constants.%Copy.impl_witness.9e0
// CHECK:STDOUT: %Copy.facet => constants.%Copy.facet.e2d
// CHECK:STDOUT: %.loc17_21.3 => constants.%.00e
// CHECK:STDOUT: %.loc17_21.2 => constants.%.00e
// CHECK:STDOUT: %impl.elem0.loc17_21.2 => constants.%ptr.as.Copy.impl.Op.167
// CHECK:STDOUT: %specific_impl_fn.loc17_21.2 => constants.%ptr.as.Copy.impl.Op.specific_fn
// CHECK:STDOUT: }
@@ -647,10 +647,10 @@ fn CallIndirect() {
// CHECK:STDOUT: %tuple.type => constants.%tuple.type.092
// CHECK:STDOUT: %require_complete => constants.%complete_type.05d
// CHECK:STDOUT: %facet_value => constants.%facet_value.352
// CHECK:STDOUT: %.loc28_12.4 => constants.%.dab
// CHECK:STDOUT: %.loc28_12.3 => constants.%.dab
// CHECK:STDOUT: %Destroy.impl_witness => constants.%Destroy.impl_witness.dcd
// CHECK:STDOUT: %Destroy.facet => constants.%Destroy.facet.694
// CHECK:STDOUT: %.loc28_12.5 => constants.%.989
// CHECK:STDOUT: %.loc28_12.4 => constants.%.989
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.79b
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.c25
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.067
@@ -1092,10 +1092,10 @@ fn CallIndirect() {
// CHECK:STDOUT: %tuple.type: type = tuple_type (constants.%X, %T.binding.as_type, constants.%Z) [symbolic = %tuple.type (constants.%tuple.type.fe4)]
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete.aed)]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %tuple.type, () [symbolic = %facet_value (constants.%facet_value.613)]
// CHECK:STDOUT: %.loc28_12.4: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %.loc28_12.4 (constants.%.c60)]
// CHECK:STDOUT: %.loc28_12.3: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %.loc28_12.3 (constants.%.c60)]
// CHECK:STDOUT: %Destroy.impl_witness: <witness> = impl_witness imports.%Destroy.impl_witness_table, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %Destroy.impl_witness (constants.%Destroy.impl_witness.17f)]
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %tuple.type, (%Destroy.impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.9f4)]
// CHECK:STDOUT: %.loc28_12.5: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc28_12.5 (constants.%.168)]
// CHECK:STDOUT: %.loc28_12.4: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc28_12.4 (constants.%.168)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.type (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.bb5)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op: @CallGeneric.%DestroyT.binding.as_type.as.Destroy.impl.Op.type (%DestroyT.binding.as_type.as.Destroy.impl.Op.type.bb5) = struct_value () [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.1ab)]
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28: <specific function> = specific_function %DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl.Op(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.824)]
@@ -1117,13 +1117,13 @@ fn CallIndirect() {
// CHECK:STDOUT: %.loc28_11.4: ref %Z = temporary %.loc28_11.2, %.loc28_11.3
// CHECK:STDOUT: %.loc28_11.5: ref %Z = converted %.loc28_11.1, %.loc28_11.4
// CHECK:STDOUT: %.loc28_11.6: %Z = acquire_value %.loc28_11.5
// CHECK:STDOUT: %.loc28_12.2: init @CallGeneric.%tuple.type (%tuple.type.fe4) = call %specific_impl_fn.loc28_4.1(%.loc28_11.6) to %.loc28_12.1
// CHECK:STDOUT: %.loc28_12.3: ref @CallGeneric.%tuple.type (%tuple.type.fe4) = temporary %.loc28_12.1, %.loc28_12.2
// CHECK:STDOUT: %impl.elem0.loc28_12: @CallGeneric.%.loc28_12.5 (%.168) = impl_witness_access constants.%Destroy.impl_witness.17f, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.1ab)]
// CHECK:STDOUT: %bound_method.loc28_12.1: <bound method> = bound_method %.loc28_12.3, %impl.elem0.loc28_12
// CHECK:STDOUT: %A.F.call: init @CallGeneric.%tuple.type (%tuple.type.fe4) = call %specific_impl_fn.loc28_4.1(%.loc28_11.6) to %.loc28_12.1
// CHECK:STDOUT: %.loc28_12.2: ref @CallGeneric.%tuple.type (%tuple.type.fe4) = temporary %.loc28_12.1, %A.F.call
// CHECK:STDOUT: %impl.elem0.loc28_12: @CallGeneric.%.loc28_12.4 (%.168) = impl_witness_access constants.%Destroy.impl_witness.17f, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.1ab)]
// CHECK:STDOUT: %bound_method.loc28_12.1: <bound method> = bound_method %.loc28_12.2, %impl.elem0.loc28_12
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0.loc28_12, @DestroyT.binding.as_type.as.Destroy.impl.Op(constants.%facet_value.613) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.824)]
// CHECK:STDOUT: %bound_method.loc28_12.2: <bound method> = bound_method %.loc28_12.3, %specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc28_12: init %empty_tuple.type = call %bound_method.loc28_12.2(%.loc28_12.3)
// CHECK:STDOUT: %bound_method.loc28_12.2: <bound method> = bound_method %.loc28_12.2, %specific_fn
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc28_12: init %empty_tuple.type = call %bound_method.loc28_12.2(%.loc28_12.2)
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc28_11.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.afb
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1: <specific function> = specific_function constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.afb, @DestroyT.binding.as_type.as.Destroy.impl.Op(constants.%facet_value.4e3) [concrete = constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1eb]
// CHECK:STDOUT: %bound_method.loc28_11: <bound method> = bound_method %.loc28_11.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1
@@ -1299,10 +1299,10 @@ fn CallIndirect() {
// CHECK:STDOUT: %tuple.type => constants.%tuple.type.415
// CHECK:STDOUT: %require_complete => constants.%complete_type.aa8
// CHECK:STDOUT: %facet_value => constants.%facet_value.71a
// CHECK:STDOUT: %.loc28_12.4 => constants.%.5ca
// CHECK:STDOUT: %.loc28_12.3 => constants.%.5ca
// CHECK:STDOUT: %Destroy.impl_witness => constants.%Destroy.impl_witness.1d2
// CHECK:STDOUT: %Destroy.facet => constants.%Destroy.facet.cb0
// CHECK:STDOUT: %.loc28_12.5 => constants.%.97c
// CHECK:STDOUT: %.loc28_12.4 => constants.%.97c
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.518
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.993
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.loc28 => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.0fc