Avoid symbolic witnesses for .Self in an impl decl (#7564)

Point symbolic witnesses into `.Self` written inside an impl decl at the
impl that is being declared. This is tricky because the impl does not
yet exist. So we use a new instruction `ImplSelfWitness` which _will_ be
replaced by the `ImplWitness` once it becomes available. The
`ImplSelfWitness` acts like a symbolic witness, except it does not
perform lookup, since we know which impl we will get a witness from.

This prevents us from finding other impls when performing lookups into
`.Self` in an impl decl, which produces incorrect/incoherent results.
This commit is contained in:
Dana Jansens
2026-07-29 16:25:23 +00:00
committed by GitHub
parent 2ac425e591
commit f51c075f8b
94 changed files with 3221 additions and 2797 deletions
+30 -8
View File
@@ -17,6 +17,7 @@
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst_kind.h"
#include "toolchain/sem_ir/singleton_insts.h"
#include "toolchain/sem_ir/specific_interface.h"
#include "toolchain/sem_ir/struct_type_field.h"
#include "toolchain/sem_ir/type_info.h"
#include "toolchain/sem_ir/typed_insts.h"
@@ -476,9 +477,18 @@ class Stringifier {
auto StringifyInst(InstId /*inst_id*/, ImplWitnessAccess inst) -> void {
auto witness_inst_id =
sem_ir_->constant_values().GetConstantInstId(inst.witness_id);
auto lookup = sem_ir_->insts().GetAs<LookupImplWitness>(witness_inst_id);
auto specific_interface =
sem_ir_->specific_interfaces().Get(lookup.query_specific_interface_id);
auto specific_interface = SemIR::SpecificInterface::None;
if (auto self_witness =
sem_ir_->insts().TryGetAs<ImplSelfWitness>(witness_inst_id)) {
specific_interface = sem_ir_->specific_interfaces().Get(
self_witness->specific_interface_id);
} else {
auto lookup = sem_ir_->insts().GetAs<LookupImplWitness>(witness_inst_id);
specific_interface = sem_ir_->specific_interfaces().Get(
lookup.query_specific_interface_id);
}
const auto& interface =
sem_ir_->interfaces().Get(specific_interface.interface_id);
if (!interface.associated_entities_id.has_value()) {
@@ -514,16 +524,28 @@ class Stringifier {
step_stack_->Push(".(");
}
if (auto lookup =
sem_ir_->insts().TryGetAs<LookupImplWitness>(witness_inst_id)) {
bool period_self = false;
if (auto self_witness =
sem_ir_->insts().TryGetAs<ImplSelfWitness>(witness_inst_id)) {
bool is_period_self = false;
if (auto sym_name = sem_ir_->insts().TryGetAs<SymbolicBinding>(
self_witness->period_self)) {
auto name_id =
sem_ir_->entity_names().Get(sym_name->entity_name_id).name_id;
is_period_self = (name_id == NameId::PeriodSelf);
}
if (!is_period_self) {
step_stack_->PushInstId(self_witness->period_self);
}
} else if (auto lookup = sem_ir_->insts().TryGetAs<LookupImplWitness>(
witness_inst_id)) {
bool is_period_self = false;
if (auto sym_name = sem_ir_->insts().TryGetAs<SymbolicBinding>(
lookup->query_self_inst_id)) {
auto name_id =
sem_ir_->entity_names().Get(sym_name->entity_name_id).name_id;
period_self = (name_id == NameId::PeriodSelf);
is_period_self = (name_id == NameId::PeriodSelf);
}
if (!period_self) {
if (!is_period_self) {
step_stack_->PushInstId(lookup->query_self_inst_id);
}
} else {