require_impls.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/check/require_impls.h"
  5. #include "toolchain/check/generic.h"
  6. #include "toolchain/check/inst.h"
  7. #include "toolchain/check/interface.h"
  8. #include "toolchain/sem_ir/ids.h"
  9. #include "toolchain/sem_ir/typed_insts.h"
  10. namespace Carbon::Check {
  11. static auto GetEnclosingDeclFromEnclosingSpecificId(
  12. Context& context, SemIR::SpecificId enclosing_specific_id) -> SemIR::Inst {
  13. return context.insts().Get(
  14. context.generics()
  15. .Get(context.specifics().Get(enclosing_specific_id).generic_id)
  16. .decl_id);
  17. }
  18. static auto GetSpecificArgsFromEnclosingSpecific(
  19. Context& context, SemIR::SpecificId enclosing_specific_id)
  20. -> llvm::SmallVector<SemIR::InstId> {
  21. auto enclosing_specific_args_id =
  22. context.specifics().GetArgsOrEmpty(enclosing_specific_id);
  23. auto enclosing_specific_args =
  24. context.inst_blocks().Get(enclosing_specific_args_id);
  25. llvm::SmallVector<SemIR::InstId> arg_ids;
  26. // Reserve space for the `Self` after the enclosing specific's args.
  27. arg_ids.reserve(enclosing_specific_args.size() + 1);
  28. llvm::append_range(arg_ids, enclosing_specific_args);
  29. return arg_ids;
  30. }
  31. auto GetRequireImplsSpecificFromEnclosingSpecific(
  32. Context& context, const SemIR::RequireImpls& require,
  33. SemIR::SpecificId enclosing_specific_id) -> RequireImplsSpecific {
  34. if (enclosing_specific_id.has_value()) {
  35. auto enclosing_generic_decl =
  36. GetEnclosingDeclFromEnclosingSpecificId(context, enclosing_specific_id);
  37. CARBON_CHECK(enclosing_generic_decl.Is<SemIR::InterfaceDecl>() ||
  38. enclosing_generic_decl.Is<SemIR::NamedConstraintDecl>(),
  39. "Incorrect enclosing specific for RequireImpls. Expected an "
  40. "interface or named constraint. Found {0}.",
  41. enclosing_generic_decl);
  42. }
  43. auto arg_ids =
  44. GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
  45. // Specifics inside an interface/constraint also include the `Self` of the
  46. // enclosing entity. We copy that `Self` from the self-specific of the
  47. // RequireImpls generic.
  48. const auto& require_generic = context.generics().Get(require.generic_id);
  49. const auto& require_self_specific =
  50. context.specifics().Get(require_generic.self_specific_id);
  51. auto require_self_specific_args =
  52. context.inst_blocks().Get(require_self_specific.args_id);
  53. // The last argument of a `require` generic is always `Self`, as `require`
  54. // can not have any parameters of its own, only enclosing parameters.
  55. auto self_inst_id = require_self_specific_args.back();
  56. CARBON_CHECK(context.insts().Is<SemIR::SymbolicBinding>(self_inst_id));
  57. arg_ids.push_back(self_inst_id);
  58. auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
  59. require.generic_id, arg_ids);
  60. // TODO: Cache the specific on Context.
  61. return {.specific_id = specific_id};
  62. }
  63. auto GetRequireImplsSpecificFromEnclosingSpecificWithSelfFacetValue(
  64. Context& context, const SemIR::RequireImpls& require,
  65. SemIR::SpecificId enclosing_specific_id,
  66. SemIR::ConstantId self_facet_value_id) -> RequireImplsSpecific {
  67. auto self_facet_value_inst_id =
  68. context.constant_values().GetInstId(self_facet_value_id);
  69. auto self_facet_value = context.insts().Get(self_facet_value_inst_id);
  70. CARBON_CHECK(context.types().Is<SemIR::FacetType>(self_facet_value.type_id()),
  71. "{0}", self_facet_value);
  72. auto arg_ids =
  73. GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
  74. arg_ids.push_back(self_facet_value_inst_id);
  75. auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
  76. require.generic_id, arg_ids);
  77. // TODO: Cache the specific on Context.
  78. return {.specific_id = specific_id};
  79. }
  80. auto GetConstantValueInRequireImplsSpecific(Context& context,
  81. RequireImplsSpecific specific,
  82. SemIR::InstId inst_id)
  83. -> SemIR::ConstantId {
  84. auto const_id = SemIR::GetConstantValueInSpecific(
  85. context.sem_ir(), specific.specific_id, inst_id);
  86. CARBON_CHECK(const_id.has_value(), "The specific has not been resolved?");
  87. return const_id;
  88. }
  89. } // namespace Carbon::Check