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_AST_RESOLVE_TOPLEVEL_H
20 #define RUST_AST_RESOLVE_TOPLEVEL_H
21
22 #include "rust-ast-resolve-base.h"
23 #include "rust-ast-resolve-type.h"
24 #include "rust-ast-resolve-implitem.h"
25 #include "rust-ast-full.h"
26 #include "rust-name-resolver.h"
27 #include "rust-session-manager.h"
28
29 namespace Rust {
30 namespace Resolver {
31
32 class ResolveTopLevel : public ResolverBase
33 {
34 using Rust::Resolver::ResolverBase::visit;
35
36 public:
37 static void go (AST::Item *item, const CanonicalPath &prefix,
38 const CanonicalPath &canonical_prefix)
39 {
40 if (item->is_marked_for_strip ())
41 return;
42
43 ResolveTopLevel resolver (prefix, canonical_prefix);
44 item->accept_vis (resolver);
45
46 NodeId current_module = resolver.resolver->peek_current_module_scope ();
47 resolver.mappings->insert_child_item_to_parent_module_mapping (
48 item->get_node_id (), current_module);
49 }
50
51 void visit (AST::Module &module) override
52 {
53 auto mod
54 = CanonicalPath::new_seg (module.get_node_id (), module.get_name ());
55 auto path = prefix.append (mod);
56 auto cpath = canonical_prefix.append (mod);
57
58 resolver->get_name_scope ().insert (
59 path, module.get_node_id (), module.get_locus (), false,
60 Rib::ItemType::Module,
61 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
62 RichLocation r (module.get_locus ());
63 r.add_range (locus);
64 rust_error_at (r, "redefined multiple times");
65 });
66
67 NodeId current_module = resolver->peek_current_module_scope ();
68 mappings->insert_module_child_item (current_module, mod);
69 mappings->insert_module_child (current_module, module.get_node_id ());
70
71 resolver->push_new_module_scope (module.get_node_id ());
72 for (auto &item : module.get_items ())
73 ResolveTopLevel::go (item.get (), path, cpath);
74
75 resolver->pop_module_scope ();
76
77 mappings->insert_canonical_path (module.get_node_id (), cpath);
78 }
79
80 void visit (AST::TypeAlias &alias) override
81 {
82 auto talias = CanonicalPath::new_seg (alias.get_node_id (),
83 alias.get_new_type_name ());
84 auto path = prefix.append (talias);
85 auto cpath = canonical_prefix.append (talias);
86
87 resolver->get_type_scope ().insert (
88 path, alias.get_node_id (), alias.get_locus (), false,
89 Rib::ItemType::Type,
90 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
91 RichLocation r (alias.get_locus ());
92 r.add_range (locus);
93 rust_error_at (r, "redefined multiple times");
94 });
95
96 NodeId current_module = resolver->peek_current_module_scope ();
97 mappings->insert_module_child_item (current_module, talias);
98 mappings->insert_canonical_path (alias.get_node_id (), cpath);
99 }
100
101 void visit (AST::TupleStruct &struct_decl) override
102 {
103 auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
104 struct_decl.get_identifier ());
105 auto path = prefix.append (decl);
106 auto cpath = canonical_prefix.append (decl);
107
108 resolver->get_type_scope ().insert (
109 path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
110 Rib::ItemType::Type,
111 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
112 RichLocation r (struct_decl.get_locus ());
113 r.add_range (locus);
114 rust_error_at (r, "redefined multiple times");
115 });
116
117 NodeId current_module = resolver->peek_current_module_scope ();
118 mappings->insert_module_child_item (current_module, decl);
119 mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
120 }
121
122 void visit (AST::Enum &enum_decl) override
123 {
124 auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
125 enum_decl.get_identifier ());
126 auto path = prefix.append (decl);
127 auto cpath = canonical_prefix.append (decl);
128
129 resolver->get_type_scope ().insert (
130 path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
131 Rib::ItemType::Type,
132 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
133 RichLocation r (enum_decl.get_locus ());
134 r.add_range (locus);
135 rust_error_at (r, "redefined multiple times");
136 });
137
138 for (auto &variant : enum_decl.get_variants ())
139 ResolveTopLevel::go (variant.get (), path, cpath);
140
141 NodeId current_module = resolver->peek_current_module_scope ();
142 mappings->insert_module_child_item (current_module, decl);
143 mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
144 }
145
146 void visit (AST::EnumItem &item) override
147 {
148 auto decl
149 = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
150 auto path = prefix.append (decl);
151 auto cpath = canonical_prefix.append (decl);
152
153 resolver->get_type_scope ().insert (
154 path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
155 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
156 RichLocation r (item.get_locus ());
157 r.add_range (locus);
158 rust_error_at (r, "redefined multiple times");
159 });
160
161 mappings->insert_canonical_path (item.get_node_id (), cpath);
162 }
163
164 void visit (AST::EnumItemTuple &item) override
165 {
166 auto decl
167 = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
168 auto path = prefix.append (decl);
169 auto cpath = canonical_prefix.append (decl);
170
171 resolver->get_type_scope ().insert (
172 path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
173 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
174 RichLocation r (item.get_locus ());
175 r.add_range (locus);
176 rust_error_at (r, "redefined multiple times");
177 });
178
179 mappings->insert_canonical_path (item.get_node_id (), cpath);
180 }
181
182 void visit (AST::EnumItemStruct &item) override
183 {
184 auto decl
185 = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
186 auto path = prefix.append (decl);
187 auto cpath = canonical_prefix.append (decl);
188
189 resolver->get_type_scope ().insert (
190 path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
191 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
192 RichLocation r (item.get_locus ());
193 r.add_range (locus);
194 rust_error_at (r, "redefined multiple times");
195 });
196
197 mappings->insert_canonical_path (item.get_node_id (), cpath);
198 }
199
200 void visit (AST::EnumItemDiscriminant &item) override
201 {
202 auto decl
203 = CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
204 auto path = prefix.append (decl);
205 auto cpath = canonical_prefix.append (decl);
206
207 resolver->get_type_scope ().insert (
208 path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
209 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
210 RichLocation r (item.get_locus ());
211 r.add_range (locus);
212 rust_error_at (r, "redefined multiple times");
213 });
214
215 mappings->insert_canonical_path (item.get_node_id (), cpath);
216 }
217
218 void visit (AST::StructStruct &struct_decl) override
219 {
220 auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
221 struct_decl.get_identifier ());
222 auto path = prefix.append (decl);
223 auto cpath = canonical_prefix.append (decl);
224
225 resolver->get_type_scope ().insert (
226 path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
227 Rib::ItemType::Type,
228 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
229 RichLocation r (struct_decl.get_locus ());
230 r.add_range (locus);
231 rust_error_at (r, "redefined multiple times");
232 });
233
234 NodeId current_module = resolver->peek_current_module_scope ();
235 mappings->insert_module_child_item (current_module, decl);
236 mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
237 }
238
239 void visit (AST::Union &union_decl) override
240 {
241 auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
242 union_decl.get_identifier ());
243 auto path = prefix.append (decl);
244 auto cpath = canonical_prefix.append (decl);
245
246 resolver->get_type_scope ().insert (
247 path, union_decl.get_node_id (), union_decl.get_locus (), false,
248 Rib::ItemType::Type,
249 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
250 RichLocation r (union_decl.get_locus ());
251 r.add_range (locus);
252 rust_error_at (r, "redefined multiple times");
253 });
254
255 NodeId current_module = resolver->peek_current_module_scope ();
256 mappings->insert_module_child_item (current_module, decl);
257 mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
258 }
259
260 void visit (AST::StaticItem &var) override
261 {
262 auto decl
263 = CanonicalPath::new_seg (var.get_node_id (), var.get_identifier ());
264 auto path = prefix.append (decl);
265 auto cpath = canonical_prefix.append (decl);
266
267 resolver->get_name_scope ().insert (
268 path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static,
269 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
270 RichLocation r (var.get_locus ());
271 r.add_range (locus);
272 rust_error_at (r, "redefined multiple times");
273 });
274
275 NodeId current_module = resolver->peek_current_module_scope ();
276 mappings->insert_module_child_item (current_module, decl);
277 mappings->insert_canonical_path (var.get_node_id (), cpath);
278 }
279
280 void visit (AST::ConstantItem &constant) override
281 {
282 auto decl = CanonicalPath::new_seg (constant.get_node_id (),
283 constant.get_identifier ());
284 auto path = prefix.append (decl);
285 auto cpath = canonical_prefix.append (decl);
286
287 resolver->get_name_scope ().insert (
288 path, constant.get_node_id (), constant.get_locus (), false,
289 Rib::ItemType::Const,
290 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
291 RichLocation r (constant.get_locus ());
292 r.add_range (locus);
293 rust_error_at (r, "redefined multiple times");
294 });
295
296 NodeId current_module = resolver->peek_current_module_scope ();
297 mappings->insert_module_child_item (current_module, decl);
298 mappings->insert_canonical_path (constant.get_node_id (), cpath);
299 }
300
301 void visit (AST::Function &function) override
302 {
303 auto decl = CanonicalPath::new_seg (function.get_node_id (),
304 function.get_function_name ());
305 auto path = prefix.append (decl);
306 auto cpath = canonical_prefix.append (decl);
307
308 resolver->get_name_scope ().insert (
309 path, function.get_node_id (), function.get_locus (), false,
310 Rib::ItemType::Function,
311 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
312 RichLocation r (function.get_locus ());
313 r.add_range (locus);
314 rust_error_at (r, "redefined multiple times");
315 });
316
317 NodeId current_module = resolver->peek_current_module_scope ();
318 mappings->insert_module_child_item (current_module, decl);
319 mappings->insert_canonical_path (function.get_node_id (), cpath);
320 }
321
322 void visit (AST::InherentImpl &impl_block) override
323 {
324 std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
325 CanonicalPath impl_type
326 = CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
327 raw_impl_type_path);
328 CanonicalPath impl_prefix = prefix.append (impl_type);
329
330 for (auto &impl_item : impl_block.get_impl_items ())
331 ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
332 }
333
334 void visit (AST::TraitImpl &impl_block) override
335 {
336 std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
337 CanonicalPath impl_type_seg
338 = CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
339 raw_impl_type_path);
340
341 std::string raw_trait_type_path = impl_block.get_trait_path ().as_string ();
342 CanonicalPath trait_type_seg
343 = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (),
344 raw_trait_type_path);
345
346 CanonicalPath projection
347 = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
348 trait_type_seg,
349 impl_type_seg);
350 CanonicalPath impl_prefix = prefix.append (projection);
351
352 resolver->get_name_scope ().insert (
353 impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
354 Rib::ItemType::TraitImpl,
355 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
356 RichLocation r (impl_block.get_locus ());
357 r.add_range (locus);
358 rust_error_at (r, "redefined multiple times");
359 });
360
361 for (auto &impl_item : impl_block.get_impl_items ())
362 ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
363 }
364
365 void visit (AST::Trait &trait) override
366 {
367 auto decl
368 = CanonicalPath::new_seg (trait.get_node_id (), trait.get_identifier ());
369 auto path = prefix.append (decl);
370 auto cpath = canonical_prefix.append (decl);
371
372 resolver->get_type_scope ().insert (
373 path, trait.get_node_id (), trait.get_locus (), false,
374 Rib::ItemType::Trait,
375 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
376 RichLocation r (trait.get_locus ());
377 r.add_range (locus);
378 rust_error_at (r, "redefined multiple times");
379 });
380
381 for (auto &item : trait.get_trait_items ())
382 ResolveTopLevelTraitItems::go (item.get (), path, cpath);
383
384 NodeId current_module = resolver->peek_current_module_scope ();
385 mappings->insert_module_child_item (current_module, decl);
386 mappings->insert_canonical_path (trait.get_node_id (), cpath);
387 }
388
389 void visit (AST::ExternBlock &extern_block) override
390 {
391 for (auto &item : extern_block.get_extern_items ())
392 {
393 ResolveToplevelExternItem::go (item.get (), prefix);
394 }
395 }
396
397 void visit (AST::ExternCrate &extern_crate) override
398 {
399 if (extern_crate.is_marked_for_strip ())
400 return;
401
402 NodeId resolved_crate = UNKNOWN_NODEID;
403 if (extern_crate.references_self ())
404 {
405 CrateNum crate_num = mappings->get_current_crate ();
406 bool ok = mappings->crate_num_to_nodeid (crate_num, resolved_crate);
407 rust_assert (ok);
408 }
409 else
410 {
411 CrateNum found_crate_num = UNKNOWN_CREATENUM;
412 bool found
413 = mappings->lookup_crate_name (extern_crate.get_referenced_crate (),
414 found_crate_num);
415 if (!found)
416 {
417 rust_error_at (extern_crate.get_locus (), "unknown crate %<%s%>",
418 extern_crate.get_referenced_crate ().c_str ());
419 return;
420 }
421
422 bool ok
423 = mappings->crate_num_to_nodeid (found_crate_num, resolved_crate);
424 if (!ok)
425 {
426 rust_internal_error_at (extern_crate.get_locus (),
427 "failed to resolve crate to nodeid");
428 return;
429 }
430 }
431
432 if (resolved_crate == UNKNOWN_NODEID)
433 {
434 rust_error_at (extern_crate.get_locus (), "failed to resolve crate");
435 return;
436 }
437
438 // mark the node as resolved
439 resolver->insert_resolved_name (extern_crate.get_node_id (),
440 resolved_crate);
441 CanonicalPath decl
442 = extern_crate.has_as_clause ()
443 ? CanonicalPath::new_seg (extern_crate.get_node_id (),
444 extern_crate.get_as_clause ())
445 : CanonicalPath::new_seg (extern_crate.get_node_id (),
446 extern_crate.get_referenced_crate ());
447
448 resolver->get_type_scope ().insert (
449 decl, resolved_crate, extern_crate.get_locus (), false,
450 Rib::ItemType::ExternCrate,
451 [&] (const CanonicalPath &, NodeId, Location locus) -> void {
452 RichLocation r (extern_crate.get_locus ());
453 r.add_range (locus);
454 rust_error_at (r, "redefined multiple times");
455 });
456 }
457
458 private:
459 ResolveTopLevel (const CanonicalPath &prefix,
460 const CanonicalPath &canonical_prefix)
461 : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
462 {}
463
464 const CanonicalPath &prefix;
465 const CanonicalPath &canonical_prefix;
466 };
467
468 } // namespace Resolver
469 } // namespace Rust
470
471 #endif // RUST_AST_RESOLVE_TOPLEVEL_H