mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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:
@@ -12,10 +12,12 @@
|
||||
#include "toolchain/check/period_self.h"
|
||||
#include "toolchain/check/subst.h"
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/check/type_completion.h"
|
||||
#include "toolchain/check/unused.h"
|
||||
#include "toolchain/sem_ir/declared_facet_type.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
#include "toolchain/sem_ir/specific_interface.h"
|
||||
#include "toolchain/sem_ir/typed_insts.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
@@ -90,6 +92,29 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
|
||||
auto period_self =
|
||||
MakePeriodSelfFacetValue(context, node_id, period_self_type_id);
|
||||
|
||||
if (context.node_stack().PeekIs(Parse::NodeKind::ImplTypeAs) ||
|
||||
context.node_stack().PeekIs(Parse::NodeKind::ImplDefaultSelfAs)) {
|
||||
// We are in an impl declaration. We want to find the interface being
|
||||
// impl'd, which will have to be on the LHS of the `where`. We want to catch
|
||||
// lookups into that interface with `.Self` so we identify it with `.Self`.
|
||||
auto identified_id = TryToIdentifyFacetType(
|
||||
context, node_id, context.constant_values().Get(period_self),
|
||||
context.types().GetTypeInstId(period_self_type_id),
|
||||
/*allow_partially_identified=*/false);
|
||||
if (identified_id.has_value()) {
|
||||
const auto& identified =
|
||||
context.identified_facet_types().Get(identified_id);
|
||||
if (identified.is_valid_impl_as_target()) {
|
||||
auto& decl_impl_interface = context.declaring_impl_decls().back();
|
||||
if (decl_impl_interface != SemIR::SpecificInterface::None) {
|
||||
CARBON_CHECK(decl_impl_interface ==
|
||||
identified.impl_as_target_interface());
|
||||
}
|
||||
decl_impl_interface = identified.impl_as_target_interface();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Going to put each requirement on `args_type_info_stack`, so we can have an
|
||||
// inst block with the varying number of requirements but keeping other
|
||||
// instructions on the current inst block from the `inst_block_stack()`.
|
||||
|
||||
Reference in New Issue
Block a user