mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:20:10 +01:00
Use early rewrites in compound member access (#7207)
We replace the non-canonical ImplWitnessAccess instruction with an ImplWitnessAccessSubstituted instruction containing the RHS of a prior rewrite constraint in the same facet type when possible, in order to access the value of the prior constraint. We were doing this only in the designator access path though, not in the compound member access. Join these two code paths when they construct the ImplWitnessAccess, and perform the early access there for both.
This commit is contained in:
@@ -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<SemIR::ImplWitnessAccess>(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<SemIR::ImplWitnessAccessSubstituted>(
|
||||
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<SemIR::ImplWitnessAccess>(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<SemIR::ImplWitnessAccess>(member_id)) {
|
||||
if (auto result = context.rewrites_stack().back().Lookup(
|
||||
context.constant_values().Get(member_id))) {
|
||||
return GetOrAddInst<SemIR::ImplWitnessAccessSubstituted>(
|
||||
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<SemIR::ImplWitnessAccess>(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,
|
||||
|
||||
@@ -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]]";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user