mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Compare ImplWitnessAccess into Self as canonical constants (#5883)
This makes all `.Self` references in a facet type canonically the same (which will remain true iff they refer to the same `Self` type in the future), removing the need to do more complex comparisons between them using the EntityName, interface, and index. This allows the comparison of types containing `.Self` references to be done correctly regardless of where the `.Self` appears, as such type expressions will all be canonically equal if they otherwise equal now, regardless of whether they are written in the context where `.Self` could have seen different `Self` facet types. In order to retain access to constraints on a base `.Self` facet type, in the case of applying `where` to an existing facet type, we: - Give the base facet type as a `RequirementBaseFacetType` constraint so that eval of `WhereExpr` can find and copy all the constraints off of it. - Introduce eager/early rewrite constraint resolution, which allows a constraint to eagerly resolve access to earlier rewrite constraints (`where .A = () and .B = .A` is eagerly transformed into `where .A = () and .B = ()`) before the full constraint resolution step. This allows use of rewrite constraints in larger type expressions, such as `where .A = () and .B = C(.A)` and `C` will know that the argument is `()`.
This commit is contained in:
+27
-18
@@ -18,6 +18,7 @@
|
||||
#include "toolchain/check/facet_type.h"
|
||||
#include "toolchain/check/generic.h"
|
||||
#include "toolchain/check/import_ref.h"
|
||||
#include "toolchain/check/name_lookup.h"
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/check/type_completion.h"
|
||||
#include "toolchain/diagnostics/diagnostic.h"
|
||||
@@ -637,6 +638,13 @@ static auto GetConstantFacetTypeInfo(EvalContext& eval_context,
|
||||
// canonical instruction, so that in a `WhereExpr` we can work with the
|
||||
// `ImplWitnessAccess` references to `.Self` on the LHS of the constraints
|
||||
// rather than the value of the associated constant they reference.
|
||||
//
|
||||
// This also implies that we may find `ImplWitnessAccessSubstituted`
|
||||
// instructions in the LHS and RHS of these constraints, which are preserved
|
||||
// to maintain them as an unresolved reference to an associated constant, but
|
||||
// which must be handled gracefully during resolution. They will be replaced
|
||||
// with the constant value of the `ImplWitnessAccess` below when they are
|
||||
// substituted with a constant value.
|
||||
info.rewrite_constraints = orig.rewrite_constraints;
|
||||
if (!ResolveFacetTypeRewriteConstraints(eval_context.context(), loc_id,
|
||||
info.rewrite_constraints)) {
|
||||
@@ -2049,31 +2057,32 @@ auto TryEvalTypedInst<SemIR::WhereExpr>(EvalContext& eval_context,
|
||||
auto typed_inst = inst.As<SemIR::WhereExpr>();
|
||||
|
||||
Phase phase = Phase::Concrete;
|
||||
SemIR::TypeId base_facet_type_id =
|
||||
eval_context.GetTypeOfInst(typed_inst.period_self_id);
|
||||
SemIR::Inst base_facet_inst =
|
||||
eval_context.types().GetAsInst(base_facet_type_id);
|
||||
SemIR::FacetTypeInfo info = {.other_requirements = false};
|
||||
|
||||
// `where` provides that the base facet is an error, `type`, or a facet
|
||||
// type.
|
||||
if (auto facet_type = base_facet_inst.TryAs<SemIR::FacetType>()) {
|
||||
info = eval_context.facet_types().Get(facet_type->facet_type_id);
|
||||
} else if (base_facet_type_id == SemIR::ErrorInst::TypeId) {
|
||||
return SemIR::ErrorInst::ConstantId;
|
||||
} else {
|
||||
CARBON_CHECK(base_facet_type_id == SemIR::TypeType::TypeId,
|
||||
"Unexpected type_id: {0}, inst: {1}", base_facet_type_id,
|
||||
base_facet_inst);
|
||||
}
|
||||
|
||||
// Add the constraints from the `WhereExpr` instruction into `info`.
|
||||
if (typed_inst.requirements_id.has_value()) {
|
||||
auto insts = eval_context.inst_blocks().Get(typed_inst.requirements_id);
|
||||
for (auto inst_id : insts) {
|
||||
if (auto rewrite =
|
||||
eval_context.insts().TryGetAs<SemIR::RequirementRewrite>(
|
||||
if (auto base =
|
||||
eval_context.insts().TryGetAs<SemIR::RequirementBaseFacetType>(
|
||||
inst_id)) {
|
||||
if (base->base_type_inst_id == SemIR::ErrorInst::TypeInstId) {
|
||||
return SemIR::ErrorInst::ConstantId;
|
||||
}
|
||||
|
||||
if (auto base_facet_type =
|
||||
eval_context.insts().TryGetAs<SemIR::FacetType>(
|
||||
base->base_type_inst_id)) {
|
||||
const auto& base_info =
|
||||
eval_context.facet_types().Get(base_facet_type->facet_type_id);
|
||||
info.extend_constraints.append(base_info.extend_constraints);
|
||||
info.self_impls_constraints.append(base_info.self_impls_constraints);
|
||||
info.rewrite_constraints.append(base_info.rewrite_constraints);
|
||||
info.other_requirements |= base_info.other_requirements;
|
||||
}
|
||||
} else if (auto rewrite =
|
||||
eval_context.insts().TryGetAs<SemIR::RequirementRewrite>(
|
||||
inst_id)) {
|
||||
info.rewrite_constraints.push_back(
|
||||
{.lhs_id = rewrite->lhs_id, .rhs_id = rewrite->rhs_id});
|
||||
} else if (auto impls =
|
||||
|
||||
Reference in New Issue
Block a user