interface.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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/interface.h"
  5. #include "toolchain/check/context.h"
  6. #include "toolchain/check/eval.h"
  7. #include "toolchain/check/generic.h"
  8. #include "toolchain/sem_ir/ids.h"
  9. #include "toolchain/sem_ir/inst.h"
  10. #include "toolchain/sem_ir/typed_insts.h"
  11. namespace Carbon::Check {
  12. auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
  13. SemIR::InstId decl_id) -> SemIR::InstId {
  14. auto& interface_info = context.interfaces().Get(interface_id);
  15. if (!interface_info.is_being_defined()) {
  16. // This should only happen if the interface is erroneously defined more than
  17. // once.
  18. // TODO: Find a way to CHECK this.
  19. return SemIR::ErrorInst::SingletonInstId;
  20. }
  21. // The interface type is the type of `Self`.
  22. auto self_type_id =
  23. context.insts().Get(interface_info.self_param_id).type_id();
  24. // Register this declaration as declaring an associated entity.
  25. auto index = SemIR::ElementIndex(
  26. context.args_type_info_stack().PeekCurrentBlockContents().size());
  27. context.args_type_info_stack().AddInstId(decl_id);
  28. // Name lookup for the declaration's name should name the associated entity,
  29. // not the declaration itself.
  30. auto type_id = context.GetAssociatedEntityType(self_type_id);
  31. return context.AddInst<SemIR::AssociatedEntity>(
  32. context.insts().GetLocId(decl_id),
  33. {.type_id = type_id, .index = index, .decl_id = decl_id});
  34. }
  35. auto GetSelfSpecificForInterfaceMemberWithSelfType(
  36. Context& context, SemIRLoc loc, SemIR::SpecificId enclosing_specific_id,
  37. SemIR::GenericId generic_id, SemIR::TypeId self_type_id,
  38. SemIR::InstId witness_inst_id) -> SemIR::SpecificId {
  39. const auto& generic = context.generics().Get(generic_id);
  40. auto bindings = context.inst_blocks().Get(generic.bindings_id);
  41. llvm::SmallVector<SemIR::InstId> arg_ids;
  42. arg_ids.reserve(bindings.size());
  43. // Start with the enclosing arguments.
  44. if (enclosing_specific_id.has_value()) {
  45. auto enclosing_specific_args_id =
  46. context.specifics().Get(enclosing_specific_id).args_id;
  47. auto enclosing_specific_args =
  48. context.inst_blocks().Get(enclosing_specific_args_id);
  49. arg_ids.assign(enclosing_specific_args.begin(),
  50. enclosing_specific_args.end());
  51. }
  52. // Add the `Self` argument. First find the `Self` binding.
  53. auto self_binding =
  54. context.insts().GetAs<SemIR::BindSymbolicName>(bindings[arg_ids.size()]);
  55. CARBON_CHECK(
  56. context.entity_names().Get(self_binding.entity_name_id).name_id ==
  57. SemIR::NameId::SelfType,
  58. "Expected a Self binding, found {0}", self_binding);
  59. // Create a facet value to be the value of `Self` in the interface.
  60. // TODO: Pass this in instead of creating it here. The caller sometimes
  61. // already has a facet value.
  62. auto type_inst_id = context.types().GetInstId(self_type_id);
  63. auto facet_value_const_id =
  64. TryEvalInst(context, SemIR::InstId::None,
  65. SemIR::FacetValue{.type_id = self_binding.type_id,
  66. .type_inst_id = type_inst_id,
  67. .witness_inst_id = witness_inst_id});
  68. arg_ids.push_back(context.constant_values().GetInstId(facet_value_const_id));
  69. // Take any trailing argument values from the self specific.
  70. // TODO: If these refer to outer arguments, for example in their types, we may
  71. // need to perform extra substitutions here.
  72. auto self_specific_args = context.inst_blocks().Get(
  73. context.specifics().Get(generic.self_specific_id).args_id);
  74. for (auto arg_id : self_specific_args.drop_front(arg_ids.size())) {
  75. arg_ids.push_back(context.constant_values().GetConstantInstId(arg_id));
  76. }
  77. auto args_id = context.inst_blocks().AddCanonical(arg_ids);
  78. return MakeSpecific(context, loc, generic_id, args_id);
  79. }
  80. auto GetTypeForSpecificAssociatedEntity(Context& context, SemIRLoc loc,
  81. SemIR::SpecificId interface_specific_id,
  82. SemIR::InstId decl_id,
  83. SemIR::TypeId self_type_id,
  84. SemIR::InstId self_witness_id)
  85. -> SemIR::TypeId {
  86. auto decl =
  87. context.insts().Get(context.constant_values().GetConstantInstId(decl_id));
  88. auto specific_id = interface_specific_id;
  89. if (auto assoc_const = decl.TryAs<SemIR::AssociatedConstantDecl>()) {
  90. specific_id = GetSelfSpecificForInterfaceMemberWithSelfType(
  91. context, loc, interface_specific_id,
  92. context.associated_constants()
  93. .Get(assoc_const->assoc_const_id)
  94. .generic_id,
  95. self_type_id, self_witness_id);
  96. }
  97. // TODO: For a `FunctionDecl`, should we substitute `Self` into the type?
  98. return SemIR::GetTypeInSpecific(context.sem_ir(), specific_id,
  99. context.insts().Get(decl_id).type_id());
  100. }
  101. } // namespace Carbon::Check