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-path.h"
28 : : #include "rust-system.h"
29 : : #include "rust-tyty.h"
30 : : #include "rust-hir-type-check.h"
31 : : #include "rust-ice-finalizer.h"
32 : : #include "rust-ast.h"
33 : :
34 : : namespace Rust {
35 : : namespace Resolver2_0 {
36 : :
37 : 4286 : Late::Late (NameResolutionContext &ctx)
38 : 4286 : : DefaultResolver (ctx), funny_error (false), block_big_self (false)
39 : 4286 : {}
40 : :
41 : : static NodeId
42 : 81434 : next_node_id ()
43 : : {
44 : 81434 : return Analysis::Mappings::get ().get_next_node_id ();
45 : : };
46 : :
47 : : static HirId
48 : 77148 : next_hir_id ()
49 : : {
50 : 77148 : return Analysis::Mappings::get ().get_next_hir_id ();
51 : : };
52 : :
53 : : void
54 : 4286 : Late::setup_builtin_types ()
55 : : {
56 : : // access the global type context to setup the TyTys
57 : 4286 : auto &ty_ctx = *Resolver::TypeCheckContext::get ();
58 : :
59 : : // Late builtin type struct helper
60 : 4286 : struct LType
61 : : {
62 : : std::string name;
63 : : NodeId node_id;
64 : : NodeId hir_id;
65 : : TyTy::BaseType *type;
66 : :
67 : 77148 : explicit LType (std::string name, TyTy::BaseType *type)
68 : 154296 : : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()),
69 : 77148 : type (type)
70 : 77148 : {}
71 : : };
72 : :
73 : 4286 : static const LType builtins[] = {
74 : 8572 : {LType ("bool", new TyTy::BoolType (next_hir_id ()))},
75 : 8572 : {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))},
76 : 8572 : {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))},
77 : 8572 : {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))},
78 : 8572 : {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))},
79 : 8572 : {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))},
80 : 8572 : {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))},
81 : 8572 : {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))},
82 : 8572 : {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))},
83 : 8572 : {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))},
84 : 8572 : {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))},
85 : 8572 : {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))},
86 : 8572 : {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))},
87 : 8572 : {LType ("usize", new TyTy::USizeType (next_hir_id ()))},
88 : 8572 : {LType ("isize", new TyTy::ISizeType (next_hir_id ()))},
89 : 8572 : {LType ("char", new TyTy::CharType (next_hir_id ()))},
90 : 8572 : {LType ("str", new TyTy::StrType (next_hir_id ()))},
91 : 8572 : {LType ("!", new TyTy::NeverType (next_hir_id ()))},
92 : :
93 : : // the unit type `()` does not play a part in name-resolution - so we only
94 : : // insert it in the type context...
95 : 85720 : };
96 : :
97 : : // There's a special Rib for putting prelude items, since prelude items need
98 : : // to satisfy certain special rules.
99 : 4286 : ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void {
100 : 81434 : for (const auto &builtin : builtins)
101 : : {
102 : 231444 : auto ok = ctx.types.insert (builtin.name, builtin.node_id);
103 : 77148 : rust_assert (ok);
104 : :
105 : 77148 : ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id);
106 : 77148 : ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type);
107 : 77148 : }
108 : 4286 : });
109 : :
110 : : // ...here!
111 : 4286 : auto *unit_type = TyTy::TupleType::get_unit_type ();
112 : 4286 : ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type);
113 : 4286 : }
114 : :
115 : : void
116 : 4286 : Late::go (AST::Crate &crate)
117 : : {
118 : 4286 : setup_builtin_types ();
119 : :
120 : 4286 : visit (crate);
121 : 4285 : }
122 : :
123 : : void
124 : 0 : Late::new_label (Identifier name, NodeId id)
125 : : {
126 : : // labels can always shadow, so `insert` should never fail. if it does, we're
127 : : // in big trouble!
128 : 0 : auto ok = ctx.labels.insert (name, id);
129 : :
130 : 0 : rust_assert (ok);
131 : 0 : }
132 : :
133 : : void
134 : 0 : Late::visit (AST::ForLoopExpr &expr)
135 : : {
136 : 0 : visit_outer_attrs (expr);
137 : :
138 : 0 : ctx.bindings.enter (BindingSource::For);
139 : :
140 : 0 : visit (expr.get_pattern ());
141 : :
142 : 0 : ctx.bindings.exit ();
143 : :
144 : 0 : visit (expr.get_iterator_expr ());
145 : :
146 : 0 : if (expr.has_loop_label ())
147 : 0 : visit (expr.get_loop_label ());
148 : :
149 : 0 : visit (expr.get_loop_block ());
150 : 0 : }
151 : :
152 : : void
153 : 30 : Late::visit_if_let_patterns (AST::IfLetExpr &expr)
154 : : {
155 : 30 : ctx.bindings.enter (BindingSource::IfLet);
156 : :
157 : 30 : DefaultResolver::visit_if_let_patterns (expr);
158 : :
159 : 30 : ctx.bindings.exit ();
160 : 30 : }
161 : :
162 : : void
163 : 2270 : Late::visit (AST::MatchArm &arm)
164 : : {
165 : 2270 : visit_outer_attrs (arm);
166 : :
167 : 2270 : ctx.bindings.enter (BindingSource::Match);
168 : :
169 : 4540 : for (auto &pattern : arm.get_patterns ())
170 : 2270 : visit (pattern);
171 : :
172 : 2270 : ctx.bindings.exit ();
173 : :
174 : 2270 : if (arm.has_match_arm_guard ())
175 : 1 : visit (arm.get_guard_expr ());
176 : 2270 : }
177 : :
178 : : void
179 : 12440 : Late::visit (AST::LetStmt &let)
180 : : {
181 : 12440 : DefaultASTVisitor::visit_outer_attrs (let);
182 : 12440 : if (let.has_type ())
183 : 2060 : visit (let.get_type ());
184 : : // visit expression before pattern
185 : : // this makes variable shadowing work properly
186 : 12440 : if (let.has_init_expr ())
187 : 11295 : visit (let.get_init_expr ());
188 : :
189 : 12440 : ctx.bindings.enter (BindingSource::Let);
190 : :
191 : 12440 : visit (let.get_pattern ());
192 : :
193 : 12440 : ctx.bindings.exit ();
194 : :
195 : 12440 : if (let.has_else_expr ())
196 : 0 : visit (let.get_init_expr ());
197 : :
198 : : // how do we deal with the fact that `let a = blipbloup` should look for a
199 : : // label and cannot go through function ribs, but `let a = blipbloup()` can?
200 : :
201 : : // how do we insert ribs here, and only pop them when we exit the current
202 : : // function?
203 : : // keep a list of ribs to pop when a scope exits? so only for blocks?
204 : : // how do we pop ribs that need to be popped not in order?
205 : : // I think it's not important if we have shadowing, correct?
206 : :
207 : : // if we have shadowing, it should work! we'll see
208 : :
209 : : // ctx.insert(Identifier name, NodeId id, Namespace ns)
210 : : // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
211 : : // Namespace::Labels,
212 : : // let.get_node_id (), [] () {});
213 : 12440 : }
214 : :
215 : : void
216 : 0 : Late::visit (AST::WhileLetLoopExpr &while_let)
217 : : {
218 : 0 : DefaultASTVisitor::visit_outer_attrs (while_let);
219 : :
220 : 0 : if (while_let.has_loop_label ())
221 : 0 : visit (while_let.get_loop_label ());
222 : :
223 : : // visit expression before pattern
224 : : // this makes variable shadowing work properly
225 : 0 : visit (while_let.get_scrutinee_expr ());
226 : :
227 : 0 : ctx.bindings.enter (BindingSource::WhileLet);
228 : :
229 : 0 : for (auto &pattern : while_let.get_patterns ())
230 : 0 : visit (pattern);
231 : :
232 : 0 : ctx.bindings.exit ();
233 : :
234 : 0 : visit (while_let.get_loop_block ());
235 : 0 : }
236 : :
237 : : static void
238 : 23852 : visit_identifier_as_pattern (NameResolutionContext &ctx,
239 : : const Identifier &ident, location_t locus,
240 : : NodeId node_id, bool is_ref, bool is_mut)
241 : : {
242 : : // do we insert in labels or in values
243 : : // but values does not allow shadowing... since functions cannot shadow
244 : : // do we insert functions in labels as well?
245 : :
246 : 23852 : if (ctx.bindings.peek ().is_and_bound (ident))
247 : : {
248 : 8 : if (ctx.bindings.peek ().get_source () == BindingSource::Param)
249 : 5 : rust_error_at (
250 : : locus, ErrorCode::E0415,
251 : : "identifier %qs is bound more than once in the same parameter list",
252 : 5 : ident.as_string ().c_str ());
253 : : else
254 : 3 : rust_error_at (
255 : : locus, ErrorCode::E0416,
256 : : "identifier %qs is bound more than once in the same pattern",
257 : 3 : ident.as_string ().c_str ());
258 : 8 : return;
259 : : }
260 : :
261 : 47688 : ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
262 : :
263 : 23844 : if (ctx.bindings.peek ().is_or_bound (ident))
264 : : {
265 : 58 : auto res = ctx.values.get (ident);
266 : 58 : rust_assert (res.has_value () && !res->is_ambiguous ());
267 : 58 : ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
268 : 58 : }
269 : : else
270 : : {
271 : : // We do want to ignore duplicated data because some situations rely on
272 : : // it.
273 : 23786 : std::ignore = ctx.values.insert_shadowable (ident, node_id);
274 : : }
275 : : }
276 : :
277 : : void
278 : 23754 : Late::visit (AST::IdentifierPattern &identifier)
279 : : {
280 : 23754 : DefaultResolver::visit (identifier);
281 : :
282 : 23754 : visit_identifier_as_pattern (ctx, identifier.get_ident (),
283 : : identifier.get_locus (),
284 : 23754 : identifier.get_node_id (),
285 : 23754 : identifier.get_is_ref (),
286 : 23754 : identifier.get_is_mut ());
287 : 23754 : }
288 : :
289 : : void
290 : 189 : Late::visit (AST::AltPattern &pattern)
291 : : {
292 : 189 : ctx.bindings.peek ().push (Binding::Kind::Or);
293 : 582 : for (auto &alt : pattern.get_alts ())
294 : : {
295 : 393 : ctx.bindings.peek ().push (Binding::Kind::Product);
296 : 393 : visit (alt);
297 : 393 : ctx.bindings.peek ().merge ();
298 : : }
299 : 189 : ctx.bindings.peek ().merge ();
300 : 189 : }
301 : :
302 : : void
303 : 17913 : Late::visit_function_params (AST::Function &function)
304 : : {
305 : 17913 : ctx.bindings.enter (BindingSource::Param);
306 : :
307 : 37287 : for (auto ¶m : function.get_function_params ())
308 : 19374 : visit (param);
309 : :
310 : 17913 : ctx.bindings.exit ();
311 : 17913 : }
312 : :
313 : : void
314 : 98 : Late::visit (AST::StructPatternFieldIdent &field)
315 : : {
316 : 98 : visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
317 : 98 : field.get_node_id (), field.is_ref (),
318 : 98 : field.is_mut ());
319 : 98 : }
320 : :
321 : : void
322 : 7942 : Late::visit (AST::SelfParam ¶m)
323 : : {
324 : : // handle similar to AST::IdentifierPattern
325 : :
326 : 7942 : DefaultResolver::visit (param);
327 : : // FIXME: this location should be a bit off
328 : : // ex: would point to the begining of "mut self" instead of the "self"
329 : 23826 : std::ignore = ctx.values.insert (Identifier ("self", param.get_locus ()),
330 : 7942 : param.get_node_id ());
331 : 7942 : }
332 : :
333 : : void
334 : 85 : Late::visit (AST::BreakExpr &expr)
335 : : {
336 : 85 : if (expr.has_label ())
337 : 21 : resolve_label (expr.get_label_unchecked ().get_lifetime ());
338 : :
339 : 85 : if (expr.has_break_expr ())
340 : : {
341 : 20 : auto &break_expr = expr.get_break_expr ();
342 : 20 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
343 : : {
344 : : /* This is a break with an expression, and the expression is
345 : : just a single identifier. See if the identifier is either
346 : : "rust" or "gcc", in which case we have "break rust" or "break
347 : : gcc", and so may need to emit our funny error. We cannot yet
348 : : emit the error here though, because the identifier may still
349 : : be in scope, and ICE'ing on valid programs would not be very
350 : : funny. */
351 : 11 : std::string ident
352 : 11 : = static_cast<AST::IdentifierExpr &> (expr.get_break_expr ())
353 : 11 : .as_string ();
354 : 11 : if (ident == "rust" || ident == "gcc")
355 : 2 : funny_error = true;
356 : 11 : }
357 : : }
358 : :
359 : 85 : DefaultResolver::visit (expr);
360 : :
361 : 84 : funny_error = false;
362 : 84 : }
363 : :
364 : : void
365 : 55 : Late::visit (AST::LoopLabel &label)
366 : : {
367 : 55 : auto &lifetime = label.get_lifetime ();
368 : 110 : ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
369 : : lifetime.get_node_id ());
370 : 55 : }
371 : :
372 : : void
373 : 22 : Late::resolve_label (AST::Lifetime &lifetime)
374 : : {
375 : 44 : if (auto resolved = ctx.labels.get (lifetime.as_string ()))
376 : : {
377 : 17 : if (resolved->get_node_id () != lifetime.get_node_id ())
378 : 17 : ctx.map_usage (Usage (lifetime.get_node_id ()),
379 : 17 : Definition (resolved->get_node_id ()));
380 : : }
381 : : else
382 : 5 : rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
383 : : "use of undeclared label %qs",
384 : 10 : lifetime.as_string ().c_str ());
385 : 22 : }
386 : :
387 : : void
388 : 10 : Late::visit (AST::ContinueExpr &expr)
389 : : {
390 : 10 : if (expr.has_label ())
391 : 1 : resolve_label (expr.get_label_unchecked ());
392 : :
393 : 10 : DefaultResolver::visit (expr);
394 : 10 : }
395 : :
396 : : void
397 : 23882 : Late::visit (AST::IdentifierExpr &expr)
398 : : {
399 : : // TODO: same thing as visit(PathInExpression) here?
400 : :
401 : 23882 : tl::optional<Rib::Definition> resolved = tl::nullopt;
402 : 23882 : if (auto value = ctx.values.get (expr.get_ident ()))
403 : : {
404 : 23861 : resolved = value;
405 : : }
406 : 21 : else if (auto type = ctx.types.get (expr.get_ident ()))
407 : : {
408 : 11 : resolved = type;
409 : : }
410 : 10 : else if (funny_error)
411 : : {
412 : 1 : diagnostics::text_finalizer (global_dc)
413 : 1 : = Resolver::funny_ice_text_finalizer;
414 : 1 : emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
415 : : "are you trying to break %s? how dare you?",
416 : 1 : expr.as_string ().c_str ());
417 : : }
418 : : else
419 : : {
420 : 9 : if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
421 : : {
422 : 3 : resolved = type;
423 : : }
424 : : else
425 : : {
426 : 6 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
427 : : "cannot find value %qs in this scope",
428 : 6 : expr.get_ident ().as_string ().c_str ());
429 : 6 : return;
430 : 9 : }
431 : 20 : }
432 : :
433 : 23875 : if (resolved->is_ambiguous ())
434 : : {
435 : 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
436 : 0 : expr.as_string ().c_str ());
437 : 0 : return;
438 : : }
439 : :
440 : 23875 : ctx.map_usage (Usage (expr.get_node_id ()),
441 : 23875 : Definition (resolved->get_node_id ()));
442 : :
443 : : // For empty types, do we perform a lookup in ctx.types or should the
444 : : // toplevel instead insert a name in ctx.values? (like it currently does)
445 : 23881 : }
446 : :
447 : : void
448 : 216 : Late::visit (AST::StructExprFieldIdentifier &expr)
449 : : {
450 : 216 : tl::optional<Rib::Definition> resolved = tl::nullopt;
451 : :
452 : 216 : if (auto value = ctx.values.get (expr.get_field_name ()))
453 : : {
454 : 216 : resolved = value;
455 : : }
456 : : // seems like we don't need a type namespace lookup
457 : : else
458 : : {
459 : 0 : rust_error_at (expr.get_locus (), "could not resolve struct field: %qs",
460 : 0 : expr.get_field_name ().as_string ().c_str ());
461 : 0 : return;
462 : 0 : }
463 : :
464 : 216 : if (resolved->is_ambiguous ())
465 : : {
466 : 0 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
467 : 0 : expr.as_string ().c_str ());
468 : 0 : return;
469 : : }
470 : :
471 : 216 : ctx.map_usage (Usage (expr.get_node_id ()),
472 : 216 : Definition (resolved->get_node_id ()));
473 : 216 : }
474 : :
475 : : void
476 : 22555 : Late::visit (AST::PathInExpression &expr)
477 : : {
478 : : // TODO: How do we have a nice error with `can't capture dynamic environment
479 : : // in a function item` error here?
480 : : // do we emit it in `get<Namespace::Labels>`?
481 : :
482 : 22555 : DefaultResolver::visit (expr);
483 : :
484 : 22555 : if (expr.is_lang_item ())
485 : : {
486 : 144 : ctx.map_usage (Usage (expr.get_node_id ()),
487 : 144 : Definition (Analysis::Mappings::get ().get_lang_item_node (
488 : 144 : expr.get_lang_item ())));
489 : 3780 : return;
490 : : }
491 : :
492 : 22411 : auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
493 : :
494 : 22411 : if (!resolved)
495 : : {
496 : 3635 : if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
497 : 4 : rust_error_at (expr.get_locus (), ErrorCode::E0433,
498 : : "Cannot find path %qs in this scope",
499 : 4 : expr.as_simple_path ().as_string ().c_str ());
500 : 3635 : return;
501 : : }
502 : :
503 : 18776 : if (resolved->is_ambiguous ())
504 : : {
505 : 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
506 : 1 : expr.as_string ().c_str ());
507 : 1 : return;
508 : : }
509 : :
510 : 18775 : ctx.map_usage (Usage (expr.get_node_id ()),
511 : 18775 : Definition (resolved->get_node_id ()));
512 : 22411 : }
513 : :
514 : : void
515 : 5588 : Late::visit_impl_type (AST::Type &type)
516 : : {
517 : : // TODO: does this have to handle reentrancy?
518 : 5588 : rust_assert (!block_big_self);
519 : 5588 : block_big_self = true;
520 : 5588 : visit (type);
521 : 5588 : block_big_self = false;
522 : 5588 : }
523 : :
524 : : void
525 : 53336 : Late::visit (AST::TypePath &type)
526 : : {
527 : : // should we add type path resolution in `ForeverStack` directly? Since it's
528 : : // quite more complicated.
529 : : // maybe we can overload `resolve_path<Namespace::Types>` to only do
530 : : // typepath-like path resolution? that sounds good
531 : :
532 : 53336 : DefaultResolver::visit (type);
533 : :
534 : : // prevent "impl Self {}" and similar
535 : 53336 : if (type.get_segments ().size () == 1
536 : 51906 : && !type.get_segments ().front ()->is_lang_item ()
537 : 104862 : && type.get_segments ().front ()->is_big_self_seg () && block_big_self)
538 : : {
539 : 2 : rust_error_at (type.get_locus (),
540 : : "%<Self%> is not valid in the self type of an impl block");
541 : 1033 : return;
542 : : }
543 : :
544 : : // this *should* mostly work
545 : : // TODO: make sure typepath-like path resolution (?) is working
546 : 53334 : auto resolved = ctx.resolve_path (type, Namespace::Types);
547 : :
548 : 53334 : if (!resolved.has_value ())
549 : : {
550 : 1029 : if (!ctx.lookup (type.get_segments ().front ()->get_node_id ()))
551 : 21 : rust_error_at (type.get_locus (), ErrorCode::E0412,
552 : : "could not resolve type path %qs",
553 : 42 : type.make_debug_string ().c_str ());
554 : 1029 : return;
555 : : }
556 : :
557 : 52305 : if (resolved->is_ambiguous ())
558 : : {
559 : 0 : rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
560 : 0 : type.make_debug_string ().c_str ());
561 : 0 : return;
562 : : }
563 : :
564 : 52305 : if (ctx.types.forward_declared (resolved->get_node_id (),
565 : : type.get_node_id ()))
566 : : {
567 : 1 : rust_error_at (type.get_locus (), ErrorCode::E0128,
568 : : "type parameters with a default cannot use forward "
569 : : "declared identifiers");
570 : : }
571 : :
572 : 52305 : ctx.map_usage (Usage (type.get_node_id ()),
573 : 52305 : Definition (resolved->get_node_id ()));
574 : 53334 : }
575 : :
576 : : void
577 : 40990 : Late::visit (AST::Visibility &vis)
578 : : {
579 : 40990 : if (!vis.has_path ())
580 : 40928 : return;
581 : :
582 : 65 : AST::SimplePath &path = vis.get_path ();
583 : :
584 : 65 : rust_assert (path.get_segments ().size ());
585 : 65 : auto &first_seg = path.get_segments ()[0];
586 : :
587 : 65 : auto mode = ResolutionMode::Normal;
588 : :
589 : 65 : if (path.has_opening_scope_resolution ())
590 : : {
591 : 0 : if (get_rust_edition () == Edition::E2015)
592 : : mode = ResolutionMode::FromRoot;
593 : : else
594 : 65 : mode = ResolutionMode::FromExtern;
595 : : }
596 : 77 : else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
597 : 74 : && !first_seg.is_lower_self_seg ())
598 : : {
599 : 7 : if (get_rust_edition () == Edition::E2015)
600 : : {
601 : : mode = ResolutionMode::FromRoot;
602 : : }
603 : : else
604 : : {
605 : 0 : rust_error_at (path.get_locus (),
606 : : "relative paths are not supported in visibilities in "
607 : : "2018 edition or later");
608 : 0 : return;
609 : : }
610 : : }
611 : :
612 : 65 : auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
613 : :
614 : 65 : if (!res.has_value ())
615 : : {
616 : 3 : rust_error_at (path.get_locus (), ErrorCode::E0433,
617 : 3 : "could not resolve path %qs", path.as_string ().c_str ());
618 : 3 : return;
619 : : }
620 : :
621 : : // TODO: is this possible?
622 : 62 : if (res->is_ambiguous ())
623 : : {
624 : 0 : rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
625 : 0 : path.as_string ().c_str ());
626 : 0 : return;
627 : : }
628 : :
629 : 62 : ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
630 : 65 : }
631 : :
632 : : void
633 : 3658 : Late::visit (AST::Trait &trait)
634 : : {
635 : : // kind of weird how this is done
636 : : // names are resolved to the node id of trait.get_implicit_self ()
637 : : // which is then resolved to the node id of trait
638 : : // we set up the latter mapping here
639 : 7316 : ctx.map_usage (Usage (trait.get_implicit_self ().get_node_id ()),
640 : 3658 : Definition (trait.get_node_id ()));
641 : :
642 : 3658 : DefaultResolver::visit (trait);
643 : 3658 : }
644 : :
645 : : void
646 : 68 : Late::visit (AST::StructExprStruct &s)
647 : : {
648 : 68 : visit_outer_attrs (s);
649 : 68 : visit_inner_attrs (s);
650 : 68 : DefaultResolver::visit (s.get_struct_name ());
651 : :
652 : 68 : auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
653 : :
654 : 68 : ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
655 : 68 : Definition (resolved->get_node_id ()));
656 : 68 : }
657 : :
658 : : void
659 : 0 : Late::visit (AST::StructExprStructBase &s)
660 : : {
661 : 0 : visit_outer_attrs (s);
662 : 0 : visit_inner_attrs (s);
663 : 0 : DefaultResolver::visit (s.get_struct_name ());
664 : 0 : visit (s.get_struct_base ());
665 : :
666 : 0 : auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
667 : :
668 : 0 : ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
669 : 0 : Definition (resolved->get_node_id ()));
670 : 0 : }
671 : :
672 : : void
673 : 1323 : Late::visit (AST::StructExprStructFields &s)
674 : : {
675 : 1323 : visit_outer_attrs (s);
676 : 1323 : visit_inner_attrs (s);
677 : 1323 : DefaultResolver::visit (s.get_struct_name ());
678 : 1323 : if (s.has_struct_base ())
679 : 63 : visit (s.get_struct_base ());
680 : 3604 : for (auto &field : s.get_fields ())
681 : 2281 : visit (field);
682 : :
683 : 1323 : auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
684 : :
685 : 1323 : ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
686 : 1323 : Definition (resolved->get_node_id ()));
687 : 1323 : }
688 : :
689 : : // needed because Late::visit (AST::GenericArg &) is non-virtual
690 : : void
691 : 3577 : Late::visit (AST::GenericArgs &args)
692 : : {
693 : 3611 : for (auto &lifetime : args.get_lifetime_args ())
694 : 34 : visit (lifetime);
695 : :
696 : 7339 : for (auto &generic : args.get_generic_args ())
697 : 3762 : visit (generic);
698 : :
699 : 3649 : for (auto &binding : args.get_binding_args ())
700 : 72 : visit (binding);
701 : 3577 : }
702 : :
703 : : void
704 : 3762 : Late::visit (AST::GenericArg &arg)
705 : : {
706 : 3762 : if (arg.get_kind () == AST::GenericArg::Kind::Either)
707 : : {
708 : : // prefer type parameter to const parameter on ambiguity
709 : 4588 : auto type = ctx.types.get (arg.get_path ());
710 : 4588 : auto value = ctx.values.get (arg.get_path ());
711 : :
712 : 2294 : if (!type.has_value () && value.has_value ())
713 : 9 : arg = arg.disambiguate_to_const ();
714 : : else
715 : 2285 : arg = arg.disambiguate_to_type ();
716 : 3481 : }
717 : :
718 : 3762 : DefaultResolver::visit (arg);
719 : 3762 : }
720 : :
721 : : void
722 : 64 : Late::visit_closure_params (AST::ClosureExpr &closure)
723 : : {
724 : 64 : ctx.bindings.enter (BindingSource::Param);
725 : :
726 : 64 : DefaultResolver::visit_closure_params (closure);
727 : :
728 : 64 : ctx.bindings.exit ();
729 : 64 : }
730 : :
731 : : void
732 : 64 : Late::visit (AST::ClosureExpr &expr)
733 : : {
734 : : // add captures
735 : 64 : auto vals = ctx.values.peek ().get_values ();
736 : 85 : for (auto &val : vals)
737 : : {
738 : 21 : ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
739 : : }
740 : :
741 : 64 : DefaultResolver::visit (expr);
742 : 64 : }
743 : :
744 : : } // namespace Resolver2_0
745 : : } // namespace Rust
|