mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Track rewrites in IdentifiedFacetType (#7866)
This allows us to collect rewrites from named constraints and use them to initialize the witness table for an `impl as` statement. Only rewrites from extend constraints are tracked, as other constraints should turn into equality constraints, as they don't modify the witness table.
This commit is contained in:
@@ -250,12 +250,19 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
// This requires that the facet type is identified, and returns the single
|
||||
// interface from the identified facet type. It returns None if an error was
|
||||
// diagnosed.
|
||||
auto specific_interface = CheckConstraintIsInterface(
|
||||
auto identified_id = CheckConstraintIsInterface(
|
||||
context, node_id, self_type_inst_id, full_constraint_type_inst_id);
|
||||
if (!specific_interface.interface_id.has_value()) {
|
||||
if (!identified_id.has_value()) {
|
||||
full_constraint_type_inst_id = SemIR::ErrorInst::TypeInstId;
|
||||
}
|
||||
|
||||
auto specific_interface =
|
||||
full_constraint_type_inst_id != SemIR::ErrorInst::InstId
|
||||
? context.identified_facet_types()
|
||||
.Get(identified_id)
|
||||
.impl_as_target_interface()
|
||||
: SemIR::SpecificInterface::None;
|
||||
|
||||
// Store an instruction in the decl's eval block that contains the target
|
||||
// interface's specific, whose constant value will be updated when specifics
|
||||
// are applied to the impl.
|
||||
@@ -268,7 +275,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
// we introduced a new instruction with a SpecificId operand instead of
|
||||
// reusing ImplSelfWitness for this.
|
||||
auto interface_inst_id =
|
||||
specific_interface.interface_id.has_value()
|
||||
full_constraint_type_inst_id != SemIR::ErrorInst::InstId
|
||||
? AddInst<SemIR::ImplSelfWitness>(
|
||||
context, node_id,
|
||||
{.type_id =
|
||||
@@ -407,7 +414,8 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id,
|
||||
// also must be part of the generic eval block by coming before
|
||||
// FinishGenericDecl().
|
||||
impl.witness_id = AddImplWitnessForDeclaration(
|
||||
context, node_id, impl, full_constraint_type_inst_id,
|
||||
context, node_id, SemIR::LocId(full_constraint_type_inst_id),
|
||||
impl, identified_id,
|
||||
context.generics().GetSelfSpecific(impl.generic_id));
|
||||
impl.witness_block_id = context.inst_block_stack().Pop();
|
||||
|
||||
|
||||
+17
-36
@@ -395,32 +395,14 @@ auto AddImpl(Context& context, const SemIR::Impl& impl,
|
||||
}
|
||||
|
||||
auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::LocId constraint_loc_id,
|
||||
const SemIR::Impl& impl,
|
||||
SemIR::TypeInstId full_constraint_id,
|
||||
SemIR::IdentifiedFacetTypeId identified_id,
|
||||
SemIR::SpecificId self_specific_id)
|
||||
-> SemIR::InstId {
|
||||
auto facet_type_id =
|
||||
context.types().GetTypeIdForTypeInstId(full_constraint_id);
|
||||
CARBON_CHECK(facet_type_id != SemIR::ErrorInst::TypeId);
|
||||
auto facet_type = context.types().GetAs<SemIR::FacetType>(facet_type_id);
|
||||
// TODO: We need to collect rewrites from named constraints too, so we will
|
||||
// want to get them from the IdentifiedFacetType, or something similar. That
|
||||
// process should also replace `.Self` in the constraints as appropriate.
|
||||
const auto& declared_facet_type =
|
||||
context.declared_facet_types().Get(facet_type.declared_facet_type_id);
|
||||
const auto& identified = context.identified_facet_types().Get(identified_id);
|
||||
|
||||
// An iterator over the rewrite_constraints where the LHS of the rewrite names
|
||||
// a member of the `impl.interface`. This filters out rewrites of names
|
||||
// from other interfaces, as they do not set values in the witness table.
|
||||
auto rewrites_into_interface_to_witness = llvm::make_filter_range(
|
||||
declared_facet_type.rewrite_constraints,
|
||||
[&](const SemIR::DeclaredFacetType::RewriteConstraint& rewrite) {
|
||||
auto access = context.insts().GetAs<SemIR::ImplWitnessAccess>(
|
||||
GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id));
|
||||
return context.insts().Is<SemIR::ImplSelfWitness>(access.witness_id);
|
||||
});
|
||||
|
||||
if (rewrites_into_interface_to_witness.empty()) {
|
||||
if (identified.rewrites().empty()) {
|
||||
// The witness table is not needed until the definition. Make a placeholder
|
||||
// for the declaration.
|
||||
auto witness_table_inst_id = AddInst<SemIR::ImplWitnessTable>(
|
||||
@@ -472,9 +454,9 @@ auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
.specific_id = self_specific_id});
|
||||
}
|
||||
|
||||
for (auto rewrite : rewrites_into_interface_to_witness) {
|
||||
auto access = context.insts().GetAs<SemIR::ImplWitnessAccess>(
|
||||
GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id));
|
||||
for (auto rewrite : identified.rewrites()) {
|
||||
auto access = context.constant_values().GetInstAs<SemIR::ImplWitnessAccess>(
|
||||
rewrite.lhs);
|
||||
auto& table_entry = table[access.index.index];
|
||||
if (table_entry == SemIR::ErrorInst::InstId) {
|
||||
// Don't overwrite an error value. This prioritizes not generating
|
||||
@@ -482,7 +464,7 @@ auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
// for it to use to attempt recovery.
|
||||
continue;
|
||||
}
|
||||
auto rewrite_inst_id = rewrite.rhs_id;
|
||||
auto rewrite_inst_id = context.constant_values().GetInstId(rewrite.rhs);
|
||||
if (rewrite_inst_id == SemIR::ErrorInst::InstId) {
|
||||
table_entry = SemIR::ErrorInst::InstId;
|
||||
continue;
|
||||
@@ -513,7 +495,7 @@ auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
CARBON_DIAGNOSTIC(RewriteForAssociatedFunction, Error,
|
||||
"rewrite specified for associated function {0}",
|
||||
SemIR::NameId);
|
||||
context.emitter().Emit(full_constraint_id, RewriteForAssociatedFunction,
|
||||
context.emitter().Emit(constraint_loc_id, RewriteForAssociatedFunction,
|
||||
fn.name_id);
|
||||
table_entry = SemIR::ErrorInst::InstId;
|
||||
continue;
|
||||
@@ -540,9 +522,8 @@ auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
// Perform the conversion of the value to the type. We skipped this when
|
||||
// forming the facet type because the type of the associated constant
|
||||
// was symbolic.
|
||||
auto converted_inst_id =
|
||||
ConvertToValueOfType(context, SemIR::LocId(full_constraint_id),
|
||||
rewrite_inst_id, assoc_const_type_id);
|
||||
auto converted_inst_id = ConvertToValueOfType(
|
||||
context, constraint_loc_id, rewrite_inst_id, assoc_const_type_id);
|
||||
// Canonicalize the converted constant value.
|
||||
converted_inst_id =
|
||||
context.constant_values().GetConstantInstId(converted_inst_id);
|
||||
@@ -559,7 +540,7 @@ auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
"after conversion to {2}",
|
||||
SemIR::NameId, InstIdAsConstant, SemIR::TypeId);
|
||||
context.emitter().Emit(
|
||||
full_constraint_id, AssociatedConstantNotConstantAfterConversion,
|
||||
constraint_loc_id, AssociatedConstantNotConstantAfterConversion,
|
||||
assoc_const.name_id, rewrite_inst_id, assoc_const_type_id);
|
||||
rewrite_inst_id = SemIR::ErrorInst::InstId;
|
||||
}
|
||||
@@ -1022,11 +1003,11 @@ auto CheckConstraintIsFacetType(Context& context, SemIR::LocId loc_id,
|
||||
auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId self_id,
|
||||
SemIR::TypeInstId constraint_id)
|
||||
-> SemIR::SpecificInterface {
|
||||
-> SemIR::IdentifiedFacetTypeId {
|
||||
auto canon_constraint_id =
|
||||
context.constant_values().GetConstantTypeInstId(constraint_id);
|
||||
if (canon_constraint_id == SemIR::ErrorInst::TypeInstId) {
|
||||
return SemIR::SpecificInterface::None;
|
||||
return SemIR::IdentifiedFacetTypeId::None;
|
||||
}
|
||||
auto identified_id = RequireIdentifiedFacetType(
|
||||
context, SemIR::LocId(constraint_id),
|
||||
@@ -1038,7 +1019,7 @@ auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
|
||||
builder.Context(loc_id, ImplOfUnidentifiedFacetType, constraint_id);
|
||||
});
|
||||
if (!identified_id.has_value()) {
|
||||
return SemIR::SpecificInterface::None;
|
||||
return SemIR::IdentifiedFacetTypeId::None;
|
||||
}
|
||||
const auto& identified = context.identified_facet_types().Get(identified_id);
|
||||
if (!identified.is_valid_impl_as_target()) {
|
||||
@@ -1046,9 +1027,9 @@ auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
|
||||
"impl as {0} interfaces, expected 1", int);
|
||||
context.emitter().Emit(loc_id, ImplOfNotOneInterface,
|
||||
identified.num_interfaces_to_impl());
|
||||
return SemIR::SpecificInterface::None;
|
||||
return SemIR::IdentifiedFacetTypeId::None;
|
||||
}
|
||||
return identified.impl_as_target_interface();
|
||||
return identified_id;
|
||||
}
|
||||
|
||||
auto GetImplInterfaceInSpecific(Context& context, const SemIR::Impl& impl,
|
||||
|
||||
@@ -52,8 +52,9 @@ auto AddImpl(Context& context, const SemIR::Impl& impl,
|
||||
// constraint facet type. `self_specific_id` will be the `specific_id` of the
|
||||
// resulting witness.
|
||||
auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::LocId constraint_loc_id,
|
||||
const SemIR::Impl& impl,
|
||||
SemIR::TypeInstId full_constraint_id,
|
||||
SemIR::IdentifiedFacetTypeId identified_id,
|
||||
SemIR::SpecificId self_specific_id)
|
||||
-> SemIR::InstId;
|
||||
|
||||
@@ -93,12 +94,13 @@ auto CheckConstraintIsFacetType(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::TypeInstId constraint_id) -> bool;
|
||||
|
||||
// Checks that the constraint specified for the impl is a valid, identified
|
||||
// facet type that extends a single interface. Returns the interface that the
|
||||
// impl implements. On error, issues a diagnostic and returns `None`.
|
||||
// facet type that extends a single interface. Returns the IdentifiedFacetType
|
||||
// which contains the interface that the impl implements. On error, issues a
|
||||
// diagnostic and returns `None`.
|
||||
auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId self_id,
|
||||
SemIR::TypeInstId constraint_id)
|
||||
-> SemIR::SpecificInterface;
|
||||
-> SemIR::IdentifiedFacetTypeId;
|
||||
|
||||
// Given a specific for the impl, returns the specific interface that the impl
|
||||
// declaration is implementing. Returns None in the case of an error being
|
||||
|
||||
@@ -471,6 +471,9 @@ static auto VerifyQueryFacetTypeConstraints(
|
||||
SemIR::ConstantId query_facet_type_const_id,
|
||||
llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls,
|
||||
llvm::ArrayRef<SemIR::InstId> witness_inst_ids) -> bool {
|
||||
// TODO: Get the rewrites and equality constraints from the
|
||||
// IdentifiedFacetType so that we also find and verify requirements from named
|
||||
// constraints.
|
||||
const auto& declared_facet_type = context.declared_facet_types().Get(
|
||||
context.constant_values()
|
||||
.GetInstAs<SemIR::FacetType>(query_facet_type_const_id)
|
||||
|
||||
@@ -227,7 +227,7 @@ fn G() {
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon
|
||||
// --- impl_as_constraint_containing_rewrite_for_concrete_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I {
|
||||
@@ -239,28 +239,14 @@ constraint N {
|
||||
}
|
||||
|
||||
class C;
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE+7]]:1: error: associated constant I1 not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: impl C as N {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE-11]]:7: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: let I1: type;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl C as N {}
|
||||
|
||||
fn F(generic _: I where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I where .(I.I1) = .Self` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: F(C);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE-5]]:14: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(generic _: I where .I1 = .Self) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon
|
||||
// --- impl_as_constraint_containing_rewrite_for_generic_interface.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T: type) {
|
||||
@@ -272,24 +258,10 @@ constraint N {
|
||||
}
|
||||
|
||||
class C;
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE+7]]:1: error: associated constant I1 not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: impl C as N {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE-11]]:7: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: let I1: type;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl C as N {}
|
||||
|
||||
fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I(.Self) where .(I(.Self).I1) = .Self` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: F(C);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE-5]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(C);
|
||||
}
|
||||
|
||||
|
||||
+2
-26
@@ -59,7 +59,7 @@ interface J {}
|
||||
// CHECK:STDERR:
|
||||
impl forall [T: type] T as I where .X impls J and .X = () {}
|
||||
|
||||
// --- fail_todo_rewrite_in_named_constraint.carbon
|
||||
// --- rewrite_in_named_constraint.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I { let X: type; }
|
||||
@@ -72,13 +72,6 @@ constraint GivesI {
|
||||
impl () as J {}
|
||||
|
||||
// The rewrite from `extend` is inherited and should satisfy that `.X impls J`.
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_named_constraint.carbon:[[@LINE+7]]:1: error: associated constant X not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI where .X impls J {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_in_named_constraint.carbon:[[@LINE-13]]:19: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: interface I { let X: type; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl forall [T: type] T as GivesI where .X impls J {}
|
||||
|
||||
// --- fail_rewrite_in_named_constraint_missing_impl.carbon
|
||||
@@ -92,12 +85,9 @@ constraint GivesI {
|
||||
}
|
||||
|
||||
// .X does not impl J.
|
||||
// CHECK:STDERR: fail_rewrite_in_named_constraint_missing_impl.carbon:[[@LINE+7]]:1: error: associated constant X not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: fail_rewrite_in_named_constraint_missing_impl.carbon:[[@LINE+4]]:1: error: constraint `GivesI where .(I.X) impls J` being implemented requires that `()` implements `J` [IdentifiedRequireImplsNotImplemented]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI where .X impls J {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_rewrite_in_named_constraint_missing_impl.carbon:[[@LINE-11]]:19: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: interface I { let X: type; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl forall [T: type] T as GivesI where .X impls J {}
|
||||
|
||||
@@ -115,13 +105,6 @@ constraint GivesI {
|
||||
impl () as J {}
|
||||
|
||||
// The rewrite from `extend` is inherited and should satisfy that `.X impls J`.
|
||||
// CHECK:STDERR: fail_todo_rewrite_and_impls_in_named_constraint.carbon:[[@LINE+11]]:1: error: associated constant X not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_rewrite_and_impls_in_named_constraint.carbon:[[@LINE-14]]:19: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: interface I { let X: type; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_rewrite_and_impls_in_named_constraint.carbon:[[@LINE+4]]:1: error: constraint `GivesI` being implemented requires that `T.(I.X)` implements `J` [IdentifiedRequireImplsNotImplemented]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -140,13 +123,6 @@ constraint GivesI {
|
||||
}
|
||||
|
||||
// .X does not impl J.
|
||||
// CHECK:STDERR: fail_rewrite_and_impls_in_named_constraint_missing_impl.carbon:[[@LINE+11]]:1: error: associated constant X not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_rewrite_and_impls_in_named_constraint_missing_impl.carbon:[[@LINE-12]]:19: note: associated constant declared here [AssociatedConstantHere]
|
||||
// CHECK:STDERR: interface I { let X: type; }
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_rewrite_and_impls_in_named_constraint_missing_impl.carbon:[[@LINE+4]]:1: error: constraint `GivesI` being implemented requires that `T.(I.X)` implements `J` [IdentifiedRequireImplsNotImplemented]
|
||||
// CHECK:STDERR: impl forall [T: type] T as GivesI {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "toolchain/base/kind_switch.h"
|
||||
#include "toolchain/check/cpp/import.h"
|
||||
#include "toolchain/check/facet_type.h"
|
||||
#include "toolchain/check/generic.h"
|
||||
#include "toolchain/check/inst.h"
|
||||
#include "toolchain/check/literal.h"
|
||||
@@ -1012,6 +1013,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
|
||||
bool partially_identified = false;
|
||||
llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> extends;
|
||||
llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> impls;
|
||||
llvm::SmallVector<SemIR::IdentifiedFacetType::Rewrite> rewrites;
|
||||
|
||||
while (!work.empty()) {
|
||||
SelfImplsFacetType next_impls = work.pop_back_val();
|
||||
@@ -1046,6 +1048,20 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
|
||||
llvm::append_range(
|
||||
impls, llvm::map_range(declared_facet_type.type_impls_interfaces,
|
||||
type_and_interface));
|
||||
if (facet_type_extends) {
|
||||
auto rewrite_as_constants =
|
||||
[&](auto rewrite) -> SemIR::IdentifiedFacetType::Rewrite {
|
||||
return {context.constant_values().Get(
|
||||
GetImplWitnessAccessWithoutSubstitution(context,
|
||||
rewrite.lhs_id)),
|
||||
context.constant_values().Get(rewrite.rhs_id)};
|
||||
};
|
||||
llvm::append_range(
|
||||
rewrites, llvm::map_range(declared_facet_type.rewrite_constraints,
|
||||
rewrite_as_constants));
|
||||
} else {
|
||||
// TODO: Store the rewrites as equality constraints.
|
||||
}
|
||||
|
||||
if (declared_facet_type.extend_named_constraints.empty() &&
|
||||
declared_facet_type.self_impls_named_constraints.empty() &&
|
||||
@@ -1229,7 +1245,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
// TODO: Process other kinds of requirements.
|
||||
return context.identified_facet_types().Add(
|
||||
{key, partially_identified, extends, impls});
|
||||
{key, partially_identified, extends, impls, rewrites});
|
||||
}
|
||||
|
||||
auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
@@ -44,7 +44,7 @@ static auto RequiredLess(const IdentifiedFacetType::RequiredImpl& lhs,
|
||||
IdentifiedFacetType::IdentifiedFacetType(
|
||||
IdentifiedFacetTypeKey key, bool partially_identified,
|
||||
llvm::ArrayRef<RequiredImpl> extends,
|
||||
llvm::ArrayRef<RequiredImpl> self_impls)
|
||||
llvm::ArrayRef<RequiredImpl> self_impls, llvm::ArrayRef<Rewrite> rewrites)
|
||||
: key_(key) {
|
||||
required_impls_.reserve(extends.size() + self_impls.size());
|
||||
llvm::append_range(required_impls_, extends);
|
||||
@@ -70,6 +70,8 @@ IdentifiedFacetType::IdentifiedFacetType(
|
||||
// same constituents but a more complete set of required interfaces.
|
||||
key_.num_require_impls = required_impls_.size();
|
||||
}
|
||||
|
||||
rewrites_.assign(rewrites);
|
||||
}
|
||||
|
||||
auto AddCanonicalWitnessesBlock(File& sem_ir,
|
||||
|
||||
@@ -42,16 +42,26 @@ struct IdentifiedFacetType {
|
||||
friend auto operator==(const RequiredImpl& lhs, const RequiredImpl& rhs)
|
||||
-> bool = default;
|
||||
};
|
||||
struct Rewrite {
|
||||
ConstantId lhs;
|
||||
ConstantId rhs;
|
||||
|
||||
friend auto operator==(const Rewrite& lhs, const Rewrite& rhs)
|
||||
-> bool = default;
|
||||
};
|
||||
|
||||
IdentifiedFacetType(IdentifiedFacetTypeKey key, bool partially_identified,
|
||||
llvm::ArrayRef<RequiredImpl> extends,
|
||||
llvm::ArrayRef<RequiredImpl> self_impls);
|
||||
llvm::ArrayRef<RequiredImpl> self_impls,
|
||||
llvm::ArrayRef<Rewrite> rewrites);
|
||||
|
||||
// The order here defines the order of impl witnesses for this facet type.
|
||||
auto required_impls() const -> llvm::ArrayRef<RequiredImpl> {
|
||||
return required_impls_;
|
||||
}
|
||||
|
||||
auto rewrites() const -> llvm::ArrayRef<Rewrite> { return rewrites_; }
|
||||
|
||||
// Can this be used to the right of an `as` in an `impl` declaration?
|
||||
auto is_valid_impl_as_target() const -> bool {
|
||||
return interface_id_.has_value();
|
||||
@@ -89,6 +99,12 @@ struct IdentifiedFacetType {
|
||||
// constraint. Sorted and deduplicated.
|
||||
llvm::SmallVector<RequiredImpl> required_impls_;
|
||||
|
||||
// Rewrite constraints from a facet type and any named constraints that it
|
||||
// references, flattened to a single list with `.Self` replaced on the RHS.
|
||||
// The witness on the LHS should be ignored other than to specify in which
|
||||
// interface the associated constant is being rewritten.
|
||||
llvm::SmallVector<Rewrite> rewrites_;
|
||||
|
||||
// The single interface from `required_impls` to implement if this is
|
||||
// the facet type to the right of an `impl`...`as`, or `None` if no such
|
||||
// single interface.
|
||||
@@ -120,7 +136,7 @@ auto AddCanonicalWitnessesBlock(File& sem_ir,
|
||||
namespace Carbon {
|
||||
extern template class CanonicalValueStore<
|
||||
SemIR::IdentifiedFacetTypeId, SemIR::IdentifiedFacetTypeKey,
|
||||
Tag<SemIR::CheckIRId>, SemIR ::IdentifiedFacetType>;
|
||||
Tag<SemIR::CheckIRId>, SemIR::IdentifiedFacetType>;
|
||||
extern template class ValueStore<SemIR::IdentifiedFacetTypeId,
|
||||
SemIR::IdentifiedFacetType,
|
||||
Tag<SemIR::CheckIRId>>;
|
||||
|
||||
Reference in New Issue
Block a user