Find impl witnesses in facets (#5060)

Impl lookup for an interface `I` for a facet with facet type requiring
an interface `I` will now succeed, getting the witness from the facet.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Dana Jansens <danakj@orodu.net>
This commit is contained in:
josh11b
2025-03-06 17:58:53 +00:00
committed by GitHub
co-authored by Josh L Dana Jansens
parent d3869a529b
commit ea1a0c8b84
5 changed files with 1381 additions and 836 deletions
@@ -33,20 +33,6 @@ fn TestSpecific(a: A({})) -> {} {
return a.(I({}).F)();
}
// --- find_blanket_impl.carbon
library "[[@TEST_NAME]]";
interface B {}
interface C {}
impl forall [T:! B] T as C {}
fn FC[TC:! C](xc: TC) {}
fn FB[TB:! B](xb: TB) {
FC(xb);
}
// CHECK:STDOUT: --- impl_forall.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
@@ -577,204 +563,3 @@ fn FB[TB:! B](xb: TB) {
// CHECK:STDOUT: %A.elem => constants.%A.elem.2af
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- find_blanket_impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %B.type: type = facet_type <@B> [concrete]
// CHECK:STDOUT: %Self.783: %B.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %C.type: type = facet_type <@C> [concrete]
// CHECK:STDOUT: %Self.02e: %C.type = bind_symbolic_name Self, 0 [symbolic]
// CHECK:STDOUT: %T: %B.type = bind_symbolic_name T, 0 [symbolic]
// CHECK:STDOUT: %T.patt: %B.type = symbolic_binding_pattern T, 0 [symbolic]
// CHECK:STDOUT: %T.as_type: type = facet_access_type %T [symbolic]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %impl_witness.1431bd.1: <witness> = impl_witness (), @impl(%T) [symbolic]
// CHECK:STDOUT: %TC: %C.type = bind_symbolic_name TC, 0 [symbolic]
// CHECK:STDOUT: %TC.patt: %C.type = symbolic_binding_pattern TC, 0 [symbolic]
// CHECK:STDOUT: %TC.as_type: type = facet_access_type %TC [symbolic]
// CHECK:STDOUT: %FC.type: type = fn_type @FC [concrete]
// CHECK:STDOUT: %FC: %FC.type = struct_value () [concrete]
// CHECK:STDOUT: %require_complete.8ca: <witness> = require_complete_type %TC.as_type [symbolic]
// CHECK:STDOUT: %TB: %B.type = bind_symbolic_name TB, 0 [symbolic]
// CHECK:STDOUT: %TB.patt: %B.type = symbolic_binding_pattern TB, 0 [symbolic]
// CHECK:STDOUT: %TB.as_type: type = facet_access_type %TB [symbolic]
// CHECK:STDOUT: %FB.type: type = fn_type @FB [concrete]
// CHECK:STDOUT: %FB: %FB.type = struct_value () [concrete]
// CHECK:STDOUT: %require_complete.e08: <witness> = require_complete_type %TB.as_type [symbolic]
// CHECK:STDOUT: %impl_witness.1431bd.2: <witness> = impl_witness (), @impl(%TB) [symbolic]
// CHECK:STDOUT: %C.facet: %C.type = facet_value %TB.as_type, %impl_witness.1431bd.2 [symbolic]
// CHECK:STDOUT: %FC.specific_fn: <specific function> = specific_function %FC, @FC(%C.facet) [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .B = %B.decl
// CHECK:STDOUT: .C = %C.decl
// CHECK:STDOUT: .FC = %FC.decl
// CHECK:STDOUT: .FB = %FB.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}
// CHECK:STDOUT: %C.decl: type = interface_decl @C [concrete = constants.%C.type] {} {}
// CHECK:STDOUT: impl_decl @impl [concrete] {
// CHECK:STDOUT: %T.patt.loc6_14.1: %B.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_14.2 (constants.%T.patt)]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %T.ref: %B.type = name_ref T, %T.loc6_14.1 [symbolic = %T.loc6_14.2 (constants.%T)]
// CHECK:STDOUT: %T.as_type.loc6_21.1: type = facet_access_type %T.ref [symbolic = %T.as_type.loc6_21.2 (constants.%T.as_type)]
// CHECK:STDOUT: %.loc6: type = converted %T.ref, %T.as_type.loc6_21.1 [symbolic = %T.as_type.loc6_21.2 (constants.%T.as_type)]
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C.type]
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
// CHECK:STDOUT: %T.loc6_14.1: %B.type = bind_symbolic_name T, 0 [symbolic = %T.loc6_14.2 (constants.%T)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (), @impl(constants.%T) [symbolic = @impl.%impl_witness (constants.%impl_witness.1431bd.1)]
// CHECK:STDOUT: %FC.decl: %FC.type = fn_decl @FC [concrete = constants.%FC] {
// CHECK:STDOUT: %TC.patt.loc8_7.1: %C.type = symbolic_binding_pattern TC, 0 [symbolic = %TC.patt.loc8_7.2 (constants.%TC.patt)]
// CHECK:STDOUT: %xc.patt: @FC.%TC.as_type.loc8_19.2 (%TC.as_type) = binding_pattern xc
// CHECK:STDOUT: %xc.param_patt: @FC.%TC.as_type.loc8_19.2 (%TC.as_type) = value_param_pattern %xc.patt, call_param0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C.type]
// CHECK:STDOUT: %TC.loc8_7.1: %C.type = bind_symbolic_name TC, 0 [symbolic = %TC.loc8_7.2 (constants.%TC)]
// CHECK:STDOUT: %xc.param: @FC.%TC.as_type.loc8_19.2 (%TC.as_type) = value_param call_param0
// CHECK:STDOUT: %.loc8_19.1: type = splice_block %.loc8_19.2 [symbolic = %TC.as_type.loc8_19.2 (constants.%TC.as_type)] {
// CHECK:STDOUT: %TC.ref: %C.type = name_ref TC, %TC.loc8_7.1 [symbolic = %TC.loc8_7.2 (constants.%TC)]
// CHECK:STDOUT: %TC.as_type.loc8_19.1: type = facet_access_type %TC.ref [symbolic = %TC.as_type.loc8_19.2 (constants.%TC.as_type)]
// CHECK:STDOUT: %.loc8_19.2: type = converted %TC.ref, %TC.as_type.loc8_19.1 [symbolic = %TC.as_type.loc8_19.2 (constants.%TC.as_type)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %xc: @FC.%TC.as_type.loc8_19.2 (%TC.as_type) = bind_name xc, %xc.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %FB.decl: %FB.type = fn_decl @FB [concrete = constants.%FB] {
// CHECK:STDOUT: %TB.patt.loc10_7.1: %B.type = symbolic_binding_pattern TB, 0 [symbolic = %TB.patt.loc10_7.2 (constants.%TB.patt)]
// CHECK:STDOUT: %xb.patt: @FB.%TB.as_type.loc10_19.2 (%TB.as_type) = binding_pattern xb
// CHECK:STDOUT: %xb.param_patt: @FB.%TB.as_type.loc10_19.2 (%TB.as_type) = value_param_pattern %xb.patt, call_param0
// CHECK:STDOUT: } {
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
// CHECK:STDOUT: %TB.loc10_7.1: %B.type = bind_symbolic_name TB, 0 [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %xb.param: @FB.%TB.as_type.loc10_19.2 (%TB.as_type) = value_param call_param0
// CHECK:STDOUT: %.loc10_19.1: type = splice_block %.loc10_19.2 [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)] {
// CHECK:STDOUT: %TB.ref: %B.type = name_ref TB, %TB.loc10_7.1 [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %TB.as_type.loc10_19.1: type = facet_access_type %TB.ref [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: %.loc10_19.2: type = converted %TB.ref, %TB.as_type.loc10_19.1 [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %xb: @FB.%TB.as_type.loc10_19.2 (%TB.as_type) = bind_name xb, %xb.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @B {
// CHECK:STDOUT: %Self: %B.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.783]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: interface @C {
// CHECK:STDOUT: %Self: %C.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self.02e]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = %Self
// CHECK:STDOUT: witness = ()
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic impl @impl(%T.loc6_14.1: %B.type) {
// CHECK:STDOUT: %T.loc6_14.2: %B.type = bind_symbolic_name T, 0 [symbolic = %T.loc6_14.2 (constants.%T)]
// CHECK:STDOUT: %T.patt.loc6_14.2: %B.type = symbolic_binding_pattern T, 0 [symbolic = %T.patt.loc6_14.2 (constants.%T.patt)]
// CHECK:STDOUT: %T.as_type.loc6_21.2: type = facet_access_type %T.loc6_14.2 [symbolic = %T.as_type.loc6_21.2 (constants.%T.as_type)]
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (), @impl(%T.loc6_14.2) [symbolic = %impl_witness (constants.%impl_witness.1431bd.1)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT:
// CHECK:STDOUT: impl: %.loc6 as %C.ref {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: witness = file.%impl_witness
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @FC(%TC.loc8_7.1: %C.type) {
// CHECK:STDOUT: %TC.loc8_7.2: %C.type = bind_symbolic_name TC, 0 [symbolic = %TC.loc8_7.2 (constants.%TC)]
// CHECK:STDOUT: %TC.patt.loc8_7.2: %C.type = symbolic_binding_pattern TC, 0 [symbolic = %TC.patt.loc8_7.2 (constants.%TC.patt)]
// CHECK:STDOUT: %TC.as_type.loc8_19.2: type = facet_access_type %TC.loc8_7.2 [symbolic = %TC.as_type.loc8_19.2 (constants.%TC.as_type)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type @FC.%TC.as_type.loc8_19.2 (%TC.as_type) [symbolic = %require_complete (constants.%require_complete.8ca)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%TC.patt.loc8_7.1: %C.type](%xc.param_patt: @FC.%TC.as_type.loc8_19.2 (%TC.as_type)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @FB(%TB.loc10_7.1: %B.type) {
// CHECK:STDOUT: %TB.loc10_7.2: %B.type = bind_symbolic_name TB, 0 [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %TB.patt.loc10_7.2: %B.type = symbolic_binding_pattern TB, 0 [symbolic = %TB.patt.loc10_7.2 (constants.%TB.patt)]
// CHECK:STDOUT: %TB.as_type.loc10_19.2: type = facet_access_type %TB.loc10_7.2 [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type @FB.%TB.as_type.loc10_19.2 (%TB.as_type) [symbolic = %require_complete (constants.%require_complete.e08)]
// CHECK:STDOUT: %impl_witness: <witness> = impl_witness (), @impl(%TB.loc10_7.2) [symbolic = %impl_witness (constants.%impl_witness.1431bd.2)]
// CHECK:STDOUT: %C.facet.loc11_8.3: %C.type = facet_value %TB.as_type.loc10_19.2, %impl_witness [symbolic = %C.facet.loc11_8.3 (constants.%C.facet)]
// CHECK:STDOUT: %FC.specific_fn.loc11_3.2: <specific function> = specific_function constants.%FC, @FC(%C.facet.loc11_8.3) [symbolic = %FC.specific_fn.loc11_3.2 (constants.%FC.specific_fn)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%TB.patt.loc10_7.1: %B.type](%xb.param_patt: @FB.%TB.as_type.loc10_19.2 (%TB.as_type)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %FC.ref: %FC.type = name_ref FC, file.%FC.decl [concrete = constants.%FC]
// CHECK:STDOUT: %xb.ref: @FB.%TB.as_type.loc10_19.2 (%TB.as_type) = name_ref xb, %xb
// CHECK:STDOUT: %TB.as_type.loc11_8.1: type = facet_access_type constants.%TB [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: %.loc11_8.1: type = converted constants.%TB, %TB.as_type.loc11_8.1 [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: %.loc11_8.2: %B.type = converted %.loc11_8.1, constants.%TB [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %.loc11_8.3: %B.type = converted constants.%TB.as_type, constants.%TB [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %C.facet.loc11_8.1: %C.type = facet_value constants.%TB.as_type, constants.%impl_witness.1431bd.2 [symbolic = %C.facet.loc11_8.3 (constants.%C.facet)]
// CHECK:STDOUT: %.loc11_8.4: %C.type = converted constants.%TB.as_type, %C.facet.loc11_8.1 [symbolic = %C.facet.loc11_8.3 (constants.%C.facet)]
// CHECK:STDOUT: %TB.as_type.loc11_8.2: type = facet_access_type constants.%TB [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: %.loc11_8.5: type = converted constants.%TB, %TB.as_type.loc11_8.2 [symbolic = %TB.as_type.loc10_19.2 (constants.%TB.as_type)]
// CHECK:STDOUT: %.loc11_8.6: %B.type = converted %.loc11_8.5, constants.%TB [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %.loc11_8.7: %B.type = converted constants.%TB.as_type, constants.%TB [symbolic = %TB.loc10_7.2 (constants.%TB)]
// CHECK:STDOUT: %C.facet.loc11_8.2: %C.type = facet_value constants.%TB.as_type, constants.%impl_witness.1431bd.2 [symbolic = %C.facet.loc11_8.3 (constants.%C.facet)]
// CHECK:STDOUT: %.loc11_8.8: %C.type = converted constants.%TB.as_type, %C.facet.loc11_8.2 [symbolic = %C.facet.loc11_8.3 (constants.%C.facet)]
// CHECK:STDOUT: %FC.specific_fn.loc11_3.1: <specific function> = specific_function %FC.ref, @FC(constants.%C.facet) [symbolic = %FC.specific_fn.loc11_3.2 (constants.%FC.specific_fn)]
// CHECK:STDOUT: %FC.call: init %empty_tuple.type = call %FC.specific_fn.loc11_3.1(%xb.ref)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @impl(constants.%T) {
// CHECK:STDOUT: %T.loc6_14.2 => constants.%T
// CHECK:STDOUT: %T.patt.loc6_14.2 => constants.%T
// CHECK:STDOUT: %T.as_type.loc6_21.2 => constants.%T.as_type
// CHECK:STDOUT: %impl_witness => constants.%impl_witness.1431bd.1
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @impl(%T.loc6_14.2) {}
// CHECK:STDOUT:
// CHECK:STDOUT: specific @FC(constants.%TC) {
// CHECK:STDOUT: %TC.loc8_7.2 => constants.%TC
// CHECK:STDOUT: %TC.patt.loc8_7.2 => constants.%TC
// CHECK:STDOUT: %TC.as_type.loc8_19.2 => constants.%TC.as_type
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @FB(constants.%TB) {
// CHECK:STDOUT: %TB.loc10_7.2 => constants.%TB
// CHECK:STDOUT: %TB.patt.loc10_7.2 => constants.%TB
// CHECK:STDOUT: %TB.as_type.loc10_19.2 => constants.%TB.as_type
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @impl(constants.%TB) {
// CHECK:STDOUT: %T.loc6_14.2 => constants.%TB
// CHECK:STDOUT: %T.patt.loc6_14.2 => constants.%TB
// CHECK:STDOUT: %T.as_type.loc6_21.2 => constants.%TB.as_type
// CHECK:STDOUT: %impl_witness => constants.%impl_witness.1431bd.2
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @FC(constants.%C.facet) {
// CHECK:STDOUT: %TC.loc8_7.2 => constants.%C.facet
// CHECK:STDOUT: %TC.patt.loc8_7.2 => constants.%C.facet
// CHECK:STDOUT: %TC.as_type.loc8_19.2 => constants.%TB.as_type
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete => constants.%require_complete.e08
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @impl(@FB.%TB.loc10_7.2) {}
// CHECK:STDOUT:
// CHECK:STDOUT: specific @FC(@FB.%C.facet.loc11_8.3) {}
// CHECK:STDOUT:
@@ -8,7 +8,9 @@
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/lookup/no_prelude/subtyping.carbon
// --- fail_todo_equivalent.carbon
// This is testing `FindWitnessInFacet` from impl_lookup.cpp
// --- equivalent.carbon
library "[[@TEST_NAME]]";
interface A {}
@@ -16,17 +18,10 @@ interface A {}
fn TakesA[T:! A](x: T) {}
fn WithExtraWhere[U:! A where .Self impls type](y: U) {
// CHECK:STDERR: fail_todo_equivalent.carbon:[[@LINE+7]]:3: error: `Core.ImplicitAs` implicitly referenced here, but package `Core` not found [CoreNotFound]
// CHECK:STDERR: TakesA(y);
// CHECK:STDERR: ^~~~~~~~~
// CHECK:STDERR: fail_todo_equivalent.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
// CHECK:STDERR: fn TakesA[T:! A](x: T) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
TakesA(y);
}
// CHECK:STDOUT: --- fail_todo_equivalent.carbon
// CHECK:STDOUT: --- equivalent.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %A.type: type = facet_type <@A> [concrete]
@@ -35,6 +30,7 @@ fn WithExtraWhere[U:! A where .Self impls type](y: U) {
// CHECK:STDOUT: %T.patt: %A.type = symbolic_binding_pattern T, 0 [symbolic]
// CHECK:STDOUT: %T.as_type: type = facet_access_type %T [symbolic]
// CHECK:STDOUT: %TakesA.type: type = fn_type @TakesA [concrete]
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %TakesA: %TakesA.type = struct_value () [concrete]
// CHECK:STDOUT: %require_complete.cf4: <witness> = require_complete_type %T.as_type [symbolic]
// CHECK:STDOUT: %.Self: %A.type = bind_symbolic_name .Self [symbolic_self]
@@ -46,6 +42,9 @@ fn WithExtraWhere[U:! A where .Self impls type](y: U) {
// CHECK:STDOUT: %WithExtraWhere.type: type = fn_type @WithExtraWhere [concrete]
// CHECK:STDOUT: %WithExtraWhere: %WithExtraWhere.type = struct_value () [concrete]
// CHECK:STDOUT: %require_complete.732: <witness> = require_complete_type %U.as_type [symbolic]
// CHECK:STDOUT: %U.as_wit: <witness> = facet_access_witness %U [symbolic]
// CHECK:STDOUT: %A.facet: %A.type = facet_value %U.as_type, %U.as_wit [symbolic]
// CHECK:STDOUT: %TakesA.specific_fn: <specific function> = specific_function %TakesA, @TakesA(%A.facet) [symbolic]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -125,12 +124,22 @@ fn WithExtraWhere[U:! A where .Self impls type](y: U) {
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type @WithExtraWhere.%U.as_type.loc7_52.2 (%U.as_type) [symbolic = %require_complete (constants.%require_complete.732)]
// CHECK:STDOUT: %U.as_wit.loc8_11.3: <witness> = facet_access_witness %U.loc7_19.2 [symbolic = %U.as_wit.loc8_11.3 (constants.%U.as_wit)]
// CHECK:STDOUT: %A.facet.loc8_11.3: %A.type = facet_value %U.as_type.loc7_52.2, %U.as_wit.loc8_11.3 [symbolic = %A.facet.loc8_11.3 (constants.%A.facet)]
// CHECK:STDOUT: %TakesA.specific_fn.loc8_3.2: <specific function> = specific_function constants.%TakesA, @TakesA(%A.facet.loc8_11.3) [symbolic = %TakesA.specific_fn.loc8_3.2 (constants.%TakesA.specific_fn)]
// CHECK:STDOUT:
// CHECK:STDOUT: fn[%U.patt.loc7_19.1: %A_where.type](%y.param_patt: @WithExtraWhere.%U.as_type.loc7_52.2 (%U.as_type)) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %TakesA.ref: %TakesA.type = name_ref TakesA, file.%TakesA.decl [concrete = constants.%TakesA]
// CHECK:STDOUT: %y.ref: @WithExtraWhere.%U.as_type.loc7_52.2 (%U.as_type) = name_ref y, %y
// CHECK:STDOUT: %.loc15: %A.type = converted constants.%U.as_type, <error> [concrete = <error>]
// CHECK:STDOUT: %U.as_wit.loc8_11.1: <witness> = facet_access_witness constants.%U [symbolic = %U.as_wit.loc8_11.3 (constants.%U.as_wit)]
// CHECK:STDOUT: %A.facet.loc8_11.1: %A.type = facet_value constants.%U.as_type, %U.as_wit.loc8_11.1 [symbolic = %A.facet.loc8_11.3 (constants.%A.facet)]
// CHECK:STDOUT: %.loc8_11.1: %A.type = converted constants.%U.as_type, %A.facet.loc8_11.1 [symbolic = %A.facet.loc8_11.3 (constants.%A.facet)]
// CHECK:STDOUT: %U.as_wit.loc8_11.2: <witness> = facet_access_witness constants.%U [symbolic = %U.as_wit.loc8_11.3 (constants.%U.as_wit)]
// CHECK:STDOUT: %A.facet.loc8_11.2: %A.type = facet_value constants.%U.as_type, %U.as_wit.loc8_11.2 [symbolic = %A.facet.loc8_11.3 (constants.%A.facet)]
// CHECK:STDOUT: %.loc8_11.2: %A.type = converted constants.%U.as_type, %A.facet.loc8_11.2 [symbolic = %A.facet.loc8_11.3 (constants.%A.facet)]
// CHECK:STDOUT: %TakesA.specific_fn.loc8_3.1: <specific function> = specific_function %TakesA.ref, @TakesA(constants.%A.facet) [symbolic = %TakesA.specific_fn.loc8_3.2 (constants.%TakesA.specific_fn)]
// CHECK:STDOUT: %TakesA.call: init %empty_tuple.type = call %TakesA.specific_fn.loc8_3.1(%y.ref)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
@@ -147,3 +156,14 @@ fn WithExtraWhere[U:! A where .Self impls type](y: U) {
// CHECK:STDOUT: %U.as_type.loc7_52.2 => constants.%U.as_type
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @TakesA(constants.%A.facet) {
// CHECK:STDOUT: %T.loc5_11.2 => constants.%A.facet
// CHECK:STDOUT: %T.patt.loc5_11.2 => constants.%A.facet
// CHECK:STDOUT: %T.as_type.loc5_21.2 => constants.%U.as_type
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
// CHECK:STDOUT: %require_complete => constants.%require_complete.732
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: specific @TakesA(@WithExtraWhere.%A.facet.loc8_11.3) {}
// CHECK:STDOUT: