decl_name_stack.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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/decl_name_stack.h"
  5. #include "toolchain/base/kind_switch.h"
  6. #include "toolchain/check/context.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. namespace Carbon::Check {
  9. auto DeclNameStack::MakeEmptyNameContext() -> NameContext {
  10. return NameContext{
  11. .enclosing_scope = context_->scope_stack().PeekIndex(),
  12. .target_scope_id = context_->scope_stack().PeekNameScopeId()};
  13. }
  14. auto DeclNameStack::MakeUnqualifiedName(SemIR::LocId loc_id,
  15. SemIR::NameId name_id) -> NameContext {
  16. NameContext context = MakeEmptyNameContext();
  17. ApplyNameQualifierTo(context, loc_id, name_id, /*is_unqualified=*/true);
  18. return context;
  19. }
  20. auto DeclNameStack::PushScopeAndStartName() -> void {
  21. decl_name_stack_.push_back(MakeEmptyNameContext());
  22. // Create a scope for any parameters introduced in this name.
  23. context_->scope_stack().Push();
  24. }
  25. auto DeclNameStack::FinishName() -> NameContext {
  26. CARBON_CHECK(decl_name_stack_.back().state != NameContext::State::Finished)
  27. << "Finished name twice";
  28. if (context_->node_stack()
  29. .PopAndDiscardSoloNodeIdIf<Parse::NodeKind::QualifiedName>()) {
  30. // Any parts from a QualifiedName will already have been processed
  31. // into the name.
  32. } else {
  33. // The name had no qualifiers, so we need to process the node now.
  34. auto [loc_id, name_id] = context_->node_stack().PopNameWithNodeId();
  35. ApplyNameQualifier(loc_id, name_id);
  36. }
  37. NameContext result = decl_name_stack_.back();
  38. decl_name_stack_.back().state = NameContext::State::Finished;
  39. return result;
  40. }
  41. auto DeclNameStack::FinishImplName() -> NameContext {
  42. CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Empty)
  43. << "Impl has a name";
  44. NameContext result = decl_name_stack_.back();
  45. decl_name_stack_.back().state = NameContext::State::Finished;
  46. return result;
  47. }
  48. auto DeclNameStack::PopScope() -> void {
  49. CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished)
  50. << "Missing call to FinishName before PopScope";
  51. context_->scope_stack().PopTo(decl_name_stack_.back().enclosing_scope);
  52. decl_name_stack_.pop_back();
  53. }
  54. auto DeclNameStack::Suspend() -> SuspendedName {
  55. CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished)
  56. << "Missing call to FinishName before Suspend";
  57. SuspendedName result = {decl_name_stack_.pop_back_val(), {}};
  58. auto enclosing_index = result.name_context.enclosing_scope;
  59. auto& scope_stack = context_->scope_stack();
  60. while (scope_stack.PeekIndex() > enclosing_index) {
  61. result.scopes.push_back(scope_stack.Suspend());
  62. }
  63. CARBON_CHECK(scope_stack.PeekIndex() == enclosing_index)
  64. << "Scope index " << enclosing_index
  65. << " does not enclose the current scope " << scope_stack.PeekIndex();
  66. return result;
  67. }
  68. auto DeclNameStack::Restore(SuspendedName sus) -> void {
  69. // The enclosing state must be the same when a name is restored.
  70. CARBON_CHECK(context_->scope_stack().PeekIndex() ==
  71. sus.name_context.enclosing_scope)
  72. << "Name restored at the wrong position in the name stack.";
  73. // clang-tidy warns that the `std::move` below has no effect. While that's
  74. // true, this `move` defends against `NameContext` growing more state later.
  75. // NOLINTNEXTLINE(performance-move-const-arg)
  76. decl_name_stack_.push_back(std::move(sus.name_context));
  77. for (auto& suspended_scope : llvm::reverse(sus.scopes)) {
  78. context_->scope_stack().Restore(std::move(suspended_scope));
  79. }
  80. }
  81. auto DeclNameStack::LookupOrAddName(NameContext name_context,
  82. SemIR::InstId target_id) -> SemIR::InstId {
  83. switch (name_context.state) {
  84. case NameContext::State::Error:
  85. // The name is invalid and a diagnostic has already been emitted.
  86. return SemIR::InstId::Invalid;
  87. case NameContext::State::Empty:
  88. CARBON_FATAL() << "Name is missing, not expected to call AddNameToLookup "
  89. "(but that may change based on error handling).";
  90. case NameContext::State::Resolved:
  91. case NameContext::State::ResolvedNonScope:
  92. return name_context.resolved_inst_id;
  93. case NameContext::State::Unresolved:
  94. if (!name_context.target_scope_id.is_valid()) {
  95. context_->AddNameToLookup(name_context.unresolved_name_id, target_id);
  96. } else {
  97. auto& name_scope =
  98. context_->name_scopes().Get(name_context.target_scope_id);
  99. if (name_context.has_qualifiers) {
  100. auto inst = context_->insts().Get(name_scope.inst_id);
  101. if (!inst.Is<SemIR::Namespace>()) {
  102. // TODO: Point at the declaration for the scoped entity.
  103. CARBON_DIAGNOSTIC(
  104. QualifiedDeclOutsideScopeEntity, Error,
  105. "Out-of-line declaration requires a declaration in "
  106. "scoped entity.");
  107. context_->emitter().Emit(name_context.loc_id,
  108. QualifiedDeclOutsideScopeEntity);
  109. }
  110. }
  111. // Exports are only tracked when the declaration is at the file-level
  112. // scope. Otherwise, it's in some other entity, such as a class.
  113. if (name_context.enclosing_scope == ScopeIndex::Package) {
  114. context_->AddExport(target_id);
  115. }
  116. auto [_, success] = name_scope.names.insert(
  117. {name_context.unresolved_name_id, target_id});
  118. CARBON_CHECK(success)
  119. << "Duplicate names should have been resolved previously: "
  120. << name_context.unresolved_name_id << " in "
  121. << name_context.target_scope_id;
  122. }
  123. return SemIR::InstId::Invalid;
  124. case NameContext::State::Finished:
  125. CARBON_FATAL() << "Finished state should only be used internally";
  126. }
  127. }
  128. auto DeclNameStack::AddNameToLookup(NameContext name_context,
  129. SemIR::InstId target_id) -> void {
  130. auto existing_inst_id = LookupOrAddName(name_context, target_id);
  131. if (existing_inst_id.is_valid()) {
  132. context_->DiagnoseDuplicateName(target_id, existing_inst_id);
  133. }
  134. }
  135. auto DeclNameStack::ApplyNameQualifier(SemIR::LocId loc_id,
  136. SemIR::NameId name_id) -> void {
  137. ApplyNameQualifierTo(decl_name_stack_.back(), loc_id, name_id,
  138. /*is_unqualified=*/false);
  139. }
  140. auto DeclNameStack::ApplyNameQualifierTo(NameContext& name_context,
  141. SemIR::LocId loc_id,
  142. SemIR::NameId name_id,
  143. bool is_unqualified) -> void {
  144. if (TryResolveQualifier(name_context, loc_id)) {
  145. // For identifier nodes, we need to perform a lookup on the identifier.
  146. auto resolved_inst_id = context_->LookupNameInDecl(
  147. name_context.loc_id, name_id, name_context.target_scope_id,
  148. /*mark_imports_used=*/false);
  149. if (!resolved_inst_id.is_valid()) {
  150. // Invalid indicates an unresolved name. Store it and return.
  151. name_context.state = NameContext::State::Unresolved;
  152. name_context.unresolved_name_id = name_id;
  153. return;
  154. } else {
  155. // Store the resolved instruction and continue for the target scope
  156. // update.
  157. name_context.resolved_inst_id = resolved_inst_id;
  158. }
  159. UpdateScopeIfNeeded(name_context, is_unqualified);
  160. }
  161. }
  162. // Push a scope corresponding to a name qualifier. For example, for
  163. //
  164. // fn Class(T:! type).F(n: i32)
  165. //
  166. // we will push the scope for `Class(T:! type)` between the scope containing the
  167. // declaration of `T` and the scope containing the declaration of `n`.
  168. static auto PushNameQualifierScope(Context& context,
  169. SemIR::InstId scope_inst_id,
  170. SemIR::NameScopeId scope_id,
  171. bool has_error = false) -> void {
  172. // If the qualifier has no parameters, we don't need to keep around a
  173. // parameter scope.
  174. context.scope_stack().PopIfEmpty();
  175. context.scope_stack().Push(scope_inst_id, scope_id, has_error);
  176. // Enter a parameter scope in case the qualified name itself has parameters.
  177. context.scope_stack().Push();
  178. }
  179. auto DeclNameStack::UpdateScopeIfNeeded(NameContext& name_context,
  180. bool is_unqualified) -> void {
  181. // This will only be reached for resolved instructions. We update the target
  182. // scope based on the resolved type.
  183. CARBON_KIND_SWITCH(context_->insts().Get(name_context.resolved_inst_id)) {
  184. case CARBON_KIND(SemIR::ClassDecl resolved_inst): {
  185. const auto& class_info = context_->classes().Get(resolved_inst.class_id);
  186. if (class_info.is_defined()) {
  187. name_context.state = NameContext::State::Resolved;
  188. name_context.target_scope_id = class_info.scope_id;
  189. if (!is_unqualified) {
  190. PushNameQualifierScope(*context_, name_context.resolved_inst_id,
  191. class_info.scope_id);
  192. }
  193. } else {
  194. name_context.state = NameContext::State::ResolvedNonScope;
  195. }
  196. break;
  197. }
  198. case CARBON_KIND(SemIR::InterfaceDecl resolved_inst): {
  199. const auto& interface_info =
  200. context_->interfaces().Get(resolved_inst.interface_id);
  201. if (interface_info.is_defined()) {
  202. name_context.state = NameContext::State::Resolved;
  203. name_context.target_scope_id = interface_info.scope_id;
  204. if (!is_unqualified) {
  205. PushNameQualifierScope(*context_, name_context.resolved_inst_id,
  206. interface_info.scope_id);
  207. }
  208. } else {
  209. name_context.state = NameContext::State::ResolvedNonScope;
  210. }
  211. break;
  212. }
  213. case CARBON_KIND(SemIR::Namespace resolved_inst): {
  214. auto scope_id = resolved_inst.name_scope_id;
  215. name_context.state = NameContext::State::Resolved;
  216. name_context.target_scope_id = scope_id;
  217. auto& scope = context_->name_scopes().Get(scope_id);
  218. if (scope.is_closed_import) {
  219. CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackage, Error,
  220. "Imported packages cannot be used for declarations.");
  221. CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackageSource, Note,
  222. "Package imported here.");
  223. context_->emitter()
  224. .Build(name_context.loc_id, QualifiedDeclOutsidePackage)
  225. .Note(scope.inst_id, QualifiedDeclOutsidePackageSource)
  226. .Emit();
  227. // Only error once per package.
  228. scope.is_closed_import = false;
  229. }
  230. if (!is_unqualified) {
  231. PushNameQualifierScope(*context_, name_context.resolved_inst_id,
  232. scope_id,
  233. context_->name_scopes().Get(scope_id).has_error);
  234. }
  235. break;
  236. }
  237. default:
  238. name_context.state = NameContext::State::ResolvedNonScope;
  239. break;
  240. }
  241. }
  242. auto DeclNameStack::TryResolveQualifier(NameContext& name_context,
  243. SemIR::LocId loc_id) -> bool {
  244. // Update has_qualifiers based on the state before any possible changes. If
  245. // this is the first qualifier, it may just be the name.
  246. name_context.has_qualifiers = name_context.state != NameContext::State::Empty;
  247. switch (name_context.state) {
  248. case NameContext::State::Error:
  249. // Already in an error state, so return without examining.
  250. return false;
  251. case NameContext::State::Unresolved:
  252. // Because more qualifiers were found, we diagnose that the earlier
  253. // qualifier failed to resolve.
  254. name_context.state = NameContext::State::Error;
  255. context_->DiagnoseNameNotFound(name_context.loc_id,
  256. name_context.unresolved_name_id);
  257. return false;
  258. case NameContext::State::ResolvedNonScope: {
  259. // Because more qualifiers were found, we diagnose that the earlier
  260. // qualifier didn't resolve to a scoped entity.
  261. if (auto class_decl = context_->insts().TryGetAs<SemIR::ClassDecl>(
  262. name_context.resolved_inst_id)) {
  263. CARBON_DIAGNOSTIC(QualifiedDeclInIncompleteClassScope, Error,
  264. "Cannot declare a member of incomplete class `{0}`.",
  265. SemIR::TypeId);
  266. auto builder = context_->emitter().Build(
  267. name_context.loc_id, QualifiedDeclInIncompleteClassScope,
  268. context_->classes().Get(class_decl->class_id).self_type_id);
  269. context_->NoteIncompleteClass(class_decl->class_id, builder);
  270. builder.Emit();
  271. } else if (auto interface_decl =
  272. context_->insts().TryGetAs<SemIR::InterfaceDecl>(
  273. name_context.resolved_inst_id)) {
  274. CARBON_DIAGNOSTIC(
  275. QualifiedDeclInUndefinedInterfaceScope, Error,
  276. "Cannot declare a member of undefined interface `{0}`.",
  277. std::string);
  278. auto builder = context_->emitter().Build(
  279. name_context.loc_id, QualifiedDeclInUndefinedInterfaceScope,
  280. context_->sem_ir().StringifyTypeExpr(
  281. context_->sem_ir()
  282. .constant_values()
  283. .Get(name_context.resolved_inst_id)
  284. .inst_id()));
  285. context_->NoteUndefinedInterface(interface_decl->interface_id, builder);
  286. builder.Emit();
  287. } else {
  288. CARBON_DIAGNOSTIC(QualifiedNameInNonScope, Error,
  289. "Name qualifiers are only allowed for entities that "
  290. "provide a scope.");
  291. CARBON_DIAGNOSTIC(QualifiedNameNonScopeEntity, Note,
  292. "Non-scope entity referenced here.");
  293. context_->emitter()
  294. .Build(loc_id, QualifiedNameInNonScope)
  295. .Note(name_context.loc_id, QualifiedNameNonScopeEntity)
  296. .Emit();
  297. }
  298. name_context.state = NameContext::State::Error;
  299. return false;
  300. }
  301. case NameContext::State::Empty:
  302. case NameContext::State::Resolved: {
  303. name_context.loc_id = loc_id;
  304. return true;
  305. }
  306. case NameContext::State::Finished:
  307. CARBON_FATAL() << "Added a qualifier after calling FinishName";
  308. }
  309. }
  310. } // namespace Carbon::Check