mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-11-10 12:28:25 +00:00
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:
1 parent
0546b48a7d
commit
fb7eff130d
28 files changed
+618
-607
No files matched your search
+1
-1
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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_
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
+91
-26
@@ -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_
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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>;
|
||||||
|
|||||||
Reference in new issue
Block a user