Line data Source code
1 : // Copyright (C) 2020-2026 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_2_0_CTX_H
20 : #define RUST_NAME_RESOLVER_2_0_CTX_H
21 :
22 : #include "optional.h"
23 : #include "rust-forever-stack.h"
24 : #include "rust-hir-map.h"
25 : #include "rust-rib.h"
26 : #include "rust-stacked-contexts.h"
27 : #include "rust-item.h"
28 : #include "rust-name-resolution.h"
29 :
30 : namespace Rust {
31 : namespace Resolver2_0 {
32 :
33 : // TODO: Add missing mappings and data structures
34 :
35 : /**
36 : The data structures we need to develop need to fill in a few roles - like the
37 : original name resolver, they need to be accessible at multiple points during the
38 : pipeline to allow compiler passes such as macro expansion or typechecking to
39 : benefit from them. Unlike the original name resolution, these data structures
40 : need to be created by multiple compiler passes: Whereas the original name
41 : resolution of gccrs tries to perform name resolution in a single pass, it fails
42 : at properly handling more complex name resolution cases such as macro name
43 : resolution, imports in general, and glob imports in particular. The goal of this
44 : new name resolution algorithm is to split the name resolution in at least two
45 : passes - `Early` name resolution, which takes care of macro name resolution and
46 : import resolution, and `Late` name resolution - your typical name resolution,
47 : for types, functions, variables...
48 :
49 : 1. `Early`
50 :
51 : The Early name resolution is tied in snuggly with macro expansion: macro
52 : expansion cannot happen without some form of name resolution (pointing an
53 : invocation to its definition) but may also *depend* on name resolution (a macro
54 : generating another macro... or importing items... and funny other cases like
55 : these). It needs to work in a fixed-point fashion alongside macro expansion:
56 : While there are imports to resolve, or macros to expand, we need to keep going
57 : and resolve them. This is achieved, among other things, by a top-level name
58 : resolution pass in charge of collection use statements and macro definitions (as
59 : well as Items, which will be useful for later passes of the name resolution).
60 :
61 : This top-level pass exists because Rust enables you to call a function
62 : before having declared it (at a lexical level, i.e calling `f(15)` at line 3
63 : while the `f` function is declared at line 1499).
64 :
65 : This Early pass needs to build the first part of our "resolution map", which
66 : will then be used in multiple contexts:
67 :
68 : 1. The MacroExpander, in a read-only fashion: fetching macro definitions for
69 : each invocation and performing the expansion.
70 : 2. `Late`, which will write more data inside that resolution map, and use it
71 : to perform its name resolution too.
72 :
73 : This is where the first challenge of this data structure lies: The existing
74 : data structures and name resolution algorithm relies on the name resolution pass
75 : happening just once. In typical name resolution fashion, when it sees a lexical
76 : scope (a new module, a function's block, a block expression...), it "pushes" a
77 : new "Scope" to a stack of these scopes, and "pops" it when exiting said lexical
78 : scope. However, because we are splitting the name resolution into two passes, we
79 : would like to avoid re-doing a bunch of work we've already done - which is why
80 : this data structure needs to allow "re-entrancy", or to at least not keep as
81 : much state as the existing one, and allow for viewing the same module multiple
82 : times without throwing a fit.
83 :
84 : We will be implementing a "forever stack" of scopes, which allows the user the
85 : pushing of new scopes onto the stack, but only simulates the popping of a scope:
86 : When pushing new scopes, more space is allocated on our stack, and we keep
87 : track of this scope as being the current one - however, when popping this scope,
88 : we do not actually delete the memory associated with it: we simply mark the
89 : previous scope (parent) as the current one.
90 :
91 : In the example below, each number indicates the "state" of our resolution map,
92 : and the carret is used to point to the current lexical scope.
93 :
94 : ```rust
95 : // []
96 : //
97 : fn main() { // [ `main` scope: {} ]
98 : // ^
99 : let a = 15; // [ `main` scope: { Decl(a) } ]
100 : // ^
101 : { _PUSH_ // [ `main` scope: { Decl(a) }, anonymous scope: {} ]
102 : // ^
103 : let a = 16; // [ `main` scope: { Decl(a) }, anonymous scope: { Decl(a) } ]
104 : // ^
105 : f(a); // [ `main` scope: { Decl(a) }, anonymous scope: { Decl(a) } ]
106 : // ^
107 : } _POP_ // [ `main` scope: { Decl(a) }, anonymous scope: { Decl(a) } ]
108 : // ^
109 : f(a); // [ `main` scope: { Decl(a) }, anonymous scope: { Decl(a) } ]
110 : // ^
111 : }
112 : ```
113 :
114 : This allows us to revisit scopes previously visited in later phases of the name
115 : resolution, and add more information if necessary.
116 :
117 : 2. `Late`
118 :
119 : `Late` name resolution possesses some unique challenges since Rust's name
120 : resolution rules are extremely complex - variable shadowing, variable capture in
121 : closures (but not inner functions!)... You can have a look at a fucked up
122 : example here:
123 :
124 : https://rustc-dev-guide.rust-lang.org/name-resolution.html#scopes-and-ribs
125 :
126 : This requires us to think about what exactly to put in our `Scope`s and what to
127 : do with our `Rib`s - and how it affects our data structures. For example, in the
128 : above example, `rustc` demonstrates how multiple `Rib`s can be created inside of
129 : a single lexical scope for variables, as the Rust programming language allows
130 : shadowing.
131 :
132 : TODO: Mention macro hygiene and that it is the same
133 : TODO: How does this affect our data structures?
134 : TODO: Last challenge - reuse the same APIs to allow the typechecker to not
135 : change?
136 : TODO: Mention that ForeverStack is templated to make sure that behavior is
137 : correct
138 : */
139 :
140 : struct IdentifierMode
141 : {
142 : bool is_ref;
143 : bool is_mut;
144 :
145 24442 : IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
146 : {}
147 :
148 58 : bool operator== (const IdentifierMode &other)
149 : {
150 58 : return other.is_ref == is_ref && other.is_mut == is_mut;
151 : }
152 :
153 232 : bool operator!= (const IdentifierMode &other) { return !(*this == other); }
154 : };
155 :
156 206636 : struct Binding
157 : {
158 : enum class Kind
159 : {
160 : Product,
161 : Or,
162 : } kind;
163 :
164 : // used to check the correctness of or-bindings
165 : bool has_expected_bindings;
166 :
167 : std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
168 :
169 34637 : Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
170 : };
171 :
172 : /**
173 : * Used to identify the source of a binding, and emit the correct error message.
174 : */
175 : enum class BindingSource
176 : {
177 : Match,
178 : Let,
179 : IfLet,
180 : WhileLet,
181 : For,
182 : /* Closure param or function param */
183 : Param
184 : };
185 :
186 136185 : class BindingLayer
187 : {
188 : BindingSource source;
189 : std::vector<Binding> bindings;
190 :
191 : bool bind_test (Identifier ident, Binding::Kind kind);
192 :
193 : public:
194 : void push (Binding::Kind kind);
195 :
196 : BindingLayer (BindingSource source);
197 :
198 : /**
199 : * Identifies if the identifier has been used in a product binding context.
200 : * eg. `let (a, a) = test();`
201 : */
202 : bool is_and_bound (Identifier ident);
203 :
204 : /**
205 : * Identifies if the identifier has been used in a or context.
206 : * eg. `let (a, 1) | (a, 2) = test()`
207 : */
208 : bool is_or_bound (Identifier ident);
209 :
210 : void insert_ident (std::string ident, location_t locus, bool is_ref,
211 : bool is_mut);
212 :
213 : void merge ();
214 :
215 : BindingSource get_source () const;
216 : };
217 :
218 : class NameResolutionContext;
219 : /*
220 : * Used to handle canonical paths
221 : * Similar to ForeverStack, but namespace independent and more specialized
222 : */
223 40900 : class CanonicalPathRecord
224 : {
225 : public:
226 : virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0;
227 :
228 : virtual bool is_root () const = 0;
229 :
230 : virtual ~CanonicalPathRecord () = default;
231 : };
232 :
233 : class CanonicalPathRecordWithParent : public CanonicalPathRecord
234 : {
235 : public:
236 36192 : CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent)
237 : {}
238 :
239 407043 : CanonicalPathRecord &get_parent () { return *parent; }
240 :
241 242141 : bool is_root () const override final { return false; }
242 :
243 : private:
244 : CanonicalPathRecord *parent;
245 : };
246 :
247 : class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
248 : {
249 : public:
250 4708 : CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg)
251 4708 : : node_id (node_id), seg (std::move (seg))
252 : {
253 4708 : rust_assert (Analysis::Mappings::get ().node_is_crate (node_id));
254 4708 : crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value ();
255 4708 : }
256 :
257 : Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
258 :
259 31117 : bool is_root () const override final { return true; }
260 :
261 : private:
262 : NodeId node_id;
263 : CrateNum crate_num;
264 : std::string seg;
265 : };
266 :
267 : class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
268 : {
269 : public:
270 30477 : CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
271 : std::string seg)
272 30477 : : CanonicalPathRecordWithParent (parent), node_id (node_id),
273 30477 : seg (std::move (seg))
274 : {
275 30477 : rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
276 30477 : }
277 :
278 : Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
279 :
280 : private:
281 : NodeId node_id;
282 : std::string seg;
283 : };
284 :
285 : class CanonicalPathRecordLookup : public CanonicalPathRecord
286 : {
287 : public:
288 5715 : CanonicalPathRecordLookup (NodeId lookup_id)
289 5715 : : lookup_id (lookup_id), cache (nullptr)
290 : {}
291 :
292 : Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
293 :
294 0 : bool is_root () const override final { return true; }
295 :
296 : private:
297 : NodeId lookup_id;
298 : CanonicalPathRecord *cache;
299 : };
300 :
301 : class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
302 : {
303 : public:
304 973 : CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
305 : NodeId type_id)
306 973 : : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
307 973 : type_record (type_id)
308 : {}
309 :
310 : Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
311 :
312 : private:
313 : NodeId impl_id;
314 : CanonicalPathRecordLookup type_record;
315 : };
316 :
317 : class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
318 : {
319 : public:
320 4742 : CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
321 : NodeId type_id, NodeId trait_path_id)
322 4742 : : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
323 4742 : type_record (type_id), trait_path_record (trait_path_id)
324 : {}
325 :
326 : Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
327 :
328 : private:
329 : NodeId impl_id;
330 : CanonicalPathRecordLookup type_record;
331 : CanonicalPathRecordLookup trait_path_record;
332 : };
333 :
334 : class CanonicalPathCtx
335 : {
336 : public:
337 4684 : CanonicalPathCtx (const NameResolutionContext &ctx)
338 4684 : : current_record (nullptr), nr_ctx (&ctx)
339 : {}
340 :
341 59700 : Resolver::CanonicalPath get_path (NodeId id) const
342 : {
343 59700 : return get_record (id).as_path (*nr_ctx);
344 : }
345 :
346 59700 : CanonicalPathRecord &get_record (NodeId id) const
347 : {
348 59700 : auto it = records.find (id);
349 59700 : rust_assert (it != records.end ());
350 59700 : return *it->second;
351 : }
352 :
353 16063 : tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const
354 : {
355 16063 : auto it = records.find (id);
356 16063 : if (it == records.end ())
357 11085 : return tl::nullopt;
358 : else
359 4978 : return it->second.get ();
360 : }
361 :
362 : void insert_record (NodeId id, const Identifier &ident)
363 : {
364 : insert_record (id, ident.as_string ());
365 : }
366 :
367 : void insert_record (NodeId id, std::string seg)
368 : {
369 : rust_assert (current_record != nullptr);
370 :
371 : auto it = records.find (id);
372 : if (it == records.end ())
373 : {
374 : auto record = new CanonicalPathRecordNormal (*current_record, id,
375 : std::move (seg));
376 : bool ok
377 : = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
378 : .second;
379 : rust_assert (ok);
380 : }
381 : }
382 :
383 204090 : template <typename F> void scope (NodeId id, const Identifier &ident, F &&f)
384 : {
385 408180 : scope (id, ident.as_string (), std::forward<F> (f));
386 204089 : }
387 :
388 204090 : template <typename F> void scope (NodeId id, std::string seg, F &&f)
389 : {
390 204090 : rust_assert (current_record != nullptr);
391 :
392 234567 : scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
393 30477 : return new CanonicalPathRecordNormal (*current_record, id,
394 30477 : std::move (seg));
395 : });
396 204089 : }
397 :
398 6332 : template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
399 : {
400 6332 : rust_assert (current_record != nullptr);
401 :
402 6332 : NodeId id = impl.get_node_id ();
403 6332 : scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
404 973 : return new CanonicalPathRecordImpl (*current_record, id,
405 973 : impl.get_type ().get_node_id ());
406 : });
407 6332 : }
408 :
409 31719 : template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
410 : {
411 31719 : rust_assert (current_record != nullptr);
412 :
413 31719 : NodeId id = impl.get_node_id ();
414 31719 : scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
415 4742 : return new CanonicalPathRecordTraitImpl (
416 4742 : *current_record, id, impl.get_type ().get_node_id (),
417 4742 : impl.get_trait_path ().get_node_id ());
418 : });
419 31719 : }
420 :
421 : template <typename F>
422 31117 : void scope_crate (NodeId node_id, std::string crate_name, F &&f)
423 : {
424 35825 : scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () {
425 4708 : return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name));
426 : });
427 : }
428 :
429 : private:
430 : template <typename FCreate, typename FCallback>
431 273258 : void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
432 : {
433 273258 : auto it = records.find (id);
434 273258 : if (it == records.end ())
435 : {
436 40900 : CanonicalPathRecord *record = std::forward<FCreate> (f_create) ();
437 40900 : it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
438 : .first;
439 : }
440 :
441 273258 : rust_assert (it->second->is_root ()
442 : || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
443 : .get_parent ()
444 : == current_record);
445 :
446 273258 : CanonicalPathRecord *stash = it->second.get ();
447 273258 : std::swap (stash, current_record);
448 :
449 273256 : std::forward<FCallback> (f_callback) ();
450 :
451 273256 : std::swap (stash, current_record);
452 273256 : }
453 :
454 : std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
455 : CanonicalPathRecord *current_record;
456 :
457 : const NameResolutionContext *nr_ctx;
458 : };
459 :
460 : // Now our resolver, which keeps track of all the `ForeverStack`s we could want
461 : class NameResolutionContext
462 : {
463 : public:
464 : NameResolutionContext ();
465 :
466 : /**
467 : * Insert a new value in the current rib.
468 : *
469 : * @param name Name of the value to insert.
470 : * @param id This value's ID, e.g the function definition's node ID.
471 : * @param ns Namespace in which to insert the value.
472 : */
473 : tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id,
474 : Namespace ns);
475 :
476 : tl::expected<NodeId, DuplicateNameError>
477 : insert_variant (Identifier name, NodeId id, bool is_also_value);
478 :
479 : tl::expected<NodeId, DuplicateNameError>
480 : insert_shadowable (Identifier name, NodeId id, Namespace ns);
481 :
482 : tl::expected<NodeId, DuplicateNameError>
483 : insert_globbed (Identifier name, NodeId id, Namespace ns);
484 :
485 : /**
486 : * Run a lambda in a "scoped" context, meaning that a new `Rib` will be pushed
487 : * before executing the lambda and then popped. This is useful for all kinds
488 : * of scope in the language, such as a block expression or when entering a
489 : * function. This variant of the function enters a new scope in *all*
490 : * namespaces, while the second variant enters a scope in *one* namespace.
491 : *
492 : * @param rib_kind New `Rib` to create when entering this scope. A function
493 : * `Rib`, or an item `Rib`... etc
494 : * @param scope_id node ID of the scope we are entering, e.g the block's
495 : * `NodeId`.
496 : * @param lambda Function to run within that scope
497 : * @param path Optional path of the scope. This is useful for scopes which
498 : * affect path resolution, such as modules. Defaults to an empty
499 : * option.
500 : */
501 : // FIXME: Do we want to handle something in particular for expected within the
502 : // scoped lambda?
503 : void scoped (Rib::Kind rib_kind, NodeId scope_id,
504 : std::function<void (void)> lambda,
505 : tl::optional<Identifier> path = {});
506 : void scoped (Rib::Kind rib_kind, Namespace ns, NodeId scope_id,
507 : std::function<void (void)> lambda,
508 : tl::optional<Identifier> path = {});
509 :
510 : ForeverStack<Namespace::Values> values;
511 : ForeverStack<Namespace::Types> types;
512 : ForeverStack<Namespace::Macros> macros;
513 : ForeverStack<Namespace::Labels> labels;
514 :
515 : Analysis::Mappings &mappings;
516 : StackedContexts<BindingLayer> bindings;
517 :
518 : CanonicalPathCtx canonical_ctx;
519 :
520 : // TODO: Rename
521 : // TODO: Use newtype pattern for Usage and Definition
522 : void map_usage (Usage usage, Definition definition);
523 :
524 : tl::optional<NodeId> lookup (NodeId usage) const;
525 :
526 59700 : Resolver::CanonicalPath to_canonical_path (NodeId id) const
527 : {
528 59700 : return canonical_ctx.get_path (id);
529 : }
530 :
531 : tl::optional<Rib::Definition>
532 94054 : resolve_path (const ResolutionPath &path, ResolutionMode mode,
533 : std::vector<Error> &collect_errors, Namespace ns)
534 : {
535 94054 : std::function<void (Usage, Definition)> insert_segment_resolution
536 94054 : = [this] (Usage seg_id, Definition id) {
537 110815 : if (resolved_nodes.find (seg_id) == resolved_nodes.end ())
538 91324 : map_usage (seg_id, id);
539 204869 : };
540 :
541 94054 : tl::optional<Rib::Definition> resolved = tl::nullopt;
542 :
543 94054 : switch (ns)
544 : {
545 27336 : case Namespace::Values:
546 54672 : resolved = values.resolve_path (path, mode, insert_segment_resolution,
547 27336 : collect_errors);
548 27336 : break;
549 63300 : case Namespace::Types:
550 126600 : resolved = types.resolve_path (path, mode, insert_segment_resolution,
551 63300 : collect_errors);
552 63300 : break;
553 3418 : case Namespace::Macros:
554 6836 : resolved = macros.resolve_path (path, mode, insert_segment_resolution,
555 3418 : collect_errors);
556 3418 : break;
557 0 : case Namespace::Labels:
558 0 : resolved = labels.resolve_path (path, mode, insert_segment_resolution,
559 0 : collect_errors);
560 0 : break;
561 0 : default:
562 0 : rust_unreachable ();
563 : }
564 :
565 : // If it fails, switch to std prelude resolution if it exists
566 94054 : if (prelude && !resolved)
567 : {
568 : // TODO: Factor this with the above
569 0 : switch (ns)
570 : {
571 0 : case Namespace::Values:
572 0 : return values.resolve_path (path, mode, insert_segment_resolution,
573 0 : collect_errors, *prelude);
574 0 : case Namespace::Types:
575 0 : return types.resolve_path (path, mode, insert_segment_resolution,
576 0 : collect_errors, *prelude);
577 0 : case Namespace::Macros:
578 0 : return macros.resolve_path (path, mode, insert_segment_resolution,
579 0 : collect_errors, *prelude);
580 0 : case Namespace::Labels:
581 0 : return labels.resolve_path (path, mode, insert_segment_resolution,
582 0 : collect_errors, *prelude);
583 : default:
584 : rust_unreachable ();
585 : }
586 : }
587 :
588 94054 : return resolved;
589 94054 : }
590 :
591 90175 : class ResolutionBuilder
592 : {
593 : public:
594 90175 : ResolutionBuilder (NameResolutionContext &ctx) : ctx (&ctx) {}
595 :
596 : template <typename S>
597 90110 : void set_path (const std::vector<S> &path_segments, NodeId node_id,
598 : bool has_opening_scope)
599 : {
600 90110 : path = ResolutionPath (path_segments, node_id);
601 90110 : mode = ResolutionMode::Normal;
602 90110 : if (has_opening_scope)
603 : {
604 738 : if (get_rust_edition () == Edition::E2015)
605 738 : mode = ResolutionMode::FromRoot;
606 : else
607 0 : mode = ResolutionMode::FromExtern;
608 : }
609 90110 : has_path_set = true;
610 90110 : }
611 :
612 : template <typename S>
613 65 : void set_path (const std::vector<S> &path_segments, NodeId node_id,
614 : ResolutionMode mode)
615 : {
616 65 : path = ResolutionPath (path_segments, node_id);
617 65 : this->mode = mode;
618 65 : has_path_set = true;
619 65 : }
620 :
621 : void set_path (const AST::SimplePath &path)
622 : {
623 : set_path (path.get_segments (), path.get_node_id (),
624 : path.has_opening_scope_resolution ());
625 : }
626 :
627 : void set_path (const AST::PathInExpression &path)
628 : {
629 : set_path (path.get_segments (), path.get_node_id (),
630 : path.opening_scope_resolution ());
631 : }
632 :
633 : void set_path (const AST::TypePath &path)
634 : {
635 : set_path (path.get_segments (), path.get_node_id (),
636 : path.has_opening_scope_resolution_op ());
637 : }
638 :
639 : void set_mode (ResolutionMode mode) { this->mode = mode; }
640 :
641 114456 : void add_namespaces (Namespace ns) { namespace_list.push_back (ns); }
642 :
643 24281 : template <typename... Args> void add_namespaces (Namespace ns, Args... rest)
644 : {
645 24281 : add_namespaces (ns);
646 24281 : add_namespaces (rest...);
647 24281 : }
648 :
649 9165 : void set_collect_errors (tl::optional<std::vector<Error> &> collect_errors)
650 : {
651 9165 : this->collect_errors = collect_errors;
652 : }
653 :
654 90175 : tl::optional<Rib::Definition> resolve ()
655 : {
656 90175 : rust_assert (has_path_set);
657 :
658 102546 : for (auto ns : namespace_list)
659 : {
660 94054 : std::vector<Error> collect_errors_inner;
661 94054 : if (auto ret
662 94054 : = ctx->resolve_path (path, mode, collect_errors_inner, ns))
663 94054 : return ret;
664 12371 : if (!collect_errors_inner.empty ())
665 : {
666 12 : if (collect_errors.has_value ())
667 : {
668 6 : std::move (collect_errors_inner.begin (),
669 : collect_errors_inner.end (),
670 : std::back_inserter (collect_errors.value ()));
671 : }
672 : else
673 : {
674 12 : for (auto &e : collect_errors_inner)
675 6 : e.emit ();
676 : }
677 : }
678 94054 : }
679 :
680 8492 : return tl::nullopt;
681 : }
682 :
683 : private:
684 : ResolutionPath path;
685 : ResolutionMode mode;
686 : bool has_path_set;
687 :
688 : std::vector<Namespace> namespace_list;
689 :
690 : tl::optional<std::vector<Error> &> collect_errors;
691 :
692 : NameResolutionContext *ctx;
693 : };
694 :
695 : template <typename S, typename... Args>
696 : tl::optional<Rib::Definition>
697 : resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
698 : tl::optional<std::vector<Error> &> collect_errors,
699 : Namespace ns_first, Args... ns_args)
700 : {
701 : ResolutionBuilder builder (*this);
702 : builder.set_path (path_segments, UNKNOWN_NODEID, mode);
703 : builder.add_namespaces (ns_first, ns_args...);
704 : builder.set_collect_errors (collect_errors);
705 :
706 : return builder.resolve ();
707 : }
708 :
709 : template <typename S, typename... Args>
710 : tl::optional<Rib::Definition>
711 9165 : resolve_path (const std::vector<S> &path_segments,
712 : bool has_opening_scope_resolution,
713 : tl::optional<std::vector<Error> &> collect_errors,
714 : Namespace ns_first, Args... ns_args)
715 : {
716 9165 : ResolutionBuilder builder (*this);
717 9165 : builder.set_path (path_segments, UNKNOWN_NODEID,
718 : has_opening_scope_resolution);
719 9165 : builder.add_namespaces (ns_first, ns_args...);
720 9165 : builder.set_collect_errors (collect_errors);
721 :
722 9165 : return builder.resolve ();
723 9165 : }
724 :
725 : template <typename S, typename... Args>
726 : tl::optional<Rib::Definition>
727 80945 : resolve_path (const std::vector<S> &path_segments,
728 : bool has_opening_scope_resolution, Namespace ns_first,
729 : Args... ns_args)
730 : {
731 80945 : ResolutionBuilder builder (*this);
732 80945 : builder.set_path (path_segments, UNKNOWN_NODEID,
733 : has_opening_scope_resolution);
734 80945 : builder.add_namespaces (ns_first, ns_args...);
735 :
736 80945 : return builder.resolve ();
737 80945 : }
738 :
739 : template <typename S, typename... Args>
740 : tl::optional<Rib::Definition>
741 65 : resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
742 : Namespace ns_first, Args... ns_args)
743 : {
744 65 : ResolutionBuilder builder (*this);
745 65 : builder.set_path (path_segments, UNKNOWN_NODEID, mode);
746 65 : builder.add_namespaces (ns_first, ns_args...);
747 :
748 65 : return builder.resolve ();
749 65 : }
750 :
751 : template <typename... Args>
752 9650 : tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
753 : Args &&...args)
754 : {
755 9165 : return resolve_path (path.get_segments (),
756 9650 : path.has_opening_scope_resolution (),
757 9650 : std::forward<Args> (args)...);
758 : }
759 :
760 : template <typename... Args>
761 25697 : tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
762 : Args &&...args)
763 : {
764 25697 : return resolve_path (path.get_segments (), path.opening_scope_resolution (),
765 25697 : std::forward<Args> (args)...);
766 : }
767 :
768 : template <typename... Args>
769 54763 : tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
770 : Args &&...args)
771 : {
772 : return resolve_path (path.get_segments (),
773 54763 : path.has_opening_scope_resolution_op (),
774 54763 : std::forward<Args> (args)...);
775 : }
776 :
777 : /* If declared with #[prelude_import], the current standard library module */
778 : tl::optional<NodeId> prelude;
779 :
780 : private:
781 : /* Map of "usage" nodes which have been resolved to a "definition" node */
782 : std::map<Usage, Definition> resolved_nodes;
783 : };
784 :
785 : } // namespace Resolver2_0
786 : } // namespace Rust
787 :
788 : #endif // ! RUST_NAME_RESOLVER_2_0_CTX_H
|