handle_require.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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/base/kind_switch.h"
  5. #include "toolchain/check/context.h"
  6. #include "toolchain/check/convert.h"
  7. #include "toolchain/check/generic.h"
  8. #include "toolchain/check/handle.h"
  9. #include "toolchain/check/inst.h"
  10. #include "toolchain/check/modifiers.h"
  11. #include "toolchain/check/name_lookup.h"
  12. #include "toolchain/check/subst.h"
  13. #include "toolchain/check/type.h"
  14. #include "toolchain/check/type_completion.h"
  15. #include "toolchain/diagnostics/diagnostic.h"
  16. #include "toolchain/parse/node_ids.h"
  17. #include "toolchain/sem_ir/ids.h"
  18. #include "toolchain/sem_ir/named_constraint.h"
  19. #include "toolchain/sem_ir/specific_named_constraint.h"
  20. #include "toolchain/sem_ir/type_iterator.h"
  21. #include "toolchain/sem_ir/typed_insts.h"
  22. namespace Carbon::Check {
  23. auto HandleParseNode(Context& context, Parse::RequireIntroducerId node_id)
  24. -> bool {
  25. // Require decls are always generic, since everything in an `interface` or
  26. // `constraint` is generic over `Self`.
  27. StartGenericDecl(context);
  28. // Create an instruction block to hold the instructions created for the type
  29. // and constraint.
  30. context.inst_block_stack().Push();
  31. // Optional modifiers follow.
  32. context.decl_introducer_state_stack().Push<Lex::TokenKind::Require>();
  33. auto scope_id = context.scope_stack().PeekNameScopeId();
  34. auto scope_inst_id = context.name_scopes().Get(scope_id).inst_id();
  35. auto scope_inst = context.insts().Get(scope_inst_id);
  36. if (!scope_inst.Is<SemIR::InterfaceWithSelfDecl>() &&
  37. !scope_inst.Is<SemIR::NamedConstraintWithSelfDecl>()) {
  38. CARBON_DIAGNOSTIC(
  39. RequireInWrongScope, Error,
  40. "`require` can only be used in an `interface` or `constraint`");
  41. context.emitter().Emit(node_id, RequireInWrongScope);
  42. scope_inst_id = SemIR::ErrorInst::InstId;
  43. }
  44. context.node_stack().Push(node_id, scope_inst_id);
  45. return true;
  46. }
  47. auto HandleParseNode(Context& context, Parse::RequireDefaultSelfImplsId node_id)
  48. -> bool {
  49. auto scope_inst_id =
  50. context.node_stack().Peek<Parse::NodeKind::RequireIntroducer>();
  51. if (scope_inst_id == SemIR::ErrorInst::InstId) {
  52. context.node_stack().Push(node_id, SemIR::ErrorInst::TypeInstId);
  53. return true;
  54. }
  55. auto lookup_result =
  56. LookupUnqualifiedName(context, node_id, SemIR::NameId::SelfType,
  57. /*required=*/true);
  58. auto self_inst_id = lookup_result.scope_result.target_inst_id();
  59. auto self_type_id = context.insts().Get(self_inst_id).type_id();
  60. if (self_type_id == SemIR::ErrorInst::TypeId) {
  61. context.node_stack().Push(node_id, SemIR::ErrorInst::TypeInstId);
  62. return true;
  63. }
  64. CARBON_CHECK(context.types().Is<SemIR::FacetType>(self_type_id));
  65. // TODO: We could simplify with a call to ExprAsType, like below?
  66. auto self_facet_as_type = AddTypeInst<SemIR::FacetAccessType>(
  67. context, node_id,
  68. {.type_id = SemIR::TypeType::TypeId,
  69. .facet_value_inst_id = self_inst_id});
  70. context.node_stack().Push(node_id, self_facet_as_type);
  71. return true;
  72. }
  73. auto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id)
  74. -> bool {
  75. auto [self_node_id, self_inst_id] = context.node_stack().PopExprWithNodeId();
  76. auto self_type = ExprAsType(context, self_node_id, self_inst_id);
  77. const auto& introducer = context.decl_introducer_state_stack().innermost();
  78. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
  79. if (self_type.type_id != SemIR::ErrorInst::TypeId) {
  80. CARBON_DIAGNOSTIC(RequireImplsExtendWithExplicitSelf, Error,
  81. "`extend require impls` with explicit type");
  82. // TODO: If the explicit self-type matches a lookup of NameId::SelfType,
  83. // add a note to the diagnostic: "remove the explicit `Self` type here",
  84. // and continue without an ErrorInst. See ExtendImplSelfAsDefault.
  85. context.emitter().Emit(self_node_id, RequireImplsExtendWithExplicitSelf);
  86. }
  87. self_type.inst_id = SemIR::ErrorInst::TypeInstId;
  88. }
  89. context.node_stack().Push(node_id, self_type.inst_id);
  90. return true;
  91. }
  92. static auto TypeStructureReferencesSelf(
  93. Context& context, SemIR::LocId loc_id, SemIR::ConstantId const_id,
  94. const SemIR::IdentifiedFacetType& identified_facet_type) -> bool {
  95. auto find_self = [&](SemIR::TypeIterator& type_iter) -> bool {
  96. while (true) {
  97. auto step = type_iter.Next();
  98. if (step.Is<SemIR::TypeIterator::Step::Done>()) {
  99. break;
  100. }
  101. CARBON_KIND_SWITCH(step.any) {
  102. case CARBON_KIND(SemIR::TypeIterator::Step::Error _): {
  103. // Don't generate more diagnostics.
  104. return true;
  105. }
  106. case CARBON_KIND(SemIR::TypeIterator::Step::SymbolicType symbolic): {
  107. if (context.entity_names().Get(symbolic.entity_name_id).name_id ==
  108. SemIR::NameId::SelfType) {
  109. return true;
  110. }
  111. break;
  112. }
  113. default:
  114. break;
  115. }
  116. }
  117. return false;
  118. };
  119. {
  120. SemIR::TypeIterator type_iter(&context.sem_ir());
  121. type_iter.Add(context.constant_values().GetInstId(const_id));
  122. if (find_self(type_iter)) {
  123. return true;
  124. }
  125. }
  126. if (identified_facet_type.required_impls().empty()) {
  127. CARBON_DIAGNOSTIC(
  128. RequireImplsMissingSelfEmptyFacetType, Error,
  129. "no `Self` reference found in `require` declaration; `Self` must "
  130. "appear in the self-type or as a generic argument for each required "
  131. "interface, but no interfaces were found");
  132. context.emitter().Emit(loc_id, RequireImplsMissingSelfEmptyFacetType);
  133. return false;
  134. }
  135. bool interfaces_all_reference_self = true;
  136. for (auto [_, specific_interface] : identified_facet_type.required_impls()) {
  137. SemIR::TypeIterator type_iter(&context.sem_ir());
  138. type_iter.Add(specific_interface);
  139. if (!find_self(type_iter)) {
  140. // TODO: The IdentifiedFacetType loses the location (since it's
  141. // canonical), but it would be nice to somehow point this diagnostic at
  142. // the particular interface in the facet type that is missing `Self`.
  143. CARBON_DIAGNOSTIC(
  144. RequireImplsMissingSelf, Error,
  145. "no `Self` reference found in `require` declaration; `Self` must "
  146. "appear in the self-type or as a generic argument for each required "
  147. "interface, but found interface `{0}` without a `Self` argument",
  148. SemIR::SpecificInterface);
  149. context.emitter().Emit(loc_id, RequireImplsMissingSelf,
  150. specific_interface);
  151. interfaces_all_reference_self = false;
  152. }
  153. }
  154. return interfaces_all_reference_self;
  155. }
  156. struct ValidateRequireResult {
  157. const SemIR::IdentifiedFacetType* identified_facet_type;
  158. };
  159. // Returns nullopt if a diagnostic has been emitted and the `require` decl is
  160. // not valid.
  161. static auto ValidateRequire(Context& context, SemIR::LocId full_require_loc_id,
  162. SemIR::LocId constraint_loc_id,
  163. SemIR::InstId self_inst_id,
  164. SemIR::InstId constraint_inst_id,
  165. SemIR::InstId scope_inst_id)
  166. -> std::optional<ValidateRequireResult> {
  167. auto self_type_id = context.types().GetTypeIdForTypeInstId(self_inst_id);
  168. auto constraint_type_id =
  169. context.types().TryGetTypeIdForTypeInstId(constraint_inst_id);
  170. if (self_type_id == SemIR::ErrorInst::TypeId ||
  171. constraint_type_id == SemIR::ErrorInst::TypeId ||
  172. scope_inst_id == SemIR::ErrorInst::InstId) {
  173. // An error was already diagnosed, don't diagnose another. We can't build a
  174. // useful `require` with an error, it couldn't do anything.
  175. return std::nullopt;
  176. }
  177. auto constraint_facet_type =
  178. context.types().TryGetAsIfValid<SemIR::FacetType>(constraint_type_id);
  179. if (!constraint_facet_type) {
  180. CARBON_DIAGNOSTIC(
  181. RequireImplsMissingFacetType, Error,
  182. "`require` declaration constrained by a non-facet type; "
  183. "expected an `interface` or `constraint` name after `impls`");
  184. context.emitter().Emit(constraint_loc_id, RequireImplsMissingFacetType);
  185. // Can't continue without a constraint to use.
  186. return std::nullopt;
  187. }
  188. if (auto named_constraint =
  189. context.insts().TryGetAs<SemIR::NamedConstraintWithSelfDecl>(
  190. scope_inst_id)) {
  191. const auto& constraint_facet_type_info =
  192. context.facet_types().Get(constraint_facet_type->facet_type_id);
  193. // TODO: Handle other impls named constraints for the
  194. // RequireImplsReferenceCycle diagnostic.
  195. if (constraint_facet_type_info.other_requirements) {
  196. context.TODO(constraint_loc_id,
  197. "facet type has constraints that we don't handle yet");
  198. return std::nullopt;
  199. }
  200. auto named_constraints_from_type_impls = llvm::map_range(
  201. constraint_facet_type_info.type_impls_named_constraints,
  202. [](auto impls) { return impls.specific_named_constraint; });
  203. auto named_constraints = llvm::concat<const SemIR::SpecificNamedConstraint>(
  204. constraint_facet_type_info.extend_named_constraints,
  205. constraint_facet_type_info.self_impls_named_constraints,
  206. named_constraints_from_type_impls);
  207. for (auto c : named_constraints) {
  208. if (c.named_constraint_id == named_constraint->named_constraint_id) {
  209. const auto& named_constraint =
  210. context.named_constraints().Get(c.named_constraint_id);
  211. CARBON_DIAGNOSTIC(RequireImplsReferenceCycle, Error,
  212. "facet type in `require` declaration refers to the "
  213. "named constraint `{0}` from within its definition",
  214. SemIR::NameId);
  215. context.emitter().Emit(constraint_loc_id, RequireImplsReferenceCycle,
  216. named_constraint.name_id);
  217. return std::nullopt;
  218. }
  219. }
  220. }
  221. auto identified_facet_type_id = RequireIdentifiedFacetType(
  222. context, constraint_loc_id, self_type_id.AsConstantId(),
  223. *constraint_facet_type, [&](auto& builder) {
  224. CARBON_DIAGNOSTIC(
  225. RequireImplsUnidentifiedFacetType, Context,
  226. "facet type {0} cannot be identified in `require` declaration",
  227. SemIR::TypeId);
  228. builder.Context(constraint_loc_id, RequireImplsUnidentifiedFacetType,
  229. constraint_type_id);
  230. });
  231. if (!identified_facet_type_id.has_value()) {
  232. // The constraint can't be used. A diagnostic was emitted by
  233. // RequireIdentifiedFacetType().
  234. return std::nullopt;
  235. }
  236. const auto& identified =
  237. context.identified_facet_types().Get(identified_facet_type_id);
  238. if (!TypeStructureReferencesSelf(context, full_require_loc_id,
  239. self_type_id.AsConstantId(), identified)) {
  240. return std::nullopt;
  241. }
  242. return ValidateRequireResult{.identified_facet_type = &identified};
  243. }
  244. auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
  245. auto [constraint_node_id, constraint_inst_id] =
  246. context.node_stack().PopExprWithNodeId();
  247. auto [self_node_id, self_inst_id] =
  248. context.node_stack().PopWithNodeId<Parse::NodeCategory::RequireImpls>();
  249. auto decl_block_id = context.inst_block_stack().Pop();
  250. // Process modifiers.
  251. auto introducer =
  252. context.decl_introducer_state_stack().Pop<Lex::TokenKind::Require>();
  253. LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);
  254. bool extend = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend);
  255. auto scope_inst_id =
  256. context.node_stack().Pop<Parse::NodeKind::RequireIntroducer>();
  257. auto validated =
  258. ValidateRequire(context, node_id, constraint_node_id, self_inst_id,
  259. constraint_inst_id, scope_inst_id);
  260. if (!validated) {
  261. // In an `extend` decl, errors get propagated into the parent scope just as
  262. // names do.
  263. if (extend) {
  264. auto scope_id = context.scope_stack().PeekNameScopeId();
  265. context.name_scopes().Get(scope_id).set_has_error();
  266. }
  267. DiscardGenericDecl(context);
  268. return true;
  269. }
  270. auto [identified_facet_type] = *validated;
  271. if (identified_facet_type->required_impls().empty()) {
  272. // A `require T impls type` adds no actual constraints, so nothing to do.
  273. // This is not an error though.
  274. DiscardGenericDecl(context);
  275. return true;
  276. }
  277. // TODO: Substitute .Self here.
  278. auto constraint_type_inst_id =
  279. context.types().GetAsTypeInstId(constraint_inst_id);
  280. auto require_impls_decl =
  281. SemIR::RequireImplsDecl{// To be filled in after.
  282. .require_impls_id = SemIR::RequireImplsId::None,
  283. .decl_block_id = decl_block_id};
  284. auto decl_id = AddPlaceholderInst(context, node_id, require_impls_decl);
  285. auto require_impls_id = context.require_impls().Add(
  286. {.self_id = self_inst_id,
  287. .facet_type_inst_id = constraint_type_inst_id,
  288. .extend_self = extend,
  289. .decl_id = decl_id,
  290. .parent_scope_id = context.scope_stack().PeekNameScopeId(),
  291. .generic_id = BuildGenericDecl(context, decl_id)});
  292. require_impls_decl.require_impls_id = require_impls_id;
  293. ReplaceInstBeforeConstantUse(context, decl_id, require_impls_decl);
  294. // We look for a complete type after BuildGenericDecl, so that the resulting
  295. // RequireCompleteType instruction is part of the enclosing interface or named
  296. // constraint generic definition. Then requiring enclosing entity to be
  297. // complete will resolve that definition (via ResolveSpecificDefinition()) and
  298. // also construct a specific for the `constraint_inst_id`, finding any
  299. // monomorphization errors that result.
  300. if (extend) {
  301. if (!RequireCompleteType(
  302. context,
  303. context.types().GetTypeIdForTypeInstId(constraint_type_inst_id),
  304. constraint_node_id, [&](auto& builder) {
  305. CARBON_DIAGNOSTIC(RequireImplsIncompleteFacetType, Context,
  306. "`extend require` of incomplete facet type {0}",
  307. InstIdAsType);
  308. builder.Context(constraint_node_id,
  309. RequireImplsIncompleteFacetType,
  310. constraint_type_inst_id);
  311. })) {
  312. return true;
  313. }
  314. // The extended scope instruction must be part of the enclosing scope (and
  315. // generic). A specific for the enclosing scope will be applied to it when
  316. // using the instruction later. To do so, we wrap the constraint facet type
  317. // it in a SpecificConstant, which preserves the require declaration's
  318. // specific along with the facet type.
  319. //
  320. // TODO: Remove the separate generic for each require decl, then we don't
  321. // need a SpecificConstant anymore, as the constraint_inst_id will already
  322. // be in the generic of the interface-with-self.
  323. auto self_specific_id = context.generics().GetSelfSpecific(
  324. context.require_impls().Get(require_impls_id).generic_id);
  325. auto constraint_id_in_self_specific = AddTypeInst<SemIR::SpecificConstant>(
  326. context, node_id,
  327. {.type_id = SemIR::TypeType::TypeId,
  328. .inst_id = constraint_inst_id,
  329. .specific_id = self_specific_id});
  330. auto enclosing_scope_id = context.scope_stack().PeekNameScopeId();
  331. auto& enclosing_scope = context.name_scopes().Get(enclosing_scope_id);
  332. enclosing_scope.AddExtendedScope(constraint_id_in_self_specific);
  333. }
  334. context.require_impls_stack().AppendToTop(require_impls_id);
  335. return true;
  336. }
  337. } // namespace Carbon::Check