Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #ifndef RUST_RIB_H
20 : : #define RUST_RIB_H
21 : :
22 : : #include "rust-system.h"
23 : : #include "rust-ast.h"
24 : : #include "optional.h"
25 : : #include "expected.h"
26 : :
27 : : namespace Rust {
28 : : namespace Resolver2_0 {
29 : :
30 : : /**
31 : :
32 : : pub enum Namespace {
33 : : /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and
34 : : `mod`s
35 : : /// (and, by extension, crates).
36 : : ///
37 : : /// Note that the type namespace includes other items; this is not an
38 : : /// exhaustive list.
39 : : TypeNS,
40 : : /// The value namespace includes `fn`s, `const`s, `static`s, and local
41 : : variables (including function arguments). ValueNS,
42 : : /// The macro namespace includes `macro_rules!` macros, declarative `macro`s,
43 : : /// procedural macros, attribute macros, `derive` macros, and non-macro
44 : : attributes
45 : : /// like `#[inline]` and `#[rustfmt::skip]`.
46 : : MacroNS,
47 : : }
48 : :
49 : : */
50 : :
51 : : // FIXME: There's no `labels` namespace, not sure if we need one or how to keep
52 : : // one
53 : : // FIXME: And where are things like loop labels kept?
54 : :
55 : : /**
56 : : * All namespaces that Rust's name resolution needs to handle
57 : : */
58 : : // TODO: Move to `rust-forever-stack.h`?
59 : : enum class Namespace
60 : : {
61 : : Values,
62 : : Types,
63 : : Labels,
64 : : Macros,
65 : : // TODO: Which namespaces are we missing?
66 : : };
67 : :
68 : : /**
69 : : * Error returned by `Rib::insert` when the key was already present in the Rib's
70 : : * map. The class contains the previously-inserted NodeId as well as the name of
71 : : * the node.
72 : : */
73 : 76 : struct DuplicateNameError
74 : : {
75 : : // TODO: We might need multiple kinds of errors later down the line
76 : : DuplicateNameError (std::string name, NodeId existing);
77 : :
78 : : std::string name;
79 : : NodeId existing;
80 : : };
81 : :
82 : : /**
83 : : * A rib is a container of nodes, either declaration or usages, as well as the
84 : : * identifier each node uses. They are used to delimit lexical scopes, and have
85 : : * an impact on name resolution - they restrict certain name accesses and serve
86 : : * as boundaries between scopes.
87 : :
88 : : * For example, if we are resolving the following *variable* use:
89 : : *
90 : : * ```rust
91 : : * fn outer() {
92 : : * let a = 15; // decl
93 : : * fn inner() -> i32 {
94 : : * a // use
95 : : * }
96 : : * }
97 : : * ```
98 : : *
99 : : * The `Function` rib we will have pushed will restrict the access to `outer`'s
100 : : * `a` declaration: Variable uses cannot cross function boundaries. On the other
101 : : * hand, if we were resolving a type usage, this would be perfectly allowed.
102 : : */
103 : 55917 : class Rib
104 : : {
105 : : public:
106 : : // TODO: Rename the class? to what? Binding? Declaration?
107 : : // This is useful for items which are in namespaces where shadowing is not
108 : : // allowed, but which are still shadowable! for example, when you do a glob
109 : : // import, if a later import has the same name as an item imported in the glob
110 : : // import, that glob imported item will need to get shadowed
111 : 10164 : class Definition
112 : : {
113 : : public:
114 : : static Definition NonShadowable (NodeId id);
115 : : static Definition Shadowable (NodeId id);
116 : :
117 : : std::vector<NodeId> ids;
118 : : bool shadowable;
119 : :
120 : 652 : Definition () = default;
121 : :
122 : 653 : Definition &operator= (const Definition &) = default;
123 : 8808 : Definition (Definition const &) = default;
124 : :
125 : : bool is_ambiguous () const;
126 : :
127 : 199 : NodeId get_node_id ()
128 : : {
129 : 199 : rust_assert (!is_ambiguous ());
130 : 199 : return ids[0];
131 : : }
132 : :
133 : : std::string to_string () const;
134 : :
135 : : private:
136 : : Definition (NodeId id, bool shadowable);
137 : : };
138 : :
139 : : enum class Kind
140 : : {
141 : : Normal,
142 : : Module,
143 : : Function,
144 : : ConstantItem, // -> this variant has a boolean
145 : : TraitOrImpl,
146 : : /* Any item other than a Module, Function, Constant, Trait or Impl block */
147 : : Item,
148 : : Closure,
149 : : MacroDefinition,
150 : : /* Ban the use of forward-declared generic parameters in defaults */
151 : : ForwardTypeParamBan,
152 : : /* Const generic, as in the following example: fn foo<T, const X: T>() {} */
153 : : ConstParamType,
154 : : } kind;
155 : :
156 : : Rib (Kind kind);
157 : : Rib (Kind kind, std::string identifier, NodeId id);
158 : : Rib (Kind kind, std::unordered_map<std::string, NodeId> values);
159 : :
160 : : // TODO: What's the correctbehavior if the key already exists? What if a decl
161 : : // and use are in the same rib? Is that possible? Okay based on RibKind?
162 : :
163 : : /**
164 : : * Insert a new node in the rib
165 : : *
166 : : * @param name The name associated with the AST node
167 : : * @param def The `Definition` to insert
168 : : *
169 : : * @return `DuplicateNameError` if the node is already present in the rib. The
170 : : * `DuplicateNameError` class contains the NodeId of the existing
171 : : * node. Returns the new NodeId on success.
172 : : */
173 : : tl::expected<NodeId, DuplicateNameError> insert (std::string name,
174 : : Definition def);
175 : :
176 : : /**
177 : : * Access an inserted NodeId.
178 : : *
179 : : * @return tl::nullopt if the key does not exist, the NodeId otherwise
180 : : */
181 : : tl::optional<Rib::Definition> get (const std::string &name);
182 : :
183 : : /* View all the values stored in the rib */
184 : : const std::unordered_map<std::string, Definition> &get_values () const;
185 : :
186 : : private:
187 : : // TODO: Switch this to (NodeId, shadowable = false);
188 : : std::unordered_map<std::string, Definition> values;
189 : : };
190 : :
191 : : } // namespace Resolver2_0
192 : : } // namespace Rust
193 : :
194 : : #endif // !RUST_RIB_H
|