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 4767 : Late::Late (NameResolutionContext &ctx)
40 4767 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
41 4767 : {}
42 :
43 : void
44 4767 : Late::go (AST::Crate &crate)
45 : {
46 4767 : Builtins::setup_type_ctx ();
47 :
48 4767 : visit (crate);
49 4765 : }
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 30 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
82 : {
83 30 : ctx.bindings.enter (BindingSource::IfLet);
84 :
85 30 : DefaultResolver::visit_if_let_patterns (expr);
86 :
87 30 : ctx.bindings.exit ();
88 30 : }
89 :
90 : void
91 2518 : Late::visit (AST::MatchArm &arm)
92 : {
93 2518 : visit_outer_attrs (arm);
94 :
95 2518 : ctx.bindings.enter (BindingSource::Match);
96 :
97 2518 : visit (arm.get_pattern ());
98 :
99 2518 : ctx.bindings.exit ();
100 :
101 2518 : if (arm.has_match_arm_guard ())
102 1 : visit (arm.get_guard_expr ());
103 2518 : }
104 :
105 : void
106 12967 : Late::visit (AST::LetStmt &let)
107 : {
108 12967 : DefaultASTVisitor::visit_outer_attrs (let);
109 12967 : if (let.has_type ())
110 2167 : visit (let.get_type ());
111 : // visit expression before pattern
112 : // this makes variable shadowing work properly
113 12967 : if (let.has_init_expr ())
114 11819 : visit (let.get_init_expr ());
115 :
116 12966 : ctx.bindings.enter (BindingSource::Let);
117 :
118 12966 : visit (let.get_pattern ());
119 :
120 12966 : ctx.bindings.exit ();
121 :
122 12966 : 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 12966 : }
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 24755 : 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 24755 : 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 8 : return;
185 : }
186 :
187 49494 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
188 :
189 24747 : if (ctx.bindings.peek ().is_or_bound (ident))
190 : {
191 58 : auto res = ctx.values.get (ident);
192 58 : rust_assert (res.has_value () && !res->is_ambiguous ());
193 58 : ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()),
194 : Namespace::Values);
195 58 : }
196 : else
197 : {
198 : // We do want to ignore duplicated data because some situations rely on
199 : // it.
200 24689 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
201 : }
202 : }
203 :
204 : void
205 24655 : Late::visit (AST::IdentifierPattern &identifier)
206 : {
207 24655 : DefaultResolver::visit (identifier);
208 :
209 24655 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
210 : identifier.get_locus (),
211 24655 : identifier.get_node_id (),
212 24655 : identifier.get_is_ref (),
213 24655 : identifier.get_is_mut ());
214 24655 : }
215 :
216 : void
217 191 : Late::visit (AST::AltPattern &pattern)
218 : {
219 191 : ctx.bindings.peek ().push (Binding::Kind::Or);
220 591 : for (auto &alt : pattern.get_alts ())
221 : {
222 400 : ctx.bindings.peek ().push (Binding::Kind::Product);
223 400 : visit (alt);
224 400 : ctx.bindings.peek ().merge ();
225 : }
226 191 : ctx.bindings.peek ().merge ();
227 191 : }
228 :
229 : void
230 18981 : Late::visit_function_params (AST::Function &function)
231 : {
232 18981 : ctx.bindings.enter (BindingSource::Param);
233 :
234 38919 : for (auto ¶m : function.get_function_params ())
235 19938 : visit (param);
236 :
237 18981 : ctx.bindings.exit ();
238 18981 : }
239 :
240 : void
241 100 : Late::visit (AST::StructPatternFieldIdent &field)
242 : {
243 : // We need to check if the Identifier resolves to a variant or empty struct
244 100 : auto path = AST::SimplePath (field.get_identifier ());
245 :
246 100 : 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 100 : visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
255 100 : field.get_node_id (), field.is_ref (),
256 100 : field.is_mut ());
257 100 : }
258 :
259 : void
260 8113 : Late::visit (AST::SelfParam ¶m)
261 : {
262 : // handle similar to AST::IdentifierPattern
263 :
264 8113 : 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 24339 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
268 8113 : param.get_node_id ());
269 8113 : }
270 :
271 : void
272 99 : Late::visit (AST::BreakExpr &expr)
273 : {
274 99 : if (expr.has_label ())
275 27 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
276 :
277 99 : 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 99 : DefaultResolver::visit (expr);
298 :
299 98 : funny_error = false;
300 98 : }
301 :
302 : void
303 71 : Late::visit (AST::LoopLabel &label)
304 : {
305 71 : auto resolved
306 71 : = ctx.lookup (label.get_lifetime ().get_node_id (), Namespace::Labels);
307 71 : if (resolved.has_value ())
308 23 : return;
309 48 : auto &lifetime = label.get_lifetime ();
310 96 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
311 : lifetime.get_node_id ());
312 : }
313 :
314 : void
315 30 : Late::resolve_label (AST::Lifetime &lifetime)
316 : {
317 60 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
318 : {
319 25 : if (resolved->get_node_id () != lifetime.get_node_id ())
320 25 : ctx.map_usage (Usage (lifetime.get_node_id ()),
321 25 : 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 30 : }
329 :
330 : void
331 17 : Late::visit (AST::ContinueExpr &expr)
332 : {
333 17 : if (expr.has_label ())
334 3 : resolve_label (expr.get_label_unchecked ());
335 :
336 17 : DefaultResolver::visit (expr);
337 17 : }
338 :
339 : void
340 24676 : Late::visit (AST::IdentifierExpr &expr)
341 : {
342 : // TODO: same thing as visit(PathInExpression) here?
343 :
344 24676 : tl::optional<Rib::Definition> resolved = tl::nullopt;
345 24676 : tl::optional<Namespace> ns = tl::nullopt;
346 :
347 24676 : if (auto value = ctx.values.get (expr.get_ident ()))
348 : {
349 24664 : resolved = value;
350 24664 : ns = Namespace::Values;
351 : }
352 12 : else if (auto type = ctx.types.get (expr.get_ident ()))
353 : {
354 0 : resolved = type;
355 0 : 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 : }
372 9 : else if (!resolved && ctx.prelude)
373 : {
374 0 : resolved
375 0 : = ctx.values.get_from_prelude (*ctx.prelude, expr.get_ident ());
376 0 : ns = Namespace::Values;
377 :
378 0 : if (!resolved)
379 0 : resolved
380 0 : = ctx.types.get_from_prelude (*ctx.prelude, expr.get_ident ());
381 0 : ns = Namespace::Types;
382 11 : }
383 :
384 11 : if (!resolved)
385 : {
386 9 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
387 : "cannot find value %qs in this scope",
388 9 : expr.get_ident ().as_string ().c_str ());
389 9 : return;
390 : }
391 11 : }
392 :
393 24666 : if (resolved->is_ambiguous ())
394 : {
395 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
396 0 : expr.as_string ().c_str ());
397 0 : return;
398 : }
399 :
400 24666 : ctx.map_usage (Usage (expr.get_node_id ()),
401 24666 : Definition (resolved->get_node_id ()), ns.value ());
402 :
403 : // For empty types, do we perform a lookup in ctx.types or should the
404 : // toplevel instead insert a name in ctx.values? (like it currently does)
405 24675 : }
406 :
407 : void
408 216 : Late::visit (AST::StructExprFieldIdentifier &expr)
409 : {
410 216 : tl::optional<Rib::Definition> resolved = tl::nullopt;
411 :
412 216 : if (auto value = ctx.values.get (expr.get_field_name ()))
413 : {
414 216 : resolved = value;
415 : }
416 : // seems like we don't need a type namespace lookup
417 : else
418 : {
419 0 : rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
420 0 : expr.get_field_name ().as_string ().c_str ());
421 0 : return;
422 0 : }
423 :
424 216 : if (resolved->is_ambiguous ())
425 : {
426 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
427 0 : expr.as_string ().c_str ());
428 0 : return;
429 : }
430 :
431 216 : ctx.map_usage (Usage (expr.get_node_id ()),
432 216 : Definition (resolved->get_node_id ()), Namespace::Values);
433 216 : }
434 :
435 : void
436 24585 : Late::visit (AST::PathInExpression &expr)
437 : {
438 : // TODO: How do we have a nice error with `can't capture dynamic environment
439 : // in a function item` error here?
440 : // do we emit it in `get<Namespace::Labels>`?
441 :
442 24585 : DefaultResolver::visit (expr);
443 :
444 : // TODO: do we need a namespace associated with each lang item?
445 24585 : if (expr.is_lang_item ())
446 : {
447 144 : ctx.map_usage (Usage (expr.get_node_id ()),
448 145 : Definition (Analysis::Mappings::get ().get_lang_item_node (
449 145 : expr.get_lang_item ())),
450 : Namespace::Values);
451 1552 : return;
452 : }
453 :
454 : // TODO: we need to know which namespace that was in actually
455 24440 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
456 :
457 24440 : if (!resolved)
458 : {
459 1407 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id (),
460 : Namespace::Values, Namespace::Types))
461 16 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
462 : "Cannot find path %qs in this scope",
463 16 : expr.as_simple_path ().as_string ().c_str ());
464 1407 : return;
465 : }
466 :
467 23033 : if (resolved->definition.is_ambiguous ())
468 : {
469 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
470 1 : expr.as_string ().c_str ());
471 1 : return;
472 : }
473 :
474 23032 : ctx.map_usage (Usage (expr.get_node_id ()),
475 23032 : Definition (resolved->definition.get_node_id ()),
476 23032 : resolved->ns);
477 24440 : }
478 :
479 : void
480 5749 : Late::visit_impl_type (AST::Type &type)
481 : {
482 : // TODO: does this have to handle reentrancy?
483 5749 : rust_assert (!block_big_self);
484 5749 : block_big_self = true;
485 5749 : visit (type);
486 5749 : block_big_self = false;
487 5749 : }
488 :
489 : template <typename P>
490 : static void
491 55633 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
492 : P &type)
493 : {
494 : // should we add type path resolution in `ForeverStack` directly? Since it's
495 : // quite more complicated.
496 : // maybe we can overload `resolve_path<Namespace::Types>` to only do
497 : // typepath-like path resolution? that sounds good
498 :
499 : // prevent "impl Self {}" and similar
500 55633 : if (type.get_segments ().size () == 1
501 54160 : && !unwrap_segment_get_lang_item (type.get_segments ().front ())
502 54160 : .has_value ()
503 53768 : && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
504 62911 : && block_big_self)
505 : {
506 2 : rust_error_at (type.get_locus (),
507 : "%<Self%> is not valid in the self type of an impl block");
508 1066 : return;
509 : }
510 :
511 : // this *should* mostly work
512 : // TODO: make sure typepath-like path resolution (?) is working
513 55631 : auto resolved = ctx.resolve_path (type, Namespace::Types);
514 :
515 55631 : if (!resolved.has_value ())
516 : {
517 1061 : if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()),
518 : Namespace::Types))
519 26 : rust_error_at (type.get_locus (), ErrorCode::E0412,
520 : "could not resolve type path %qs",
521 52 : unwrap_segment_error_string (type).c_str ());
522 1061 : return;
523 : }
524 :
525 54570 : if (resolved->definition.is_ambiguous ())
526 : {
527 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
528 0 : unwrap_segment_error_string (type).c_str ());
529 0 : return;
530 : }
531 :
532 54570 : if (ctx.types.forward_declared (resolved->definition.get_node_id (),
533 54570 : type.get_node_id ()))
534 : {
535 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
536 : "type parameters with a default cannot use forward "
537 : "declared identifiers");
538 : }
539 :
540 109140 : if (Analysis::Mappings::get ().is_module (
541 54570 : resolved->definition.get_node_id ()))
542 : {
543 3 : if (type.get_segments ().size () == 1)
544 : {
545 3 : if (auto resolved
546 3 : = Builtins::find_builtin_node_id (type.as_string ()))
547 : {
548 2 : ctx.map_usage (Usage (type.get_node_id ()),
549 2 : Definition (*resolved), Namespace::Types);
550 :
551 : // In that specific case, we also override the segment resolution
552 : // as it causes issues later down the line during typechecking
553 2 : ctx.map_usage (Usage (unwrap_segment_node_id (
554 2 : type.get_segments ().front ())),
555 2 : Definition (*resolved), Namespace::Types);
556 : }
557 : else
558 : {
559 1 : rust_error_at (type.get_locus (), ErrorCode::E0573,
560 : "expected type, found module %qs",
561 2 : unwrap_segment_error_string (type).c_str ());
562 : }
563 : }
564 :
565 3 : return;
566 : }
567 :
568 54567 : ctx.map_usage (Usage (type.get_node_id ()),
569 54567 : Definition (resolved->definition.get_node_id ()),
570 : Namespace::Types);
571 55631 : }
572 :
573 : void
574 55551 : Late::visit (AST::TypePath &type)
575 : {
576 55551 : DefaultResolver::visit (type);
577 :
578 55551 : resolve_type_path_like (ctx, block_big_self, type);
579 55551 : }
580 :
581 : void
582 43433 : Late::visit (AST::Visibility &vis)
583 : {
584 43433 : if (!vis.has_path ())
585 43371 : return;
586 :
587 65 : AST::SimplePath &path = vis.get_path ();
588 :
589 65 : rust_assert (path.get_segments ().size ());
590 65 : auto &first_seg = path.get_segments ()[0];
591 :
592 65 : auto mode = ResolutionMode::Normal;
593 :
594 65 : if (path.has_opening_scope_resolution ())
595 : {
596 0 : if (get_rust_edition () == Edition::E2015)
597 : mode = ResolutionMode::FromRoot;
598 : else
599 65 : mode = ResolutionMode::FromExtern;
600 : }
601 77 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
602 74 : && !first_seg.is_lower_self_seg ())
603 : {
604 7 : if (get_rust_edition () == Edition::E2015)
605 : {
606 : mode = ResolutionMode::FromRoot;
607 : }
608 : else
609 : {
610 0 : rust_error_at (path.get_locus (),
611 : "relative paths are not supported in visibilities in "
612 : "2018 edition or later");
613 0 : return;
614 : }
615 : }
616 :
617 65 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
618 :
619 65 : if (!res.has_value ())
620 : {
621 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
622 3 : "could not resolve path %qs", path.as_string ().c_str ());
623 3 : return;
624 : }
625 :
626 : // TODO: is this possible?
627 62 : if (res->definition.is_ambiguous ())
628 : {
629 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
630 0 : path.as_string ().c_str ());
631 0 : return;
632 : }
633 :
634 62 : ctx.map_usage (Usage (path.get_node_id ()),
635 62 : Definition (res->definition.get_node_id ()), res->ns);
636 65 : }
637 :
638 : void
639 3999 : Late::visit (AST::Trait &trait)
640 : {
641 : // kind of weird how this is done
642 : // names are resolved to the node id of trait.get_implicit_self ()
643 : // which is then resolved to the node id of trait
644 : // we set up the latter mapping here
645 3999 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
646 3999 : Definition (trait.get_node_id ()), Namespace::Types);
647 :
648 3999 : DefaultResolver::visit (trait);
649 3999 : }
650 :
651 : void
652 82 : Late::visit (AST::StructExprStruct &s)
653 : {
654 82 : visit_outer_attrs (s);
655 82 : visit_inner_attrs (s);
656 82 : DefaultResolver::visit (s.get_struct_name ());
657 :
658 82 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
659 82 : }
660 :
661 : void
662 0 : Late::visit (AST::StructExprStructBase &s)
663 : {
664 0 : visit_outer_attrs (s);
665 0 : visit_inner_attrs (s);
666 0 : DefaultResolver::visit (s.get_struct_name ());
667 0 : visit (s.get_struct_base ());
668 :
669 0 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
670 0 : }
671 :
672 : void
673 1372 : Late::visit (AST::StructExprStructFields &s)
674 : {
675 1372 : visit_outer_attrs (s);
676 1372 : visit_inner_attrs (s);
677 :
678 1372 : auto &path = s.get_struct_name ();
679 :
680 1372 : DefaultResolver::visit (path);
681 1372 : if (s.has_struct_base ())
682 63 : visit (s.get_struct_base ());
683 3710 : for (auto &field : s.get_fields ())
684 2338 : visit (field);
685 :
686 1372 : auto resolved = ctx.resolve_path (path, Namespace::Types);
687 :
688 1372 : if (!resolved)
689 : {
690 0 : rust_error_at (path.get_locus (), ErrorCode::E0433,
691 0 : "could not resolve path %qs", path.as_string ().c_str ());
692 0 : return;
693 : }
694 :
695 1372 : ctx.map_usage (Usage (path.get_node_id ()),
696 1372 : Definition (resolved->definition.get_node_id ()),
697 : Namespace::Types);
698 1372 : }
699 :
700 : // needed because Late::visit (AST::GenericArg &) is non-virtual
701 : void
702 3722 : Late::visit (AST::GenericArgs &args)
703 : {
704 3756 : for (auto &lifetime : args.get_lifetime_args ())
705 34 : visit (lifetime);
706 :
707 7638 : for (auto &generic : args.get_generic_args ())
708 3916 : visit (generic);
709 :
710 3794 : for (auto &binding : args.get_binding_args ())
711 72 : visit (binding);
712 3722 : }
713 :
714 : void
715 3916 : Late::visit (AST::GenericArg &arg)
716 : {
717 3916 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
718 : {
719 : // prefer type parameter to const parameter on ambiguity
720 4800 : auto type = ctx.types.get (arg.get_path ());
721 4800 : auto value = ctx.values.get (arg.get_path ());
722 :
723 2400 : if (!type.has_value () && value.has_value ())
724 31 : arg = arg.disambiguate_to_const ();
725 : else
726 2369 : arg = arg.disambiguate_to_type ();
727 3634 : }
728 :
729 3916 : DefaultResolver::visit (arg);
730 3916 : }
731 :
732 : void
733 67 : Late::visit_closure_params (AST::ClosureExpr &closure)
734 : {
735 67 : ctx.bindings.enter (BindingSource::Param);
736 :
737 67 : DefaultResolver::visit_closure_params (closure);
738 :
739 67 : ctx.bindings.exit ();
740 67 : }
741 :
742 : void
743 67 : Late::visit (AST::ClosureExpr &expr)
744 : {
745 : // add captures
746 67 : auto vals = ctx.values.peek ().get_values ();
747 88 : for (auto &val : vals)
748 : {
749 21 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
750 : }
751 :
752 67 : DefaultResolver::visit (expr);
753 67 : }
754 :
755 : } // namespace Resolver2_0
756 : } // namespace Rust
|