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-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 4692 : Late::Late (NameResolutionContext &ctx)
39 4692 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
40 4692 : {}
41 :
42 : void
43 4692 : Late::go (AST::Crate &crate)
44 : {
45 4692 : Builtins::setup_type_ctx ();
46 :
47 4692 : visit (crate);
48 4690 : }
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 2509 : Late::visit (AST::MatchArm &arm)
91 : {
92 2509 : visit_outer_attrs (arm);
93 :
94 2509 : ctx.bindings.enter (BindingSource::Match);
95 :
96 2509 : visit (arm.get_pattern ());
97 :
98 2509 : ctx.bindings.exit ();
99 :
100 2509 : if (arm.has_match_arm_guard ())
101 1 : visit (arm.get_guard_expr ());
102 2509 : }
103 :
104 : void
105 12767 : Late::visit (AST::LetStmt &let)
106 : {
107 12767 : DefaultASTVisitor::visit_outer_attrs (let);
108 12767 : if (let.has_type ())
109 2108 : visit (let.get_type ());
110 : // visit expression before pattern
111 : // this makes variable shadowing work properly
112 12767 : if (let.has_init_expr ())
113 11619 : visit (let.get_init_expr ());
114 :
115 12766 : ctx.bindings.enter (BindingSource::Let);
116 :
117 12766 : visit (let.get_pattern ());
118 :
119 12766 : ctx.bindings.exit ();
120 :
121 12766 : if (let.has_else_expr ())
122 5 : visit (let.get_else_expr ());
123 :
124 : // how do we deal with the fact that `let a = blipbloup` should look for a
125 : // label and cannot go through function ribs, but `let a = blipbloup()` can?
126 :
127 : // how do we insert ribs here, and only pop them when we exit the current
128 : // function?
129 : // keep a list of ribs to pop when a scope exits? so only for blocks?
130 : // how do we pop ribs that need to be popped not in order?
131 : // I think it's not important if we have shadowing, correct?
132 :
133 : // if we have shadowing, it should work! we'll see
134 :
135 : // ctx.insert(Identifier name, NodeId id, Namespace ns)
136 : // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
137 : // Namespace::Labels,
138 : // let.get_node_id (), [] () {});
139 12766 : }
140 :
141 : void
142 0 : Late::visit (AST::WhileLetLoopExpr &while_let)
143 : {
144 0 : DefaultASTVisitor::visit_outer_attrs (while_let);
145 :
146 0 : if (while_let.has_loop_label ())
147 0 : visit (while_let.get_loop_label ());
148 :
149 : // visit expression before pattern
150 : // this makes variable shadowing work properly
151 0 : visit (while_let.get_scrutinee_expr ());
152 :
153 0 : ctx.bindings.enter (BindingSource::WhileLet);
154 :
155 0 : visit (while_let.get_pattern ());
156 :
157 0 : ctx.bindings.exit ();
158 :
159 0 : visit (while_let.get_loop_block ());
160 0 : }
161 :
162 : static void
163 24478 : visit_identifier_as_pattern (NameResolutionContext &ctx,
164 : const Identifier &ident, location_t locus,
165 : NodeId node_id, bool is_ref, bool is_mut)
166 : {
167 : // do we insert in labels or in values
168 : // but values does not allow shadowing... since functions cannot shadow
169 : // do we insert functions in labels as well?
170 :
171 24478 : if (ctx.bindings.peek ().is_and_bound (ident))
172 : {
173 8 : if (ctx.bindings.peek ().get_source () == BindingSource::Param)
174 5 : rust_error_at (
175 : locus, ErrorCode::E0415,
176 : "identifier %qs is bound more than once in the same parameter list",
177 5 : ident.as_string ().c_str ());
178 : else
179 3 : rust_error_at (
180 : locus, ErrorCode::E0416,
181 : "identifier %qs is bound more than once in the same pattern",
182 3 : ident.as_string ().c_str ());
183 8 : return;
184 : }
185 :
186 48940 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
187 :
188 24470 : if (ctx.bindings.peek ().is_or_bound (ident))
189 : {
190 58 : auto res = ctx.values.get (ident);
191 58 : rust_assert (res.has_value () && !res->is_ambiguous ());
192 58 : ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
193 58 : }
194 : else
195 : {
196 : // We do want to ignore duplicated data because some situations rely on
197 : // it.
198 24412 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
199 : }
200 : }
201 :
202 : void
203 24378 : Late::visit (AST::IdentifierPattern &identifier)
204 : {
205 24378 : DefaultResolver::visit (identifier);
206 :
207 24378 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
208 : identifier.get_locus (),
209 24378 : identifier.get_node_id (),
210 24378 : identifier.get_is_ref (),
211 24378 : identifier.get_is_mut ());
212 24378 : }
213 :
214 : void
215 191 : Late::visit (AST::AltPattern &pattern)
216 : {
217 191 : ctx.bindings.peek ().push (Binding::Kind::Or);
218 591 : for (auto &alt : pattern.get_alts ())
219 : {
220 400 : ctx.bindings.peek ().push (Binding::Kind::Product);
221 400 : visit (alt);
222 400 : ctx.bindings.peek ().merge ();
223 : }
224 191 : ctx.bindings.peek ().merge ();
225 191 : }
226 :
227 : void
228 18719 : Late::visit_function_params (AST::Function &function)
229 : {
230 18719 : ctx.bindings.enter (BindingSource::Param);
231 :
232 38417 : for (auto ¶m : function.get_function_params ())
233 19698 : visit (param);
234 :
235 18719 : ctx.bindings.exit ();
236 18719 : }
237 :
238 : void
239 100 : Late::visit (AST::StructPatternFieldIdent &field)
240 : {
241 : // We need to check if the Identifier resolves to a variant or empty struct
242 100 : auto path = AST::SimplePath (field.get_identifier ());
243 :
244 100 : if (auto resolved = ctx.resolve_path (path, Namespace::Types))
245 : {
246 0 : ctx.map_usage (Usage (field.get_node_id ()),
247 0 : Definition (resolved->get_node_id ()));
248 0 : return;
249 0 : }
250 :
251 100 : visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
252 100 : field.get_node_id (), field.is_ref (),
253 100 : field.is_mut ());
254 100 : }
255 :
256 : void
257 7985 : Late::visit (AST::SelfParam ¶m)
258 : {
259 : // handle similar to AST::IdentifierPattern
260 :
261 7985 : DefaultResolver::visit (param);
262 : // FIXME: this location should be a bit off
263 : // ex: would point to the beginning of "mut self" instead of the "self"
264 23955 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
265 7985 : param.get_node_id ());
266 7985 : }
267 :
268 : void
269 97 : Late::visit (AST::BreakExpr &expr)
270 : {
271 97 : if (expr.has_label ())
272 25 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
273 :
274 97 : if (expr.has_break_expr ())
275 : {
276 24 : auto &break_expr = expr.get_break_expr_unchecked ();
277 24 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
278 : {
279 : /* This is a break with an expression, and the expression is
280 : just a single identifier. See if the identifier is either
281 : "rust" or "gcc", in which case we have "break rust" or "break
282 : gcc", and so may need to emit our funny error. We cannot yet
283 : emit the error here though, because the identifier may still
284 : be in scope, and ICE'ing on valid programs would not be very
285 : funny. */
286 11 : std::string ident = static_cast<AST::IdentifierExpr &> (
287 11 : expr.get_break_expr_unchecked ())
288 11 : .as_string ();
289 11 : if (ident == "rust" || ident == "gcc")
290 2 : funny_error = true;
291 11 : }
292 : }
293 :
294 97 : DefaultResolver::visit (expr);
295 :
296 96 : funny_error = false;
297 96 : }
298 :
299 : void
300 67 : Late::visit (AST::LoopLabel &label)
301 : {
302 67 : auto resolved = ctx.lookup (label.get_lifetime ().get_node_id ());
303 67 : if (resolved.has_value ())
304 21 : return;
305 46 : auto &lifetime = label.get_lifetime ();
306 92 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
307 : lifetime.get_node_id ());
308 : }
309 :
310 : void
311 28 : Late::resolve_label (AST::Lifetime &lifetime)
312 : {
313 56 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
314 : {
315 23 : if (resolved->get_node_id () != lifetime.get_node_id ())
316 23 : ctx.map_usage (Usage (lifetime.get_node_id ()),
317 23 : Definition (resolved->get_node_id ()));
318 : }
319 : else
320 5 : rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
321 : "use of undeclared label %qs",
322 10 : lifetime.as_string ().c_str ());
323 28 : }
324 :
325 : void
326 17 : Late::visit (AST::ContinueExpr &expr)
327 : {
328 17 : if (expr.has_label ())
329 3 : resolve_label (expr.get_label_unchecked ());
330 :
331 17 : DefaultResolver::visit (expr);
332 17 : }
333 :
334 : void
335 24444 : Late::visit (AST::IdentifierExpr &expr)
336 : {
337 : // TODO: same thing as visit(PathInExpression) here?
338 :
339 24444 : tl::optional<Rib::Definition> resolved = tl::nullopt;
340 :
341 24444 : if (auto value = ctx.values.get (expr.get_ident ()))
342 : {
343 24432 : resolved = value;
344 : }
345 12 : else if (auto type = ctx.types.get (expr.get_ident ()))
346 : {
347 0 : resolved = type;
348 : }
349 12 : else if (funny_error)
350 : {
351 1 : diagnostics::text_finalizer (global_dc)
352 1 : = Resolver::funny_ice_text_finalizer;
353 1 : emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
354 : "are you trying to break %s? how dare you?",
355 1 : expr.as_string ().c_str ());
356 : }
357 : else
358 : {
359 11 : if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
360 : {
361 2 : resolved = type;
362 : }
363 9 : else if (!resolved && ctx.prelude)
364 : {
365 0 : resolved
366 0 : = ctx.values.get_from_prelude (*ctx.prelude, expr.get_ident ());
367 :
368 0 : if (!resolved)
369 0 : resolved
370 0 : = ctx.types.get_from_prelude (*ctx.prelude, expr.get_ident ());
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 11 : }
381 :
382 24434 : 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 24434 : ctx.map_usage (Usage (expr.get_node_id ()),
390 24434 : Definition (resolved->get_node_id ()));
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 24443 : }
395 :
396 : void
397 216 : Late::visit (AST::StructExprFieldIdentifier &expr)
398 : {
399 216 : tl::optional<Rib::Definition> resolved = tl::nullopt;
400 :
401 216 : if (auto value = ctx.values.get (expr.get_field_name ()))
402 : {
403 216 : 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 216 : 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 216 : ctx.map_usage (Usage (expr.get_node_id ()),
421 216 : Definition (resolved->get_node_id ()));
422 216 : }
423 :
424 : void
425 24441 : 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 24441 : DefaultResolver::visit (expr);
432 :
433 24441 : if (expr.is_lang_item ())
434 : {
435 144 : ctx.map_usage (Usage (expr.get_node_id ()),
436 145 : Definition (Analysis::Mappings::get ().get_lang_item_node (
437 145 : expr.get_lang_item ())));
438 1544 : return;
439 : }
440 :
441 24296 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
442 :
443 24296 : if (!resolved)
444 : {
445 1399 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
446 14 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
447 : "Cannot find path %qs in this scope",
448 14 : expr.as_simple_path ().as_string ().c_str ());
449 1399 : return;
450 : }
451 :
452 22897 : if (resolved->is_ambiguous ())
453 : {
454 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
455 1 : expr.as_string ().c_str ());
456 1 : return;
457 : }
458 :
459 22896 : ctx.map_usage (Usage (expr.get_node_id ()),
460 22896 : Definition (resolved->get_node_id ()));
461 24296 : }
462 :
463 : void
464 5653 : Late::visit_impl_type (AST::Type &type)
465 : {
466 : // TODO: does this have to handle reentrancy?
467 5653 : rust_assert (!block_big_self);
468 5653 : block_big_self = true;
469 5653 : visit (type);
470 5653 : block_big_self = false;
471 5653 : }
472 :
473 : template <typename P>
474 : static void
475 54872 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
476 : P &type)
477 : {
478 : // should we add type path resolution in `ForeverStack` directly? Since it's
479 : // quite more complicated.
480 : // maybe we can overload `resolve_path<Namespace::Types>` to only do
481 : // typepath-like path resolution? that sounds good
482 :
483 : // prevent "impl Self {}" and similar
484 54872 : if (type.get_segments ().size () == 1
485 53422 : && !unwrap_segment_get_lang_item (type.get_segments ().front ())
486 53422 : .has_value ()
487 53030 : && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
488 62140 : && block_big_self)
489 : {
490 2 : rust_error_at (type.get_locus (),
491 : "%<Self%> is not valid in the self type of an impl block");
492 1041 : return;
493 : }
494 :
495 : // this *should* mostly work
496 : // TODO: make sure typepath-like path resolution (?) is working
497 54870 : auto resolved = ctx.resolve_path (type, Namespace::Types);
498 :
499 54870 : if (!resolved.has_value ())
500 : {
501 1039 : if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ())))
502 26 : rust_error_at (type.get_locus (), ErrorCode::E0412,
503 : "could not resolve type path %qs",
504 52 : unwrap_segment_error_string (type).c_str ());
505 1039 : return;
506 : }
507 :
508 53831 : if (resolved->is_ambiguous ())
509 : {
510 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
511 0 : unwrap_segment_error_string (type).c_str ());
512 0 : return;
513 : }
514 :
515 53831 : if (ctx.types.forward_declared (resolved->get_node_id (),
516 53831 : type.get_node_id ()))
517 : {
518 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
519 : "type parameters with a default cannot use forward "
520 : "declared identifiers");
521 : }
522 :
523 53831 : ctx.map_usage (Usage (type.get_node_id ()),
524 53831 : Definition (resolved->get_node_id ()));
525 54870 : }
526 :
527 : void
528 54790 : Late::visit (AST::TypePath &type)
529 : {
530 54790 : DefaultResolver::visit (type);
531 :
532 54790 : resolve_type_path_like (ctx, block_big_self, type);
533 54790 : }
534 :
535 : void
536 42762 : Late::visit (AST::Visibility &vis)
537 : {
538 42762 : if (!vis.has_path ())
539 42700 : return;
540 :
541 65 : AST::SimplePath &path = vis.get_path ();
542 :
543 65 : rust_assert (path.get_segments ().size ());
544 65 : auto &first_seg = path.get_segments ()[0];
545 :
546 65 : auto mode = ResolutionMode::Normal;
547 :
548 65 : if (path.has_opening_scope_resolution ())
549 : {
550 0 : if (get_rust_edition () == Edition::E2015)
551 : mode = ResolutionMode::FromRoot;
552 : else
553 65 : mode = ResolutionMode::FromExtern;
554 : }
555 77 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
556 74 : && !first_seg.is_lower_self_seg ())
557 : {
558 7 : if (get_rust_edition () == Edition::E2015)
559 : {
560 : mode = ResolutionMode::FromRoot;
561 : }
562 : else
563 : {
564 0 : rust_error_at (path.get_locus (),
565 : "relative paths are not supported in visibilities in "
566 : "2018 edition or later");
567 0 : return;
568 : }
569 : }
570 :
571 65 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
572 :
573 65 : if (!res.has_value ())
574 : {
575 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
576 3 : "could not resolve path %qs", path.as_string ().c_str ());
577 3 : return;
578 : }
579 :
580 : // TODO: is this possible?
581 62 : if (res->is_ambiguous ())
582 : {
583 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
584 0 : path.as_string ().c_str ());
585 0 : return;
586 : }
587 :
588 62 : ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
589 65 : }
590 :
591 : void
592 3918 : Late::visit (AST::Trait &trait)
593 : {
594 : // kind of weird how this is done
595 : // names are resolved to the node id of trait.get_implicit_self ()
596 : // which is then resolved to the node id of trait
597 : // we set up the latter mapping here
598 3918 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
599 3918 : Definition (trait.get_node_id ()));
600 :
601 3918 : DefaultResolver::visit (trait);
602 3918 : }
603 :
604 : void
605 82 : Late::visit (AST::StructExprStruct &s)
606 : {
607 82 : visit_outer_attrs (s);
608 82 : visit_inner_attrs (s);
609 82 : DefaultResolver::visit (s.get_struct_name ());
610 :
611 82 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
612 82 : }
613 :
614 : void
615 0 : Late::visit (AST::StructExprStructBase &s)
616 : {
617 0 : visit_outer_attrs (s);
618 0 : visit_inner_attrs (s);
619 0 : DefaultResolver::visit (s.get_struct_name ());
620 0 : visit (s.get_struct_base ());
621 :
622 0 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
623 0 : }
624 :
625 : void
626 1334 : Late::visit (AST::StructExprStructFields &s)
627 : {
628 1334 : visit_outer_attrs (s);
629 1334 : visit_inner_attrs (s);
630 :
631 1334 : auto &path = s.get_struct_name ();
632 :
633 1334 : DefaultResolver::visit (path);
634 1334 : if (s.has_struct_base ())
635 63 : visit (s.get_struct_base ());
636 3628 : for (auto &field : s.get_fields ())
637 2294 : visit (field);
638 :
639 1334 : auto resolved = ctx.resolve_path (path, Namespace::Types);
640 :
641 1334 : if (!resolved)
642 : {
643 0 : rust_error_at (path.get_locus (), ErrorCode::E0433,
644 0 : "could not resolve path %qs", path.as_string ().c_str ());
645 0 : return;
646 : }
647 :
648 1334 : ctx.map_usage (Usage (path.get_node_id ()),
649 1334 : Definition (resolved->get_node_id ()));
650 1334 : }
651 :
652 : // needed because Late::visit (AST::GenericArg &) is non-virtual
653 : void
654 3674 : Late::visit (AST::GenericArgs &args)
655 : {
656 3715 : for (auto &lifetime : args.get_lifetime_args ())
657 41 : visit (lifetime);
658 :
659 7530 : for (auto &generic : args.get_generic_args ())
660 3856 : visit (generic);
661 :
662 3746 : for (auto &binding : args.get_binding_args ())
663 72 : visit (binding);
664 3674 : }
665 :
666 : void
667 3856 : Late::visit (AST::GenericArg &arg)
668 : {
669 3856 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
670 : {
671 : // prefer type parameter to const parameter on ambiguity
672 4694 : auto type = ctx.types.get (arg.get_path ());
673 4694 : auto value = ctx.values.get (arg.get_path ());
674 :
675 2347 : if (!type.has_value () && value.has_value ())
676 31 : arg = arg.disambiguate_to_const ();
677 : else
678 2316 : arg = arg.disambiguate_to_type ();
679 3551 : }
680 :
681 3856 : DefaultResolver::visit (arg);
682 3856 : }
683 :
684 : void
685 67 : Late::visit_closure_params (AST::ClosureExpr &closure)
686 : {
687 67 : ctx.bindings.enter (BindingSource::Param);
688 :
689 67 : DefaultResolver::visit_closure_params (closure);
690 :
691 67 : ctx.bindings.exit ();
692 67 : }
693 :
694 : void
695 67 : Late::visit (AST::ClosureExpr &expr)
696 : {
697 : // add captures
698 67 : auto vals = ctx.values.peek ().get_values ();
699 88 : for (auto &val : vals)
700 : {
701 21 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
702 : }
703 :
704 67 : DefaultResolver::visit (expr);
705 67 : }
706 :
707 : } // namespace Resolver2_0
708 : } // namespace Rust
|