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 4506 : Late::Late (NameResolutionContext &ctx)
39 4506 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
40 4506 : {}
41 :
42 : void
43 4506 : Late::go (AST::Crate &crate)
44 : {
45 4506 : Builtins::setup_type_ctx ();
46 :
47 4506 : visit (crate);
48 4505 : }
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 2492 : Late::visit (AST::MatchArm &arm)
91 : {
92 2492 : visit_outer_attrs (arm);
93 :
94 2492 : ctx.bindings.enter (BindingSource::Match);
95 :
96 2492 : visit (arm.get_pattern ());
97 :
98 2492 : ctx.bindings.exit ();
99 :
100 2492 : if (arm.has_match_arm_guard ())
101 1 : visit (arm.get_guard_expr ());
102 2492 : }
103 :
104 : void
105 12714 : Late::visit (AST::LetStmt &let)
106 : {
107 12714 : DefaultASTVisitor::visit_outer_attrs (let);
108 12714 : if (let.has_type ())
109 2099 : visit (let.get_type ());
110 : // visit expression before pattern
111 : // this makes variable shadowing work properly
112 12714 : if (let.has_init_expr ())
113 11566 : visit (let.get_init_expr ());
114 :
115 12714 : ctx.bindings.enter (BindingSource::Let);
116 :
117 12714 : visit (let.get_pattern ());
118 :
119 12714 : ctx.bindings.exit ();
120 :
121 12714 : 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 12714 : }
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 24296 : 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 24296 : 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 48576 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
187 :
188 24288 : 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 24230 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
199 : }
200 : }
201 :
202 : void
203 24196 : Late::visit (AST::IdentifierPattern &identifier)
204 : {
205 24196 : DefaultResolver::visit (identifier);
206 :
207 24196 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
208 : identifier.get_locus (),
209 24196 : identifier.get_node_id (),
210 24196 : identifier.get_is_ref (),
211 24196 : identifier.get_is_mut ());
212 24196 : }
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 18239 : Late::visit_function_params (AST::Function &function)
229 : {
230 18239 : ctx.bindings.enter (BindingSource::Param);
231 :
232 37777 : for (auto ¶m : function.get_function_params ())
233 19538 : visit (param);
234 :
235 18239 : ctx.bindings.exit ();
236 18239 : }
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 7982 : Late::visit (AST::SelfParam ¶m)
258 : {
259 : // handle similar to AST::IdentifierPattern
260 :
261 7982 : 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 23946 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
265 7982 : param.get_node_id ());
266 7982 : }
267 :
268 : void
269 95 : Late::visit (AST::BreakExpr &expr)
270 : {
271 95 : if (expr.has_label ())
272 23 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
273 :
274 95 : if (expr.has_break_expr ())
275 : {
276 22 : auto &break_expr = expr.get_break_expr_unchecked ();
277 22 : 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 95 : DefaultResolver::visit (expr);
295 :
296 94 : funny_error = false;
297 94 : }
298 :
299 : void
300 63 : Late::visit (AST::LoopLabel &label)
301 : {
302 63 : auto &lifetime = label.get_lifetime ();
303 126 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
304 : lifetime.get_node_id ());
305 63 : }
306 :
307 : void
308 26 : Late::resolve_label (AST::Lifetime &lifetime)
309 : {
310 52 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
311 : {
312 21 : if (resolved->get_node_id () != lifetime.get_node_id ())
313 21 : ctx.map_usage (Usage (lifetime.get_node_id ()),
314 21 : Definition (resolved->get_node_id ()));
315 : }
316 : else
317 5 : rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
318 : "use of undeclared label %qs",
319 10 : lifetime.as_string ().c_str ());
320 26 : }
321 :
322 : void
323 17 : Late::visit (AST::ContinueExpr &expr)
324 : {
325 17 : if (expr.has_label ())
326 3 : resolve_label (expr.get_label_unchecked ());
327 :
328 17 : DefaultResolver::visit (expr);
329 17 : }
330 :
331 : void
332 24345 : Late::visit (AST::IdentifierExpr &expr)
333 : {
334 : // TODO: same thing as visit(PathInExpression) here?
335 :
336 24345 : tl::optional<Rib::Definition> resolved = tl::nullopt;
337 :
338 24345 : if (auto value = ctx.values.get (expr.get_ident ()))
339 : {
340 24325 : resolved = value;
341 : }
342 20 : else if (auto type = ctx.types.get (expr.get_ident ()))
343 : {
344 11 : resolved = type;
345 : }
346 9 : else if (funny_error)
347 : {
348 1 : diagnostics::text_finalizer (global_dc)
349 1 : = Resolver::funny_ice_text_finalizer;
350 1 : emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
351 : "are you trying to break %s? how dare you?",
352 1 : expr.as_string ().c_str ());
353 : }
354 : else
355 : {
356 8 : if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
357 : {
358 2 : resolved = type;
359 : }
360 6 : else if (!resolved && ctx.prelude)
361 : {
362 0 : resolved
363 0 : = ctx.values.get_from_prelude (*ctx.prelude, expr.get_ident ());
364 :
365 0 : if (!resolved)
366 0 : resolved
367 0 : = ctx.types.get_from_prelude (*ctx.prelude, expr.get_ident ());
368 8 : }
369 :
370 8 : if (!resolved)
371 : {
372 6 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
373 : "cannot find value %qs in this scope",
374 6 : expr.get_ident ().as_string ().c_str ());
375 6 : return;
376 : }
377 19 : }
378 :
379 24338 : if (resolved->is_ambiguous ())
380 : {
381 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
382 0 : expr.as_string ().c_str ());
383 0 : return;
384 : }
385 :
386 24338 : ctx.map_usage (Usage (expr.get_node_id ()),
387 24338 : Definition (resolved->get_node_id ()));
388 :
389 : // For empty types, do we perform a lookup in ctx.types or should the
390 : // toplevel instead insert a name in ctx.values? (like it currently does)
391 24344 : }
392 :
393 : void
394 216 : Late::visit (AST::StructExprFieldIdentifier &expr)
395 : {
396 216 : tl::optional<Rib::Definition> resolved = tl::nullopt;
397 :
398 216 : if (auto value = ctx.values.get (expr.get_field_name ()))
399 : {
400 216 : resolved = value;
401 : }
402 : // seems like we don't need a type namespace lookup
403 : else
404 : {
405 0 : rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
406 0 : expr.get_field_name ().as_string ().c_str ());
407 0 : return;
408 0 : }
409 :
410 216 : if (resolved->is_ambiguous ())
411 : {
412 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
413 0 : expr.as_string ().c_str ());
414 0 : return;
415 : }
416 :
417 216 : ctx.map_usage (Usage (expr.get_node_id ()),
418 216 : Definition (resolved->get_node_id ()));
419 216 : }
420 :
421 : void
422 22919 : Late::visit (AST::PathInExpression &expr)
423 : {
424 : // TODO: How do we have a nice error with `can't capture dynamic environment
425 : // in a function item` error here?
426 : // do we emit it in `get<Namespace::Labels>`?
427 :
428 22919 : DefaultResolver::visit (expr);
429 :
430 22919 : if (expr.is_lang_item ())
431 : {
432 144 : ctx.map_usage (Usage (expr.get_node_id ()),
433 144 : Definition (Analysis::Mappings::get ().get_lang_item_node (
434 144 : expr.get_lang_item ())));
435 1540 : return;
436 : }
437 :
438 22775 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
439 :
440 22775 : if (!resolved)
441 : {
442 1395 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
443 6 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
444 : "Cannot find path %qs in this scope",
445 6 : expr.as_simple_path ().as_string ().c_str ());
446 1395 : return;
447 : }
448 :
449 21380 : if (resolved->is_ambiguous ())
450 : {
451 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
452 1 : expr.as_string ().c_str ());
453 1 : return;
454 : }
455 :
456 21379 : ctx.map_usage (Usage (expr.get_node_id ()),
457 21379 : Definition (resolved->get_node_id ()));
458 22775 : }
459 :
460 : void
461 5648 : Late::visit_impl_type (AST::Type &type)
462 : {
463 : // TODO: does this have to handle reentrancy?
464 5648 : rust_assert (!block_big_self);
465 5648 : block_big_self = true;
466 5648 : visit (type);
467 5648 : block_big_self = false;
468 5648 : }
469 :
470 : template <typename P>
471 : static void
472 54370 : resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self,
473 : P &type)
474 : {
475 : // should we add type path resolution in `ForeverStack` directly? Since it's
476 : // quite more complicated.
477 : // maybe we can overload `resolve_path<Namespace::Types>` to only do
478 : // typepath-like path resolution? that sounds good
479 :
480 : // prevent "impl Self {}" and similar
481 54370 : if (type.get_segments ().size () == 1
482 52920 : && !unwrap_segment_get_lang_item (type.get_segments ().front ())
483 52920 : .has_value ()
484 52530 : && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg ()
485 61636 : && block_big_self)
486 : {
487 2 : rust_error_at (type.get_locus (),
488 : "%<Self%> is not valid in the self type of an impl block");
489 1040 : return;
490 : }
491 :
492 : // this *should* mostly work
493 : // TODO: make sure typepath-like path resolution (?) is working
494 54368 : auto resolved = ctx.resolve_path (type, Namespace::Types);
495 :
496 54368 : if (!resolved.has_value ())
497 : {
498 1038 : if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ())))
499 25 : rust_error_at (type.get_locus (), ErrorCode::E0412,
500 : "could not resolve type path %qs",
501 50 : unwrap_segment_error_string (type).c_str ());
502 1038 : return;
503 : }
504 :
505 53330 : if (resolved->is_ambiguous ())
506 : {
507 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
508 0 : unwrap_segment_error_string (type).c_str ());
509 0 : return;
510 : }
511 :
512 53330 : if (ctx.types.forward_declared (resolved->get_node_id (),
513 53330 : type.get_node_id ()))
514 : {
515 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
516 : "type parameters with a default cannot use forward "
517 : "declared identifiers");
518 : }
519 :
520 53330 : ctx.map_usage (Usage (type.get_node_id ()),
521 53330 : Definition (resolved->get_node_id ()));
522 54368 : }
523 :
524 : void
525 54289 : Late::visit (AST::TypePath &type)
526 : {
527 54289 : DefaultResolver::visit (type);
528 :
529 54289 : resolve_type_path_like (ctx, block_big_self, type);
530 54289 : }
531 :
532 : void
533 41890 : Late::visit (AST::Visibility &vis)
534 : {
535 41890 : if (!vis.has_path ())
536 41828 : return;
537 :
538 65 : AST::SimplePath &path = vis.get_path ();
539 :
540 65 : rust_assert (path.get_segments ().size ());
541 65 : auto &first_seg = path.get_segments ()[0];
542 :
543 65 : auto mode = ResolutionMode::Normal;
544 :
545 65 : if (path.has_opening_scope_resolution ())
546 : {
547 0 : if (get_rust_edition () == Edition::E2015)
548 : mode = ResolutionMode::FromRoot;
549 : else
550 65 : mode = ResolutionMode::FromExtern;
551 : }
552 77 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
553 74 : && !first_seg.is_lower_self_seg ())
554 : {
555 7 : if (get_rust_edition () == Edition::E2015)
556 : {
557 : mode = ResolutionMode::FromRoot;
558 : }
559 : else
560 : {
561 0 : rust_error_at (path.get_locus (),
562 : "relative paths are not supported in visibilities in "
563 : "2018 edition or later");
564 0 : return;
565 : }
566 : }
567 :
568 65 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
569 :
570 65 : if (!res.has_value ())
571 : {
572 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
573 3 : "could not resolve path %qs", path.as_string ().c_str ());
574 3 : return;
575 : }
576 :
577 : // TODO: is this possible?
578 62 : if (res->is_ambiguous ())
579 : {
580 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
581 0 : path.as_string ().c_str ());
582 0 : return;
583 : }
584 :
585 62 : ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
586 65 : }
587 :
588 : void
589 3755 : Late::visit (AST::Trait &trait)
590 : {
591 : // kind of weird how this is done
592 : // names are resolved to the node id of trait.get_implicit_self ()
593 : // which is then resolved to the node id of trait
594 : // we set up the latter mapping here
595 3755 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
596 3755 : Definition (trait.get_node_id ()));
597 :
598 3755 : DefaultResolver::visit (trait);
599 3755 : }
600 :
601 : void
602 81 : Late::visit (AST::StructExprStruct &s)
603 : {
604 81 : visit_outer_attrs (s);
605 81 : visit_inner_attrs (s);
606 81 : DefaultResolver::visit (s.get_struct_name ());
607 :
608 81 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
609 81 : }
610 :
611 : void
612 0 : Late::visit (AST::StructExprStructBase &s)
613 : {
614 0 : visit_outer_attrs (s);
615 0 : visit_inner_attrs (s);
616 0 : DefaultResolver::visit (s.get_struct_name ());
617 0 : visit (s.get_struct_base ());
618 :
619 0 : resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
620 0 : }
621 :
622 : void
623 1326 : Late::visit (AST::StructExprStructFields &s)
624 : {
625 1326 : visit_outer_attrs (s);
626 1326 : visit_inner_attrs (s);
627 :
628 1326 : auto &path = s.get_struct_name ();
629 :
630 1326 : DefaultResolver::visit (path);
631 1326 : if (s.has_struct_base ())
632 63 : visit (s.get_struct_base ());
633 3612 : for (auto &field : s.get_fields ())
634 2286 : visit (field);
635 :
636 1326 : auto resolved = ctx.resolve_path (path, Namespace::Types);
637 :
638 1326 : if (!resolved)
639 : {
640 0 : rust_error_at (path.get_locus (), ErrorCode::E0433,
641 0 : "could not resolve path %qs", path.as_string ().c_str ());
642 0 : return;
643 : }
644 :
645 1326 : ctx.map_usage (Usage (path.get_node_id ()),
646 1326 : Definition (resolved->get_node_id ()));
647 1326 : }
648 :
649 : // needed because Late::visit (AST::GenericArg &) is non-virtual
650 : void
651 3672 : Late::visit (AST::GenericArgs &args)
652 : {
653 3713 : for (auto &lifetime : args.get_lifetime_args ())
654 41 : visit (lifetime);
655 :
656 7526 : for (auto &generic : args.get_generic_args ())
657 3854 : visit (generic);
658 :
659 3744 : for (auto &binding : args.get_binding_args ())
660 72 : visit (binding);
661 3672 : }
662 :
663 : void
664 3854 : Late::visit (AST::GenericArg &arg)
665 : {
666 3854 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
667 : {
668 : // prefer type parameter to const parameter on ambiguity
669 4692 : auto type = ctx.types.get (arg.get_path ());
670 4692 : auto value = ctx.values.get (arg.get_path ());
671 :
672 2346 : if (!type.has_value () && value.has_value ())
673 30 : arg = arg.disambiguate_to_const ();
674 : else
675 2316 : arg = arg.disambiguate_to_type ();
676 3550 : }
677 :
678 3854 : DefaultResolver::visit (arg);
679 3854 : }
680 :
681 : void
682 67 : Late::visit_closure_params (AST::ClosureExpr &closure)
683 : {
684 67 : ctx.bindings.enter (BindingSource::Param);
685 :
686 67 : DefaultResolver::visit_closure_params (closure);
687 :
688 67 : ctx.bindings.exit ();
689 67 : }
690 :
691 : void
692 67 : Late::visit (AST::ClosureExpr &expr)
693 : {
694 : // add captures
695 67 : auto vals = ctx.values.peek ().get_values ();
696 88 : for (auto &val : vals)
697 : {
698 21 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
699 : }
700 :
701 67 : DefaultResolver::visit (expr);
702 67 : }
703 :
704 : } // namespace Resolver2_0
705 : } // namespace Rust
|