scope_stack.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. #ifndef CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_
  5. #define CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_
  6. #include "common/array_stack.h"
  7. #include "common/move_only.h"
  8. #include "common/set.h"
  9. #include "llvm/ADT/SmallVector.h"
  10. #include "toolchain/check/full_pattern_stack.h"
  11. #include "toolchain/check/lexical_lookup.h"
  12. #include "toolchain/check/scope_index.h"
  13. #include "toolchain/sem_ir/file.h"
  14. #include "toolchain/sem_ir/ids.h"
  15. namespace Carbon::Check {
  16. class Context;
  17. // A stack of lexical and semantic scopes that we are currently performing
  18. // checking within.
  19. class ScopeStack {
  20. public:
  21. explicit ScopeStack(Context& context);
  22. // A scope in which `break` and `continue` can be used.
  23. struct BreakContinueScope {
  24. SemIR::InstBlockId break_target;
  25. SemIR::InstBlockId continue_target;
  26. };
  27. // A non-lexical scope in which unqualified lookup may be required.
  28. struct NonLexicalScope {
  29. // The index of the scope in the scope stack.
  30. ScopeIndex scope_index;
  31. // The corresponding name scope.
  32. SemIR::NameScopeId name_scope_id;
  33. // The corresponding specific.
  34. SemIR::SpecificId specific_id;
  35. };
  36. // Information about a scope that has been temporarily removed from the stack.
  37. // This type is large, so moves of this type should be avoided.
  38. struct SuspendedScope;
  39. // Pushes a scope for a declaration name's parameters.
  40. auto PushForDeclName() -> void;
  41. // Pushes a non-function entity scope. Functions must use
  42. // `PushForFunctionBody` instead.
  43. auto PushForEntity(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
  44. SemIR::SpecificId specific_id,
  45. bool lexical_lookup_has_load_error = false) -> void;
  46. // Pushes a scope which should be in the same region as the current scope.
  47. // These can be in a function without breaking `return` scoping. For example,
  48. // this is used by struct literals and code blocks.
  49. auto PushForSameRegion() -> void;
  50. // Pushes a function scope.
  51. auto PushForFunctionBody(SemIR::InstId scope_inst_id) -> void;
  52. // Pops the top scope from scope_stack_. Removes names from lexical_lookup_.
  53. // If `check_unused` is set, checks and emits diagnostics for unused names.
  54. auto Pop(bool check_unused = false) -> void;
  55. // Pops the top scope from scope_stack_ if it contains no names.
  56. auto PopIfEmpty(bool check_unused = false) -> void {
  57. if (scope_stack_.back().num_names == 0) {
  58. Pop(check_unused);
  59. }
  60. }
  61. // Pops scopes until we return to the specified scope index.
  62. auto PopTo(ScopeIndex index, bool check_unused = false) -> void;
  63. // Returns the scope index associated with the current scope.
  64. auto PeekIndex() const -> ScopeIndex { return Peek().index; }
  65. // Returns the name scope associated with the current lexical scope, if any.
  66. auto PeekNameScopeId() const -> SemIR::NameScopeId { return Peek().scope_id; }
  67. // Returns the instruction associated with the current scope, or `None` if
  68. // there is no such instruction, such as for a block scope.
  69. auto PeekInstId() const -> SemIR::InstId { return Peek().scope_inst_id; }
  70. // Returns the specific associated with the innermost enclosing scope that is
  71. // associated with a specific. This will generally be the self specific of the
  72. // innermost enclosing generic, as there is no way to enter any other specific
  73. // scope.
  74. auto PeekSpecificId() const -> SemIR::SpecificId {
  75. return Peek().specific_id;
  76. }
  77. // Returns true if the current scope is inside a function scope (either the
  78. // scope itself, or a lexical scope), without an intervening entity scope.
  79. auto IsInFunctionScope() const -> bool {
  80. return !return_scope_stack_.empty() &&
  81. !return_scope_stack_.back().nested_scope_index.has_value();
  82. }
  83. // Returns the current scope, if it is of the specified kind. Otherwise,
  84. // returns nullopt.
  85. template <typename InstT>
  86. auto TryGetCurrentScopeAs() -> std::optional<InstT> {
  87. auto inst_id = PeekInstId();
  88. if (!inst_id.has_value()) {
  89. return std::nullopt;
  90. }
  91. return sem_ir().insts().TryGetAs<InstT>(inst_id);
  92. }
  93. // Returns the current scope, assuming it is of the specified kind.
  94. // Check-fails if there is no instruction for a current scope, or the scope is
  95. // of a different kind.
  96. template <typename InstT>
  97. auto GetCurrentScopeAs() -> InstT {
  98. auto inst_id = PeekInstId();
  99. CARBON_CHECK(inst_id.has_value());
  100. return sem_ir().insts().GetAs<InstT>(inst_id);
  101. }
  102. // If there is no `returned var` in scope, sets the given instruction to be
  103. // the current `returned var` and returns an `None`. If there
  104. // is already a `returned var`, returns it instead.
  105. auto SetReturnedVarOrGetExisting(SemIR::InstId inst_id, SemIR::NameId name_id)
  106. -> SemIR::InstId;
  107. // Returns the `returned var` instruction that's currently in scope, or `None`
  108. // if there isn't one.
  109. auto GetReturnedVar() -> SemIR::InstId {
  110. CARBON_CHECK(IsInFunctionScope(), "Handling return but not in a function");
  111. return return_scope_stack_.back().returned_var;
  112. }
  113. // Returns the decl ID for the current return scope.
  114. auto GetReturnScopeDeclId() -> SemIR::InstId {
  115. CARBON_CHECK(IsInFunctionScope(), "Handling return but not in a function");
  116. return return_scope_stack_.back().decl_id;
  117. }
  118. // Looks up the name `name_id` in the current scope and enclosing scopes, but
  119. // do not look past `scope_index`. Returns the existing lookup result, if any.
  120. // If `use_loc_id` is specified, the name is marked as used at that location.
  121. auto LookupInLexicalScopesWithin(SemIR::NameId name_id,
  122. ScopeIndex scope_index,
  123. SemIR::LocId use_loc_id, bool is_reachable)
  124. -> SemIR::InstId;
  125. // Looks up the name `name_id` in the current scope and related lexical
  126. // scopes. Returns the innermost lexical lookup result, if any, along with a
  127. // list of non-lexical scopes in which lookup should also be performed,
  128. // ordered from outermost to innermost. If `use_loc_id` is specified, the
  129. // name is marked as used at that location.
  130. auto LookupInLexicalScopes(SemIR::NameId name_id, SemIR::LocId use_loc_id,
  131. bool is_reachable)
  132. -> std::pair<SemIR::InstId, llvm::ArrayRef<NonLexicalScope>>;
  133. // Looks up the name `name_id` in the current scope, or in `scope_index` if
  134. // specified. Returns the existing instruction if the name is already declared
  135. // in that scope or any unfinished scope within it, and otherwise adds the
  136. // name with the value `target_id` and returns `None`. `is_decl_reachable`
  137. // indicates whether the name was declared in a reachable position.
  138. auto LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,
  139. ScopeIndex scope_index = ScopeIndex::None,
  140. bool is_decl_reachable = true) -> SemIR::InstId;
  141. // Prepares to add a compile-time binding in the current scope, and returns
  142. // its index. The added binding must then be pushed using
  143. // `PushCompileTimeBinding`.
  144. auto AddCompileTimeBinding() -> SemIR::CompileTimeBindIndex {
  145. auto index = scope_stack_.back().next_compile_time_bind_index;
  146. ++scope_stack_.back().next_compile_time_bind_index.index;
  147. return index;
  148. }
  149. // Pushes a compile-time binding into the current scope.
  150. auto PushCompileTimeBinding(SemIR::InstId bind_id) -> void {
  151. compile_time_binding_stack_.AppendToTop(bind_id);
  152. }
  153. // Temporarily removes the top of the stack and its lexical lookup results.
  154. auto Suspend() -> SuspendedScope;
  155. // Restores a suspended scope stack entry.
  156. auto Restore(SuspendedScope&& scope) -> void;
  157. // Runs verification that the processing cleanly finished.
  158. auto VerifyOnFinish() const -> void;
  159. auto break_continue_stack() -> llvm::SmallVector<BreakContinueScope>& {
  160. return break_continue_stack_;
  161. }
  162. auto destroy_id_stack() -> ArrayStack<SemIR::InstId>& {
  163. return destroy_id_stack_;
  164. }
  165. auto compile_time_binding_stack() -> ArrayStack<SemIR::InstId>& {
  166. return compile_time_binding_stack_;
  167. }
  168. auto full_pattern_stack() -> FullPatternStack& { return full_pattern_stack_; }
  169. private:
  170. auto sem_ir() const -> const SemIR::File&;
  171. auto lexical_lookup() -> LexicalLookup& { return lexical_lookup_; }
  172. // An entry in scope_stack_.
  173. struct ScopeStackEntry : public MoveOnly<ScopeStackEntry> {
  174. auto is_lexical_scope() const -> bool { return !scope_id.has_value(); }
  175. // The sequential index of this scope entry within the file.
  176. ScopeIndex index;
  177. // The instruction associated with this entry, if any. This can be one of:
  178. //
  179. // - A `ClassDecl`, for a class definition scope.
  180. // - A `FunctionDecl`, for the outermost scope in a function
  181. // definition.
  182. // - Invalid, for any other scope.
  183. SemIR::InstId scope_inst_id;
  184. // The name scope associated with this entry, if any.
  185. SemIR::NameScopeId scope_id;
  186. // The specific associated with this entry, if any.
  187. SemIR::SpecificId specific_id;
  188. // The next compile-time binding index to allocate in this scope.
  189. SemIR::CompileTimeBindIndex next_compile_time_bind_index;
  190. // Whether lexical_lookup_ has load errors from this scope or an ancestor
  191. // scope.
  192. bool lexical_lookup_has_load_error;
  193. // Whether a `returned var` was introduced in this scope, and needs to be
  194. // unregistered when the scope ends.
  195. bool has_returned_var = false;
  196. // Whether there are any ids in the `names` set.
  197. int num_names = 0;
  198. // Names which are registered with lexical_lookup_, and will need to be
  199. // unregistered when the scope ends.
  200. Set<SemIR::NameId> names = {};
  201. };
  202. // A scope in which `return` can be used.
  203. struct ReturnScope {
  204. // The `FunctionDecl`.
  205. SemIR::InstId decl_id;
  206. // The value corresponding to the current `returned var`, if any. Will be
  207. // set and unset as `returned var`s are declared and go out of scope.
  208. SemIR::InstId returned_var = SemIR::InstId::None;
  209. // When a nested scope interrupts a return scope, this is the index of the
  210. // outermost interrupting scope (the one closest to the function scope).
  211. // This can then be used to determine whether we're actually inside the most
  212. // recent `ReturnScope`, or inside a different entity scope.
  213. //
  214. // This won't be set for functions directly inside functions, because they
  215. // will have their own `ReturnScope`.
  216. // For example, when a `class` is inside a `fn`, it interrupts the function
  217. // body by setting this on `PushEntity`; `Pop` will set it back to `None`.
  218. ScopeIndex nested_scope_index = ScopeIndex::None;
  219. };
  220. // Pushes a scope onto scope_stack_. NameScopeId::None is used for new scopes.
  221. // lexical_lookup_has_load_error is used to limit diagnostics when a given
  222. // namespace may contain a mix of both successful and failed name imports.
  223. auto Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
  224. SemIR::SpecificId specific_id, bool lexical_lookup_has_load_error)
  225. -> void;
  226. auto Peek() const -> const ScopeStackEntry& { return scope_stack_.back(); }
  227. // Returns whether lexical lookup currently has any load errors.
  228. auto LexicalLookupHasLoadError() const -> bool {
  229. return !scope_stack_.empty() &&
  230. scope_stack_.back().lexical_lookup_has_load_error;
  231. }
  232. // If inside a return scope, marks a nested scope (see `nested_scope_index`).
  233. // Called after pushing the new scope.
  234. auto MarkNestingIfInReturnScope() -> void {
  235. if (!return_scope_stack_.empty() &&
  236. !return_scope_stack_.back().nested_scope_index.has_value()) {
  237. return_scope_stack_.back().nested_scope_index = scope_stack_.back().index;
  238. }
  239. }
  240. // Marks the name `name_id` as used at the given location.
  241. auto MarkUsed(SemIR::NameId name_id, SemIR::LocId loc_id, bool is_reachable)
  242. -> void;
  243. // Checks that the provided scope's `next_compile_time_bind_index` matches the
  244. // full size of the current `compile_time_binding_stack_`. The values should
  245. // always match, and this is used to validate the correspondence during
  246. // significant changes.
  247. auto VerifyNextCompileTimeBindIndex(llvm::StringLiteral label,
  248. const ScopeStackEntry& scope) -> void;
  249. // Context, used only for checks and emitting diagnostics.
  250. Context* context_;
  251. // A stack of scopes from which we can `return`.
  252. llvm::SmallVector<ReturnScope> return_scope_stack_;
  253. // A stack of `break` and `continue` targets.
  254. llvm::SmallVector<BreakContinueScope> break_continue_stack_;
  255. // A stack for scope context.
  256. llvm::SmallVector<ScopeStackEntry> scope_stack_;
  257. // A stack of instances to destroy. This only has entries inside of function
  258. // bodies, where destruction on scope exit is required.
  259. ArrayStack<SemIR::InstId> destroy_id_stack_;
  260. // Information about non-lexical scopes. This is a subset of the entries and
  261. // the information in scope_stack_.
  262. llvm::SmallVector<NonLexicalScope> non_lexical_scope_stack_;
  263. // A stack of the current compile time bindings.
  264. ArrayStack<SemIR::InstId> compile_time_binding_stack_;
  265. // The index of the next scope that will be pushed onto scope_stack_. The
  266. // first is always the package scope.
  267. ScopeIndex next_scope_index_ = ScopeIndex::Package;
  268. // Tracks lexical lookup results.
  269. LexicalLookup lexical_lookup_;
  270. // Stack of full-patterns currently being checked.
  271. FullPatternStack full_pattern_stack_;
  272. };
  273. struct ScopeStack::SuspendedScope : public MoveOnly<SuspendedScope> {
  274. // An item that was suspended within this scope. This represents either a
  275. // lexical lookup entry in this scope, or a compile time binding entry in this
  276. // scope.
  277. //
  278. // TODO: For compile-time bindings, the common case is that they will both
  279. // have a suspended lexical lookup entry and a suspended compile time binding
  280. // entry. We should be able to store that as a single ScopeItem rather than
  281. // two.
  282. struct ScopeItem {
  283. static constexpr uint32_t IndexForCompileTimeBinding = -1;
  284. // The scope index for a LexicalLookup::SuspendedResult, or
  285. // CompileTimeBindingIndex for a suspended compile time binding.
  286. uint32_t index;
  287. // The instruction within the scope.
  288. SemIR::InstId inst_id;
  289. // Whether the name was declared in a reachable position.
  290. bool is_decl_reachable;
  291. // The location of the first use of the name, if any.
  292. SemIR::LocId use_loc_id;
  293. };
  294. // The suspended scope stack entry.
  295. ScopeStackEntry entry;
  296. // The list of items that were within this scope when it was suspended. The
  297. // inline size is an attempt to keep the size of a `SuspendedFunction`
  298. // reasonable while avoiding heap allocations most of the time.
  299. llvm::SmallVector<ScopeItem, 8> suspended_items;
  300. };
  301. } // namespace Carbon::Check
  302. #endif // CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_