From fb7eff130db358269913e1003ae39d259d3d1f55 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 21 Oct 2026 13:20:54 +0000 Subject: [PATCH] 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. --- scripts/lldbinit.py | 2 +- toolchain/check/BUILD | 2 + toolchain/check/context.cpp | 3 +- toolchain/check/context.h | 15 +- toolchain/check/dump.cpp | 37 +- toolchain/check/eval_inst.cpp | 1 + toolchain/check/facet_type.cpp | 229 ---------- toolchain/check/facet_type.h | 56 --- toolchain/check/handle_impl.cpp | 3 +- toolchain/check/handle_require.cpp | 4 +- toolchain/check/handle_where.cpp | 1 + toolchain/check/identified_facet_type.cpp | 391 ++++++++++++++++++ .../{sem_ir => check}/identified_facet_type.h | 117 ++++-- toolchain/check/impl.cpp | 13 +- toolchain/check/impl.h | 7 +- toolchain/check/impl_lookup.cpp | 20 +- toolchain/check/impl_lookup.h | 2 +- toolchain/check/import_ref.cpp | 4 +- toolchain/check/type_completion.cpp | 52 +-- toolchain/check/type_completion.h | 5 +- toolchain/sem_ir/BUILD | 2 - toolchain/sem_ir/declared_facet_type.cpp | 5 - toolchain/sem_ir/dump.cpp | 64 +-- toolchain/sem_ir/dump.h | 20 +- toolchain/sem_ir/file.cpp | 1 - toolchain/sem_ir/file.h | 10 - toolchain/sem_ir/identified_facet_type.cpp | 152 ------- toolchain/sem_ir/ids.h | 7 - 28 files changed, 618 insertions(+), 607 deletions(-) create mode 100644 toolchain/check/identified_facet_type.cpp rename toolchain/{sem_ir => check}/identified_facet_type.h (54%) delete mode 100644 toolchain/sem_ir/identified_facet_type.cpp diff --git a/scripts/lldbinit.py b/scripts/lldbinit.py index 25db83329faa..1ea2bb9a7fdf 100644 --- a/scripts/lldbinit.py +++ b/scripts/lldbinit.py @@ -97,7 +97,7 @@ Example usage: "function": "SemIR::MakeFunctionId", "generated_function": "SemIR::MakeGeneratedFunctionId", "generic": "SemIR::MakeGenericId", - "identified_facet_type": "SemIR::MakeIdentifiedFacetTypeId", + "identified_facet_type": "Check::MakeIdentifiedFacetTypeId", "impl": "SemIR::MakeImplId", "inst": "SemIR::MakeInstId", "inst_block": "SemIR::MakeInstBlockId", diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index eb6c141647a4..901d3dabd10c 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -48,6 +48,7 @@ cc_library( "function.cpp", "generic.cpp", "global_init.cpp", + "identified_facet_type.cpp", "impl.cpp", "impl_lookup.cpp", "impl_validation.cpp", @@ -116,6 +117,7 @@ cc_library( "function.h", "generic.h", "global_init.h", + "identified_facet_type.h", "impl.h", "impl_lookup.h", "impl_validation.h", diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 856377f6dd03..3f5454a9025d 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -40,7 +40,8 @@ Context::Context(DiagnosticEmitterBase* emitter, TODO(loc_id, label); }), 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. import_irs().Reserve(imported_ir_count); import_ir_constant_values_.reserve(imported_ir_count); diff --git a/toolchain/check/context.h b/toolchain/check/context.h index d81eb46143a9..913112cf1f47 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -21,6 +21,7 @@ #include "toolchain/check/full_pattern_stack.h" #include "toolchain/check/generic_region_stack.h" #include "toolchain/check/global_init.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/inst_block_stack.h" #include "toolchain/check/node_stack.h" #include "toolchain/check/param_and_arg_refs_stack.h" @@ -33,7 +34,6 @@ #include "toolchain/parse/tree_and_subtrees.h" #include "toolchain/sem_ir/declared_facet_type.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/import_ir.h" #include "toolchain/sem_ir/inst.h" @@ -367,6 +367,13 @@ class 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. // -------------------------------------------------------------------------- @@ -414,9 +421,6 @@ class Context { auto declared_facet_types() -> SemIR::DeclaredFacetTypeStore& { 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 specific_interfaces() -> SemIR::SpecificInterfaceStore& { return sem_ir().specific_interfaces(); @@ -671,6 +675,9 @@ class Context { // This is updated by `DeclNameStack`. During monomorphization, it is updated // by `TryEvalBlockForSpecific`. SemIR::NameScopeId access_context_ = SemIR::NameScopeId::None; + + // Storage for identified facet types. + IdentifiedFacetTypeStore identified_facet_types_; }; inline constexpr Context::FormExpr Context::FormExpr::Error = { diff --git a/toolchain/check/dump.cpp b/toolchain/check/dump.cpp index 21b8742e8a9f..def9afbad8b7 100644 --- a/toolchain/check/dump.cpp +++ b/toolchain/check/dump.cpp @@ -100,9 +100,35 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context, } LLVM_DUMP_METHOD static auto Dump( - const Context& context, - SemIR::IdentifiedFacetTypeId identified_facet_type_id) -> std::string { - return SemIR::Dump(context.sem_ir(), identified_facet_type_id); + const Context& context, 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 = + 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) @@ -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); } +LLVM_DUMP_METHOD static auto MakeIdentifiedFacetTypeId(int id) + -> IdentifiedFacetTypeId { + return IdentifiedFacetTypeId(id); +} + } // namespace Carbon::Check #endif // NDEBUG diff --git a/toolchain/check/eval_inst.cpp b/toolchain/check/eval_inst.cpp index a6069468133c..adc8e580026c 100644 --- a/toolchain/check/eval_inst.cpp +++ b/toolchain/check/eval_inst.cpp @@ -14,6 +14,7 @@ #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/impl_lookup.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/inst.h" diff --git a/toolchain/check/facet_type.cpp b/toolchain/check/facet_type.cpp index bb573f3c919b..f1b6fb86fb0b 100644 --- a/toolchain/check/facet_type.cpp +++ b/toolchain/check/facet_type.cpp @@ -4,9 +4,7 @@ #include "toolchain/check/facet_type.h" -#include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" -#include "toolchain/check/generic.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/inst.h" #include "toolchain/check/interface.h" @@ -541,231 +539,4 @@ auto FindWhere(Context& context, SemIR::ConstantId const_id) -> bool { 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( - orig_inst_id)) { - return SubstIdentifiedWitness(*witness); - } - if (auto witness = - context().insts().TryGetAs(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()) { - return SubstIdentifiedWitness(*witness); - } - if (auto witness = new_inst.TryAs()) { - 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(replaced_id)); - return replaced_id; - } - } - - auto const_id = EvalOrAddInst( - 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(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 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 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 diff --git a/toolchain/check/facet_type.h b/toolchain/check/facet_type.h index 016c64abf6dc..65037e3cc542 100644 --- a/toolchain/check/facet_type.h +++ b/toolchain/check/facet_type.h @@ -6,7 +6,6 @@ #define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_ #include "toolchain/check/context.h" -#include "toolchain/sem_ir/identified_facet_type.h" #include "toolchain/sem_ir/ids.h" namespace Carbon::Check { @@ -75,61 +74,6 @@ auto GetConstantFacetValueForTypeAndInterface( // type with an arbitrary facet type (including a `where` expression). 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 #endif // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_ diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 34e6bed16681..8b619386c81a 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -12,6 +12,7 @@ #include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/impl.h" #include "toolchain/check/inst.h" #include "toolchain/check/modifiers.h" @@ -209,7 +210,7 @@ struct BuildImplDeclResult { SemIR::ImplId impl_id; SemIR::InstId impl_decl_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 diff --git a/toolchain/check/handle_require.cpp b/toolchain/check/handle_require.cpp index d777961fc07a..6d93bd19ff8c 100644 --- a/toolchain/check/handle_require.cpp +++ b/toolchain/check/handle_require.cpp @@ -106,7 +106,7 @@ auto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id) static auto TypeStructureReferencesSelf( 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 { while (true) { auto step = type_iter.Next(); @@ -173,7 +173,7 @@ static auto TypeStructureReferencesSelf( } 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 diff --git a/toolchain/check/handle_where.cpp b/toolchain/check/handle_where.cpp index 7868f3d49d77..eca1aa6df576 100644 --- a/toolchain/check/handle_where.cpp +++ b/toolchain/check/handle_where.cpp @@ -8,6 +8,7 @@ #include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/inst.h" #include "toolchain/check/period_self.h" #include "toolchain/check/subst.h" diff --git a/toolchain/check/identified_facet_type.cpp b/toolchain/check/identified_facet_type.cpp new file mode 100644 index 000000000000..0eafa1e2de77 --- /dev/null +++ b/toolchain/check/identified_facet_type.cpp @@ -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 +using LessThanFn = llvm::function_refbool>; + +template +static auto SortAndDeduplicate(VecT& vec, + LessThanFn 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 extends, + llvm::ArrayRef self_impls, llvm::ArrayRef rewrites, + llvm::ArrayRef 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& witnesses) + -> SemIR::InstBlockId { + // Small blocks don't need to be sorted. + if (witnesses.size() <= 1) { + return context.inst_blocks().AddCanonical(witnesses); + } + + llvm::SmallVector> + 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( + 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( + orig_inst_id)) { + return SubstIdentifiedWitness(*witness); + } + if (auto witness = + context().insts().TryGetAs(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()) { + return SubstIdentifiedWitness(*witness); + } + if (auto witness = new_inst.TryAs()) { + 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(replaced_id)); + return replaced_id; + } + } + + auto const_id = EvalOrAddInst( + 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(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 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 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, Check::IdentifiedFacetType>; +template class ValueStore>; +} // namespace Carbon diff --git a/toolchain/sem_ir/identified_facet_type.h b/toolchain/check/identified_facet_type.h similarity index 54% rename from toolchain/sem_ir/identified_facet_type.h rename to toolchain/check/identified_facet_type.h index 7f739053807d..7aeee27b0fd6 100644 --- a/toolchain/sem_ir/identified_facet_type.h +++ b/toolchain/check/identified_facet_type.h @@ -2,22 +2,32 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ -#define CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ +#ifndef CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_ +#define CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_ #include "llvm/ADT/SmallVector.h" #include "toolchain/base/canonical_value_store.h" #include "toolchain/sem_ir/declared_facet_type.h" #include "toolchain/sem_ir/ids.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 { + static constexpr llvm::StringLiteral Label = "identified_facet_type"; + + using IdBase::IdBase; +}; + +class Context; struct IdentifiedFacetTypeKey { - DeclaredFacetTypeId declared_facet_type_id; - ConstantId self_const_id; + SemIR::DeclaredFacetTypeId declared_facet_type_id; + SemIR::ConstantId self_const_id; // 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. // Uses -1 for identifying a facet type with a self-type from outside the @@ -36,22 +46,22 @@ struct IdentifiedFacetTypeKey { struct IdentifiedFacetType { // A requirement that `self_facet_value` implements the `specific_interface`. struct RequiredImpl { - ConstantId self_facet_value; - SpecificInterface specific_interface; + SemIR::ConstantId self_facet_value; + SemIR::SpecificInterface specific_interface; friend auto operator==(const RequiredImpl& lhs, const RequiredImpl& rhs) -> bool = default; }; struct Rewrite { - ConstantId lhs; - ConstantId rhs; + SemIR::ConstantId lhs; + SemIR::ConstantId rhs; friend auto operator==(const Rewrite& lhs, const Rewrite& rhs) -> bool = default; }; struct Equivalent { - ConstantId lhs; - ConstantId rhs; + SemIR::ConstantId lhs; + SemIR::ConstantId rhs; friend auto operator==(const Equivalent& lhs, const Equivalent& rhs) -> bool = default; @@ -80,11 +90,11 @@ struct IdentifiedFacetType { // The interface to implement when this facet type is used in an `impl` // declaration. - auto impl_as_target_interface() const -> SpecificInterface { + auto impl_as_target_interface() const -> SemIR::SpecificInterface { if (is_valid_impl_as_target()) { return {.interface_id = interface_id_, .specific_id = specific_id_}; } 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 facet type to the right of an `impl`...`as`, or `None` if no such // single interface. - InterfaceId interface_id_ = InterfaceId::None; + SemIR::InterfaceId interface_id_ = SemIR::InterfaceId::None; union { // If `interface_id` is `None`, the number of interfaces to report in a // diagnostic about why this facet type can't be implemented. int num_interface_to_impl_ = 0; // If `interface_id` is not `None`, the specific for that interface. - SpecificId specific_id_; + SemIR::SpecificId specific_id_; }; }; using IdentifiedFacetTypeStore = CanonicalValueStore, IdentifiedFacetType>; + Tag, IdentifiedFacetType>; // 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 // the canonical witness order, and returns the resulting block ID. This assumes // witnesses have already been deduplicated, and do not contain errors, because // it's mainly for imports. -auto AddCanonicalWitnessesBlock(File& sem_ir, - llvm::SmallVector& witnesses) - -> InstBlockId; +auto AddCanonicalWitnessesBlock(Context& context, + llvm::SmallVector& witnesses) + -> 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 { extern template class CanonicalValueStore< - SemIR::IdentifiedFacetTypeId, SemIR::IdentifiedFacetTypeKey, - Tag, SemIR::IdentifiedFacetType>; -extern template class ValueStore, Check::IdentifiedFacetType>; +extern template class ValueStore>; } // namespace Carbon -#endif // CARBON_TOOLCHAIN_SEM_IR_IDENTIFIED_FACET_TYPE_H_ +#endif // CARBON_TOOLCHAIN_CHECK_IDENTIFIED_FACET_TYPE_H_ diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index fa3812985ddc..f057c55b2a3b 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -12,6 +12,7 @@ #include "toolchain/check/facet_type.h" #include "toolchain/check/function.h" #include "toolchain/check/generic.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/impl_lookup.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/inst.h" @@ -27,7 +28,6 @@ #include "toolchain/check/type_structure.h" #include "toolchain/diagnostics/emitter.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/impl.h" #include "toolchain/sem_ir/inst.h" @@ -442,7 +442,7 @@ class SubstWithImplWitness : public SubstIdentifiedWitnessesCallbacks { auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id, SemIR::LocId constraint_loc_id, const SemIR::Impl& impl, - SemIR::IdentifiedFacetTypeId identified_id, + IdentifiedFacetTypeId identified_id, SemIR::SpecificId self_specific_id) -> SemIR::InstId { 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, SemIR::Impl& impl, SemIR::TypeInstId full_constraint_id, - SemIR::IdentifiedFacetTypeId identified_id) - -> void { + IdentifiedFacetTypeId identified_id) -> void { if (impl.witness_id == SemIR::ErrorInst::InstId) { return; } @@ -1011,7 +1010,7 @@ auto CheckConstraintIsFacetType(Context& context, SemIR::LocId loc_id, auto CheckConstraintIsInterface(Context& context, SemIR::LocId loc_id, SemIR::InstId self_id, SemIR::TypeInstId full_constraint_id) - -> SemIR::IdentifiedFacetTypeId { + -> IdentifiedFacetTypeId { auto identified_id = RequireIdentifiedFacetType( context, SemIR::LocId(full_constraint_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); }); if (!identified_id.has_value()) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } const auto& identified = context.identified_facet_types().Get(identified_id); 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); context.emitter().Emit(loc_id, ImplOfNotOneInterface, identified.num_interfaces_to_impl()); - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } return identified_id; } diff --git a/toolchain/check/impl.h b/toolchain/check/impl.h index 4bfce5a9c776..2b5789571e29 100644 --- a/toolchain/check/impl.h +++ b/toolchain/check/impl.h @@ -54,7 +54,7 @@ auto AddImpl(Context& context, const SemIR::Impl& impl, auto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id, SemIR::LocId constraint_loc_id, const SemIR::Impl& impl, - SemIR::IdentifiedFacetTypeId identified_id, + IdentifiedFacetTypeId identified_id, SemIR::SpecificId self_specific_id) -> SemIR::InstId; @@ -70,8 +70,7 @@ auto FinishImplWitness(Context& context, const SemIR::Impl& impl_id) -> void; auto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id, SemIR::Impl& impl, SemIR::TypeInstId full_constraint_id, - SemIR::IdentifiedFacetTypeId identified_id) - -> void; + IdentifiedFacetTypeId identified_id) -> void; // Sets all unset members of the witness for `impl` to the error instruction and // 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, SemIR::InstId self_id, SemIR::TypeInstId full_constraint_id) - -> SemIR::IdentifiedFacetTypeId; + -> IdentifiedFacetTypeId; // Given a specific for the impl, returns the specific interface that the impl // declaration is implementing. Returns None in the case of an error being diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index 0405ec6942f2..dbc52e278010 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -16,8 +16,8 @@ #include "toolchain/check/deduce.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/eval.h" -#include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/impl.h" #include "toolchain/check/import_ref.h" #include "toolchain/check/inst.h" @@ -27,7 +27,6 @@ #include "toolchain/check/type_completion.h" #include "toolchain/check/type_structure.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/impl.h" #include "toolchain/sem_ir/inst.h" @@ -307,10 +306,9 @@ static auto TryGetSpecificWitnessIdForImpl( impl.witness_id); } -static auto ThawPeriodSelfInRequiredImpl( - Context& context, SemIR::LocId loc_id, - SemIR::IdentifiedFacetType::RequiredImpl req) - -> SemIR::IdentifiedFacetType::RequiredImpl { +static auto ThawPeriodSelfInRequiredImpl(Context& context, SemIR::LocId loc_id, + IdentifiedFacetType::RequiredImpl req) + -> IdentifiedFacetType::RequiredImpl { auto self_inst_id = context.constant_values().GetInstId(req.self_facet_value); self_inst_id = ThawPeriodSelf(context, self_inst_id); req.self_facet_value = context.constant_values().Get(self_inst_id); @@ -528,7 +526,7 @@ class SubstMatchingWitnessesFromImplLookup public: explicit SubstMatchingWitnessesFromImplLookup( Context* context, - llvm::ArrayRef req_impls, + llvm::ArrayRef req_impls, llvm::ArrayRef found_witness_inst_ids) : SubstIdentifiedWitnessesCallbacks(context), req_impls_(req_impls), @@ -556,7 +554,7 @@ class SubstMatchingWitnessesFromImplLookup } private: - llvm::ArrayRef req_impls_; + llvm::ArrayRef req_impls_; llvm::ArrayRef 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 // replace those with real witnesses as we process them. - llvm::SmallVector req_impls( + llvm::SmallVector req_impls( required_identified.required_impls()); // 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()) { // Rewrites are treated as equivalent requirements in impl lookup. - SemIR::IdentifiedFacetType::Equivalent equiv = {.lhs = rewrite.lhs, - .rhs = rewrite.rhs}; + IdentifiedFacetType::Equivalent equiv = {.lhs = rewrite.lhs, + .rhs = rewrite.rhs}; equiv = SubstIdentifiedWitnesses(context, loc_id, equiv, subst_witnesses_callbacks); if (equiv.lhs != equiv.rhs) { diff --git a/toolchain/check/impl_lookup.h b/toolchain/check/impl_lookup.h index 62db7f7b697d..a45fd7b50c67 100644 --- a/toolchain/check/impl_lookup.h +++ b/toolchain/check/impl_lookup.h @@ -8,7 +8,7 @@ #include #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/inst.h" #include "toolchain/sem_ir/typed_insts.h" diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 2f50c0866f13..c8c9ad618124 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -19,6 +19,7 @@ #include "toolchain/check/eval.h" #include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/import.h" #include "toolchain/check/inst.h" #include "toolchain/check/name_lookup.h" @@ -29,7 +30,6 @@ #include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/file.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/impl.h" #include "toolchain/sem_ir/import_ir.h" @@ -4038,7 +4038,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, auto witnesses_block_id = SemIR::InstBlockId::None; if (inst.witnesses_block_id.has_value()) { witnesses_block_id = - AddCanonicalWitnessesBlock(resolver.local_ir(), witnesses); + AddCanonicalWitnessesBlock(resolver.local_context(), witnesses); } return ResolveResult::Deduplicated( diff --git a/toolchain/check/type_completion.cpp b/toolchain/check/type_completion.cpp index ee1a80de4199..24e934bc1bcb 100644 --- a/toolchain/check/type_completion.cpp +++ b/toolchain/check/type_completion.cpp @@ -11,6 +11,7 @@ #include "toolchain/check/cpp/import.h" #include "toolchain/check/facet_type.h" #include "toolchain/check/generic.h" +#include "toolchain/check/identified_facet_type.h" #include "toolchain/check/inst.h" #include "toolchain/check/literal.h" #include "toolchain/check/period_self.h" @@ -21,7 +22,6 @@ #include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/declared_facet_type.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/named_constraint.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 facet_type_const_id, bool allow_partially_identified, bool diagnose) - -> SemIR::IdentifiedFacetTypeId { + -> IdentifiedFacetTypeId { if (facet_type_const_id == SemIR::ErrorInst::ConstantId) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } 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 // work of identifying the facet type (though we could skip the mapping of // constant values into specifics). - auto key = SemIR::IdentifiedFacetTypeKey{ - .declared_facet_type_id = declared_facet_type_id, - .self_const_id = initial_self_const_id}; + auto key = + IdentifiedFacetTypeKey{.declared_facet_type_id = declared_facet_type_id, + .self_const_id = initial_self_const_id}; if (auto identified_id = context.identified_facet_types().Lookup(key); identified_id.has_value()) { 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, initial_self_const_id); if (subst_id == SemIR::ErrorInst::ConstantId) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } declared_facet_type_id = context.constant_values() .GetInstAs(subst_id) @@ -1020,10 +1020,10 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, // Outputs for the IdentifiedFacetType. bool partially_identified = false; - llvm::SmallVector extends; - llvm::SmallVector impls; - llvm::SmallVector rewrites; - llvm::SmallVector equivalents; + llvm::SmallVector extends; + llvm::SmallVector impls; + llvm::SmallVector rewrites; + llvm::SmallVector equivalents; while (!work.empty()) { 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); auto self_and_interface = [&](SemIR::SpecificInterface impls_interface) - -> SemIR::IdentifiedFacetType::RequiredImpl { + -> IdentifiedFacetType::RequiredImpl { return {self_const_id, impls_interface}; }; auto type_and_interface = [&](SemIR::DeclaredFacetType::TypeImplsInterface impls) - -> SemIR::IdentifiedFacetType::RequiredImpl { + -> IdentifiedFacetType::RequiredImpl { return {context.constant_values().Get(impls.self_type), impls.specific_interface}; }; @@ -1060,7 +1060,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, type_and_interface)); if (facet_type_extends) { auto rewrite_as_constants = - [&](auto rewrite) -> SemIR::IdentifiedFacetType::Rewrite { + [&](auto rewrite) -> IdentifiedFacetType::Rewrite { return {context.constant_values().Get( GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id)), @@ -1071,7 +1071,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, rewrite_as_constants)); } else { auto rewrite_as_constants = - [&](auto rewrite) -> SemIR::IdentifiedFacetType::Equivalent { + [&](auto rewrite) -> IdentifiedFacetType::Equivalent { return {context.constant_values().Get( GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id)), @@ -1111,14 +1111,14 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, DiagnoseIncompleteNamedConstraint(context, extends.named_constraint_id); } - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf( context, loc_id, constraint.generic_id, constraint.generic_with_self_id, extends.specific_id, self_const_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)) { @@ -1136,7 +1136,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, context.sem_ir(), require_specific_id, require.facet_type_inst_id); if (require_self == SemIR::ErrorInst::ConstantId || require_facet_type == SemIR::ErrorInst::ConstantId) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } auto declared_facet_type_id = @@ -1168,14 +1168,14 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, if (diagnose) { DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id); } - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf( context, loc_id, constraint.generic_id, constraint.generic_with_self_id, impls.specific_id, self_const_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)) { @@ -1193,7 +1193,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, context.sem_ir(), require_specific_id, require.facet_type_inst_id); if (require_self == SemIR::ErrorInst::ConstantId || require_facet_type == SemIR::ErrorInst::ConstantId) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } auto declared_facet_type_id = @@ -1226,7 +1226,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, if (diagnose) { DiagnoseIncompleteNamedConstraint(context, impls.named_constraint_id); } - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } 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, context.constant_values().Get(self_type_inst_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)) { @@ -1252,7 +1252,7 @@ static auto IdentifyFacetType(Context& context, SemIR::LocId loc_id, context.sem_ir(), require_specific_id, require.facet_type_inst_id); if (require_self == SemIR::ErrorInst::ConstantId || require_facet_type == SemIR::ErrorInst::ConstantId) { - return SemIR::IdentifiedFacetTypeId::None; + return IdentifiedFacetTypeId::None; } auto declared_facet_type_id = @@ -1272,7 +1272,7 @@ auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id, SemIR::ConstantId self_const_id, SemIR::TypeId facet_type_type_id, bool allow_partially_identified) - -> SemIR::IdentifiedFacetTypeId { + -> IdentifiedFacetTypeId { return IdentifyFacetType(context, loc_id, self_const_id, facet_type_type_id.AsConstantId(), allow_partially_identified, @@ -1283,7 +1283,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id, SemIR::ConstantId self_const_id, SemIR::TypeId facet_type_type_id, DiagnosticContextFn diagnostic_context, - bool diagnose) -> SemIR::IdentifiedFacetTypeId { + bool diagnose) -> IdentifiedFacetTypeId { CARBON_CHECK(diagnostic_context); Diagnostics::ContextScope scope(&context.emitter(), diagnostic_context); return IdentifyFacetType(context, loc_id, self_const_id, diff --git a/toolchain/check/type_completion.h b/toolchain/check/type_completion.h index 99df4cadda1f..231f7eeaae8c 100644 --- a/toolchain/check/type_completion.h +++ b/toolchain/check/type_completion.h @@ -79,7 +79,7 @@ auto TryToIdentifyFacetType(Context& context, SemIR::LocId loc_id, SemIR::ConstantId self_const_id, SemIR::TypeId facet_type_type_id, bool allow_partially_identified) - -> SemIR::IdentifiedFacetTypeId; + -> IdentifiedFacetTypeId; // 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 @@ -107,8 +107,7 @@ auto RequireIdentifiedFacetType(Context& context, SemIR::LocId loc_id, SemIR::ConstantId self_const_id, SemIR::TypeId facet_type_type_id, DiagnosticContextFn diagnostic_context, - bool diagnose = true) - -> SemIR::IdentifiedFacetTypeId; + bool diagnose = true) -> IdentifiedFacetTypeId; // Emits an error diagnostic explaining that a class is incomplete. // diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 951cd624b287..d88e2f4951b9 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -106,7 +106,6 @@ cc_library( "file.cpp", "function.cpp", "generic.cpp", - "identified_facet_type.cpp", "impl.cpp", "import_ir.cpp", "inst.cpp", @@ -143,7 +142,6 @@ cc_library( "file.h", "function.h", "generic.h", - "identified_facet_type.h", "impl.h", "import_cpp.h", "import_ir.h", diff --git a/toolchain/sem_ir/declared_facet_type.cpp b/toolchain/sem_ir/declared_facet_type.cpp index 64ba9924243f..44439022abd2 100644 --- a/toolchain/sem_ir/declared_facet_type.cpp +++ b/toolchain/sem_ir/declared_facet_type.cpp @@ -303,11 +303,6 @@ namespace Carbon { template class CanonicalValueStore>; -template class CanonicalValueStore< - SemIR::IdentifiedFacetTypeId, SemIR::IdentifiedFacetTypeKey, - Tag, SemIR::IdentifiedFacetType>; template class ValueStore>; -template class ValueStore>; } // namespace Carbon diff --git a/toolchain/sem_ir/dump.cpp b/toolchain/sem_ir/dump.cpp index 5d27380550a3..92397c373279 100644 --- a/toolchain/sem_ir/dump.cpp +++ b/toolchain/sem_ir/dump.cpp @@ -22,7 +22,7 @@ LLVM_DUMP_METHOD auto Dump(const File& file) -> std::string { 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; if (name_id.has_value()) { out << " `" << file.names().GetFormatted(name_id) << "`"; @@ -30,8 +30,8 @@ static auto DumpNameIfValid(const File& file, NameId name_id) -> std::string { return out.TakeStr(); } -static auto DumpNameOfEntityName(const File& file, - const EntityName& entity_name) -> std::string { +auto DumpNameOfEntityName(const File& file, const EntityName& entity_name) + -> std::string { RawStringOstream out; out << " `"; out << file.names().GetFormatted(entity_name.name_id); @@ -42,7 +42,7 @@ static auto DumpNameOfEntityName(const File& file, 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; // 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 @@ -84,8 +84,7 @@ static auto DumpLocSummary(const File& file, LocId loc_id) -> std::string { return out.TakeStr(); } -static auto DumpConstantSummary(const File& file, ConstantId const_id) - -> std::string { +auto DumpConstantSummary(const File& file, ConstantId const_id) -> std::string { RawStringOstream out; out << const_id; if (!const_id.has_value()) { @@ -101,7 +100,7 @@ static auto DumpConstantSummary(const File& file, ConstantId const_id) 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; out << type_id; if (!type_id.has_value()) { @@ -124,7 +123,7 @@ static auto DumpTypeSummary(const File& file, TypeId type_id) -> std::string { 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; out << inst_id; 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(); } -static auto DumpGenericSummary(const File& file, GenericId generic_id) - -> std::string { +auto DumpGenericSummary(const File& file, GenericId generic_id) -> std::string { RawStringOstream out; out << generic_id; if (!generic_id.has_value()) { @@ -147,7 +145,7 @@ static auto DumpGenericSummary(const File& file, GenericId generic_id) return out.TakeStr(); } -static auto DumpInterfaceSummary(const File& file, InterfaceId interface_id) +auto DumpInterfaceSummary(const File& file, InterfaceId interface_id) -> std::string { RawStringOstream out; out << interface_id; @@ -158,8 +156,8 @@ static auto DumpInterfaceSummary(const File& file, InterfaceId interface_id) return out.TakeStr(); } -static auto DumpNamedConstraintSummary(const File& file, - NamedConstraintId named_constraint_id) +auto DumpNamedConstraintSummary(const File& file, + NamedConstraintId named_constraint_id) -> std::string { RawStringOstream out; out << named_constraint_id; @@ -170,7 +168,7 @@ static auto DumpNamedConstraintSummary(const File& file, return out.TakeStr(); } -static auto DumpSpecificSummary(const File& file, SpecificId specific_id) +auto DumpSpecificSummary(const File& file, SpecificId specific_id) -> std::string { RawStringOstream out; out << specific_id; @@ -180,8 +178,7 @@ static auto DumpSpecificSummary(const File& file, SpecificId specific_id) return out.TakeStr(); } -static auto DumpRequireImplsSummary(const File& file, - RequireImplsId require_impls_id) +auto DumpRequireImplsSummary(const File& file, RequireImplsId require_impls_id) -> std::string { RawStringOstream out; out << require_impls_id; @@ -380,37 +377,6 @@ LLVM_DUMP_METHOD auto Dump(const File& file, GenericId generic_id) 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 { RawStringOstream out; 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 { return NameScopeId(id); } -LLVM_DUMP_METHOD static auto MakeIdentifiedFacetTypeId(int id) - -> IdentifiedFacetTypeId { - return IdentifiedFacetTypeId(id); -} LLVM_DUMP_METHOD static auto MakeImportIRInstId(int id) -> ImportIRInstId { return ImportIRInstId(id); } diff --git a/toolchain/sem_ir/dump.h b/toolchain/sem_ir/dump.h index 883eca36f9e1..e3150e5bb459 100644 --- a/toolchain/sem_ir/dump.h +++ b/toolchain/sem_ir/dump.h @@ -29,6 +29,24 @@ 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, RawBundleId bundle_id) -> std::string; 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, FunctionId function_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, ImportIRInstId import_inst_id) -> std::string; auto Dump(const File& file, const Inst& inst) -> std::string; diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 977d2272485b..74c82686872d 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -59,7 +59,6 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id, associated_constants_(check_ir_id), // 1 reserved id for `DeclaredFacetTypeId::Empty`. declared_facet_types_(check_ir_id, 1), - identified_facet_types_(check_ir_id), impls_(*this), specific_interfaces_(check_ir_id), generics_(check_ir_id), diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index 5ffd7ae178c8..c5d9b89fcd5f 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -29,7 +29,6 @@ #include "toolchain/sem_ir/field.h" #include "toolchain/sem_ir/function.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/impl.h" #include "toolchain/sem_ir/import_cpp.h" @@ -241,12 +240,6 @@ class File : public Printable { auto AppendCppMangledTypeName(ClassId class_id, llvm::raw_ostream& out) const -> 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() const -> const ImplStore& { return impls_; } auto specific_interfaces() -> SpecificInterfaceStore& { @@ -429,9 +422,6 @@ class File : public Printable { // Storage for declared facet types. DeclaredFacetTypeStore declared_facet_types_; - // Storage for identified facet types. - IdentifiedFacetTypeStore identified_facet_types_; - // Storage for impls. ImplStore impls_; diff --git a/toolchain/sem_ir/identified_facet_type.cpp b/toolchain/sem_ir/identified_facet_type.cpp deleted file mode 100644 index 42b6a6358f98..000000000000 --- a/toolchain/sem_ir/identified_facet_type.cpp +++ /dev/null @@ -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 -using LessThanFn = llvm::function_refbool>; - -template -static auto SortAndDeduplicate(VecT& vec, - LessThanFn 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 extends, - llvm::ArrayRef self_impls, llvm::ArrayRef rewrites, - llvm::ArrayRef 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& witnesses) - -> InstBlockId { - // Small blocks don't need to be sorted. - if (witnesses.size() <= 1) { - return sem_ir.inst_blocks().AddCanonical(witnesses); - } - - llvm::SmallVector> 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(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 diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index a226af249398..99e8b89b35ac 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -378,13 +378,6 @@ struct DeclaredFacetTypeId : public IdBase { inline constexpr DeclaredFacetTypeId DeclaredFacetTypeId::Empty = DeclaredFacetTypeId(0); -// The ID of an resolved facet type value. -struct IdentifiedFacetTypeId : public IdBase { - static constexpr llvm::StringLiteral Label = "identified_facet_type"; - - using IdBase::IdBase; -}; - // The ID of an `Impl`. struct ImplId : public IdBase { using DiagnosticType = Diagnostics::TypeInfo;