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 : #include "optional.h"
20 : #include "rust-ast-full.h"
21 : #include "rust-diagnostics.h"
22 : #include "rust-expr.h"
23 : #include "rust-hir-map.h"
24 : #include "rust-late-name-resolver-2.0.h"
25 : #include "rust-default-resolver.h"
26 : #include "rust-name-resolution-context.h"
27 : #include "rust-resolve-builtins.h"
28 : #include "rust-path.h"
29 : #include "rust-rib.h"
30 : #include "rust-system.h"
31 : #include "rust-tyty.h"
32 : #include "rust-hir-type-check.h"
33 : #include "rust-ice-finalizer.h"
34 : #include "rust-ast.h"
35 :
36 : namespace Rust {
37 : namespace Resolver2_0 {
38 :
39 4865 : Late::Late (NameResolutionContext &ctx)
40 4865 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
41 4865 : {}
42 :
43 : void
44 4865 : Late::go (AST::Crate &crate)
45 : {
46 4865 : Builtins::setup_type_ctx ();
47 :
48 4865 : visit (crate);
49 4863 : }
50 :
51 : void
52 0 : Late::new_label (Identifier name, NodeId id)
53 : {
54 : // labels can always shadow, so `insert` should never fail. if it does, we're
55 : // in big trouble!
56 0 : auto ok = ctx.labels.insert (name, id);
57 :
58 0 : rust_assert (ok);
59 0 : }
60 :
61 : void
62 0 : Late::visit (AST::ForLoopExpr &expr)
63 : {
64 0 : visit_outer_attrs (expr);
65 :
66 0 : ctx.bindings.enter (BindingSource::For);
67 :
68 0 : visit (expr.get_pattern ());
69 :
70 0 : ctx.bindings.exit ();
71 :
72 0 : visit (expr.get_iterator_expr ());
73 :
74 0 : if (expr.has_loop_label ())
75 0 : visit (expr.get_loop_label ());
76 :
77 0 : visit (expr.get_loop_block ());
78 0 : }
79 :
80 : void
81 121 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
82 : {
83 121 : ctx.bindings.enter (BindingSource::IfLet);
84 :
85 121 : DefaultResolver::visit_if_let_patterns (expr);
86 :
87 121 : ctx.bindings.exit ();
88 121 : }
89 :
90 : void
91 51102 : Late::visit (AST::MatchArm &arm)
92 : {
93 51102 : visit_outer_attrs (arm);
94 :
95 51102 : ctx.bindings.enter (BindingSource::Match);
96 :
97 51102 : visit (arm.get_pattern ());
98 :
99 51102 : ctx.bindings.exit ();
100 :
101 51102 : if (arm.has_match_arm_guard ())
102 34 : visit (arm.get_guard_expr ());
103 51102 : }
104 :
105 : void
106 16989 : Late::visit (AST::LetStmt &let)
107 : {
108 16989 : DefaultASTVisitor::visit_outer_attrs (let);
109 16989 : if (let.has_type ())
110 2598 : visit (let.get_type ());
111 : // visit expression before pattern
112 : // this makes variable shadowing work properly
113 16989 : if (let.has_init_expr ())
114 15606 : visit (let.get_init_expr ());
115 :
116 16988 : ctx.bindings.enter (BindingSource::Let);
117 :
118 16988 : visit (let.get_pattern ());
119 :
120 16988 : ctx.bindings.exit ();
121 :
122 16988 : if (let.has_else_expr ())
123 5 : visit (let.get_else_expr ());
124 :
125 : // how do we deal with the fact that `let a = blipbloup` should look for a
126 : // label and cannot go through function ribs, but `let a = blipbloup()` can?
127 :
128 : // how do we insert ribs here, and only pop them when we exit the current
129 : // function?
130 : // keep a list of ribs to pop when a scope exits? so only for blocks?
131 : // how do we pop ribs that need to be popped not in order?
132 : // I think it's not important if we have shadowing, correct?
133 :
134 : // if we have shadowing, it should work! we'll see
135 :
136 : // ctx.insert(Identifier name, NodeId id, Namespace ns)
137 : // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
138 : // Namespace::Labels,
139 : // let.get_node_id (), [] () {});
140 16988 : }
141 :
142 : void
143 0 : Late::visit (AST::WhileLetLoopExpr &while_let)
144 : {
145 0 : DefaultASTVisitor::visit_outer_attrs (while_let);
146 :
147 0 : if (while_let.has_loop_label ())
148 0 : visit (while_let.get_loop_label ());
149 :
150 : // visit expression before pattern
151 : // this makes variable shadowing work properly
152 0 : visit (while_let.get_scrutinee_expr ());
153 :
154 0 : ctx.bindings.enter (BindingSource::WhileLet);
155 :
156 0 : visit (while_let.get_pattern ());
157 :
158 0 : ctx.bindings.exit ();
159 :
160 0 : visit (while_let.get_loop_block ());
161 0 : }
162 :
163 : static void
164 45685 : visit_identifier_as_pattern (NameResolutionContext &ctx,
165 : const Identifier &ident, location_t locus,
166 : NodeId node_id, bool is_ref, bool is_mut)
167 : {
168 : // do we insert in labels or in values
169 : // but values does not allow shadowing... since functions cannot shadow
170 : // do we insert functions in labels as well?
171 :
172 45685 : if (ctx.bindings.peek ().is_and_bound (ident))
173 : {
174 8 : if (ctx.bindings.peek ().get_source () == BindingSource::Param)
175 5 : rust_error_at (
176 : locus, ErrorCode::E0415,
177 : "identifier %qs is bound more than once in the same parameter list",
178 5 : ident.as_string ().c_str ());
179 : else
180 3 : rust_error_at (
181 : locus, ErrorCode::E0416,
182 : "identifier %qs is bound more than once in the same pattern",
183 3 : ident.as_string ().c_str ());
184 : return;
185 : }
186 :
187 91354 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
188 :
189 45677 : if (ctx.bindings.peek ().is_or_bound (ident))
190 : {
191 59 : auto res = ctx.values.get (ident);
192 59 : rust_assert (res.has_value () && !res->is_ambiguous ());
193 59 : ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()),
194 : Namespace::Values);
195 59 : }
196 : else
197 : {
198 : // We do want to ignore duplicated data because some situations rely on
199 : // it.
200 45618 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
201 : }
202 : }
203 :
204 : void
205 45567 : Late::visit (AST::IdentifierPattern &identifier)
206 : {
207 45567 : DefaultResolver::visit (identifier);
208 :
209 45567 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
210 : identifier.get_locus (),
211 45567 : identifier.get_node_id (),
212 : identifier.get_is_ref (),
213 : identifier.get_is_mut ());
214 45567 : }
215 :
216 : void
217 230 : Late::visit (AST::AltPattern &pattern)
218 : {
219 230 : ctx.bindings.peek ().push (Binding::Kind::Or);
220 731 : for (auto &alt : pattern.get_alts ())
221 : {
222 501 : ctx.bindings.peek ().push (Binding::Kind::Product);
223 501 : visit (alt);
224 501 : ctx.bindings.peek ().merge ();
225 : }
226 230 : ctx.bindings.peek ().merge ();
227 230 : }
228 :
229 : void
230 31426 : Late::visit_function_params (AST::Function &function)
231 : {
232 31426 : ctx.bindings.enter (BindingSource::Param);
233 :
234 74364 : for (auto ¶m : function.get_function_params ())
235 42938 : visit (param);
236 :
237 31426 : ctx.bindings.exit ();
238 31426 : }
239 :
240 : void
241 118 : Late::visit (AST::StructPatternFieldIdent &field)
242 : {
243 : // We need to check if the Identifier resolves to a variant or empty struct
244 118 : auto path = AST::SimplePath (field.get_identifier ());
245 :
246 118 : if (auto resolved = ctx.resolve_path (path, Namespace::Types))
247 : {
248 0 : ctx.map_usage (Usage (field.get_node_id ()),
249 0 : Definition (resolved->definition.get_node_id ()),
250 : Namespace::Types);
251 0 : return;
252 0 : }
253 :
254 118 : visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
255 : field.get_node_id (), field.is_ref (),
256 : field.is_mut ());
257 118 : }
258 :
259 : void
260 16314 : Late::visit (AST::SelfParam ¶m)
261 : {
262 : // handle similar to AST::IdentifierPattern
263 :
264 16314 : DefaultResolver::visit (param);
265 : // FIXME: this location should be a bit off
266 : // ex: would point to the beginning of "mut self" instead of the "self"
267 48942 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
268 16314 : param.get_node_id ());
269 16314 : }
270 :
271 : void
272 266 : Late::visit (AST::BreakExpr &expr)
273 : {
274 266 : if (expr.has_label ())
275 37 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
276 :
277 266 : if (expr.has_break_expr ())
278 : {
279 26 : auto &break_expr = expr.get_break_expr_unchecked ();
280 26 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
281 : {
282 : /* This is a break with an expression, and the expression is
283 : just a single identifier. See if the identifier is either
284 : "rust" or "gcc", in which case we have "break rust" or "break
285 : gcc", and so may need to emit our funny error. We cannot yet
286 : emit the error here though, because the identifier may still
287 : be in scope, and ICE'ing on valid programs would not be very
288 : funny. */
289 11 : std::string ident = static_cast<AST::IdentifierExpr &> (
290 11 : expr.get_break_expr_unchecked ())
291 11 : .as_string ();
292 11 : if (ident == "rust" || ident == "gcc")
293 2 : funny_error = true;
294 11 : }
295 : }
296 :
297 266 : DefaultResolver::visit (expr);
298 :
299 265 : funny_error = false;
300 265 : }
301 :
302 : void
303 96 : Late::visit (AST::LoopLabel &label)
304 : {
305 96 : auto resolved
306 96 : = ctx.lookup (label.get_lifetime ().get_node_id (), Namespace::Labels);
307 96 : if (resolved.has_value ())
308 33 : return;
309 63 : auto &lifetime = label.get_lifetime ();
310 126 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
311 : lifetime.get_node_id ());
312 : }
313 :
314 : void
315 50 : Late::resolve_label (AST::Lifetime &lifetime)
316 : {
317 100 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
318 : {
319 45 : if (resolved->get_node_id () != lifetime.get_node_id ())
320 45 : ctx.map_usage (Usage (lifetime.get_node_id ()),
321 45 : Definition (resolved->get_node_id ()),
322 : Namespace::Labels);
323 : }
324 : else
325 5 : rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
326 : "use of undeclared label %qs",
327 10 : lifetime.as_string ().c_str ());
328 50 : }
329 :
330 : void
331 40 : Late::visit (AST::ContinueExpr &expr)
332 : {
333 40 : if (expr.has_label ())
334 13 : resolve_label (expr.get_label_unchecked ());
335 :
336 40 : DefaultResolver::visit (expr);
337 40 : }
338 :
339 : void
340 146774 : Late::visit (AST::IdentifierExpr &expr)
341 : {
342 : // TODO: same thing as visit(PathInExpression) here?
343 :
344 146774 : tl::optional<Rib::Definition> resolved = tl::nullopt;
345 146774 : tl::optional<Namespace> ns = tl::nullopt;
346 :
347 146774 : if (auto value = ctx.values.get (expr.get_ident ()))
348 : {
349 146760 : resolved = value;
350 146760 : ns = Namespace::Values;
351 : }
352 14 : else if (auto type = ctx.types.get (expr.get_ident ()))
353 : {
354 2 : resolved = type;
355 2 : ns = Namespace::Types;
356 : }
357 12 : else if (funny_error)
358 : {
359 1 : diagnostics::text_finalizer (global_dc)
360 1 : = Resolver::funny_ice_text_finalizer;
361 1 : emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
362 : "are you trying to break %s? how dare you?",
363 1 : expr.as_string ().c_str ());
364 : }
365 : else
366 : {
367 11 : if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
368 : {
369 2 : resolved = type;
370 2 : ns = Namespace::Types;
371 11 : }
372 :
373 11 : if (!resolved)
374 : {
375 9 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
376 : "cannot find value %qs in this scope",
377 9 : expr.get_ident ().as_string ().c_str ());
378 9 : return;
379 : }
380 13 : }
381 :
382 146764 : if (resolved->is_ambiguous ())
383 : {
384 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
385 0 : expr.as_string ().c_str ());
386 0 : return;
387 : }
388 :
389 146764 : ctx.map_usage (Usage (expr.get_node_id ()),
390 146764 : Definition (resolved->get_node_id ()), ns.value ());
391 :
392 : // For empty types, do we perform a lookup in ctx.types or should the
393 : // toplevel instead insert a name in ctx.values? (like it currently does)
394 146773 : }
395 :
396 : void
397 401 : Late::visit (AST::StructExprFieldIdentifier &expr)
398 : {
399 401 : tl::optional<Rib::Definition> resolved = tl::nullopt;
400 :
401 401 : if (auto value = ctx.values.get (expr.get_field_name ()))
402 : {
403 401 : resolved = value;
404 : }
405 : // seems like we don't need a type namespace lookup
406 : else
407 : {
408 0 : rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
409 0 : expr.get_field_name ().as_string ().c_str ());
410 0 : return;
411 0 : }
412 :
413 401 : if (resolved->is_ambiguous ())
414 : {
415 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
416 0 : expr.as_string ().c_str ());
417 0 : return;
418 : }
419 :
420 401 : ctx.map_usage (Usage (expr.get_node_id ()),
421 401 : Definition (resolved->get_node_id ()), Namespace::Values);
422 401 : }
423 :
424 : void
425 100037 : Late::visit (AST::PathInExpression &expr)
426 : {
427 : // TODO: How do we have a nice error with `can't capture dynamic environment
428 : // in a function item` error here?
429 : // do we emit it in `get<Namespace::Labels>`?
430 :
431 100037 : DefaultResolver::visit (expr);
432 :
433 : // TODO: do we need a namespace associated with each lang item?
434 100037 : if (expr.is_lang_item ())
435 : {
436 1728 : ctx.map_usage (Usage (expr.get_node_id ()),
437 1729 : Definition (Analysis::Mappings::get ().get_lang_item_node (
438 1729 : expr.get_lang_item ())),
439 : Namespace::Values);
440 1728 : return;
441 : }
442 :
443 : // TODO: we need to know which namespace that was in actually
444 98308 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
445 :
446 98308 : if (!resolved)
447 : {
448 7063 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id (),
449 : Namespace::Values, Namespace::Types))
450 16 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
451 : "Cannot find path %qs in this scope",
452 16 : expr.as_simple_path ().as_string ().c_str ());
453 : return;
454 : }
455 :
456 91245 : if (resolved->definition.is_ambiguous ())
457 : {
458 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
459 1 : expr.as_string ().c_str ());
460 1 : return;
461 : }
462 :
463 91244 : ctx.map_usage (Usage (expr.get_node_id ()),
464 91244 : Definition (resolved->definition.get_node_id ()),
465 91244 : resolved->ns);
466 100036 : }
467 :
468 : void
469 12802 : Late::visit_impl_type (AST::Type &type)
470 : {
471 : // TODO: does this have to handle reentrancy?
472 12802 : rust_assert (!block_big_self);
473 12802 : block_big_self = true;
474 12802 : visit (type);
475 12802 : block_big_self = false;
476 12802 : }
477 :
478 : template <typename P>
479 : static void
480 131316 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
481 : P &type)
482 : {
483 : // should we add type path resolution in `ForeverStack` directly? Since it's
484 : // quite more complicated.
485 : // maybe we can overload `resolve_path<Namespace::Types>` to only do
486 : // typepath-like path resolution? that sounds good
487 :
488 : // prevent "impl Self {}" and similar
489 131316 : if (type.get_segments ().size () == 1
490 126237 : && !unwrap_segment_get_lang_item (type.get_segments ().front ())
491 126237 : .has_value ()
492 125029 : && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
493 142497 : && block_big_self)
494 : {
495 2 : rust_error_at (type.get_locus (),
496 : "%<Self%> is not valid in the self type of an impl block");
497 2 : return;
498 : }
499 :
500 : // this *should* mostly work
501 : // TODO: make sure typepath-like path resolution (?) is working
502 131314 : auto resolved = ctx.resolve_path (type, Namespace::Types);
503 :
504 131314 : if (!resolved.has_value ())
505 : {
506 2107 : if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()),
507 : Namespace::Types))
508 26 : rust_error_at (type.get_locus (), ErrorCode::E0412,
509 : "could not resolve type path %qs",
510 52 : unwrap_segment_error_string (type).c_str ());
511 : return;
512 : }
513 :
514 129207 : if (resolved->definition.is_ambiguous ())
515 : {
516 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
517 0 : unwrap_segment_error_string (type).c_str ());
518 0 : return;
519 : }
520 :
521 129207 : if (ctx.types.forward_declared (resolved->definition.get_node_id (),
522 129207 : type.get_node_id ()))
523 : {
524 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
525 : "type parameters with a default cannot use forward "
526 : "declared identifiers");
527 : }
528 :
529 258414 : if (Analysis::Mappings::get ().is_module (
530 129207 : resolved->definition.get_node_id ()))
531 : {
532 87 : if (type.get_segments ().size () == 1)
533 : {
534 87 : if (auto resolved
535 87 : = Builtins::find_builtin_node_id (type.as_string ()))
536 : {
537 86 : ctx.map_usage (Usage (type.get_node_id ()),
538 86 : Definition (*resolved), Namespace::Types);
539 :
540 : // In that specific case, we also override the segment resolution
541 : // as it causes issues later down the line during typechecking
542 86 : ctx.map_usage (Usage (unwrap_segment_node_id (
543 86 : type.get_segments ().front ())),
544 86 : Definition (*resolved), Namespace::Types);
545 : }
546 : else
547 : {
548 1 : rust_error_at (type.get_locus (), ErrorCode::E0573,
549 : "expected type, found module %qs",
550 2 : unwrap_segment_error_string (type).c_str ());
551 : }
552 : }
553 :
554 : return;
555 : }
556 :
557 129120 : ctx.map_usage (Usage (type.get_node_id ()),
558 129120 : Definition (resolved->definition.get_node_id ()),
559 : Namespace::Types);
560 131316 : }
561 :
562 : void
563 131210 : Late::visit (AST::TypePath &type)
564 : {
565 131210 : DefaultResolver::visit (type);
566 :
567 131210 : resolve_type_path_like (ctx, block_big_self, type);
568 131210 : }
569 :
570 : void
571 69244 : Late::visit (AST::Visibility &vis)
572 : {
573 69244 : if (!vis.has_path ())
574 68866 : return;
575 :
576 381 : AST::SimplePath &path = vis.get_path ();
577 :
578 381 : rust_assert (path.get_segments ().size ());
579 381 : auto &first_seg = path.get_segments ()[0];
580 :
581 381 : auto mode = ResolutionMode::Normal;
582 :
583 381 : if (path.has_opening_scope_resolution ())
584 : {
585 0 : if (get_rust_edition () == Edition::E2015)
586 : mode = ResolutionMode::FromRoot;
587 : else
588 381 : mode = ResolutionMode::FromExtern;
589 : }
590 494 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
591 391 : && !first_seg.is_lower_self_seg ())
592 : {
593 7 : if (get_rust_edition () == Edition::E2015)
594 : {
595 : mode = ResolutionMode::FromRoot;
596 : }
597 : else
598 : {
599 0 : rust_error_at (path.get_locus (),
600 : "relative paths are not supported in visibilities in "
601 : "2018 edition or later");
602 0 : return;
603 : }
604 : }
605 :
606 381 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
607 :
608 381 : if (!res.has_value ())
609 : {
610 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
611 3 : "could not resolve path %qs", path.as_string ().c_str ());
612 3 : return;
613 : }
614 :
615 : // TODO: is this possible?
616 378 : if (res->definition.is_ambiguous ())
617 : {
618 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
619 0 : path.as_string ().c_str ());
620 0 : return;
621 : }
622 :
623 378 : ctx.map_usage (Usage (path.get_node_id ()),
624 378 : Definition (res->definition.get_node_id ()), res->ns);
625 69244 : }
626 :
627 : void
628 4158 : Late::visit (AST::Trait &trait)
629 : {
630 : // kind of weird how this is done
631 : // names are resolved to the node id of trait.get_implicit_self ()
632 : // which is then resolved to the node id of trait
633 : // we set up the latter mapping here
634 4158 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
635 4158 : Definition (trait.get_node_id ()), Namespace::Types);
636 :
637 4158 : DefaultResolver::visit (trait);
638 4158 : }
639 :
640 : void
641 106 : Late::visit (AST::StructExprStruct &s)
642 : {
643 106 : visit_outer_attrs (s);
644 106 : visit_inner_attrs (s);
645 106 : DefaultResolver::visit (s.get_struct_name ());
646 :
647 106 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
648 106 : }
649 :
650 : void
651 0 : Late::visit (AST::StructExprStructBase &s)
652 : {
653 0 : visit_outer_attrs (s);
654 0 : visit_inner_attrs (s);
655 0 : DefaultResolver::visit (s.get_struct_name ());
656 0 : visit (s.get_struct_base ());
657 :
658 0 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
659 0 : }
660 :
661 : void
662 1772 : Late::visit (AST::StructExprStructFields &s)
663 : {
664 1772 : visit_outer_attrs (s);
665 1772 : visit_inner_attrs (s);
666 :
667 1772 : auto &path = s.get_struct_name ();
668 :
669 1772 : DefaultResolver::visit (path);
670 1772 : if (s.has_struct_base ())
671 66 : visit (s.get_struct_base ());
672 4905 : for (auto &field : s.get_fields ())
673 3133 : visit (field);
674 :
675 1772 : auto resolved = ctx.resolve_path (path, Namespace::Types);
676 :
677 1772 : if (!resolved)
678 : {
679 0 : rust_error_at (path.get_locus (), ErrorCode::E0433,
680 0 : "could not resolve path %qs", path.as_string ().c_str ());
681 0 : return;
682 : }
683 :
684 1772 : ctx.map_usage (Usage (path.get_node_id ()),
685 1772 : Definition (resolved->definition.get_node_id ()),
686 : Namespace::Types);
687 1772 : }
688 :
689 : // needed because Late::visit (AST::GenericArg &) is non-virtual
690 : void
691 18480 : Late::visit (AST::GenericArgs &args)
692 : {
693 19968 : for (auto &lifetime : args.get_lifetime_args ())
694 1488 : visit (lifetime);
695 :
696 36872 : for (auto &generic : args.get_generic_args ())
697 18392 : visit (generic);
698 :
699 18810 : for (auto &binding : args.get_binding_args ())
700 330 : visit (binding);
701 18480 : }
702 :
703 : void
704 18392 : Late::visit (AST::GenericArg &arg)
705 : {
706 18392 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
707 : {
708 : // prefer type parameter to const parameter on ambiguity
709 24668 : auto type = ctx.types.get (arg.get_path ());
710 24668 : auto value = ctx.values.get (arg.get_path ());
711 :
712 12334 : if (!type.has_value () && value.has_value ())
713 65 : arg = arg.disambiguate_to_const ();
714 : else
715 12269 : arg = arg.disambiguate_to_type ();
716 15840 : }
717 :
718 18392 : DefaultResolver::visit (arg);
719 18392 : }
720 :
721 : void
722 368 : Late::visit_closure_params (AST::ClosureExpr &closure)
723 : {
724 368 : ctx.bindings.enter (BindingSource::Param);
725 :
726 368 : DefaultResolver::visit_closure_params (closure);
727 :
728 368 : ctx.bindings.exit ();
729 368 : }
730 :
731 : void
732 368 : Late::visit (AST::ClosureExpr &expr)
733 : {
734 : // add captures
735 368 : auto vals = ctx.values.peek ().get_values ();
736 447 : for (auto &val : vals)
737 : {
738 79 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
739 : }
740 :
741 368 : DefaultResolver::visit (expr);
742 368 : }
743 :
744 : } // namespace Resolver2_0
745 : } // namespace Rust
|