From bbca8668aef03ca995bc2dbddff4e36be3ff082d Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 25 May 2026 19:02:06 -0400 Subject: [PATCH] Allow witnesses to come from a facet with partially identified type in the lookup target (#7260) We allow impl lookup to use `Self` which is partially identified, but we were only allowing this for the `Self` facet appearing in the impl lookup query self. We should also allow it when `Self` appears in the impl lookup query target facet type. But demonstrate that `Self` appearing in the interface of an ImplWitnessAccess (a compound member access) is not sufficient at this time, as it does not put `Self` into the type structure. --- toolchain/check/impl_lookup.cpp | 2 +- .../testdata/named_constraint/require.carbon | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index ac1ffc0befe0..53516fae4580 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -432,7 +432,7 @@ static auto CollectFacetWitnessSources( { SemIR::TypeIterator iter(&context.sem_ir()); iter.Add(context.insts().GetAs(query_facet_type_inst_id)); - collect_facets(iter, /*allow_partially_identified=*/false); + collect_facets(iter, /*allow_partially_identified=*/true); } if (!context.where_stack().empty()) { diff --git a/toolchain/check/testdata/named_constraint/require.carbon b/toolchain/check/testdata/named_constraint/require.carbon index d614b9ef29b9..1e6e9f2ebdd6 100644 --- a/toolchain/check/testdata/named_constraint/require.carbon +++ b/toolchain/check/testdata/named_constraint/require.carbon @@ -699,6 +699,46 @@ fn G(T:! Z) { T as N; } +// --- partially_identified_witness_from_self_in_lookup_facet_type.carbon +library "[[@TEST_NAME]]"; + +interface Z(T:! type) { + let Z1:! type; +} +interface Y(T:! type) {} + +class C {} + +constraint N { + require C impls Z(Self); + // Test that we can find the `C impls Z(Self)` witness above through the + // `Self` in the lookup target facet type in `C as Z(Self)`. + require C.(Z(Self).Z1) impls Y(Self); +} + +// --- fail_self_in_compound_member_access_is_not_in_type_structure.carbon +library "[[@TEST_NAME]]"; + +interface Z(T:! type) { + let Z1:! type; +} +interface Y {} + +class C {} + +constraint N { + require C impls Z(Self); + // The type structure is `? impls Y`, where the `?` is dependent on `Self` but + // it is not `Self`. Since `Self` is not directly part of the type structure, + // we don't accept this require decl. + // + // CHECK:STDERR: fail_self_in_compound_member_access_is_not_in_type_structure.carbon:[[@LINE+4]]:3: error: no `Self` reference found in `require` declaration; `Self` must appear in the self-type or as a generic argument for each required interface, but found interface `Y` without a `Self` argument [RequireImplsMissingSelf] + // CHECK:STDERR: require C.(Z(Self).Z1) impls Y; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + require C.(Z(Self).Z1) impls Y; +} + // CHECK:STDOUT: --- extend.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants {