| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- // 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/require_impls.h"
- #include "toolchain/check/generic.h"
- #include "toolchain/check/inst.h"
- #include "toolchain/check/interface.h"
- #include "toolchain/sem_ir/ids.h"
- #include "toolchain/sem_ir/typed_insts.h"
- namespace Carbon::Check {
- static auto GetEnclosingDeclFromEnclosingSpecificId(
- Context& context, SemIR::SpecificId enclosing_specific_id) -> SemIR::Inst {
- return context.insts().Get(
- context.generics()
- .Get(context.specifics().Get(enclosing_specific_id).generic_id)
- .decl_id);
- }
- static auto GetSpecificArgsFromEnclosingSpecific(
- Context& context, SemIR::SpecificId enclosing_specific_id)
- -> llvm::SmallVector<SemIR::InstId> {
- auto enclosing_specific_args_id =
- context.specifics().GetArgsOrEmpty(enclosing_specific_id);
- auto enclosing_specific_args =
- context.inst_blocks().Get(enclosing_specific_args_id);
- llvm::SmallVector<SemIR::InstId> arg_ids;
- // Reserve space for the `Self` after the enclosing specific's args.
- arg_ids.reserve(enclosing_specific_args.size() + 1);
- llvm::append_range(arg_ids, enclosing_specific_args);
- return arg_ids;
- }
- auto GetRequireImplsSpecificFromEnclosingSpecific(
- Context& context, const SemIR::RequireImpls& require,
- SemIR::SpecificId enclosing_specific_id) -> RequireImplsSpecific {
- if (enclosing_specific_id.has_value()) {
- auto enclosing_generic_decl =
- GetEnclosingDeclFromEnclosingSpecificId(context, enclosing_specific_id);
- CARBON_CHECK(enclosing_generic_decl.Is<SemIR::InterfaceDecl>() ||
- enclosing_generic_decl.Is<SemIR::NamedConstraintDecl>(),
- "Incorrect enclosing specific for RequireImpls. Expected an "
- "interface or named constraint. Found {0}.",
- enclosing_generic_decl);
- }
- auto arg_ids =
- GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
- // Specifics inside an interface/constraint also include the `Self` of the
- // enclosing entity. We copy that `Self` from the self-specific of the
- // RequireImpls generic.
- const auto& require_generic = context.generics().Get(require.generic_id);
- const auto& require_self_specific =
- context.specifics().Get(require_generic.self_specific_id);
- auto require_self_specific_args =
- context.inst_blocks().Get(require_self_specific.args_id);
- // The last argument of a `require` generic is always `Self`, as `require`
- // can not have any parameters of its own, only enclosing parameters.
- auto self_inst_id = require_self_specific_args.back();
- CARBON_CHECK(context.insts().Is<SemIR::SymbolicBinding>(self_inst_id));
- arg_ids.push_back(self_inst_id);
- auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
- require.generic_id, arg_ids);
- // TODO: Cache the specific on Context.
- return {.specific_id = specific_id};
- }
- auto GetRequireImplsSpecificFromEnclosingSpecificWithSelfFacetValue(
- Context& context, const SemIR::RequireImpls& require,
- SemIR::SpecificId enclosing_specific_id,
- SemIR::ConstantId self_facet_value_id) -> RequireImplsSpecific {
- auto self_facet_value_inst_id =
- context.constant_values().GetInstId(self_facet_value_id);
- auto self_facet_value = context.insts().Get(self_facet_value_inst_id);
- CARBON_CHECK(context.types().Is<SemIR::FacetType>(self_facet_value.type_id()),
- "{0}", self_facet_value);
- auto arg_ids =
- GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
- arg_ids.push_back(self_facet_value_inst_id);
- auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
- require.generic_id, arg_ids);
- // TODO: Cache the specific on Context.
- return {.specific_id = specific_id};
- }
- auto GetConstantValueInRequireImplsSpecific(Context& context,
- RequireImplsSpecific specific,
- SemIR::InstId inst_id)
- -> SemIR::ConstantId {
- auto const_id = SemIR::GetConstantValueInSpecific(
- context.sem_ir(), specific.specific_id, inst_id);
- CARBON_CHECK(const_id.has_value(), "The specific has not been resolved?");
- return const_id;
- }
- } // namespace Carbon::Check
|