require_impls.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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/interface.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. namespace Carbon::Check {
  9. static auto GetEnclosingDeclFromEnclosingSpecificId(
  10. Context& context, SemIR::SpecificId enclosing_specific_id) -> SemIR::Inst {
  11. return context.insts().Get(
  12. context.generics()
  13. .Get(context.specifics().Get(enclosing_specific_id).generic_id)
  14. .decl_id);
  15. }
  16. static auto GetSpecificArgsFromEnclosingSpecific(
  17. Context& context, SemIR::SpecificId enclosing_specific_id)
  18. -> llvm::SmallVector<SemIR::InstId> {
  19. auto enclosing_specific_args_id =
  20. context.specifics().GetArgsOrEmpty(enclosing_specific_id);
  21. auto enclosing_specific_args =
  22. context.inst_blocks().Get(enclosing_specific_args_id);
  23. llvm::SmallVector<SemIR::InstId> arg_ids;
  24. // Reserve space for the `Self` after the enclosing specific's args.
  25. arg_ids.reserve(enclosing_specific_args.size() + 1);
  26. llvm::append_range(arg_ids, enclosing_specific_args);
  27. return arg_ids;
  28. }
  29. auto GetRequireImplsSpecificFromEnclosingSpecific(
  30. Context& context, const SemIR::RequireImpls& require,
  31. SemIR::SpecificId enclosing_specific_id) -> RequireImplsSpecific {
  32. if (enclosing_specific_id.has_value()) {
  33. auto enclosing_generic_decl =
  34. GetEnclosingDeclFromEnclosingSpecificId(context, enclosing_specific_id);
  35. CARBON_CHECK(enclosing_generic_decl.Is<SemIR::InterfaceDecl>() ||
  36. enclosing_generic_decl.Is<SemIR::NamedConstraintDecl>(),
  37. "Incorrect enclosing specific for RequireImpls. Expected an "
  38. "interface or named constraint. Found {0}.",
  39. enclosing_generic_decl);
  40. }
  41. auto arg_ids =
  42. GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
  43. // Specifics inside an interface/constraint also include the `Self` of the
  44. // enclosing entity. We copy that `Self` from the self-specific of the
  45. // RequireImpls generic.
  46. const auto& require_generic = context.generics().Get(require.generic_id);
  47. const auto& require_self_specific =
  48. context.specifics().Get(require_generic.self_specific_id);
  49. auto require_self_specific_args =
  50. context.inst_blocks().Get(require_self_specific.args_id);
  51. // The last argument of a `require` generic is always `Self`, as `require`
  52. // can not have any parameters of its own, only enclosing parameters.
  53. auto self_inst_id = require_self_specific_args.back();
  54. CARBON_CHECK(context.insts().Is<SemIR::SymbolicBinding>(self_inst_id));
  55. arg_ids.push_back(self_inst_id);
  56. auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
  57. require.generic_id, arg_ids);
  58. // TODO: Cache the specific on Context.
  59. return {.specific_id = specific_id};
  60. }
  61. auto GetRequireImplsSpecificFromEnclosingSpecificWithSelfType(
  62. Context& context, const SemIR::RequireImpls& require,
  63. SemIR::SpecificId enclosing_specific_id, SemIR::TypeInstId self_id,
  64. SemIR::InstId witness_id) -> RequireImplsSpecific {
  65. if (enclosing_specific_id.has_value()) {
  66. auto enclosing_generic_decl =
  67. GetEnclosingDeclFromEnclosingSpecificId(context, enclosing_specific_id);
  68. CARBON_CHECK(enclosing_generic_decl.Is<SemIR::InterfaceDecl>(),
  69. "Incorrect enclosing specific for RequireImpls with explicit "
  70. "self type. Expected an interface. Found {0}.",
  71. enclosing_generic_decl);
  72. }
  73. // Construct a facet value around the `self_id` type of the correct facet
  74. // type for the `Self` in the require's self-specific.
  75. auto self_facet_value = GetSelfFacetValueForInterfaceMemberSpecific(
  76. context, enclosing_specific_id, require.generic_id,
  77. context.types().GetTypeIdForTypeInstId(self_id), witness_id);
  78. auto arg_ids =
  79. GetSpecificArgsFromEnclosingSpecific(context, enclosing_specific_id);
  80. arg_ids.push_back(self_facet_value);
  81. auto specific_id = MakeSpecific(context, SemIR::LocId(require.decl_id),
  82. require.generic_id, arg_ids);
  83. // TODO: Cache the specific on Context.
  84. return {.specific_id = specific_id};
  85. }
  86. auto GetConstantValueInRequireImplsSpecific(Context& context,
  87. RequireImplsSpecific specific,
  88. SemIR::InstId inst_id)
  89. -> SemIR::ConstantId {
  90. auto const_id = SemIR::GetConstantValueInSpecific(
  91. context.sem_ir(), specific.specific_id, inst_id);
  92. CARBON_CHECK(const_id.has_value(), "The specific has not been resolved?");
  93. return const_id;
  94. }
  95. } // namespace Carbon::Check