interface.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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 <algorithm>
  6. #include <cstddef>
  7. #include "common/concepts.h"
  8. #include "toolchain/check/context.h"
  9. #include "toolchain/check/core_identifier.h"
  10. #include "toolchain/check/eval.h"
  11. #include "toolchain/check/generic.h"
  12. #include "toolchain/check/inst.h"
  13. #include "toolchain/check/merge.h"
  14. #include "toolchain/check/name_lookup.h"
  15. #include "toolchain/check/type.h"
  16. #include "toolchain/sem_ir/entity_with_params_base.h"
  17. #include "toolchain/sem_ir/ids.h"
  18. #include "toolchain/sem_ir/inst.h"
  19. #include "toolchain/sem_ir/typed_insts.h"
  20. namespace Carbon::Check {
  21. auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
  22. SemIR::InstId decl_id) -> SemIR::InstId {
  23. auto& interface_info = context.interfaces().Get(interface_id);
  24. if (!interface_info.is_being_defined()) {
  25. // This should only happen if the interface is erroneously defined more than
  26. // once.
  27. // TODO: Find a way to CHECK this.
  28. return SemIR::ErrorInst::InstId;
  29. }
  30. // This associated entity is being declared as a member of the self specific
  31. // of the interface.
  32. auto interface_specific_id =
  33. context.generics().GetSelfSpecific(interface_info.generic_id);
  34. // Register this declaration as declaring an associated entity.
  35. auto index = SemIR::ElementIndex(
  36. context.args_type_info_stack().PeekCurrentBlockContents().size());
  37. context.args_type_info_stack().AddInstId(decl_id);
  38. // Name lookup for the declaration's name should name the associated entity,
  39. // not the declaration itself.
  40. auto type_id =
  41. GetAssociatedEntityType(context, interface_id, interface_specific_id);
  42. return AddInst<SemIR::AssociatedEntity>(
  43. context, SemIR::LocId(decl_id),
  44. {.type_id = type_id, .index = index, .decl_id = decl_id});
  45. }
  46. // Returns the `Self` binding for an interface, given a specific for the
  47. // interface and a generic for an associated entity within it.
  48. static auto GetSelfBinding(Context& context,
  49. SemIR::SpecificId interface_specific_id,
  50. SemIR::GenericId assoc_entity_generic_id)
  51. -> SemIR::InstId {
  52. const auto& generic = context.generics().Get(assoc_entity_generic_id);
  53. auto bindings = context.inst_blocks().Get(generic.bindings_id);
  54. auto interface_args_id =
  55. context.specifics().GetArgsOrEmpty(interface_specific_id);
  56. auto interface_args = context.inst_blocks().Get(interface_args_id);
  57. // The `Self` binding is the first binding after the interface's arguments.
  58. auto self_binding_id = bindings[interface_args.size()];
  59. // Check that we found the self binding. The binding might be a
  60. // `SymbolicBinding` or an `ImportRef` naming one.
  61. auto self_binding_const_inst_id =
  62. context.constant_values().GetConstantInstId(self_binding_id);
  63. auto bind_name_inst =
  64. context.insts().GetAs<SemIR::SymbolicBinding>(self_binding_const_inst_id);
  65. CARBON_CHECK(
  66. context.entity_names().Get(bind_name_inst.entity_name_id).name_id ==
  67. SemIR::NameId::SelfType,
  68. "Expected a Self binding, found {0}", bind_name_inst);
  69. return self_binding_id;
  70. }
  71. // Given a `Self` type and a witness that it implements an interface, along with
  72. // that interface's `Self` binding, forms and returns a facet that can be used
  73. // as the argument for that `Self` binding.
  74. static auto GetSelfFacet(Context& context,
  75. SemIR::SpecificId interface_specific_id,
  76. SemIR::GenericId generic_id,
  77. SemIR::TypeId self_type_id,
  78. SemIR::InstId self_witness_id) -> SemIR::InstId {
  79. auto self_binding_id =
  80. GetSelfBinding(context, interface_specific_id, generic_id);
  81. auto self_facet_type_id = SemIR::GetTypeOfInstInSpecific(
  82. context.sem_ir(), interface_specific_id, self_binding_id);
  83. // Create a facet value to be the value of `Self` in the interface.
  84. // TODO: Pass this in instead of creating it here. The caller sometimes
  85. // already has a facet value.
  86. auto type_inst_id = context.types().GetInstId(self_type_id);
  87. auto witnesses_block_id =
  88. context.inst_blocks().AddCanonical({self_witness_id});
  89. auto self_value_const_id = TryEvalInst(
  90. context, SemIR::FacetValue{.type_id = self_facet_type_id,
  91. .type_inst_id = type_inst_id,
  92. .witnesses_block_id = witnesses_block_id});
  93. return context.constant_values().GetInstId(self_value_const_id);
  94. }
  95. // Builds and returns the argument list from `interface_specific_id` with a
  96. // value for the `Self` parameter of `generic_id` appended.
  97. static auto GetGenericArgsWithSelfType(Context& context,
  98. SemIR::SpecificId interface_specific_id,
  99. SemIR::GenericId generic_id,
  100. SemIR::TypeId self_type_id,
  101. SemIR::InstId witness_inst_id,
  102. std::size_t reserve_args_size = 0)
  103. -> llvm::SmallVector<SemIR::InstId> {
  104. auto interface_args_id =
  105. context.specifics().GetArgsOrEmpty(interface_specific_id);
  106. auto interface_args = context.inst_blocks().Get(interface_args_id);
  107. llvm::SmallVector<SemIR::InstId> arg_ids;
  108. arg_ids.reserve(std::max(reserve_args_size, interface_args.size() + 1));
  109. // Start with the enclosing arguments from the interface.
  110. llvm::append_range(arg_ids, interface_args);
  111. // Add the `Self` argument.
  112. arg_ids.push_back(GetSelfFacet(context, interface_specific_id, generic_id,
  113. self_type_id, witness_inst_id));
  114. return arg_ids;
  115. }
  116. auto GetSelfSpecificForInterfaceMemberWithSelfType(
  117. Context& context, SemIR::LocId loc_id,
  118. SemIR::SpecificId interface_specific_id, SemIR::GenericId generic_id,
  119. SemIR::SpecificId enclosing_specific_id, SemIR::TypeId self_type_id,
  120. SemIR::InstId witness_inst_id) -> SemIR::SpecificId {
  121. const auto& generic = context.generics().Get(generic_id);
  122. auto self_specific_args = context.inst_blocks().Get(
  123. context.specifics().Get(generic.self_specific_id).args_id);
  124. auto arg_ids = GetGenericArgsWithSelfType(
  125. context, interface_specific_id, generic_id, self_type_id, witness_inst_id,
  126. self_specific_args.size());
  127. // Determine the number of specific arguments that enclose the point where
  128. // this self specific will be used from. In an impl, this will be the number
  129. // of parameters that the impl has.
  130. int num_enclosing_specific_args =
  131. context.inst_blocks()
  132. .Get(context.specifics().GetArgsOrEmpty(enclosing_specific_id))
  133. .size();
  134. // The index of each remaining generic parameter is adjusted to match the
  135. // numbering at the point where the self specific is used.
  136. int index_delta = num_enclosing_specific_args - arg_ids.size();
  137. // Take any trailing argument values from the self specific.
  138. // TODO: If these refer to outer arguments, for example in their types, we may
  139. // need to perform extra substitutions here.
  140. for (auto arg_id : self_specific_args.drop_front(arg_ids.size())) {
  141. auto new_arg_id = context.constant_values().GetConstantInstId(arg_id);
  142. if (index_delta) {
  143. // If this parameter would have a new index in the context described by
  144. // `enclosing_specific_id`, form a new binding with an adjusted index.
  145. auto bind_name = context.insts().GetAs<SemIR::SymbolicBinding>(
  146. context.constant_values().GetConstantInstId(arg_id));
  147. auto entity_name = context.entity_names().Get(bind_name.entity_name_id);
  148. entity_name.bind_index_value += index_delta;
  149. CARBON_CHECK(entity_name.bind_index_value >= 0);
  150. bind_name.entity_name_id =
  151. context.entity_names().AddCanonical(entity_name);
  152. new_arg_id =
  153. context.constant_values().GetInstId(TryEvalInst(context, bind_name));
  154. }
  155. arg_ids.push_back(new_arg_id);
  156. }
  157. return MakeSpecific(context, loc_id, generic_id, arg_ids);
  158. }
  159. auto GetTypeForSpecificAssociatedEntity(Context& context, SemIR::LocId loc_id,
  160. SemIR::SpecificId interface_specific_id,
  161. SemIR::InstId decl_id,
  162. SemIR::TypeId self_type_id,
  163. SemIR::InstId self_witness_id)
  164. -> SemIR::TypeId {
  165. auto decl_constant_inst_id =
  166. context.constant_values().GetConstantInstId(decl_id);
  167. if (decl_constant_inst_id == SemIR::ErrorInst::InstId) {
  168. return SemIR::ErrorInst::TypeId;
  169. }
  170. auto decl = context.insts().Get(decl_constant_inst_id);
  171. if (auto assoc_const = decl.TryAs<SemIR::AssociatedConstantDecl>()) {
  172. // Form a specific for the associated constant, and grab the type from
  173. // there.
  174. auto generic_id = context.associated_constants()
  175. .Get(assoc_const->assoc_const_id)
  176. .generic_id;
  177. auto arg_ids =
  178. GetGenericArgsWithSelfType(context, interface_specific_id, generic_id,
  179. self_type_id, self_witness_id);
  180. auto const_specific_id = MakeSpecific(context, loc_id, generic_id, arg_ids);
  181. return SemIR::GetTypeOfInstInSpecific(context.sem_ir(), const_specific_id,
  182. decl_id);
  183. }
  184. if (auto fn = context.types().TryGetAs<SemIR::FunctionType>(decl.type_id())) {
  185. // Form the type of the function within the interface, and attach the `Self`
  186. // type.
  187. auto interface_fn_type_id = SemIR::GetTypeOfInstInSpecific(
  188. context.sem_ir(), interface_specific_id, decl_id);
  189. auto self_facet_id =
  190. GetSelfFacet(context, interface_specific_id,
  191. context.functions().Get(fn->function_id).generic_id,
  192. self_type_id, self_witness_id);
  193. return GetFunctionTypeWithSelfType(
  194. context, context.types().GetInstId(interface_fn_type_id),
  195. self_facet_id);
  196. }
  197. CARBON_FATAL("Unexpected kind for associated constant {0}", decl);
  198. }
  199. auto AddSelfGenericParameter(Context& context, SemIR::LocId definition_loc_id,
  200. SemIR::TypeId type_id, SemIR::NameScopeId scope_id,
  201. bool is_template) -> SemIR::InstId {
  202. auto entity_name_id = context.entity_names().AddSymbolicBindingName(
  203. SemIR::NameId::SelfType, scope_id,
  204. context.scope_stack().AddCompileTimeBinding(), is_template);
  205. // Because there is no equivalent non-symbolic value, we use `None` as
  206. // the `value_id` on the `SymbolicBinding`.
  207. auto self_param_inst_id =
  208. AddInst<SemIR::SymbolicBinding>(context, definition_loc_id,
  209. {.type_id = type_id,
  210. .entity_name_id = entity_name_id,
  211. .value_id = SemIR::InstId::None});
  212. context.scope_stack().PushCompileTimeBinding(self_param_inst_id);
  213. context.name_scopes().AddRequiredName(scope_id, SemIR::NameId::SelfType,
  214. self_param_inst_id);
  215. return self_param_inst_id;
  216. }
  217. template <typename EntityT>
  218. requires std::same_as<EntityT, SemIR::Interface>
  219. static auto TryGetEntity(Context& context, SemIR::Inst inst)
  220. -> const SemIR::EntityWithParamsBase* {
  221. if (auto decl = inst.TryAs<SemIR::InterfaceDecl>()) {
  222. return &context.interfaces().Get(decl->interface_id);
  223. } else {
  224. return nullptr;
  225. }
  226. }
  227. template <typename EntityT>
  228. requires std::same_as<EntityT, SemIR::NamedConstraint>
  229. static auto TryGetEntity(Context& context, SemIR::Inst inst)
  230. -> const SemIR::EntityWithParamsBase* {
  231. if (auto decl = inst.TryAs<SemIR::NamedConstraintDecl>()) {
  232. return &context.named_constraints().Get(decl->named_constraint_id);
  233. } else {
  234. return nullptr;
  235. }
  236. }
  237. template <typename EntityT>
  238. requires std::same_as<EntityT, SemIR::Interface>
  239. static constexpr auto DeclTokenKind() -> Lex::TokenKind {
  240. return Lex::TokenKind::Interface;
  241. }
  242. template <typename EntityT>
  243. requires std::same_as<EntityT, SemIR::NamedConstraint>
  244. static constexpr auto DeclTokenKind() -> Lex::TokenKind {
  245. return Lex::TokenKind::Constraint;
  246. }
  247. template <typename EntityT>
  248. requires SameAsOneOf<EntityT, SemIR::Interface, SemIR::NamedConstraint>
  249. auto TryGetExistingDecl(Context& context, const NameComponent& name,
  250. SemIR::ScopeLookupResult lookup_result,
  251. const EntityT& entity, bool is_definition)
  252. -> std::optional<SemIR::Inst> {
  253. if (lookup_result.is_poisoned()) {
  254. // This is a declaration of a poisoned name.
  255. DiagnosePoisonedName(context, name.name_id,
  256. lookup_result.poisoning_loc_id(), name.name_loc_id);
  257. return std::nullopt;
  258. }
  259. if (!lookup_result.is_found()) {
  260. return std::nullopt;
  261. }
  262. SemIR::InstId existing_id = lookup_result.target_inst_id();
  263. SemIR::Inst existing_decl_inst = context.insts().Get(existing_id);
  264. const auto* existing_decl_entity =
  265. TryGetEntity<EntityT>(context, existing_decl_inst);
  266. if (!existing_decl_entity) {
  267. // This is a redeclaration with a different entity kind.
  268. DiagnoseDuplicateName(context, name.name_id, name.name_loc_id,
  269. SemIR::LocId(existing_id));
  270. return std::nullopt;
  271. }
  272. if (!CheckRedeclParamsMatch(
  273. context,
  274. DeclParams(SemIR::LocId(entity.latest_decl_id()),
  275. name.first_param_node_id, name.last_param_node_id,
  276. name.implicit_param_patterns_id, name.param_patterns_id),
  277. DeclParams(*existing_decl_entity))) {
  278. // Mismatch is diagnosed already if found.
  279. return std::nullopt;
  280. }
  281. // TODO: This should be refactored a little, particularly for
  282. // prev_import_ir_id. See similar logic for classes and functions, which
  283. // might also be refactored to merge.
  284. DiagnoseIfInvalidRedecl(
  285. context, DeclTokenKind<EntityT>(), existing_decl_entity->name_id,
  286. RedeclInfo(entity, SemIR::LocId(entity.latest_decl_id()), is_definition),
  287. RedeclInfo(*existing_decl_entity,
  288. SemIR::LocId(existing_decl_entity->latest_decl_id()),
  289. existing_decl_entity->has_definition_started()),
  290. /*prev_import_ir_id=*/SemIR::ImportIRId::None);
  291. if (is_definition && existing_decl_entity->has_definition_started()) {
  292. // DiagnoseIfInvalidRedecl would diagnose an error in this case, since we'd
  293. // have two definitions. Given the declaration parts of the definitions
  294. // match, we would be able to use the prior declaration for error recovery,
  295. // except that having two definitions causes larger problems for generics.
  296. // All interfaces (and named constraints) are generic with an implicit Self
  297. // compile time binding.
  298. return std::nullopt;
  299. }
  300. // This is a matching redeclaration of an existing entity of the same type.
  301. return existing_decl_inst;
  302. }
  303. template auto TryGetExistingDecl(Context& context, const NameComponent& name,
  304. SemIR::ScopeLookupResult lookup_result,
  305. const SemIR::Interface& entity,
  306. bool is_definition)
  307. -> std::optional<SemIR::Inst>;
  308. template auto TryGetExistingDecl(Context& context, const NameComponent& name,
  309. SemIR::ScopeLookupResult lookup_result,
  310. const SemIR::NamedConstraint& entity,
  311. bool is_definition)
  312. -> std::optional<SemIR::Inst>;
  313. } // namespace Carbon::Check