1 // Copyright (C) 2020-2023 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_NAME_RESOLVER_H
20 #define RUST_NAME_RESOLVER_H
21
22 #include "rust-system.h"
23 #include "rust-canonical-path.h"
24 #include "rust-hir-map.h"
25 #include "rust-hir-type-check.h"
26
27 namespace Rust {
28 namespace Resolver {
29
30 class Rib
31 {
32 public:
33 enum ItemType
34 {
35 Var,
36 Param,
37 Function,
38 Type,
39 Module,
40 Static,
41 Const,
42 Trait,
43 Impl,
44 TraitImpl,
45 ExternCrate,
46 MacroDecl,
47 Label,
48 Unknown
49 };
50
51 // FIXME
52 // Rust uses local_def_ids assigned by def_collector on the AST. Consider
53 // moving to a local-def-id
54 Rib (CrateNum crateNum, NodeId node_id);
55
56 // this takes the relative paths of items within a compilation unit for lookup
57 void insert_name (
58 const CanonicalPath &path, NodeId id, Location locus, bool shadow,
59 ItemType type,
60 std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb);
61
62 bool lookup_canonical_path (const NodeId &id, CanonicalPath *ident);
63 bool lookup_name (const CanonicalPath &ident, NodeId *id);
64 void clear_name (const CanonicalPath &ident, NodeId id);
65 void append_reference_for_def (NodeId def, NodeId ref);
66 bool have_references_for_node (NodeId def) const;
67 bool decl_was_declared_here (NodeId def) const;
68 bool lookup_decl_type (NodeId def, ItemType *type) const;
69 void debug () const;
70 std::string debug_str () const;
71
72 CrateNum get_crate_num () const { return crate_num; }
73 NodeId get_node_id () const { return node_id; }
74 std::map<NodeId, Location> &get_declarations () { return decls_within_rib; }
75
76 private:
77 CrateNum crate_num;
78 NodeId node_id;
79 std::map<CanonicalPath, NodeId> path_mappings;
80 std::map<NodeId, CanonicalPath> reverse_path_mappings;
81 std::map<NodeId, Location> decls_within_rib;
82 std::map<NodeId, std::set<NodeId>> references;
83 std::map<NodeId, ItemType> decl_type_mappings;
84 };
85
86 class Scope
87 {
88 public:
89 Scope (CrateNum crate_num);
90
91 void
92 insert (const CanonicalPath &ident, NodeId id, Location locus, bool shadow,
93 Rib::ItemType type,
94 std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb);
95
96 void insert (const CanonicalPath &ident, NodeId id, Location locus,
97 Rib::ItemType type = Rib::ItemType::Unknown);
98 bool lookup (const CanonicalPath &ident, NodeId *id);
99 bool lookup_decl_type (NodeId id, Rib::ItemType *type);
100 bool lookup_rib_for_decl (NodeId id, const Rib **rib);
101
102 void iterate (std::function<bool (Rib *)> cb);
103 void iterate (std::function<bool (const Rib *)> cb) const;
104
105 Rib *peek ();
106 void push (NodeId id);
107 Rib *pop ();
108
109 bool decl_was_declared_here (NodeId def) const;
110 void append_reference_for_def (NodeId refId, NodeId defId);
111
112 CrateNum get_crate_num () const { return crate_num; }
113
114 const std::vector<Rib *> &get_context () const { return stack; };
115
116 private:
117 CrateNum crate_num;
118 std::vector<Rib *> stack;
119 };
120
121 class Resolver
122 {
123 public:
124 static Resolver *get ();
125 ~Resolver () {}
126
127 // these builtin types
128 void insert_builtin_types (Rib *r);
129
130 // these will be required for type resolution passes to
131 // map back to tyty nodes
132 std::vector<AST::Type *> &get_builtin_types ();
133
134 void push_new_name_rib (Rib *r);
135 void push_new_type_rib (Rib *r);
136 void push_new_label_rib (Rib *r);
137 void push_new_macro_rib (Rib *r);
138
139 bool find_name_rib (NodeId id, Rib **rib);
140 bool find_type_rib (NodeId id, Rib **rib);
141 bool find_label_rib (NodeId id, Rib **rib);
142 bool find_macro_rib (NodeId id, Rib **rib);
143
144 void insert_resolved_name (NodeId refId, NodeId defId);
145 bool lookup_resolved_name (NodeId refId, NodeId *defId);
146
147 void insert_resolved_type (NodeId refId, NodeId defId);
148 bool lookup_resolved_type (NodeId refId, NodeId *defId);
149
150 void insert_resolved_label (NodeId refId, NodeId defId);
151 bool lookup_resolved_label (NodeId refId, NodeId *defId);
152
153 void insert_resolved_macro (NodeId refId, NodeId defId);
154 bool lookup_resolved_macro (NodeId refId, NodeId *defId);
155
156 void insert_resolved_misc (NodeId refId, NodeId defId);
157 bool lookup_resolved_misc (NodeId refId, NodeId *defId);
158
159 // proxy for scoping
160 Scope &get_name_scope () { return name_scope; }
161 Scope &get_type_scope () { return type_scope; }
162 Scope &get_label_scope () { return label_scope; }
163 Scope &get_macro_scope () { return macro_scope; }
164
165 NodeId get_global_type_node_id () { return global_type_node_id; }
166 void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; }
167 NodeId get_unit_type_node_id () { return unit_ty_node_id; }
168
169 void push_new_module_scope (NodeId module_id)
170 {
171 current_module_stack.push_back (module_id);
172 }
173
174 void pop_module_scope ()
175 {
176 rust_assert (!current_module_stack.empty ());
177 current_module_stack.pop_back ();
178 }
179
180 NodeId peek_current_module_scope () const
181 {
182 rust_assert (!current_module_stack.empty ());
183 return current_module_stack.back ();
184 }
185
186 NodeId peek_crate_module_scope () const
187 {
188 rust_assert (!current_module_stack.empty ());
189 return current_module_stack.front ();
190 }
191
192 NodeId peek_parent_module_scope () const
193 {
194 rust_assert (current_module_stack.size () > 1);
195 return current_module_stack.at (current_module_stack.size () - 2);
196 }
197
198 void push_closure_context (NodeId closure_expr_id);
199 void pop_closure_context ();
200 void insert_captured_item (NodeId id);
201 const std::set<NodeId> &get_captures (NodeId id) const;
202
203 protected:
204 bool decl_needs_capture (NodeId decl_rib_node_id, NodeId closure_rib_node_id,
205 const Scope &scope);
206
207 private:
208 Resolver ();
209
210 void generate_builtins ();
211 void setup_builtin (const std::string &name, TyTy::BaseType *tyty);
212
213 Analysis::Mappings *mappings;
214 TypeCheckContext *tyctx;
215
216 std::vector<AST::Type *> builtins;
217
218 Scope name_scope;
219 Scope type_scope;
220 Scope label_scope;
221 Scope macro_scope;
222
223 NodeId global_type_node_id;
224 NodeId unit_ty_node_id;
225
226 // map a AST Node to a Rib
227 std::map<NodeId, Rib *> name_ribs;
228 std::map<NodeId, Rib *> type_ribs;
229 std::map<NodeId, Rib *> label_ribs;
230 std::map<NodeId, Rib *> macro_ribs;
231
232 // Rust uses DefIds to namespace these under a crate_num
233 // but then it uses the def_collector to assign local_defids
234 // to each ast node as well. not sure if this is going to fit
235 // with gcc very well to compile a full crate in one go but we will
236 // see.
237
238 // these are of the form ref->Def-NodeId
239 // we need two namespaces one for names and ones for types
240 std::map<NodeId, NodeId> resolved_names;
241 std::map<NodeId, NodeId> resolved_types;
242 std::map<NodeId, NodeId> resolved_labels;
243 std::map<NodeId, NodeId> resolved_macros;
244
245 // misc
246 std::map<NodeId, NodeId> misc_resolved_items;
247
248 // keep track of the current module scope ids
249 std::vector<NodeId> current_module_stack;
250
251 // captured variables mappings
252 std::vector<NodeId> closure_context;
253 std::map<NodeId, std::set<NodeId>> closures_capture_mappings;
254 };
255
256 } // namespace Resolver
257 } // namespace Rust
258
259 #endif // RUST_NAME_RESOLVER_H