Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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-system.h"
30 : : #include "rust-tyty.h"
31 : : #include "rust-hir-type-check.h"
32 : : #include "rust-ice-finalizer.h"
33 : : #include "rust-ast.h"
34 : :
35 : : namespace Rust {
36 : : namespace Resolver2_0 {
37 : :
38 : 4444 : Late::Late (NameResolutionContext &ctx)
39 : 4444 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
40 : 4444 : {}
41 : :
42 : : void
43 : 4444 : Late::go (AST::Crate &crate)
44 : : {
45 : 4444 : Builtins::setup_type_ctx ();
46 : :
47 : 4444 : visit (crate);
48 : 4443 : }
49 : :
50 : : void
51 : 0 : Late::new_label (Identifier name, NodeId id)
52 : : {
53 : : // labels can always shadow, so `insert` should never fail. if it does, we're
54 : : // in big trouble!
55 : 0 : auto ok = ctx.labels.insert (name, id);
56 : :
57 : 0 : rust_assert (ok);
58 : 0 : }
59 : :
60 : : void
61 : 0 : Late::visit (AST::ForLoopExpr &expr)
62 : : {
63 : 0 : visit_outer_attrs (expr);
64 : :
65 : 0 : ctx.bindings.enter (BindingSource::For);
66 : :
67 : 0 : visit (expr.get_pattern ());
68 : :
69 : 0 : ctx.bindings.exit ();
70 : :
71 : 0 : visit (expr.get_iterator_expr ());
72 : :
73 : 0 : if (expr.has_loop_label ())
74 : 0 : visit (expr.get_loop_label ());
75 : :
76 : 0 : visit (expr.get_loop_block ());
77 : 0 : }
78 : :
79 : : void
80 : 30 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
81 : : {
82 : 30 : ctx.bindings.enter (BindingSource::IfLet);
83 : :
84 : 30 : DefaultResolver::visit_if_let_patterns (expr);
85 : :
86 : 30 : ctx.bindings.exit ();
87 : 30 : }
88 : :
89 : : void
90 : 2459 : Late::visit (AST::MatchArm &arm)
91 : : {
92 : 2459 : visit_outer_attrs (arm);
93 : :
94 : 2459 : ctx.bindings.enter (BindingSource::Match);
95 : :
96 : 4918 : for (auto &pattern : arm.get_patterns ())
97 : 2459 : visit (pattern);
98 : :
99 : 2459 : ctx.bindings.exit ();
100 : :
101 : 2459 : if (arm.has_match_arm_guard ())
102 : 1 : visit (arm.get_guard_expr ());
103 : 2459 : }
104 : :
105 : : void
106 : 12671 : Late::visit (AST::LetStmt &let)
107 : : {
108 : 12671 : DefaultASTVisitor::visit_outer_attrs (let);
109 : 12671 : if (let.has_type ())
110 : 2092 : visit (let.get_type ());
111 : : // visit expression before pattern
112 : : // this makes variable shadowing work properly
113 : 12671 : if (let.has_init_expr ())
114 : 11523 : visit (let.get_init_expr ());
115 : :
116 : 12671 : ctx.bindings.enter (BindingSource::Let);
117 : :
118 : 12671 : visit (let.get_pattern ());
119 : :
120 : 12671 : ctx.bindings.exit ();
121 : :
122 : 12671 : if (let.has_else_expr ())
123 : 0 : visit (let.get_init_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 : 12671 : }
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 : for (auto &pattern : while_let.get_patterns ())
157 : 0 : visit (pattern);
158 : :
159 : 0 : ctx.bindings.exit ();
160 : :
161 : 0 : visit (while_let.get_loop_block ());
162 : 0 : }
163 : :
164 : : static void
165 : 24234 : 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 : 24234 : 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 : 8 : return;
186 : : }
187 : :
188 : 48452 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
189 : :
190 : 24226 : if (ctx.bindings.peek ().is_or_bound (ident))
191 : : {
192 : 58 : auto res = ctx.values.get (ident);
193 : 58 : rust_assert (res.has_value () && !res->is_ambiguous ());
194 : 58 : ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
195 : 58 : }
196 : : else
197 : : {
198 : : // We do want to ignore duplicated data because some situations rely on
199 : : // it.
200 : 24168 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
201 : : }
202 : : }
203 : :
204 : : void
205 : 24136 : Late::visit (AST::IdentifierPattern &identifier)
206 : : {
207 : 24136 : DefaultResolver::visit (identifier);
208 : :
209 : 24136 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
210 : : identifier.get_locus (),
211 : 24136 : identifier.get_node_id (),
212 : 24136 : identifier.get_is_ref (),
213 : 24136 : identifier.get_is_mut ());
214 : 24136 : }
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 : 18160 : Late::visit_function_params (AST::Function &function)
231 : : {
232 : 18160 : ctx.bindings.enter (BindingSource::Param);
233 : :
234 : 37683 : for (auto ¶m : function.get_function_params ())
235 : 19523 : visit (param);
236 : :
237 : 18160 : ctx.bindings.exit ();
238 : 18160 : }
239 : :
240 : : void
241 : 98 : Late::visit (AST::StructPatternFieldIdent &field)
242 : : {
243 : 98 : visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
244 : 98 : field.get_node_id (), field.is_ref (),
245 : 98 : field.is_mut ());
246 : 98 : }
247 : :
248 : : void
249 : 7982 : Late::visit (AST::SelfParam ¶m)
250 : : {
251 : : // handle similar to AST::IdentifierPattern
252 : :
253 : 7982 : DefaultResolver::visit (param);
254 : : // FIXME: this location should be a bit off
255 : : // ex: would point to the begining of "mut self" instead of the "self"
256 : 23946 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
257 : 7982 : param.get_node_id ());
258 : 7982 : }
259 : :
260 : : void
261 : 89 : Late::visit (AST::BreakExpr &expr)
262 : : {
263 : 89 : if (expr.has_label ())
264 : 21 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
265 : :
266 : 89 : if (expr.has_break_expr ())
267 : : {
268 : 22 : auto &break_expr = expr.get_break_expr ();
269 : 22 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
270 : : {
271 : : /* This is a break with an expression, and the expression is
272 : : just a single identifier. See if the identifier is either
273 : : "rust" or "gcc", in which case we have "break rust" or "break
274 : : gcc", and so may need to emit our funny error. We cannot yet
275 : : emit the error here though, because the identifier may still
276 : : be in scope, and ICE'ing on valid programs would not be very
277 : : funny. */
278 : 11 : std::string ident
279 : 11 : = static_cast<AST::IdentifierExpr &> (expr.get_break_expr ())
280 : 11 : .as_string ();
281 : 11 : if (ident == "rust" || ident == "gcc")
282 : 2 : funny_error = true;
283 : 11 : }
284 : : }
285 : :
286 : 89 : DefaultResolver::visit (expr);
287 : :
288 : 88 : funny_error = false;
289 : 88 : }
290 : :
291 : : void
292 : 55 : Late::visit (AST::LoopLabel &label)
293 : : {
294 : 55 : auto &lifetime = label.get_lifetime ();
295 : 110 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
296 : : lifetime.get_node_id ());
297 : 55 : }
298 : :
299 : : void
300 : 22 : Late::resolve_label (AST::Lifetime &lifetime)
301 : : {
302 : 44 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
303 : : {
304 : 17 : if (resolved->get_node_id () != lifetime.get_node_id ())
305 : 17 : ctx.map_usage (Usage (lifetime.get_node_id ()),
306 : 17 : Definition (resolved->get_node_id ()));
307 : : }
308 : : else
309 : 5 : rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
310 : : "use of undeclared label %qs",
311 : 10 : lifetime.as_string ().c_str ());
312 : 22 : }
313 : :
314 : : void
315 : 12 : Late::visit (AST::ContinueExpr &expr)
316 : : {
317 : 12 : if (expr.has_label ())
318 : 1 : resolve_label (expr.get_label_unchecked ());
319 : :
320 : 12 : DefaultResolver::visit (expr);
321 : 12 : }
322 : :
323 : : void
324 : 24296 : Late::visit (AST::IdentifierExpr &expr)
325 : : {
326 : : // TODO: same thing as visit(PathInExpression) here?
327 : :
328 : 24296 : tl::optional<Rib::Definition> resolved = tl::nullopt;
329 : 24296 : if (auto value = ctx.values.get (expr.get_ident ()))
330 : : {
331 : 24276 : resolved = value;
332 : : }
333 : 20 : else if (auto type = ctx.types.get (expr.get_ident ()))
334 : : {
335 : 11 : resolved = type;
336 : : }
337 : 9 : else if (funny_error)
338 : : {
339 : 1 : diagnostics::text_finalizer (global_dc)
340 : 1 : = Resolver::funny_ice_text_finalizer;
341 : 1 : emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
342 : : "are you trying to break %s? how dare you?",
343 : 1 : expr.as_string ().c_str ());
344 : : }
345 : : else
346 : : {
347 : 8 : if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
348 : : {
349 : 2 : resolved = type;
350 : : }
351 : : else
352 : : {
353 : 6 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
354 : : "cannot find value %qs in this scope",
355 : 6 : expr.get_ident ().as_string ().c_str ());
356 : 6 : return;
357 : 8 : }
358 : 19 : }
359 : :
360 : 24289 : if (resolved->is_ambiguous ())
361 : : {
362 : 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
363 : 0 : expr.as_string ().c_str ());
364 : 0 : return;
365 : : }
366 : :
367 : 24289 : ctx.map_usage (Usage (expr.get_node_id ()),
368 : 24289 : Definition (resolved->get_node_id ()));
369 : :
370 : : // For empty types, do we perform a lookup in ctx.types or should the
371 : : // toplevel instead insert a name in ctx.values? (like it currently does)
372 : 24295 : }
373 : :
374 : : void
375 : 216 : Late::visit (AST::StructExprFieldIdentifier &expr)
376 : : {
377 : 216 : tl::optional<Rib::Definition> resolved = tl::nullopt;
378 : :
379 : 216 : if (auto value = ctx.values.get (expr.get_field_name ()))
380 : : {
381 : 216 : resolved = value;
382 : : }
383 : : // seems like we don't need a type namespace lookup
384 : : else
385 : : {
386 : 0 : rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
387 : 0 : expr.get_field_name ().as_string ().c_str ());
388 : 0 : return;
389 : 0 : }
390 : :
391 : 216 : if (resolved->is_ambiguous ())
392 : : {
393 : 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
394 : 0 : expr.as_string ().c_str ());
395 : 0 : return;
396 : : }
397 : :
398 : 216 : ctx.map_usage (Usage (expr.get_node_id ()),
399 : 216 : Definition (resolved->get_node_id ()));
400 : 216 : }
401 : :
402 : : void
403 : 22859 : Late::visit (AST::PathInExpression &expr)
404 : : {
405 : : // TODO: How do we have a nice error with `can't capture dynamic environment
406 : : // in a function item` error here?
407 : : // do we emit it in `get<Namespace::Labels>`?
408 : :
409 : 22859 : DefaultResolver::visit (expr);
410 : :
411 : 22859 : if (expr.is_lang_item ())
412 : : {
413 : 144 : ctx.map_usage (Usage (expr.get_node_id ()),
414 : 144 : Definition (Analysis::Mappings::get ().get_lang_item_node (
415 : 144 : expr.get_lang_item ())));
416 : 1539 : return;
417 : : }
418 : :
419 : 22715 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
420 : :
421 : 22715 : if (!resolved)
422 : : {
423 : 1394 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
424 : 4 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
425 : : "Cannot find path %qs in this scope",
426 : 4 : expr.as_simple_path ().as_string ().c_str ());
427 : 1394 : return;
428 : : }
429 : :
430 : 21321 : if (resolved->is_ambiguous ())
431 : : {
432 : 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
433 : 1 : expr.as_string ().c_str ());
434 : 1 : return;
435 : : }
436 : :
437 : 21320 : ctx.map_usage (Usage (expr.get_node_id ()),
438 : 21320 : Definition (resolved->get_node_id ()));
439 : 22715 : }
440 : :
441 : : void
442 : 5640 : Late::visit_impl_type (AST::Type &type)
443 : : {
444 : : // TODO: does this have to handle reentrancy?
445 : 5640 : rust_assert (!block_big_self);
446 : 5640 : block_big_self = true;
447 : 5640 : visit (type);
448 : 5640 : block_big_self = false;
449 : 5640 : }
450 : :
451 : : template <typename P>
452 : : static void
453 : 55549 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
454 : : P &type)
455 : : {
456 : : // should we add type path resolution in `ForeverStack` directly? Since it's
457 : : // quite more complicated.
458 : : // maybe we can overload `resolve_path<Namespace::Types>` to only do
459 : : // typepath-like path resolution? that sounds good
460 : :
461 : : // prevent "impl Self {}" and similar
462 : 55549 : if (type.get_segments ().size () == 1
463 : 54001 : && !unwrap_segment_get_lang_item (type.get_segments ().front ())
464 : 54001 : .has_value ()
465 : 53611 : && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
466 : 62858 : && block_big_self)
467 : : {
468 : 2 : rust_error_at (type.get_locus (),
469 : : "%<Self%> is not valid in the self type of an impl block");
470 : 1036 : return;
471 : : }
472 : :
473 : : // this *should* mostly work
474 : : // TODO: make sure typepath-like path resolution (?) is working
475 : 55547 : auto resolved = ctx.resolve_path (type, Namespace::Types);
476 : :
477 : 55547 : if (!resolved.has_value ())
478 : : {
479 : 1034 : if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ())))
480 : 23 : rust_error_at (type.get_locus (), ErrorCode::E0412,
481 : : "could not resolve type path %qs",
482 : 46 : unwrap_segment_error_string (type).c_str ());
483 : 1034 : return;
484 : : }
485 : :
486 : 54513 : if (resolved->is_ambiguous ())
487 : : {
488 : 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
489 : 0 : unwrap_segment_error_string (type).c_str ());
490 : 0 : return;
491 : : }
492 : :
493 : 54513 : if (ctx.types.forward_declared (resolved->get_node_id (),
494 : 54513 : type.get_node_id ()))
495 : : {
496 : 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
497 : : "type parameters with a default cannot use forward "
498 : : "declared identifiers");
499 : : }
500 : :
501 : 54513 : ctx.map_usage (Usage (type.get_node_id ()),
502 : 54513 : Definition (resolved->get_node_id ()));
503 : 55547 : }
504 : :
505 : : void
506 : 54146 : Late::visit (AST::TypePath &type)
507 : : {
508 : 54146 : DefaultResolver::visit (type);
509 : :
510 : 54146 : resolve_type_path_like (ctx, block_big_self, type);
511 : 54146 : }
512 : :
513 : : void
514 : 41674 : Late::visit (AST::Visibility &vis)
515 : : {
516 : 41674 : if (!vis.has_path ())
517 : 41612 : return;
518 : :
519 : 65 : AST::SimplePath &path = vis.get_path ();
520 : :
521 : 65 : rust_assert (path.get_segments ().size ());
522 : 65 : auto &first_seg = path.get_segments ()[0];
523 : :
524 : 65 : auto mode = ResolutionMode::Normal;
525 : :
526 : 65 : if (path.has_opening_scope_resolution ())
527 : : {
528 : 0 : if (get_rust_edition () == Edition::E2015)
529 : : mode = ResolutionMode::FromRoot;
530 : : else
531 : 65 : mode = ResolutionMode::FromExtern;
532 : : }
533 : 77 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
534 : 74 : && !first_seg.is_lower_self_seg ())
535 : : {
536 : 7 : if (get_rust_edition () == Edition::E2015)
537 : : {
538 : : mode = ResolutionMode::FromRoot;
539 : : }
540 : : else
541 : : {
542 : 0 : rust_error_at (path.get_locus (),
543 : : "relative paths are not supported in visibilities in "
544 : : "2018 edition or later");
545 : 0 : return;
546 : : }
547 : : }
548 : :
549 : 65 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
550 : :
551 : 65 : if (!res.has_value ())
552 : : {
553 : 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
554 : 3 : "could not resolve path %qs", path.as_string ().c_str ());
555 : 3 : return;
556 : : }
557 : :
558 : : // TODO: is this possible?
559 : 62 : if (res->is_ambiguous ())
560 : : {
561 : 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
562 : 0 : path.as_string ().c_str ());
563 : 0 : return;
564 : : }
565 : :
566 : 62 : ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
567 : 65 : }
568 : :
569 : : void
570 : 3733 : Late::visit (AST::Trait &trait)
571 : : {
572 : : // kind of weird how this is done
573 : : // names are resolved to the node id of trait.get_implicit_self ()
574 : : // which is then resolved to the node id of trait
575 : : // we set up the latter mapping here
576 : 3733 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
577 : 3733 : Definition (trait.get_node_id ()));
578 : :
579 : 3733 : DefaultResolver::visit (trait);
580 : 3733 : }
581 : :
582 : : void
583 : 78 : Late::visit (AST::StructExprStruct &s)
584 : : {
585 : 78 : visit_outer_attrs (s);
586 : 78 : visit_inner_attrs (s);
587 : 78 : DefaultResolver::visit (s.get_struct_name ());
588 : :
589 : 78 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
590 : 78 : }
591 : :
592 : : void
593 : 0 : Late::visit (AST::StructExprStructBase &s)
594 : : {
595 : 0 : visit_outer_attrs (s);
596 : 0 : visit_inner_attrs (s);
597 : 0 : DefaultResolver::visit (s.get_struct_name ());
598 : 0 : visit (s.get_struct_base ());
599 : :
600 : 0 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
601 : 0 : }
602 : :
603 : : void
604 : 1325 : Late::visit (AST::StructExprStructFields &s)
605 : : {
606 : 1325 : visit_outer_attrs (s);
607 : 1325 : visit_inner_attrs (s);
608 : 1325 : DefaultResolver::visit (s.get_struct_name ());
609 : 1325 : if (s.has_struct_base ())
610 : 63 : visit (s.get_struct_base ());
611 : 3609 : for (auto &field : s.get_fields ())
612 : 2284 : visit (field);
613 : :
614 : 1325 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
615 : 1325 : }
616 : :
617 : : // needed because Late::visit (AST::GenericArg &) is non-virtual
618 : : void
619 : 3665 : Late::visit (AST::GenericArgs &args)
620 : : {
621 : 3706 : for (auto &lifetime : args.get_lifetime_args ())
622 : 41 : visit (lifetime);
623 : :
624 : 7512 : for (auto &generic : args.get_generic_args ())
625 : 3847 : visit (generic);
626 : :
627 : 3737 : for (auto &binding : args.get_binding_args ())
628 : 72 : visit (binding);
629 : 3665 : }
630 : :
631 : : void
632 : 3847 : Late::visit (AST::GenericArg &arg)
633 : : {
634 : 3847 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
635 : : {
636 : : // prefer type parameter to const parameter on ambiguity
637 : 4678 : auto type = ctx.types.get (arg.get_path ());
638 : 4678 : auto value = ctx.values.get (arg.get_path ());
639 : :
640 : 2339 : if (!type.has_value () && value.has_value ())
641 : 30 : arg = arg.disambiguate_to_const ();
642 : : else
643 : 2309 : arg = arg.disambiguate_to_type ();
644 : 3543 : }
645 : :
646 : 3847 : DefaultResolver::visit (arg);
647 : 3847 : }
648 : :
649 : : void
650 : 67 : Late::visit_closure_params (AST::ClosureExpr &closure)
651 : : {
652 : 67 : ctx.bindings.enter (BindingSource::Param);
653 : :
654 : 67 : DefaultResolver::visit_closure_params (closure);
655 : :
656 : 67 : ctx.bindings.exit ();
657 : 67 : }
658 : :
659 : : void
660 : 67 : Late::visit (AST::ClosureExpr &expr)
661 : : {
662 : : // add captures
663 : 67 : auto vals = ctx.values.peek ().get_values ();
664 : 88 : for (auto &val : vals)
665 : : {
666 : 21 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
667 : : }
668 : :
669 : 67 : DefaultResolver::visit (expr);
670 : 67 : }
671 : :
672 : : } // namespace Resolver2_0
673 : : } // namespace Rust
|