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