diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 3ff6cf55159f..94b62ec6f079 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -178,6 +178,26 @@ static auto ScopeNeedsImplLookup(Context& context, return true; } +static auto PerformImplWitnessAccessAndSubstitute( + Context& context, SemIR::LocId loc_id, SemIR::ImplWitnessAccess access) + -> SemIR::InstId { + auto access_id = + GetOrAddInst(context, loc_id, access); + + if (!context.rewrites_stack().empty()) { + if (auto result = context.rewrites_stack().back().Lookup( + context.constant_values().Get(access_id))) { + return GetOrAddInst( + context, loc_id, + {.type_id = access.type_id, + .impl_witness_access_id = access_id, + .value_id = result.value()}); + } + } + + return access_id; +} + static auto AccessMemberOfImplWitness( Context& context, SemIR::LocId loc_id, SemIR::InstId witness_id, SemIR::SpecificId interface_with_self_specific_id, SemIR::InstId member_id) @@ -203,10 +223,11 @@ static auto AccessMemberOfImplWitness( auto assoc_type_id = GetTypeForSpecificAssociatedEntity( context, interface_with_self_specific_id, assoc_entity->decl_id); - return GetOrAddInst(context, loc_id, - {.type_id = assoc_type_id, - .witness_id = witness_id, - .index = assoc_entity->index}); + return PerformImplWitnessAccessAndSubstitute( + context, loc_id, + SemIR::ImplWitnessAccess{.type_id = assoc_type_id, + .witness_id = witness_id, + .index = assoc_entity->index}); } // For an impl lookup query with a single interface in it, we can convert the @@ -356,20 +377,6 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, } } - if (!context.rewrites_stack().empty()) { - if (auto access = - context.insts().TryGetAs(member_id)) { - if (auto result = context.rewrites_stack().back().Lookup( - context.constant_values().Get(member_id))) { - return GetOrAddInst( - context, loc_id, - {.type_id = access->type_id, - .impl_witness_access_id = member_id, - .value_id = result.value()}); - } - } - } - return member_id; } @@ -715,10 +722,11 @@ static auto GetAssociatedValueImpl(Context& context, SemIR::LocId loc_id, context, interface_with_self_specific_id, assoc_entity.decl_id); // Now that we have the witness, an index into it, and the type of the // result, return the element of the witness. - return GetOrAddInst(context, loc_id, - {.type_id = assoc_type_id, - .witness_id = witness_id, - .index = assoc_entity.index}); + return PerformImplWitnessAccessAndSubstitute( + context, loc_id, + SemIR::ImplWitnessAccess{.type_id = assoc_type_id, + .witness_id = witness_id, + .index = assoc_entity.index}); } auto GetAssociatedValue(Context& context, SemIR::LocId loc_id, diff --git a/toolchain/check/testdata/facet/early_rewrites.carbon b/toolchain/check/testdata/facet/early_rewrites.carbon index 8729e78a79ae..1fd7dfc2d313 100644 --- a/toolchain/check/testdata/facet/early_rewrites.carbon +++ b/toolchain/check/testdata/facet/early_rewrites.carbon @@ -323,6 +323,27 @@ fn G(T:! J where .J1 = D) { F(T); } +// --- early_rewrite_of_compound_access.carbon +library "[[@TEST_NAME]]"; + +interface Z { + let Z1:! type; + let Z2:! type; +} + +interface Y {} +class NeedY(T:! Y) {} + +impl () as Y {} + +// These are written differently but should behave the same. + +// Designator access of `.Z1`. +fn F(_:! Z where .Z1 = () and .Z2 = NeedY(.Z1)) {} + +// Compound member access of `.Z1`. +fn G(_:! Z where .Z1 = () and .Z2 = NeedY(.Self.(Z.Z1))) {} + // --- fail_todo_resolved_constraint_visible_in_type_parameter.carbon library "[[@TEST_NAME]]";