Move IdentifiedFacetType to check (#8004)

`IdentifiedFacetType` is a concept that is only used by check. It does
not appear in the semir output, unlike `DeclaredFacetType`s.
`IdentifiedFacetType` is used in check to collapse named constraints
together, building a single structure of requirements from a
`DeclaredFacetType` and any referenced named constraints. This is used
for operations like impl lookup, and building `FacetValue`s.

The outputs of `IdentifiedFacetType` are now in an intermediate state,
where they contain `IdentifiedWitness`es, and need to be processed
before they are used. We'd like to build that into the API of
`IdentifiedFacetType` so that their use is more robust. But the
`IdentifiedWitnesses` need to be replaced by subst, which is a part of
check, so we need to move `IdentifiedFacetType` to check in order to
build the type on top of subst.
This commit is contained in:
Dana Jansens authored and GitHub committed 2026-10-21 13:20:54 +00:00
1 parent 0546b48a7d
commit fb7eff130d
28 files changed
+618 -607

No files matched your search

+1 -1
View File
@@ -97,7 +97,7 @@ Example usage:
"function": "SemIR::MakeFunctionId", "function": "SemIR::MakeFunctionId",
"generated_function": "SemIR::MakeGeneratedFunctionId", "generated_function": "SemIR::MakeGeneratedFunctionId",
"generic": "SemIR::MakeGenericId", "generic": "SemIR::MakeGenericId",
"identified_facet_type": "SemIR::MakeIdentifiedFacetTypeId", "identified_facet_type": "Check::MakeIdentifiedFacetTypeId",
"impl": "SemIR::MakeImplId", "impl": "SemIR::MakeImplId",
"inst": "SemIR::MakeInstId", "inst": "SemIR::MakeInstId",
"inst_block": "SemIR::MakeInstBlockId", "inst_block": "SemIR::MakeInstBlockId",
+2
View File
@@ -48,6 +48,7 @@ cc_library(
"function.cpp", "function.cpp",
"generic.cpp", "generic.cpp",
"global_init.cpp", "global_init.cpp",
"identified_facet_type.cpp",
"impl.cpp", "impl.cpp",
"impl_lookup.cpp", "impl_lookup.cpp",
"impl_validation.cpp", "impl_validation.cpp",
@@ -116,6 +117,7 @@ cc_library(
"function.h", "function.h",
"generic.h", "generic.h",
"global_init.h", "global_init.h",
"identified_facet_type.h",
"impl.h", "impl.h",
"impl_lookup.h", "impl_lookup.h",
"impl_validation.h", "impl_validation.h",
+2 -1
View File
@@ -40,7 +40,8 @@ Context::Context(DiagnosticEmitterBase* emitter,
TODO(loc_id, label); TODO(loc_id, label);
}), }),
core_identifiers_(&identifiers()), core_identifiers_(&identifiers()),
mangle_string_fingerprint_(mangle_string_fingerprint) { mangle_string_fingerprint_(mangle_string_fingerprint),
identified_facet_types_(sem_ir->check_ir_id()) {
// Prepare fields which relate to the number of IRs available for import. // Prepare fields which relate to the number of IRs available for import.
import_irs().Reserve(imported_ir_count); import_irs().Reserve(imported_ir_count);
import_ir_constant_values_.reserve(imported_ir_count); import_ir_constant_values_.reserve(imported_ir_count);
+11 -4
View File
@@ -21,6 +21,7 @@
#include "toolchain/check/full_pattern_stack.h" #include "toolchain/check/full_pattern_stack.h"
#include "toolchain/check/generic_region_stack.h" #include "toolchain/check/generic_region_stack.h"
#include "toolchain/check/global_init.h" #include "toolchain/check/global_init.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/inst_block_stack.h" #include "toolchain/check/inst_block_stack.h"
#include "toolchain/check/node_stack.h" #include "toolchain/check/node_stack.h"
#include "toolchain/check/param_and_arg_refs_stack.h" #include "toolchain/check/param_and_arg_refs_stack.h"
@@ -33,7 +34,6 @@
#include "toolchain/parse/tree_and_subtrees.h" #include "toolchain/parse/tree_and_subtrees.h"
#include "toolchain/sem_ir/declared_facet_type.h" #include "toolchain/sem_ir/declared_facet_type.h"
#include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/import_ir.h" #include "toolchain/sem_ir/import_ir.h"
#include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst.h"
@@ -367,6 +367,13 @@ class Context {
auto access_context() -> SemIR::NameScopeId& { return access_context_; } auto access_context() -> SemIR::NameScopeId& { return access_context_; }
auto identified_facet_types() -> IdentifiedFacetTypeStore& {
return identified_facet_types_;
}
auto identified_facet_types() const -> const IdentifiedFacetTypeStore& {
return identified_facet_types_;
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Directly expose SemIR::File data accessors for brevity in calls. // Directly expose SemIR::File data accessors for brevity in calls.
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -414,9 +421,6 @@ class Context {
auto declared_facet_types() -> SemIR::DeclaredFacetTypeStore& { auto declared_facet_types() -> SemIR::DeclaredFacetTypeStore& {
return sem_ir().declared_facet_types(); return sem_ir().declared_facet_types();
} }
auto identified_facet_types() -> SemIR::IdentifiedFacetTypeStore& {
return sem_ir().identified_facet_types();
}
auto impls() -> SemIR::ImplStore& { return sem_ir().impls(); } auto impls() -> SemIR::ImplStore& { return sem_ir().impls(); }
auto specific_interfaces() -> SemIR::SpecificInterfaceStore& { auto specific_interfaces() -> SemIR::SpecificInterfaceStore& {
return sem_ir().specific_interfaces(); return sem_ir().specific_interfaces();
@@ -671,6 +675,9 @@ class Context {
// This is updated by `DeclNameStack`. During monomorphization, it is updated // This is updated by `DeclNameStack`. During monomorphization, it is updated
// by `TryEvalBlockForSpecific`. // by `TryEvalBlockForSpecific`.
SemIR::NameScopeId access_context_ = SemIR::NameScopeId::None; SemIR::NameScopeId access_context_ = SemIR::NameScopeId::None;
// Storage for identified facet types.
IdentifiedFacetTypeStore identified_facet_types_;
}; };
inline constexpr Context::FormExpr Context::FormExpr::Error = { inline constexpr Context::FormExpr Context::FormExpr::Error = {
+34 -3
View File
@@ -100,9 +100,35 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context,
} }
LLVM_DUMP_METHOD static auto Dump( LLVM_DUMP_METHOD static auto Dump(
const Context& context, const Context& context, IdentifiedFacetTypeId identified_facet_type_id)
SemIR::IdentifiedFacetTypeId identified_facet_type_id) -> std::string { -> std::string {
return SemIR::Dump(context.sem_ir(), identified_facet_type_id); RawStringOstream out;
out << identified_facet_type_id;
if (!identified_facet_type_id.has_value()) {
return out.TakeStr();
}
const auto& identified_facet_type =
context.identified_facet_types().Get(identified_facet_type_id);
for (auto [i, req_impl] :
llvm::enumerate(identified_facet_type.required_impls())) {
auto [self, req_interface] = req_impl;
out << "\n - self: " << DumpConstantSummary(context.sem_ir(), self);
out << "\n impls: "
<< DumpInterfaceSummary(context.sem_ir(), req_interface.interface_id);
if (req_interface.specific_id.has_value()) {
out << "; "
<< DumpSpecificSummary(context.sem_ir(), req_interface.specific_id);
}
if (req_interface == identified_facet_type.impl_as_target_interface()) {
out << "\n - `impl as` target";
}
}
if (!identified_facet_type.is_valid_impl_as_target()) {
out << "\n - " << identified_facet_type.num_interfaces_to_impl()
<< " possible `impl as` targets";
}
return out.TakeStr();
} }
LLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::ImplId impl_id) LLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::ImplId impl_id)
@@ -207,6 +233,11 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::TypeId type_id)
return SemIR::Dump(context.sem_ir(), type_id); return SemIR::Dump(context.sem_ir(), type_id);
} }
LLVM_DUMP_METHOD static auto MakeIdentifiedFacetTypeId(int id)
-> IdentifiedFacetTypeId {
return IdentifiedFacetTypeId(id);
}
} // namespace Carbon::Check } // namespace Carbon::Check
#endif // NDEBUG #endif // NDEBUG
+1
View File
@@ -14,6 +14,7 @@
#include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/diagnostic_helpers.h"
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/impl_lookup.h" #include "toolchain/check/impl_lookup.h"
#include "toolchain/check/import_ref.h" #include "toolchain/check/import_ref.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
-229
View File
@@ -4,9 +4,7 @@
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/context.h" #include "toolchain/check/context.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/import_ref.h" #include "toolchain/check/import_ref.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
#include "toolchain/check/interface.h" #include "toolchain/check/interface.h"
@@ -541,231 +539,4 @@ auto FindWhere(Context& context, SemIR::ConstantId const_id) -> bool {
return found; return found;
} }
class EvaluateSubstCallbacks : public SubstInstCallbacks {
public:
explicit EvaluateSubstCallbacks(
Context* context, SemIR::LocId loc_id,
SubstIdentifiedWitnessesCallbacks* subst_callbacks = nullptr)
: SubstInstCallbacks(context),
loc_id_(loc_id),
subst_callbacks_(subst_callbacks) {}
auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
// SubstPeriodSelf recurses into facet types, so we need to do the same to
// find those witnesses first. So we can't early out if the inst has a
// concrete constant value.
if (inst_id == SemIR::TypeType::TypeInstId ||
inst_id == SemIR::ErrorInst::InstId) {
return FullySubstituted;
}
return SubstOperands;
}
auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {
if (auto witness = context().insts().TryGetAs<SemIR::IdentifiedWitness>(
orig_inst_id)) {
return SubstIdentifiedWitness(*witness);
}
if (auto witness =
context().insts().TryGetAs<SemIR::ImplSelfWitness>(orig_inst_id)) {
return SubstImplSelfWitness(*witness);
}
return orig_inst_id;
}
auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst new_inst)
-> SemIR::InstId override {
if (auto witness = new_inst.TryAs<SemIR::IdentifiedWitness>()) {
return SubstIdentifiedWitness(*witness);
}
if (auto witness = new_inst.TryAs<SemIR::ImplSelfWitness>()) {
return SubstImplSelfWitness(*witness);
}
return RebuildNewInst(loc_id_, new_inst);
}
auto RebuildSpecific(SemIR::SpecificId orig_specific_id,
SemIR::InstBlockId args_id)
-> SemIR::SpecificId override {
auto generic_id = context().specifics().Get(orig_specific_id).generic_id;
// Drop the `identified` flag from any specifics we create here, as we have
// substituted the IdentifiedWitness instructions away.
return context().specifics().GetOrAdd(generic_id, args_id,
/*identified=*/false);
}
private:
auto SubstIdentifiedWitness(SemIR::IdentifiedWitness witness)
-> SemIR::InstId {
if (subst_callbacks_) {
auto replaced_id = subst_callbacks_->ReplaceIdentified(witness);
if (replaced_id.has_value()) {
CARBON_CHECK(
!context().insts().Is<SemIR::IdentifiedWitness>(replaced_id));
return replaced_id;
}
}
auto const_id = EvalOrAddInst<SemIR::LookupImplWitness>(
context(), loc_id_,
{.type_id = witness.type_id,
.query_self_inst_id = witness.query_self_inst_id,
.query_specific_interface_id = witness.query_specific_interface_id});
auto inst_id = context().constant_values().GetInstId(const_id);
CARBON_CHECK(!context().insts().Is<SemIR::IdentifiedWitness>(inst_id));
return inst_id;
}
auto SubstImplSelfWitness(SemIR::ImplSelfWitness witness) -> SemIR::InstId {
if (subst_callbacks_) {
auto replaced_id = subst_callbacks_->ReplaceImplSelfWitness(witness);
if (replaced_id.has_value()) {
return replaced_id;
}
}
return RebuildNewInst(loc_id_, witness);
}
SemIR::LocId loc_id_;
SubstIdentifiedWitnessesCallbacks* subst_callbacks_;
};
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::RequiredImpl req)
-> SemIR::IdentifiedFacetType::RequiredImpl {
if (context.eval_impl_lookup_to_identified_witness()) {
return req;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto self_id = SubstInst(
context, context.constant_values().GetInstId(req.self_facet_value),
callbacks);
auto interface =
EvaluateIdentifiedWitnesses(context, loc_id, req.specific_interface);
return {.self_facet_value = context.constant_values().Get(self_id),
.specific_interface = interface};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::Rewrite rewrite)
-> SemIR::IdentifiedFacetType::Rewrite {
if (context.eval_impl_lookup_to_identified_witness()) {
return rewrite;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto lhs_id = SubstInst(
context, context.constant_values().GetInstId(rewrite.lhs), callbacks);
auto rhs_id = SubstInst(
context, context.constant_values().GetInstId(rewrite.rhs), callbacks);
return {.lhs = context.constant_values().Get(lhs_id),
.rhs = context.constant_values().Get(rhs_id)};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterface interface)
-> SemIR::SpecificInterface {
if (context.eval_impl_lookup_to_identified_witness()) {
return interface;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto specific_id = interface.specific_id;
if (specific_id.has_value()) {
const auto& specific = context.specifics().Get(specific_id);
llvm::SmallVector<SemIR::InstId> args(
context.inst_blocks().Get(specific.args_id));
for (auto& arg_id : args) {
arg_id = SubstInst(context, arg_id, callbacks);
}
specific_id = MakeSpecific(context, loc_id, specific.generic_id, args);
}
return {.interface_id = interface.interface_id, .specific_id = specific_id};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id)
-> SemIR::ConstantId {
if (context.eval_impl_lookup_to_identified_witness()) {
return const_id;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto inst_id = context.constant_values().GetInstId(const_id);
inst_id = SubstInst(context, inst_id, callbacks);
return context.constant_values().Get(inst_id);
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::RequiredImpl req,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::IdentifiedFacetType::RequiredImpl {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto self_id = SubstInst(
context, context.constant_values().GetInstId(req.self_facet_value),
subst_callbacks);
auto interface_id = req.specific_interface.interface_id;
auto specific_id = req.specific_interface.specific_id;
if (specific_id.has_value()) {
const auto& specific = context.specifics().Get(specific_id);
llvm::SmallVector<SemIR::InstId> args(
context.inst_blocks().Get(specific.args_id));
for (auto& arg_id : args) {
arg_id = SubstInst(context, arg_id, subst_callbacks);
}
specific_id = MakeSpecific(context, loc_id, specific.generic_id, args);
}
return {.self_facet_value = context.constant_values().Get(self_id),
.specific_interface = {.interface_id = interface_id,
.specific_id = specific_id}};
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::Equivalent equiv,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::IdentifiedFacetType::Equivalent {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto lhs_inst_id = SubstInst(
context, context.constant_values().GetInstId(equiv.lhs), subst_callbacks);
auto rhs_inst_id = SubstInst(
context, context.constant_values().GetInstId(equiv.rhs), subst_callbacks);
return {context.constant_values().Get(lhs_inst_id),
context.constant_values().Get(rhs_inst_id)};
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::ConstantId {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto inst_id = SubstInst(
context, context.constant_values().GetInstId(const_id), subst_callbacks);
return context.constant_values().Get(inst_id);
}
} // namespace Carbon::Check } // namespace Carbon::Check
-56
View File
@@ -6,7 +6,6 @@
#define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_ #define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_
#include "toolchain/check/context.h" #include "toolchain/check/context.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
namespace Carbon::Check { namespace Carbon::Check {
@@ -75,61 +74,6 @@ auto GetConstantFacetValueForTypeAndInterface(
// type with an arbitrary facet type (including a `where` expression). // type with an arbitrary facet type (including a `where` expression).
auto FindWhere(Context& context, SemIR::ConstantId const_id) -> bool; auto FindWhere(Context& context, SemIR::ConstantId const_id) -> bool;
// Replace all IdentifiedWitnesses with LookupImplWitnesses, which will evaluate
// and perform an impl lookup. If part of an ImplWitnessAccess, the result may
// replace the access and witness with the value of an associated constant from
// an impl.
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::RequiredImpl req)
-> SemIR::IdentifiedFacetType::RequiredImpl;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::Rewrite rewrite)
-> SemIR::IdentifiedFacetType::Rewrite;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterface interface)
-> SemIR::SpecificInterface;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id)
-> SemIR::ConstantId;
class SubstIdentifiedWitnessesCallbacks {
public:
explicit SubstIdentifiedWitnessesCallbacks(Context* context)
: context_(context) {}
auto context() const -> Context& { return *context_; }
// Callback to return an InstId to use in place of the IdentifiedWitness. If
// it returns None, the substitution will replace it with a LookupImplWitness
// which will be evaluated to perform an impl lookup.
virtual auto ReplaceIdentified(SemIR::IdentifiedWitness witness)
-> SemIR::InstId = 0;
// Callback to return an InstId to use in place of the ImplSelfWitness. If it
// returns None, the ImplSelfWitness will be left in place.
virtual auto ReplaceImplSelfWitness(SemIR::ImplSelfWitness witness)
-> SemIR::InstId = 0;
private:
Context* context_;
};
// Replace all IdentifiedWitnesses based on the behaviour of a callback that is
// run as each witness is visited. Also gives the opportunity to replace
// ImplSelfWitness in the same substitution pass.
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::RequiredImpl req,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::IdentifiedFacetType::RequiredImpl;
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::IdentifiedFacetType::Equivalent equiv,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::IdentifiedFacetType::Equivalent;
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::ConstantId;
} // namespace Carbon::Check } // namespace Carbon::Check
#endif // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_ #endif // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_
+2 -1
View File
@@ -12,6 +12,7 @@
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/handle.h" #include "toolchain/check/handle.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/impl.h" #include "toolchain/check/impl.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
#include "toolchain/check/modifiers.h" #include "toolchain/check/modifiers.h"
@@ -209,7 +210,7 @@ struct BuildImplDeclResult {
SemIR::ImplId impl_id; SemIR::ImplId impl_id;
SemIR::InstId impl_decl_id; SemIR::InstId impl_decl_id;
SemIR::TypeInstId full_constraint_type_inst_id; SemIR::TypeInstId full_constraint_type_inst_id;
SemIR::IdentifiedFacetTypeId identified_id; IdentifiedFacetTypeId identified_id;
}; };
// Build an ImplDecl describing the signature of an impl. This handles the // Build an ImplDecl describing the signature of an impl. This handles the
+2 -2
View File
@@ -106,7 +106,7 @@ auto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id)
static auto TypeStructureReferencesSelf( static auto TypeStructureReferencesSelf(
Context& context, SemIR::LocId loc_id, SemIR::ConstantId const_id, Context& context, SemIR::LocId loc_id, SemIR::ConstantId const_id,
const SemIR::IdentifiedFacetType& identified_facet_type) -> bool { const IdentifiedFacetType& identified_facet_type) -> bool {
auto find_self = [&](SemIR::TypeIterator& type_iter) -> bool { auto find_self = [&](SemIR::TypeIterator& type_iter) -> bool {
while (true) { while (true) {
auto step = type_iter.Next(); auto step = type_iter.Next();
@@ -173,7 +173,7 @@ static auto TypeStructureReferencesSelf(
} }
struct ValidateRequireResult { struct ValidateRequireResult {
const SemIR::IdentifiedFacetType* identified_facet_type; const IdentifiedFacetType* identified_facet_type;
}; };
// Returns nullopt if a diagnostic has been emitted and the `require` decl is // Returns nullopt if a diagnostic has been emitted and the `require` decl is
+1
View File
@@ -8,6 +8,7 @@
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/handle.h" #include "toolchain/check/handle.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
#include "toolchain/check/period_self.h" #include "toolchain/check/period_self.h"
#include "toolchain/check/subst.h" #include "toolchain/check/subst.h"
+391
View File
@@ -0,0 +1,391 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/base/canonical_value_store_impl.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/base/value_store_impl.h"
#include "toolchain/check/context.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/inst.h"
#include "toolchain/check/subst.h"
namespace Carbon::Check {
template <typename T>
using LessThanFn = llvm::function_ref<auto(const T&, const T&)->bool>;
template <typename VecT>
static auto SortAndDeduplicate(VecT& vec,
LessThanFn<typename VecT::value_type> compare)
-> void {
llvm::sort(vec, compare);
vec.erase(llvm::unique(vec), vec.end());
}
// Canonically ordered by the numerical ids. Matches the order of RequiredLess
// when the `self_facet_value` is the same for all interfaces.
static auto InterfaceLess(const SemIR::SpecificInterface& lhs,
const SemIR::SpecificInterface& rhs) -> bool {
return std::tie(lhs.interface_id.index, lhs.specific_id.index) <
std::tie(rhs.interface_id.index, rhs.specific_id.index);
}
// Canonically ordered by the numerical ids.
static auto RequiredLess(const IdentifiedFacetType::RequiredImpl& lhs,
const IdentifiedFacetType::RequiredImpl& rhs) -> bool {
return std::tie(lhs.self_facet_value.index,
lhs.specific_interface.interface_id.index,
lhs.specific_interface.specific_id.index) <
std::tie(rhs.self_facet_value.index,
rhs.specific_interface.interface_id.index,
rhs.specific_interface.specific_id.index);
}
// Canonically ordered by the numerical ids.
static auto RewriteLess(const IdentifiedFacetType::Rewrite& lhs,
const IdentifiedFacetType::Rewrite& rhs) -> bool {
return std::tie(lhs.lhs.index, lhs.rhs.index) <
std::tie(rhs.lhs.index, rhs.rhs.index);
}
// Canonically ordered by the numerical ids.
static auto EquivalentLess(const IdentifiedFacetType::Equivalent& lhs,
const IdentifiedFacetType::Equivalent& rhs) -> bool {
return std::tie(lhs.lhs.index, lhs.rhs.index) <
std::tie(rhs.lhs.index, rhs.rhs.index);
}
IdentifiedFacetType::IdentifiedFacetType(
IdentifiedFacetTypeKey key, bool partially_identified,
llvm::ArrayRef<RequiredImpl> extends,
llvm::ArrayRef<RequiredImpl> self_impls, llvm::ArrayRef<Rewrite> rewrites,
llvm::ArrayRef<Equivalent> equivalents)
: key_(key) {
required_impls_.reserve(extends.size() + self_impls.size());
llvm::append_range(required_impls_, extends);
SortAndDeduplicate(required_impls_, RequiredLess);
// If there's a single extended interface then we present as that interface.
// Otherwise, we record the number extended interfaces.
if (required_impls_.size() == 1) {
interface_id_ = required_impls_.front().specific_interface.interface_id;
specific_id_ = required_impls_.front().specific_interface.specific_id;
} else {
interface_id_ = SemIR::InterfaceId::None;
num_interface_to_impl_ = required_impls_.size();
}
llvm::append_range(required_impls_, self_impls);
SortAndDeduplicate(required_impls_, RequiredLess);
SortAndDeduplicate(required_impls_, RequiredLess);
if (partially_identified) {
// This marks the IdentifiedFacetType as being partially identified, and
// prevents the key from colliding with a fully identified facet type, or
// with other partially (but differently) identified facet types, with the
// same constituents but a more complete set of required interfaces.
key_.num_require_impls = required_impls_.size();
}
rewrites_.assign(rewrites);
SortAndDeduplicate(rewrites_, RewriteLess);
equivalents_.assign(equivalents);
SortAndDeduplicate(equivalents_, EquivalentLess);
}
auto AddCanonicalWitnessesBlock(Context& context,
llvm::SmallVector<SemIR::InstId>& witnesses)
-> SemIR::InstBlockId {
// Small blocks don't need to be sorted.
if (witnesses.size() <= 1) {
return context.inst_blocks().AddCanonical(witnesses);
}
llvm::SmallVector<std::pair<SemIR::SpecificInterface, SemIR::InstId>>
sortable;
sortable.reserve(witnesses.size());
// Produce the sorted order based on the witness's SpecificInterface.
for (auto witness_id : witnesses) {
auto inst = context.insts().Get(witness_id);
CARBON_KIND_SWITCH(inst) {
case CARBON_KIND(SemIR::CustomWitness witness): {
sortable.push_back({context.specific_interfaces().Get(
witness.query_specific_interface_id),
witness_id});
break;
}
case CARBON_KIND(SemIR::ImplWitness witness): {
auto table = context.insts().GetAs<SemIR::ImplWitnessTable>(
witness.witness_table_id);
sortable.push_back(
{context.impls().Get(table.impl_id).interface, witness_id});
break;
}
case CARBON_KIND(SemIR::LookupImplWitness witness): {
sortable.push_back({context.specific_interfaces().Get(
witness.query_specific_interface_id),
witness_id});
break;
}
default:
CARBON_FATAL("Unhandled inst: {0}", inst);
}
}
// This matches the sort order of IdentifiedFacetType::required_interfaces,
// which is the order of the witnesses returned from impl lookup, and is
// canonical order in which the witnesses must appear for a given facet type
// so that ImplWitnessAccess can find the appropriate witness.
llvm::sort(sortable, [](auto& lhs, auto& rhs) {
return InterfaceLess(lhs.first, rhs.first);
});
// Update the original list with the new order (reusing to avoid an
// allocation).
for (auto [witness_id, sortable_entry] :
llvm::zip_equal(witnesses, sortable)) {
witness_id = sortable_entry.second;
}
return context.inst_blocks().AddCanonical(witnesses);
}
class EvaluateSubstCallbacks : public SubstInstCallbacks {
public:
explicit EvaluateSubstCallbacks(
Context* context, SemIR::LocId loc_id,
SubstIdentifiedWitnessesCallbacks* subst_callbacks = nullptr)
: SubstInstCallbacks(context),
loc_id_(loc_id),
subst_callbacks_(subst_callbacks) {}
auto Subst(SemIR::InstId& inst_id) -> SubstResult override {
// SubstPeriodSelf recurses into facet types, so we need to do the same to
// find those witnesses first. So we can't early out if the inst has a
// concrete constant value.
if (inst_id == SemIR::TypeType::TypeInstId ||
inst_id == SemIR::ErrorInst::InstId) {
return FullySubstituted;
}
return SubstOperands;
}
auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {
if (auto witness = context().insts().TryGetAs<SemIR::IdentifiedWitness>(
orig_inst_id)) {
return SubstIdentifiedWitness(*witness);
}
if (auto witness =
context().insts().TryGetAs<SemIR::ImplSelfWitness>(orig_inst_id)) {
return SubstImplSelfWitness(*witness);
}
return orig_inst_id;
}
auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst new_inst)
-> SemIR::InstId override {
if (auto witness = new_inst.TryAs<SemIR::IdentifiedWitness>()) {
return SubstIdentifiedWitness(*witness);
}
if (auto witness = new_inst.TryAs<SemIR::ImplSelfWitness>()) {
return SubstImplSelfWitness(*witness);
}
return RebuildNewInst(loc_id_, new_inst);
}
auto RebuildSpecific(SemIR::SpecificId orig_specific_id,
SemIR::InstBlockId args_id)
-> SemIR::SpecificId override {
auto generic_id = context().specifics().Get(orig_specific_id).generic_id;
// Drop the `identified` flag from any specifics we create here, as we have
// substituted the IdentifiedWitness instructions away.
return context().specifics().GetOrAdd(generic_id, args_id,
/*identified=*/false);
}
private:
auto SubstIdentifiedWitness(SemIR::IdentifiedWitness witness)
-> SemIR::InstId {
if (subst_callbacks_) {
auto replaced_id = subst_callbacks_->ReplaceIdentified(witness);
if (replaced_id.has_value()) {
CARBON_CHECK(
!context().insts().Is<SemIR::IdentifiedWitness>(replaced_id));
return replaced_id;
}
}
auto const_id = EvalOrAddInst<SemIR::LookupImplWitness>(
context(), loc_id_,
{.type_id = witness.type_id,
.query_self_inst_id = witness.query_self_inst_id,
.query_specific_interface_id = witness.query_specific_interface_id});
auto inst_id = context().constant_values().GetInstId(const_id);
CARBON_CHECK(!context().insts().Is<SemIR::IdentifiedWitness>(inst_id));
return inst_id;
}
auto SubstImplSelfWitness(SemIR::ImplSelfWitness witness) -> SemIR::InstId {
if (subst_callbacks_) {
auto replaced_id = subst_callbacks_->ReplaceImplSelfWitness(witness);
if (replaced_id.has_value()) {
return replaced_id;
}
}
return RebuildNewInst(loc_id_, witness);
}
SemIR::LocId loc_id_;
SubstIdentifiedWitnessesCallbacks* subst_callbacks_;
};
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::RequiredImpl req)
-> IdentifiedFacetType::RequiredImpl {
if (context.eval_impl_lookup_to_identified_witness()) {
return req;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto self_id = SubstInst(
context, context.constant_values().GetInstId(req.self_facet_value),
callbacks);
auto interface =
EvaluateIdentifiedWitnesses(context, loc_id, req.specific_interface);
return {.self_facet_value = context.constant_values().Get(self_id),
.specific_interface = interface};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::Rewrite rewrite)
-> IdentifiedFacetType::Rewrite {
if (context.eval_impl_lookup_to_identified_witness()) {
return rewrite;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto lhs_id = SubstInst(
context, context.constant_values().GetInstId(rewrite.lhs), callbacks);
auto rhs_id = SubstInst(
context, context.constant_values().GetInstId(rewrite.rhs), callbacks);
return {.lhs = context.constant_values().Get(lhs_id),
.rhs = context.constant_values().Get(rhs_id)};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterface interface)
-> SemIR::SpecificInterface {
if (context.eval_impl_lookup_to_identified_witness()) {
return interface;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto specific_id = interface.specific_id;
if (specific_id.has_value()) {
const auto& specific = context.specifics().Get(specific_id);
llvm::SmallVector<SemIR::InstId> args(
context.inst_blocks().Get(specific.args_id));
for (auto& arg_id : args) {
arg_id = SubstInst(context, arg_id, callbacks);
}
specific_id = MakeSpecific(context, loc_id, specific.generic_id, args);
}
return {.interface_id = interface.interface_id, .specific_id = specific_id};
}
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id)
-> SemIR::ConstantId {
if (context.eval_impl_lookup_to_identified_witness()) {
return const_id;
}
EvaluateSubstCallbacks callbacks(&context, loc_id);
auto inst_id = context.constant_values().GetInstId(const_id);
inst_id = SubstInst(context, inst_id, callbacks);
return context.constant_values().Get(inst_id);
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::RequiredImpl req,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> IdentifiedFacetType::RequiredImpl {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto self_id = SubstInst(
context, context.constant_values().GetInstId(req.self_facet_value),
subst_callbacks);
auto interface_id = req.specific_interface.interface_id;
auto specific_id = req.specific_interface.specific_id;
if (specific_id.has_value()) {
const auto& specific = context.specifics().Get(specific_id);
llvm::SmallVector<SemIR::InstId> args(
context.inst_blocks().Get(specific.args_id));
for (auto& arg_id : args) {
arg_id = SubstInst(context, arg_id, subst_callbacks);
}
specific_id = MakeSpecific(context, loc_id, specific.generic_id, args);
}
return {.self_facet_value = context.constant_values().Get(self_id),
.specific_interface = {.interface_id = interface_id,
.specific_id = specific_id}};
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::Equivalent equiv,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> IdentifiedFacetType::Equivalent {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto lhs_inst_id = SubstInst(
context, context.constant_values().GetInstId(equiv.lhs), subst_callbacks);
auto rhs_inst_id = SubstInst(
context, context.constant_values().GetInstId(equiv.rhs), subst_callbacks);
return {context.constant_values().Get(lhs_inst_id),
context.constant_values().Get(rhs_inst_id)};
}
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::ConstantId {
// SubstIdentifiedWitnesses allows the caller to cleverly replace witnesses
// coming from identify with their own. If we do this in the middle of
// identify, it means there is another caller waiting for identify and they
// may also want to do their own replacements. This would be problematic! But
// since during identify we only create specifics, and resolving them through
// eval should not end up here, we make note of that.
CARBON_CHECK(!context.eval_impl_lookup_to_identified_witness(),
"SubstIdentifiedWitnesses called during identify");
EvaluateSubstCallbacks subst_callbacks(&context, loc_id, &callbacks);
auto inst_id = SubstInst(
context, context.constant_values().GetInstId(const_id), subst_callbacks);
return context.constant_values().Get(inst_id);
}
} // namespace Carbon::Check
namespace Carbon {
template class CanonicalValueStore<
Check::IdentifiedFacetTypeId, Check::IdentifiedFacetTypeKey,
Tag<SemIR::CheckIRId>, Check::IdentifiedFacetType>;
template class ValueStore<Check::IdentifiedFacetTypeId,
Check::IdentifiedFacetType, Tag<SemIR::CheckIRId>>;
} // namespace Carbon
@@ -2,22 +2,32 @@
// Exceptions. See /LICENSE for license information. // Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ #ifndef CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_
#define CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ #define CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "toolchain/base/canonical_value_store.h" #include "toolchain/base/canonical_value_store.h"
#include "toolchain/sem_ir/declared_facet_type.h" #include "toolchain/sem_ir/declared_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/specific_interface.h" #include "toolchain/sem_ir/specific_interface.h"
#include "toolchain/sem_ir/typed_insts.h"
namespace Carbon::SemIR { namespace Carbon::Check {
class File; // The ID of an identified facet type, which flattens referenced named
// constraints together into a single structure, and replaces any `.Self`
// references with a self facet.
struct IdentifiedFacetTypeId : public IdBase<IdentifiedFacetTypeId> {
static constexpr llvm::StringLiteral Label = "identified_facet_type";
using IdBase::IdBase;
};
class Context;
struct IdentifiedFacetTypeKey { struct IdentifiedFacetTypeKey {
DeclaredFacetTypeId declared_facet_type_id; SemIR::DeclaredFacetTypeId declared_facet_type_id;
ConstantId self_const_id; SemIR::ConstantId self_const_id;
// Inside a named constraint, each identification of the `Self` facet type can // Inside a named constraint, each identification of the `Self` facet type can
// be unique, as it can be modified by each require declaration seen so far. // be unique, as it can be modified by each require declaration seen so far.
// Uses -1 for identifying a facet type with a self-type from outside the // Uses -1 for identifying a facet type with a self-type from outside the
@@ -36,22 +46,22 @@ struct IdentifiedFacetTypeKey {
struct IdentifiedFacetType { struct IdentifiedFacetType {
// A requirement that `self_facet_value` implements the `specific_interface`. // A requirement that `self_facet_value` implements the `specific_interface`.
struct RequiredImpl { struct RequiredImpl {
ConstantId self_facet_value; SemIR::ConstantId self_facet_value;
SpecificInterface specific_interface; SemIR::SpecificInterface specific_interface;
friend auto operator==(const RequiredImpl& lhs, const RequiredImpl& rhs) friend auto operator==(const RequiredImpl& lhs, const RequiredImpl& rhs)
-> bool = default; -> bool = default;
}; };
struct Rewrite { struct Rewrite {
ConstantId lhs; SemIR::ConstantId lhs;
ConstantId rhs; SemIR::ConstantId rhs;
friend auto operator==(const Rewrite& lhs, const Rewrite& rhs) friend auto operator==(const Rewrite& lhs, const Rewrite& rhs)
-> bool = default; -> bool = default;
}; };
struct Equivalent { struct Equivalent {
ConstantId lhs; SemIR::ConstantId lhs;
ConstantId rhs; SemIR::ConstantId rhs;
friend auto operator==(const Equivalent& lhs, const Equivalent& rhs) friend auto operator==(const Equivalent& lhs, const Equivalent& rhs)
-> bool = default; -> bool = default;
@@ -80,11 +90,11 @@ struct IdentifiedFacetType {
// The interface to implement when this facet type is used in an `impl` // The interface to implement when this facet type is used in an `impl`
// declaration. // declaration.
auto impl_as_target_interface() const -> SpecificInterface { auto impl_as_target_interface() const -> SemIR::SpecificInterface {
if (is_valid_impl_as_target()) { if (is_valid_impl_as_target()) {
return {.interface_id = interface_id_, .specific_id = specific_id_}; return {.interface_id = interface_id_, .specific_id = specific_id_};
} else { } else {
return SpecificInterface::None; return SemIR::SpecificInterface::None;
} }
} }
@@ -125,38 +135,93 @@ struct IdentifiedFacetType {
// The single interface from `required_impls` to implement if this is // 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 // the facet type to the right of an `impl`...`as`, or `None` if no such
// single interface. // single interface.
InterfaceId interface_id_ = InterfaceId::None; SemIR::InterfaceId interface_id_ = SemIR::InterfaceId::None;
union { union {
// If `interface_id` is `None`, the number of interfaces to report in a // If `interface_id` is `None`, the number of interfaces to report in a
// diagnostic about why this facet type can't be implemented. // diagnostic about why this facet type can't be implemented.
int num_interface_to_impl_ = 0; int num_interface_to_impl_ = 0;
// If `interface_id` is not `None`, the specific for that interface. // If `interface_id` is not `None`, the specific for that interface.
SpecificId specific_id_; SemIR::SpecificId specific_id_;
}; };
}; };
using IdentifiedFacetTypeStore = using IdentifiedFacetTypeStore =
CanonicalValueStore<IdentifiedFacetTypeId, IdentifiedFacetTypeKey, CanonicalValueStore<IdentifiedFacetTypeId, IdentifiedFacetTypeKey,
Tag<CheckIRId>, IdentifiedFacetType>; Tag<SemIR::CheckIRId>, IdentifiedFacetType>;
// Given an array of witnesses, sorts them to match the ordering of the specific // Given an array of witnesses, sorts them to match the ordering of the specific
// interfaces in the IdentifiedFacetType that produced the witness set, which is // interfaces in the IdentifiedFacetType that produced the witness set, which is
// the canonical witness order, and returns the resulting block ID. This assumes // the canonical witness order, and returns the resulting block ID. This assumes
// witnesses have already been deduplicated, and do not contain errors, because // witnesses have already been deduplicated, and do not contain errors, because
// it's mainly for imports. // it's mainly for imports.
auto AddCanonicalWitnessesBlock(File& sem_ir, auto AddCanonicalWitnessesBlock(Context& context,
llvm::SmallVector<InstId>& witnesses) llvm::SmallVector<SemIR::InstId>& witnesses)
-> InstBlockId; -> SemIR::InstBlockId;
} // namespace Carbon::SemIR // Replace all IdentifiedWitnesses with LookupImplWitnesses, which will evaluate
// and perform an impl lookup. If part of an ImplWitnessAccess, the result may
// replace the access and witness with the value of an associated constant from
// an impl.
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::RequiredImpl req)
-> IdentifiedFacetType::RequiredImpl;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::Rewrite rewrite)
-> IdentifiedFacetType::Rewrite;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterface interface)
-> SemIR::SpecificInterface;
auto EvaluateIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id)
-> SemIR::ConstantId;
class SubstIdentifiedWitnessesCallbacks {
public:
explicit SubstIdentifiedWitnessesCallbacks(Context* context)
: context_(context) {}
auto context() const -> Context& { return *context_; }
// Callback to return an InstId to use in place of the IdentifiedWitness. If
// it returns None, the substitution will replace it with a LookupImplWitness
// which will be evaluated to perform an impl lookup.
virtual auto ReplaceIdentified(SemIR::IdentifiedWitness witness)
-> SemIR::InstId = 0;
// Callback to return an InstId to use in place of the ImplSelfWitness. If it
// returns None, the ImplSelfWitness will be left in place.
virtual auto ReplaceImplSelfWitness(SemIR::ImplSelfWitness witness)
-> SemIR::InstId = 0;
private:
Context* context_;
};
// Replace all IdentifiedWitnesses based on the behaviour of a callback that is
// run as each witness is visited. Also gives the opportunity to replace
// ImplSelfWitness in the same substitution pass.
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::RequiredImpl req,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> IdentifiedFacetType::RequiredImpl;
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
IdentifiedFacetType::Equivalent equiv,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> IdentifiedFacetType::Equivalent;
auto SubstIdentifiedWitnesses(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId const_id,
SubstIdentifiedWitnessesCallbacks& callbacks)
-> SemIR::ConstantId;
} // namespace Carbon::Check
namespace Carbon { namespace Carbon {
extern template class CanonicalValueStore< extern template class CanonicalValueStore<
SemIR::IdentifiedFacetTypeId, SemIR::IdentifiedFacetTypeKey, Check::IdentifiedFacetTypeId, Check::IdentifiedFacetTypeKey,
Tag<SemIR::CheckIRId>, SemIR::IdentifiedFacetType>; Tag<SemIR::CheckIRId>, Check::IdentifiedFacetType>;
extern template class ValueStore<SemIR::IdentifiedFacetTypeId, extern template class ValueStore<Check::IdentifiedFacetTypeId,
SemIR::IdentifiedFacetType, Check::IdentifiedFacetType,
Tag<SemIR::CheckIRId>>; Tag<SemIR::CheckIRId>>;
} // namespace Carbon } // namespace Carbon
#endif // CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ #endif // CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_
+6 -7
View File
@@ -12,6 +12,7 @@
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/function.h" #include "toolchain/check/function.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/impl_lookup.h" #include "toolchain/check/impl_lookup.h"
#include "toolchain/check/import_ref.h" #include "toolchain/check/import_ref.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
@@ -27,7 +28,6 @@
#include "toolchain/check/type_structure.h" #include "toolchain/check/type_structure.h"
#include "toolchain/diagnostics/emitter.h" #include "toolchain/diagnostics/emitter.h"
#include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/generic.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/impl.h" #include "toolchain/sem_ir/impl.h"
#include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst.h"
@@ -442,7 +442,7 @@ class SubstWithImplWitness : public SubstIdentifiedWitnessesCallbacks {
auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id, auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
SemIR::LocId constraint_loc_id, SemIR::LocId constraint_loc_id,
const SemIR::Impl& impl, const SemIR::Impl& impl,
SemIR::IdentifiedFacetTypeId identified_id, IdentifiedFacetTypeId identified_id,
SemIR::SpecificId self_specific_id) SemIR::SpecificId self_specific_id)
-> SemIR::InstId { -> SemIR::InstId {
const auto& identified = context.identified_facet_types().Get(identified_id); const auto& identified = context.identified_facet_types().Get(identified_id);
@@ -841,8 +841,7 @@ auto FinishImplWitness(Context& context, const SemIR::Impl& impl) -> void {
auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id, auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id,
SemIR::Impl& impl, SemIR::Impl& impl,
SemIR::TypeInstId full_constraint_id, SemIR::TypeInstId full_constraint_id,
SemIR::IdentifiedFacetTypeId identified_id) IdentifiedFacetTypeId identified_id) -> void {
-> void {
if (impl.witness_id == SemIR::ErrorInst::InstId) { if (impl.witness_id == SemIR::ErrorInst::InstId) {
return; return;
} }
@@ -1011,7 +1010,7 @@ auto CheckConstraintIsFacetType(Context& context, SemIR::LocId loc_id,
auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id, auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
SemIR::InstId self_id, SemIR::InstId self_id,
SemIR::TypeInstId full_constraint_id) SemIR::TypeInstId full_constraint_id)
-> SemIR::IdentifiedFacetTypeId { -> IdentifiedFacetTypeId {
auto identified_id = RequireIdentifiedFacetType( auto identified_id = RequireIdentifiedFacetType(
context, SemIR::LocId(full_constraint_id), context, SemIR::LocId(full_constraint_id),
context.constant_values().Get(self_id), context.constant_values().Get(self_id),
@@ -1023,7 +1022,7 @@ auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
builder.Attach(loc_id, ImplOfUnidentifiedFacetType, full_constraint_id); builder.Attach(loc_id, ImplOfUnidentifiedFacetType, full_constraint_id);
}); });
if (!identified_id.has_value()) { if (!identified_id.has_value()) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
const auto& identified = context.identified_facet_types().Get(identified_id); const auto& identified = context.identified_facet_types().Get(identified_id);
if (!identified.is_valid_impl_as_target()) { if (!identified.is_valid_impl_as_target()) {
@@ -1031,7 +1030,7 @@ auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
"impl as {0} interfaces, expected 1", int); "impl as {0} interfaces, expected 1", int);
context.emitter().Emit(loc_id, ImplOfNotOneInterface, context.emitter().Emit(loc_id, ImplOfNotOneInterface,
identified.num_interfaces_to_impl()); identified.num_interfaces_to_impl());
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
return identified_id; return identified_id;
} }
+3 -4
View File
@@ -54,7 +54,7 @@ auto AddImpl(Context& context, const SemIR::Impl& impl,
auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id, auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,
SemIR::LocId constraint_loc_id, SemIR::LocId constraint_loc_id,
const SemIR::Impl& impl, const SemIR::Impl& impl,
SemIR::IdentifiedFacetTypeId identified_id, IdentifiedFacetTypeId identified_id,
SemIR::SpecificId self_specific_id) SemIR::SpecificId self_specific_id)
-> SemIR::InstId; -> SemIR::InstId;
@@ -70,8 +70,7 @@ auto FinishImplWitness(Context& context, const SemIR::Impl& impl_id) -> void;
auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id, auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id,
SemIR::Impl& impl, SemIR::Impl& impl,
SemIR::TypeInstId full_constraint_id, SemIR::TypeInstId full_constraint_id,
SemIR::IdentifiedFacetTypeId identified_id) IdentifiedFacetTypeId identified_id) -> void;
-> void;
// Sets all unset members of the witness for `impl` to the error instruction and // Sets all unset members of the witness for `impl` to the error instruction and
// sets the witness id in the `Impl` to an error. // sets the witness id in the `Impl` to an error.
@@ -102,7 +101,7 @@ auto CheckConstraintIsFacetType(Context& context, SemIR::LocId loc_id,
auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id, auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id,
SemIR::InstId self_id, SemIR::InstId self_id,
SemIR::TypeInstId full_constraint_id) SemIR::TypeInstId full_constraint_id)
-> SemIR::IdentifiedFacetTypeId; -> IdentifiedFacetTypeId;
// Given a specific for the impl, returns the specific interface that the impl // 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 // declaration is implementing. Returns None in the case of an error being
+9 -11
View File
@@ -16,8 +16,8 @@
#include "toolchain/check/deduce.h" #include "toolchain/check/deduce.h"
#include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/diagnostic_helpers.h"
#include "toolchain/check/eval.h" #include "toolchain/check/eval.h"
#include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/impl.h" #include "toolchain/check/impl.h"
#include "toolchain/check/import_ref.h" #include "toolchain/check/import_ref.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
@@ -27,7 +27,6 @@
#include "toolchain/check/type_completion.h" #include "toolchain/check/type_completion.h"
#include "toolchain/check/type_structure.h" #include "toolchain/check/type_structure.h"
#include "toolchain/sem_ir/declared_facet_type.h" #include "toolchain/sem_ir/declared_facet_type.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/impl.h" #include "toolchain/sem_ir/impl.h"
#include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst.h"
@@ -307,10 +306,9 @@ static auto TryGetSpecificWitnessIdForImpl(
impl.witness_id); impl.witness_id);
} }
static auto ThawPeriodSelfInRequiredImpl( static auto ThawPeriodSelfInRequiredImpl(Context& context, SemIR::LocId loc_id,
Context& context, SemIR::LocId loc_id, IdentifiedFacetType::RequiredImpl req)
SemIR::IdentifiedFacetType::RequiredImpl req) -> IdentifiedFacetType::RequiredImpl {
-> SemIR::IdentifiedFacetType::RequiredImpl {
auto self_inst_id = context.constant_values().GetInstId(req.self_facet_value); auto self_inst_id = context.constant_values().GetInstId(req.self_facet_value);
self_inst_id = ThawPeriodSelf(context, self_inst_id); self_inst_id = ThawPeriodSelf(context, self_inst_id);
req.self_facet_value = context.constant_values().Get(self_inst_id); req.self_facet_value = context.constant_values().Get(self_inst_id);
@@ -528,7 +526,7 @@ class SubstMatchingWitnessesFromImplLookup
public: public:
explicit SubstMatchingWitnessesFromImplLookup( explicit SubstMatchingWitnessesFromImplLookup(
Context* context, Context* context,
llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls, llvm::ArrayRef<IdentifiedFacetType::RequiredImpl> req_impls,
llvm::ArrayRef<SemIR::InstId> found_witness_inst_ids) llvm::ArrayRef<SemIR::InstId> found_witness_inst_ids)
: SubstIdentifiedWitnessesCallbacks(context), : SubstIdentifiedWitnessesCallbacks(context),
req_impls_(req_impls), req_impls_(req_impls),
@@ -556,7 +554,7 @@ class SubstMatchingWitnessesFromImplLookup
} }
private: private:
llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls_; llvm::ArrayRef<IdentifiedFacetType::RequiredImpl> req_impls_;
llvm::ArrayRef<SemIR::InstId> found_witness_inst_ids_; llvm::ArrayRef<SemIR::InstId> found_witness_inst_ids_;
}; };
@@ -943,7 +941,7 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
} }
// These RequiredImpls have IdentifiedWitnesses in them initially. We will // These RequiredImpls have IdentifiedWitnesses in them initially. We will
// replace those with real witnesses as we process them. // replace those with real witnesses as we process them.
llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> req_impls( llvm::SmallVector<IdentifiedFacetType::RequiredImpl> req_impls(
required_identified.required_impls()); required_identified.required_impls());
// Find all the facets in the query and their witnesses. // Find all the facets in the query and their witnesses.
@@ -1062,8 +1060,8 @@ auto LookupImplWitness(Context& context, SemIR::LocId loc_id,
} }
for (auto rewrite : required_identified.rewrites()) { for (auto rewrite : required_identified.rewrites()) {
// Rewrites are treated as equivalent requirements in impl lookup. // Rewrites are treated as equivalent requirements in impl lookup.
SemIR::IdentifiedFacetType::Equivalent equiv = {.lhs = rewrite.lhs, IdentifiedFacetType::Equivalent equiv = {.lhs = rewrite.lhs,
.rhs = rewrite.rhs}; .rhs = rewrite.rhs};
equiv = SubstIdentifiedWitnesses(context, loc_id, equiv, equiv = SubstIdentifiedWitnesses(context, loc_id, equiv,
subst_witnesses_callbacks); subst_witnesses_callbacks);
if (equiv.lhs != equiv.rhs) { if (equiv.lhs != equiv.rhs) {
+1 -1
View File
@@ -8,7 +8,7 @@
#include <variant> #include <variant>
#include "toolchain/check/context.h" #include "toolchain/check/context.h"
#include "toolchain/sem_ir/identified_facet_type.h" #include "toolchain/check/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/typed_insts.h" #include "toolchain/sem_ir/typed_insts.h"
+2 -2
View File
@@ -19,6 +19,7 @@
#include "toolchain/check/eval.h" #include "toolchain/check/eval.h"
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/import.h" #include "toolchain/check/import.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
#include "toolchain/check/name_lookup.h" #include "toolchain/check/name_lookup.h"
@@ -29,7 +30,6 @@
#include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/constant.h"
#include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/function.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/impl.h" #include "toolchain/sem_ir/impl.h"
#include "toolchain/sem_ir/import_ir.h" #include "toolchain/sem_ir/import_ir.h"
@@ -4038,7 +4038,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
auto witnesses_block_id = SemIR::InstBlockId::None; auto witnesses_block_id = SemIR::InstBlockId::None;
if (inst.witnesses_block_id.has_value()) { if (inst.witnesses_block_id.has_value()) {
witnesses_block_id = witnesses_block_id =
AddCanonicalWitnessesBlock(resolver.local_ir(), witnesses); AddCanonicalWitnessesBlock(resolver.local_context(), witnesses);
} }
return ResolveResult::Deduplicated<SemIR::FacetValue>( return ResolveResult::Deduplicated<SemIR::FacetValue>(
+26 -26
View File
@@ -11,6 +11,7 @@
#include "toolchain/check/cpp/import.h" #include "toolchain/check/cpp/import.h"
#include "toolchain/check/facet_type.h" #include "toolchain/check/facet_type.h"
#include "toolchain/check/generic.h" #include "toolchain/check/generic.h"
#include "toolchain/check/identified_facet_type.h"
#include "toolchain/check/inst.h" #include "toolchain/check/inst.h"
#include "toolchain/check/literal.h" #include "toolchain/check/literal.h"
#include "toolchain/check/period_self.h" #include "toolchain/check/period_self.h"
@@ -21,7 +22,6 @@
#include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/constant.h"
#include "toolchain/sem_ir/declared_facet_type.h" #include "toolchain/sem_ir/declared_facet_type.h"
#include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/generic.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/named_constraint.h" #include "toolchain/sem_ir/named_constraint.h"
#include "toolchain/sem_ir/specific_interface.h" #include "toolchain/sem_ir/specific_interface.h"
@@ -958,9 +958,9 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId initial_self_const_id, SemIR::ConstantId initial_self_const_id,
SemIR::ConstantId facet_type_const_id, SemIR::ConstantId facet_type_const_id,
bool allow_partially_identified, bool diagnose) bool allow_partially_identified, bool diagnose)
-> SemIR::IdentifiedFacetTypeId { -> IdentifiedFacetTypeId {
if (facet_type_const_id == SemIR::ErrorInst::ConstantId) { if (facet_type_const_id == SemIR::ErrorInst::ConstantId) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto declared_facet_type_id = auto declared_facet_type_id =
@@ -975,9 +975,9 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
// set of required impls that it contains, which requires us to do most of the // set of required impls that it contains, which requires us to do most of the
// work of identifying the facet type (though we could skip the mapping of // work of identifying the facet type (though we could skip the mapping of
// constant values into specifics). // constant values into specifics).
auto key = SemIR::IdentifiedFacetTypeKey{ auto key =
.declared_facet_type_id = declared_facet_type_id, IdentifiedFacetTypeKey{.declared_facet_type_id = declared_facet_type_id,
.self_const_id = initial_self_const_id}; .self_const_id = initial_self_const_id};
if (auto identified_id = context.identified_facet_types().Lookup(key); if (auto identified_id = context.identified_facet_types().Lookup(key);
identified_id.has_value()) { identified_id.has_value()) {
return identified_id; return identified_id;
@@ -999,7 +999,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
auto subst_id = SubstPeriodSelf(context, loc_id, facet_type_const_id, auto subst_id = SubstPeriodSelf(context, loc_id, facet_type_const_id,
initial_self_const_id); initial_self_const_id);
if (subst_id == SemIR::ErrorInst::ConstantId) { if (subst_id == SemIR::ErrorInst::ConstantId) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
declared_facet_type_id = context.constant_values() declared_facet_type_id = context.constant_values()
.GetInstAs<SemIR::FacetType>(subst_id) .GetInstAs<SemIR::FacetType>(subst_id)
@@ -1020,10 +1020,10 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
// Outputs for the IdentifiedFacetType. // Outputs for the IdentifiedFacetType.
bool partially_identified = false; bool partially_identified = false;
llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> extends; llvm::SmallVector<IdentifiedFacetType::RequiredImpl> extends;
llvm::SmallVector<SemIR::IdentifiedFacetType::RequiredImpl> impls; llvm::SmallVector<IdentifiedFacetType::RequiredImpl> impls;
llvm::SmallVector<SemIR::IdentifiedFacetType::Rewrite> rewrites; llvm::SmallVector<IdentifiedFacetType::Rewrite> rewrites;
llvm::SmallVector<SemIR::IdentifiedFacetType::Equivalent> equivalents; llvm::SmallVector<IdentifiedFacetType::Equivalent> equivalents;
while (!work.empty()) { while (!work.empty()) {
SelfImplsFacetType next_impls = work.pop_back_val(); SelfImplsFacetType next_impls = work.pop_back_val();
@@ -1033,12 +1033,12 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
context.declared_facet_types().Get(next_impls.declared_facet_type); context.declared_facet_types().Get(next_impls.declared_facet_type);
auto self_and_interface = [&](SemIR::SpecificInterface impls_interface) auto self_and_interface = [&](SemIR::SpecificInterface impls_interface)
-> SemIR::IdentifiedFacetType::RequiredImpl { -> IdentifiedFacetType::RequiredImpl {
return {self_const_id, impls_interface}; return {self_const_id, impls_interface};
}; };
auto type_and_interface = auto type_and_interface =
[&](SemIR::DeclaredFacetType::TypeImplsInterface impls) [&](SemIR::DeclaredFacetType::TypeImplsInterface impls)
-> SemIR::IdentifiedFacetType::RequiredImpl { -> IdentifiedFacetType::RequiredImpl {
return {context.constant_values().Get(impls.self_type), return {context.constant_values().Get(impls.self_type),
impls.specific_interface}; impls.specific_interface};
}; };
@@ -1060,7 +1060,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
type_and_interface)); type_and_interface));
if (facet_type_extends) { if (facet_type_extends) {
auto rewrite_as_constants = auto rewrite_as_constants =
[&](auto rewrite) -> SemIR::IdentifiedFacetType::Rewrite { [&](auto rewrite) -> IdentifiedFacetType::Rewrite {
return {context.constant_values().Get( return {context.constant_values().Get(
GetImplWitnessAccessWithoutSubstitution(context, GetImplWitnessAccessWithoutSubstitution(context,
rewrite.lhs_id)), rewrite.lhs_id)),
@@ -1071,7 +1071,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
rewrite_as_constants)); rewrite_as_constants));
} else { } else {
auto rewrite_as_constants = auto rewrite_as_constants =
[&](auto rewrite) -> SemIR::IdentifiedFacetType::Equivalent { [&](auto rewrite) -> IdentifiedFacetType::Equivalent {
return {context.constant_values().Get( return {context.constant_values().Get(
GetImplWitnessAccessWithoutSubstitution(context, GetImplWitnessAccessWithoutSubstitution(context,
rewrite.lhs_id)), rewrite.lhs_id)),
@@ -1111,14 +1111,14 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
DiagnoseIncompleteNamedConstraint(context, DiagnoseIncompleteNamedConstraint(context,
extends.named_constraint_id); extends.named_constraint_id);
} }
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf( auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(
context, loc_id, constraint.generic_id, context, loc_id, constraint.generic_id,
constraint.generic_with_self_id, extends.specific_id, self_const_id); constraint.generic_with_self_id, extends.specific_id, self_const_id);
if (context.specifics().HasError(constraint_with_self_specific_id)) { if (context.specifics().HasError(constraint_with_self_specific_id)) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
for (auto require_impls_id : llvm::reverse(require_impls_ids)) { for (auto require_impls_id : llvm::reverse(require_impls_ids)) {
@@ -1136,7 +1136,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
context.sem_ir(), require_specific_id, require.facet_type_inst_id); context.sem_ir(), require_specific_id, require.facet_type_inst_id);
if (require_self == SemIR::ErrorInst::ConstantId || if (require_self == SemIR::ErrorInst::ConstantId ||
require_facet_type == SemIR::ErrorInst::ConstantId) { require_facet_type == SemIR::ErrorInst::ConstantId) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto declared_facet_type_id = auto declared_facet_type_id =
@@ -1168,14 +1168,14 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
if (diagnose) { if (diagnose) {
DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id); DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id);
} }
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf( auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(
context, loc_id, constraint.generic_id, context, loc_id, constraint.generic_id,
constraint.generic_with_self_id, impls.specific_id, self_const_id); constraint.generic_with_self_id, impls.specific_id, self_const_id);
if (context.specifics().HasError(constraint_with_self_specific_id)) { if (context.specifics().HasError(constraint_with_self_specific_id)) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
for (auto require_impls_id : llvm::reverse(require_impls_ids)) { for (auto require_impls_id : llvm::reverse(require_impls_ids)) {
@@ -1193,7 +1193,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
context.sem_ir(), require_specific_id, require.facet_type_inst_id); context.sem_ir(), require_specific_id, require.facet_type_inst_id);
if (require_self == SemIR::ErrorInst::ConstantId || if (require_self == SemIR::ErrorInst::ConstantId ||
require_facet_type == SemIR::ErrorInst::ConstantId) { require_facet_type == SemIR::ErrorInst::ConstantId) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto declared_facet_type_id = auto declared_facet_type_id =
@@ -1226,7 +1226,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
if (diagnose) { if (diagnose) {
DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id); DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id);
} }
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf( auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(
@@ -1234,7 +1234,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
constraint.generic_with_self_id, impls.specific_id, constraint.generic_with_self_id, impls.specific_id,
context.constant_values().Get(self_type_inst_id)); context.constant_values().Get(self_type_inst_id));
if (context.specifics().HasError(constraint_with_self_specific_id)) { if (context.specifics().HasError(constraint_with_self_specific_id)) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
for (auto require_impls_id : llvm::reverse(require_impls_ids)) { for (auto require_impls_id : llvm::reverse(require_impls_ids)) {
@@ -1252,7 +1252,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id,
context.sem_ir(), require_specific_id, require.facet_type_inst_id); context.sem_ir(), require_specific_id, require.facet_type_inst_id);
if (require_self == SemIR::ErrorInst::ConstantId || if (require_self == SemIR::ErrorInst::ConstantId ||
require_facet_type == SemIR::ErrorInst::ConstantId) { require_facet_type == SemIR::ErrorInst::ConstantId) {
return SemIR::IdentifiedFacetTypeId::None; return IdentifiedFacetTypeId::None;
} }
auto declared_facet_type_id = auto declared_facet_type_id =
@@ -1272,7 +1272,7 @@ auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId self_const_id, SemIR::ConstantId self_const_id,
SemIR::TypeId facet_type_type_id, SemIR::TypeId facet_type_type_id,
bool allow_partially_identified) bool allow_partially_identified)
-> SemIR::IdentifiedFacetTypeId { -> IdentifiedFacetTypeId {
return IdentifyFacetType(context, loc_id, self_const_id, return IdentifyFacetType(context, loc_id, self_const_id,
facet_type_type_id.AsConstantId(), facet_type_type_id.AsConstantId(),
allow_partially_identified, allow_partially_identified,
@@ -1283,7 +1283,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId self_const_id, SemIR::ConstantId self_const_id,
SemIR::TypeId facet_type_type_id, SemIR::TypeId facet_type_type_id,
DiagnosticContextFn diagnostic_context, DiagnosticContextFn diagnostic_context,
bool diagnose) -> SemIR::IdentifiedFacetTypeId { bool diagnose) -> IdentifiedFacetTypeId {
CARBON_CHECK(diagnostic_context); CARBON_CHECK(diagnostic_context);
Diagnostics::ContextScope scope(&context.emitter(), diagnostic_context); Diagnostics::ContextScope scope(&context.emitter(), diagnostic_context);
return IdentifyFacetType(context, loc_id, self_const_id, return IdentifyFacetType(context, loc_id, self_const_id,
+2 -3
View File
@@ -79,7 +79,7 @@ auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId self_const_id, SemIR::ConstantId self_const_id,
SemIR::TypeId facet_type_type_id, SemIR::TypeId facet_type_type_id,
bool allow_partially_identified) bool allow_partially_identified)
-> SemIR::IdentifiedFacetTypeId; -> IdentifiedFacetTypeId;
// Requires the named constraints in the facet type to be complete, so that the // Requires the named constraints in the facet type to be complete, so that the
// set of interfaces the facet type requires is known. The `self_const_id` is a // set of interfaces the facet type requires is known. The `self_const_id` is a
@@ -107,8 +107,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId self_const_id, SemIR::ConstantId self_const_id,
SemIR::TypeId facet_type_type_id, SemIR::TypeId facet_type_type_id,
DiagnosticContextFn diagnostic_context, DiagnosticContextFn diagnostic_context,
bool diagnose = true) bool diagnose = true) -> IdentifiedFacetTypeId;
-> SemIR::IdentifiedFacetTypeId;
// Emits an error diagnostic explaining that a class is incomplete. // Emits an error diagnostic explaining that a class is incomplete.
// //
-2
View File
@@ -106,7 +106,6 @@ cc_library(
"file.cpp", "file.cpp",
"function.cpp", "function.cpp",
"generic.cpp", "generic.cpp",
"identified_facet_type.cpp",
"impl.cpp", "impl.cpp",
"import_ir.cpp", "import_ir.cpp",
"inst.cpp", "inst.cpp",
@@ -143,7 +142,6 @@ cc_library(
"file.h", "file.h",
"function.h", "function.h",
"generic.h", "generic.h",
"identified_facet_type.h",
"impl.h", "impl.h",
"import_cpp.h", "import_cpp.h",
"import_ir.h", "import_ir.h",
-5
View File
@@ -303,11 +303,6 @@ namespace Carbon {
template class CanonicalValueStore<SemIR::DeclaredFacetTypeId, template class CanonicalValueStore<SemIR::DeclaredFacetTypeId,
SemIR::DeclaredFacetType, SemIR::DeclaredFacetType,
Tag<SemIR::CheckIRId>>; Tag<SemIR::CheckIRId>>;
template class CanonicalValueStore<
SemIR::IdentifiedFacetTypeId, SemIR::IdentifiedFacetTypeKey,
Tag<SemIR::CheckIRId>, SemIR::IdentifiedFacetType>;
template class ValueStore<SemIR::DeclaredFacetTypeId, SemIR::DeclaredFacetType, template class ValueStore<SemIR::DeclaredFacetTypeId, SemIR::DeclaredFacetType,
Tag<SemIR::CheckIRId>>; Tag<SemIR::CheckIRId>>;
template class ValueStore<SemIR::IdentifiedFacetTypeId,
SemIR::IdentifiedFacetType, Tag<SemIR::CheckIRId>>;
} // namespace Carbon } // namespace Carbon
+13 -51
View File
@@ -22,7 +22,7 @@ LLVM_DUMP_METHOD auto Dump(const File& file) -> std::string {
return PrintToString(file); return PrintToString(file);
} }
static auto DumpNameIfValid(const File& file, NameId name_id) -> std::string { auto DumpNameIfValid(const File& file, NameId name_id) -> std::string {
RawStringOstream out; RawStringOstream out;
if (name_id.has_value()) { if (name_id.has_value()) {
out << " `" << file.names().GetFormatted(name_id) << "`"; out << " `" << file.names().GetFormatted(name_id) << "`";
@@ -30,8 +30,8 @@ static auto DumpNameIfValid(const File& file, NameId name_id) -> std::string {
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpNameOfEntityName(const File& file, auto DumpNameOfEntityName(const File& file, const EntityName& entity_name)
const EntityName& entity_name) -> std::string { -> std::string {
RawStringOstream out; RawStringOstream out;
out << " `"; out << " `";
out << file.names().GetFormatted(entity_name.name_id); out << file.names().GetFormatted(entity_name.name_id);
@@ -42,7 +42,7 @@ static auto DumpNameOfEntityName(const File& file,
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpLocSummary(const File& file, LocId loc_id) -> std::string { auto DumpLocSummary(const File& file, LocId loc_id) -> std::string {
RawStringOstream out; RawStringOstream out;
// TODO: If the canonical location is None but the original is an InstId, // TODO: If the canonical location is None but the original is an InstId,
// should we dump the InstId anyway even though it has no location? Is that // should we dump the InstId anyway even though it has no location? Is that
@@ -84,8 +84,7 @@ static auto DumpLocSummary(const File& file, LocId loc_id) -> std::string {
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpConstantSummary(const File& file, ConstantId const_id) auto DumpConstantSummary(const File& file, ConstantId const_id) -> std::string {
-> std::string {
RawStringOstream out; RawStringOstream out;
out << const_id; out << const_id;
if (!const_id.has_value()) { if (!const_id.has_value()) {
@@ -101,7 +100,7 @@ static auto DumpConstantSummary(const File& file, ConstantId const_id)
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpTypeSummary(const File& file, TypeId type_id) -> std::string { auto DumpTypeSummary(const File& file, TypeId type_id) -> std::string {
RawStringOstream out; RawStringOstream out;
out << type_id; out << type_id;
if (!type_id.has_value()) { if (!type_id.has_value()) {
@@ -124,7 +123,7 @@ static auto DumpTypeSummary(const File& file, TypeId type_id) -> std::string {
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpInstSummary(const File& file, InstId inst_id) -> std::string { auto DumpInstSummary(const File& file, InstId inst_id) -> std::string {
RawStringOstream out; RawStringOstream out;
out << inst_id; out << inst_id;
if (inst_id.has_value() && inst_id != InstId::InitTombstone && if (inst_id.has_value() && inst_id != InstId::InitTombstone &&
@@ -134,8 +133,7 @@ static auto DumpInstSummary(const File& file, InstId inst_id) -> std::string {
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpGenericSummary(const File& file, GenericId generic_id) auto DumpGenericSummary(const File& file, GenericId generic_id) -> std::string {
-> std::string {
RawStringOstream out; RawStringOstream out;
out << generic_id; out << generic_id;
if (!generic_id.has_value()) { if (!generic_id.has_value()) {
@@ -147,7 +145,7 @@ static auto DumpGenericSummary(const File& file, GenericId generic_id)
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpInterfaceSummary(const File& file, InterfaceId interface_id) auto DumpInterfaceSummary(const File& file, InterfaceId interface_id)
-> std::string { -> std::string {
RawStringOstream out; RawStringOstream out;
out << interface_id; out << interface_id;
@@ -158,8 +156,8 @@ static auto DumpInterfaceSummary(const File& file, InterfaceId interface_id)
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpNamedConstraintSummary(const File& file, auto DumpNamedConstraintSummary(const File& file,
NamedConstraintId named_constraint_id) NamedConstraintId named_constraint_id)
-> std::string { -> std::string {
RawStringOstream out; RawStringOstream out;
out << named_constraint_id; out << named_constraint_id;
@@ -170,7 +168,7 @@ static auto DumpNamedConstraintSummary(const File& file,
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpSpecificSummary(const File& file, SpecificId specific_id) auto DumpSpecificSummary(const File& file, SpecificId specific_id)
-> std::string { -> std::string {
RawStringOstream out; RawStringOstream out;
out << specific_id; out << specific_id;
@@ -180,8 +178,7 @@ static auto DumpSpecificSummary(const File& file, SpecificId specific_id)
return out.TakeStr(); return out.TakeStr();
} }
static auto DumpRequireImplsSummary(const File& file, auto DumpRequireImplsSummary(const File& file, RequireImplsId require_impls_id)
RequireImplsId require_impls_id)
-> std::string { -> std::string {
RawStringOstream out; RawStringOstream out;
out << require_impls_id; out << require_impls_id;
@@ -380,37 +377,6 @@ LLVM_DUMP_METHOD auto Dump(const File& file, GenericId generic_id)
return out.TakeStr(); return out.TakeStr();
} }
LLVM_DUMP_METHOD auto Dump(const File& file,
IdentifiedFacetTypeId identified_facet_type_id)
-> std::string {
RawStringOstream out;
out << identified_facet_type_id;
if (!identified_facet_type_id.has_value()) {
return out.TakeStr();
}
const auto& identified_facet_type =
file.identified_facet_types().Get(identified_facet_type_id);
for (auto [i, req_impl] :
llvm::enumerate(identified_facet_type.required_impls())) {
auto [self, req_interface] = req_impl;
out << "\n - self: " << DumpConstantSummary(file, self);
out << "\n impls: "
<< DumpInterfaceSummary(file, req_interface.interface_id);
if (req_interface.specific_id.has_value()) {
out << "; " << DumpSpecificSummary(file, req_interface.specific_id);
}
if (req_interface == identified_facet_type.impl_as_target_interface()) {
out << "\n - `impl as` target";
}
}
if (!identified_facet_type.is_valid_impl_as_target()) {
out << "\n - " << identified_facet_type.num_interfaces_to_impl()
<< " possible `impl as` targets";
}
return out.TakeStr();
}
LLVM_DUMP_METHOD auto Dump(const File& file, ImplId impl_id) -> std::string { LLVM_DUMP_METHOD auto Dump(const File& file, ImplId impl_id) -> std::string {
RawStringOstream out; RawStringOstream out;
out << impl_id; out << impl_id;
@@ -725,10 +691,6 @@ LLVM_DUMP_METHOD static auto MakeNameId(int id) -> NameId { return NameId(id); }
LLVM_DUMP_METHOD static auto MakeNameScopeId(int id) -> NameScopeId { LLVM_DUMP_METHOD static auto MakeNameScopeId(int id) -> NameScopeId {
return NameScopeId(id); return NameScopeId(id);
} }
LLVM_DUMP_METHOD static auto MakeIdentifiedFacetTypeId(int id)
-> IdentifiedFacetTypeId {
return IdentifiedFacetTypeId(id);
}
LLVM_DUMP_METHOD static auto MakeImportIRInstId(int id) -> ImportIRInstId { LLVM_DUMP_METHOD static auto MakeImportIRInstId(int id) -> ImportIRInstId {
return ImportIRInstId(id); return ImportIRInstId(id);
} }
+18 -2
View File
@@ -29,6 +29,24 @@
namespace Carbon::SemIR { namespace Carbon::SemIR {
auto DumpNameIfValid(const File& file, NameId name_id) -> std::string;
auto DumpNameOfEntityName(const File& file, const EntityName& entity_name)
-> std::string;
auto DumpLocSummary(const File& file, LocId loc_id) -> std::string;
auto DumpConstantSummary(const File& file, ConstantId const_id) -> std::string;
auto DumpTypeSummary(const File& file, TypeId type_id) -> std::string;
auto DumpInstSummary(const File& file, InstId inst_id) -> std::string;
auto DumpGenericSummary(const File& file, GenericId generic_id) -> std::string;
auto DumpInterfaceSummary(const File& file, InterfaceId interface_id)
-> std::string;
auto DumpNamedConstraintSummary(const File& file,
NamedConstraintId named_constraint_id)
-> std::string;
auto DumpSpecificSummary(const File& file, SpecificId specific_id)
-> std::string;
auto DumpRequireImplsSummary(const File& file, RequireImplsId require_impls_id)
-> std::string;
auto Dump(const File& file) -> std::string; auto Dump(const File& file) -> std::string;
auto Dump(const File& file, RawBundleId bundle_id) -> std::string; auto Dump(const File& file, RawBundleId bundle_id) -> std::string;
auto Dump(const File& file, GeneratedFunctionId generated_function_id) auto Dump(const File& file, GeneratedFunctionId generated_function_id)
@@ -45,8 +63,6 @@ auto Dump(const File& file, EntityNameId entity_name_id) -> std::string;
auto Dump(const File& file, FieldId field_id) -> std::string; auto Dump(const File& file, FieldId field_id) -> std::string;
auto Dump(const File& file, FunctionId function_id) -> std::string; auto Dump(const File& file, FunctionId function_id) -> std::string;
auto Dump(const File& file, GenericId generic_id) -> std::string; auto Dump(const File& file, GenericId generic_id) -> std::string;
auto Dump(const File& file, IdentifiedFacetTypeId identified_facet_type_id)
-> std::string;
auto Dump(const File& file, ImplId impl_id) -> std::string; auto Dump(const File& file, ImplId impl_id) -> std::string;
auto Dump(const File& file, ImportIRInstId import_inst_id) -> std::string; auto Dump(const File& file, ImportIRInstId import_inst_id) -> std::string;
auto Dump(const File& file, const Inst& inst) -> std::string; auto Dump(const File& file, const Inst& inst) -> std::string;
-1
View File
@@ -59,7 +59,6 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id,
associated_constants_(check_ir_id), associated_constants_(check_ir_id),
// 1 reserved id for `DeclaredFacetTypeId::Empty`. // 1 reserved id for `DeclaredFacetTypeId::Empty`.
declared_facet_types_(check_ir_id, 1), declared_facet_types_(check_ir_id, 1),
identified_facet_types_(check_ir_id),
impls_(*this), impls_(*this),
specific_interfaces_(check_ir_id), specific_interfaces_(check_ir_id),
generics_(check_ir_id), generics_(check_ir_id),
-10
View File
@@ -29,7 +29,6 @@
#include "toolchain/sem_ir/field.h" #include "toolchain/sem_ir/field.h"
#include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/function.h"
#include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/generic.h"
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/impl.h" #include "toolchain/sem_ir/impl.h"
#include "toolchain/sem_ir/import_cpp.h" #include "toolchain/sem_ir/import_cpp.h"
@@ -241,12 +240,6 @@ class File : public Printable<File> {
auto AppendCppMangledTypeName(ClassId class_id, llvm::raw_ostream& out) const auto AppendCppMangledTypeName(ClassId class_id, llvm::raw_ostream& out) const
-> bool; -> bool;
auto identified_facet_types() -> IdentifiedFacetTypeStore& {
return identified_facet_types_;
}
auto identified_facet_types() const -> const IdentifiedFacetTypeStore& {
return identified_facet_types_;
}
auto impls() -> ImplStore& { return impls_; } auto impls() -> ImplStore& { return impls_; }
auto impls() const -> const ImplStore& { return impls_; } auto impls() const -> const ImplStore& { return impls_; }
auto specific_interfaces() -> SpecificInterfaceStore& { auto specific_interfaces() -> SpecificInterfaceStore& {
@@ -429,9 +422,6 @@ class File : public Printable<File> {
// Storage for declared facet types. // Storage for declared facet types.
DeclaredFacetTypeStore declared_facet_types_; DeclaredFacetTypeStore declared_facet_types_;
// Storage for identified facet types.
IdentifiedFacetTypeStore identified_facet_types_;
// Storage for impls. // Storage for impls.
ImplStore impls_; ImplStore impls_;
-152
View File
@@ -1,152 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/sem_ir/identified_facet_type.h"
#include "toolchain/base/canonical_value_store_impl.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/base/value_store_impl.h"
#include "toolchain/sem_ir/file.h"
namespace Carbon::SemIR {
template <typename T>
using LessThanFn = llvm::function_ref<auto(const T&, const T&)->bool>;
template <typename VecT>
static auto SortAndDeduplicate(VecT& vec,
LessThanFn<typename VecT::value_type> compare)
-> void {
llvm::sort(vec, compare);
vec.erase(llvm::unique(vec), vec.end());
}
// Canonically ordered by the numerical ids. Matches the order of RequiredLess
// when the `self_facet_value` is the same for all interfaces.
static auto InterfaceLess(const SpecificInterface& lhs,
const SpecificInterface& rhs) -> bool {
return std::tie(lhs.interface_id.index, lhs.specific_id.index) <
std::tie(rhs.interface_id.index, rhs.specific_id.index);
}
// Canonically ordered by the numerical ids.
static auto RequiredLess(const IdentifiedFacetType::RequiredImpl& lhs,
const IdentifiedFacetType::RequiredImpl& rhs) -> bool {
return std::tie(lhs.self_facet_value.index,
lhs.specific_interface.interface_id.index,
lhs.specific_interface.specific_id.index) <
std::tie(rhs.self_facet_value.index,
rhs.specific_interface.interface_id.index,
rhs.specific_interface.specific_id.index);
}
// Canonically ordered by the numerical ids.
static auto RewriteLess(const IdentifiedFacetType::Rewrite& lhs,
const IdentifiedFacetType::Rewrite& rhs) -> bool {
return std::tie(lhs.lhs.index, lhs.rhs.index) <
std::tie(rhs.lhs.index, rhs.rhs.index);
}
// Canonically ordered by the numerical ids.
static auto EquivalentLess(const IdentifiedFacetType::Equivalent& lhs,
const IdentifiedFacetType::Equivalent& rhs) -> bool {
return std::tie(lhs.lhs.index, lhs.rhs.index) <
std::tie(rhs.lhs.index, rhs.rhs.index);
}
IdentifiedFacetType::IdentifiedFacetType(
IdentifiedFacetTypeKey key, bool partially_identified,
llvm::ArrayRef<RequiredImpl> extends,
llvm::ArrayRef<RequiredImpl> self_impls, llvm::ArrayRef<Rewrite> rewrites,
llvm::ArrayRef<Equivalent> equivalents)
: key_(key) {
required_impls_.reserve(extends.size() + self_impls.size());
llvm::append_range(required_impls_, extends);
SortAndDeduplicate(required_impls_, RequiredLess);
// If there's a single extended interface then we present as that interface.
// Otherwise, we record the number extended interfaces.
if (required_impls_.size() == 1) {
interface_id_ = required_impls_.front().specific_interface.interface_id;
specific_id_ = required_impls_.front().specific_interface.specific_id;
} else {
interface_id_ = InterfaceId::None;
num_interface_to_impl_ = required_impls_.size();
}
llvm::append_range(required_impls_, self_impls);
SortAndDeduplicate(required_impls_, RequiredLess);
SortAndDeduplicate(required_impls_, RequiredLess);
if (partially_identified) {
// This marks the IdentifiedFacetType as being partially identified, and
// prevents the key from colliding with a fully identified facet type, or
// with other partially (but differently) identified facet types, with the
// same constituents but a more complete set of required interfaces.
key_.num_require_impls = required_impls_.size();
}
rewrites_.assign(rewrites);
SortAndDeduplicate(rewrites_, RewriteLess);
equivalents_.assign(equivalents);
SortAndDeduplicate(equivalents_, EquivalentLess);
}
auto AddCanonicalWitnessesBlock(File& sem_ir,
llvm::SmallVector<InstId>& witnesses)
-> InstBlockId {
// Small blocks don't need to be sorted.
if (witnesses.size() <= 1) {
return sem_ir.inst_blocks().AddCanonical(witnesses);
}
llvm::SmallVector<std::pair<SpecificInterface, InstId>> sortable;
sortable.reserve(witnesses.size());
// Produce the sorted order based on the witness's SpecificInterface.
for (auto witness_id : witnesses) {
auto inst = sem_ir.insts().Get(witness_id);
CARBON_KIND_SWITCH(inst) {
case CARBON_KIND(CustomWitness witness): {
sortable.push_back({sem_ir.specific_interfaces().Get(
witness.query_specific_interface_id),
witness_id});
break;
}
case CARBON_KIND(ImplWitness witness): {
auto table =
sem_ir.insts().GetAs<ImplWitnessTable>(witness.witness_table_id);
sortable.push_back(
{sem_ir.impls().Get(table.impl_id).interface, witness_id});
break;
}
case CARBON_KIND(LookupImplWitness witness): {
sortable.push_back({sem_ir.specific_interfaces().Get(
witness.query_specific_interface_id),
witness_id});
break;
}
default:
CARBON_FATAL("Unhandled inst: {0}", inst);
}
}
// This matches the sort order of IdentifiedFacetType::required_interfaces,
// which is the order of the witnesses returned from impl lookup, and is
// canonical order in which the witnesses must appear for a given facet type
// so that ImplWitnessAccess can find the appropriate witness.
llvm::sort(sortable, [](auto& lhs, auto& rhs) {
return InterfaceLess(lhs.first, rhs.first);
});
// Update the original list with the new order (reusing to avoid an
// allocation).
for (auto [witness_id, sortable_entry] :
llvm::zip_equal(witnesses, sortable)) {
witness_id = sortable_entry.second;
}
return sem_ir.inst_blocks().AddCanonical(witnesses);
}
} // namespace Carbon::SemIR
-7
View File
@@ -378,13 +378,6 @@ struct DeclaredFacetTypeId : public IdBase<DeclaredFacetTypeId> {
inline constexpr DeclaredFacetTypeId DeclaredFacetTypeId::Empty = inline constexpr DeclaredFacetTypeId DeclaredFacetTypeId::Empty =
DeclaredFacetTypeId(0); DeclaredFacetTypeId(0);
// The ID of an resolved facet type value.
struct IdentifiedFacetTypeId : public IdBase<IdentifiedFacetTypeId> {
static constexpr llvm::StringLiteral Label = "identified_facet_type";
using IdBase::IdBase;
};
// The ID of an `Impl`. // The ID of an `Impl`.
struct ImplId : public IdBase<ImplId> { struct ImplId : public IdBase<ImplId> {
using DiagnosticType = Diagnostics::TypeInfo<std::string>; using DiagnosticType = Diagnostics::TypeInfo<std::string>;