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 "rust-ast-resolve-expr.h"
20 : : #include "rust-ast-resolve-stmt.h"
21 : : #include "rust-ast-resolve-struct-expr-field.h"
22 : : #include "rust-ast-resolve-type.h"
23 : : #include "rust-ast-resolve-pattern.h"
24 : : #include "rust-ast-resolve-path.h"
25 : : #include "rust-expr.h"
26 : : #include "rust-ice-finalizer.h"
27 : :
28 : : namespace Rust {
29 : : namespace Resolver {
30 : :
31 : : void
32 : 94227 : ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix,
33 : : const CanonicalPath &canonical_prefix, bool funny_error)
34 : : {
35 : 94227 : ResolveExpr resolver (prefix, canonical_prefix, funny_error);
36 : 94227 : expr.accept_vis (resolver);
37 : 94224 : }
38 : :
39 : : void
40 : 792 : ResolveExpr::visit (AST::TupleIndexExpr &expr)
41 : : {
42 : 792 : ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix);
43 : 792 : }
44 : :
45 : : void
46 : 472 : ResolveExpr::visit (AST::TupleExpr &expr)
47 : : {
48 : 472 : if (expr.is_unit ())
49 : : return;
50 : :
51 : 1136 : for (auto &elem : expr.get_tuple_elems ())
52 : 795 : ResolveExpr::go (*elem, prefix, canonical_prefix);
53 : : }
54 : :
55 : : void
56 : 15105 : ResolveExpr::visit (AST::PathInExpression &expr)
57 : : {
58 : 15105 : ResolvePath::go (expr);
59 : 15105 : }
60 : :
61 : : void
62 : 114 : ResolveExpr::visit (AST::QualifiedPathInExpression &expr)
63 : : {
64 : 114 : ResolvePath::go (expr);
65 : 114 : }
66 : :
67 : : void
68 : 488 : ResolveExpr::visit (AST::ReturnExpr &expr)
69 : : {
70 : 488 : if (expr.has_returned_expr ())
71 : 464 : ResolveExpr::go (expr.get_returned_expr (), prefix, canonical_prefix);
72 : 488 : }
73 : :
74 : : void
75 : 8888 : ResolveExpr::visit (AST::CallExpr &expr)
76 : : {
77 : 8888 : ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix);
78 : 19366 : for (auto ¶m : expr.get_params ())
79 : 10478 : ResolveExpr::go (*param, prefix, canonical_prefix);
80 : 8888 : }
81 : :
82 : : void
83 : 1404 : ResolveExpr::visit (AST::MethodCallExpr &expr)
84 : : {
85 : 1404 : ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
86 : :
87 : 1404 : if (expr.get_method_name ().has_generic_args ())
88 : : {
89 : 22 : AST::GenericArgs &args = expr.get_method_name ().get_generic_args ();
90 : 22 : ResolveGenericArgs::go (args, prefix, canonical_prefix);
91 : : }
92 : :
93 : 1404 : auto const &in_params = expr.get_params ();
94 : 2055 : for (auto ¶m : in_params)
95 : 651 : ResolveExpr::go (*param, prefix, canonical_prefix);
96 : 1404 : }
97 : :
98 : : void
99 : 0 : ResolveExpr::visit (AST::ErrorPropagationExpr &expr)
100 : : {
101 : 0 : ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix);
102 : 0 : }
103 : :
104 : : void
105 : 1693 : ResolveExpr::visit (AST::AssignmentExpr &expr)
106 : : {
107 : 1693 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
108 : 1693 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
109 : 1693 : }
110 : :
111 : : void
112 : 17552 : ResolveExpr::visit (AST::IdentifierExpr &expr)
113 : : {
114 : 35104 : if (resolver->get_name_scope ().lookup (
115 : 35104 : CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
116 : : &resolved_node))
117 : : {
118 : 17514 : resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
119 : : }
120 : 76 : else if (resolver->get_type_scope ().lookup (
121 : 76 : CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
122 : : &resolved_node))
123 : : {
124 : 30 : resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
125 : : }
126 : 8 : else if (funny_error)
127 : : {
128 : : /* This was a "break rust" or "break gcc", and the identifier failed to
129 : : resolve. Emit a funny ICE. We set the finalizer to our custom one,
130 : : and use the lower-level emit_diagnostic () instead of the more common
131 : : internal_error_no_backtrace () in order to pass our locus. */
132 : 1 : diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer;
133 : 1 : emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
134 : : "are you trying to break %s? how dare you?",
135 : 1 : expr.as_string ().c_str ());
136 : : }
137 : : else
138 : : {
139 : 7 : rust_error_at (expr.get_locus (), ErrorCode::E0425,
140 : : "cannot find value %qs in this scope",
141 : 14 : expr.as_string ().c_str ());
142 : : }
143 : 17551 : }
144 : :
145 : : void
146 : 2823 : ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
147 : : {
148 : 2823 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
149 : 2823 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
150 : 2823 : }
151 : :
152 : : void
153 : 219 : ResolveExpr::visit (AST::CompoundAssignmentExpr &expr)
154 : : {
155 : 219 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
156 : 219 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
157 : 219 : }
158 : :
159 : : void
160 : 953 : ResolveExpr::visit (AST::ComparisonExpr &expr)
161 : : {
162 : 953 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
163 : 953 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
164 : 953 : }
165 : :
166 : : void
167 : 287 : ResolveExpr::visit (AST::LazyBooleanExpr &expr)
168 : : {
169 : 287 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
170 : 287 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
171 : 287 : }
172 : :
173 : : void
174 : 317 : ResolveExpr::visit (AST::NegationExpr &expr)
175 : : {
176 : 317 : ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix);
177 : 317 : }
178 : :
179 : : void
180 : 4283 : ResolveExpr::visit (AST::TypeCastExpr &expr)
181 : : {
182 : 4283 : ResolveType::go (expr.get_type_to_cast_to ());
183 : 4283 : ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix);
184 : 4283 : }
185 : :
186 : : void
187 : 350 : ResolveExpr::visit (AST::IfExpr &expr)
188 : : {
189 : 350 : ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix);
190 : 350 : ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
191 : 350 : }
192 : :
193 : : void
194 : 501 : ResolveExpr::visit (AST::IfExprConseqElse &expr)
195 : : {
196 : 501 : ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix);
197 : 501 : ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
198 : 501 : ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix);
199 : 501 : }
200 : :
201 : : void
202 : 18 : ResolveExpr::visit (AST::IfLetExpr &expr)
203 : : {
204 : 18 : ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix);
205 : :
206 : 18 : NodeId scope_node_id = expr.get_node_id ();
207 : 18 : resolver->get_name_scope ().push (scope_node_id);
208 : 18 : resolver->get_type_scope ().push (scope_node_id);
209 : 18 : resolver->get_label_scope ().push (scope_node_id);
210 : 18 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
211 : 18 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
212 : 18 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
213 : :
214 : : // We know expr.get_patterns () has one pattern at most
215 : : // so there's no reason to handle it like an AltPattern.
216 : 18 : std::vector<PatternBinding> bindings
217 : 36 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
218 : :
219 : 36 : for (auto &pattern : expr.get_patterns ())
220 : : {
221 : 18 : PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
222 : : }
223 : :
224 : 18 : ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
225 : :
226 : 18 : resolver->get_name_scope ().pop ();
227 : 18 : resolver->get_type_scope ().pop ();
228 : 18 : resolver->get_label_scope ().pop ();
229 : 18 : }
230 : :
231 : : void
232 : 12 : ResolveExpr::visit (AST::IfLetExprConseqElse &expr)
233 : : {
234 : 12 : ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix);
235 : :
236 : 12 : NodeId scope_node_id = expr.get_node_id ();
237 : 12 : resolver->get_name_scope ().push (scope_node_id);
238 : 12 : resolver->get_type_scope ().push (scope_node_id);
239 : 12 : resolver->get_label_scope ().push (scope_node_id);
240 : 12 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
241 : 12 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
242 : 12 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
243 : :
244 : : // We know expr.get_patterns () has one pattern at most
245 : : // so there's no reason to handle it like an AltPattern.
246 : 12 : std::vector<PatternBinding> bindings
247 : 24 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
248 : :
249 : 24 : for (auto &pattern : expr.get_patterns ())
250 : : {
251 : 12 : PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
252 : : }
253 : :
254 : 12 : ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix);
255 : 12 : ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix);
256 : :
257 : 12 : resolver->get_name_scope ().pop ();
258 : 12 : resolver->get_type_scope ().pop ();
259 : 12 : resolver->get_label_scope ().pop ();
260 : 12 : }
261 : :
262 : : void
263 : 16631 : ResolveExpr::visit (AST::BlockExpr &expr)
264 : : {
265 : 16631 : NodeId scope_node_id = expr.get_node_id ();
266 : 16631 : resolver->get_name_scope ().push (scope_node_id);
267 : 16631 : resolver->get_type_scope ().push (scope_node_id);
268 : 16631 : resolver->get_label_scope ().push (scope_node_id);
269 : 16631 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
270 : 16631 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
271 : 16631 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
272 : :
273 : 16631 : if (expr.has_label ())
274 : : {
275 : 0 : auto label = expr.get_label ();
276 : 0 : if (label.get_lifetime ().get_lifetime_type ()
277 : : != AST::Lifetime::LifetimeType::NAMED)
278 : : {
279 : 0 : rust_error_at (label.get_locus (),
280 : : "Labels must be a named lifetime value");
281 : 0 : return;
282 : : }
283 : :
284 : 0 : auto label_name = label.get_lifetime ().get_lifetime_name ();
285 : 0 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
286 : 0 : resolver->get_label_scope ().insert (
287 : 0 : CanonicalPath::new_seg (label.get_node_id (), label_name),
288 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
289 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
290 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
291 : 0 : rust_error_at (locus, "was defined here");
292 : 0 : });
293 : 0 : }
294 : :
295 : 35272 : for (auto &s : expr.get_statements ())
296 : : {
297 : 18641 : if (s->is_item ())
298 : 350 : ResolveStmt::go (*s, prefix, canonical_prefix,
299 : 700 : CanonicalPath::create_empty ());
300 : : }
301 : :
302 : 35271 : for (auto &s : expr.get_statements ())
303 : : {
304 : 18641 : if (!s->is_item ())
305 : 18291 : ResolveStmt::go (*s, prefix, canonical_prefix,
306 : 36581 : CanonicalPath::create_empty ());
307 : : }
308 : :
309 : 16630 : if (expr.has_tail_expr ())
310 : 11623 : ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix);
311 : :
312 : 16630 : resolver->get_name_scope ().pop ();
313 : 16630 : resolver->get_type_scope ().pop ();
314 : 16630 : resolver->get_label_scope ().pop ();
315 : : }
316 : :
317 : : void
318 : 25 : translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
319 : : const CanonicalPath &canonical_prefix)
320 : : {
321 : 25 : const auto &operands = expr.get_operands ();
322 : 25 : using RegisterType = AST::InlineAsmOperand::RegisterType;
323 : 52 : for (auto &operand : operands)
324 : : {
325 : 27 : switch (operand.get_register_type ())
326 : : {
327 : 10 : case RegisterType::In: {
328 : 10 : auto in = operand.get_in ();
329 : 10 : ResolveExpr::go (*in.expr, prefix, canonical_prefix);
330 : 10 : break;
331 : 10 : }
332 : 17 : case RegisterType::Out: {
333 : 17 : auto out = operand.get_out ();
334 : 17 : ResolveExpr::go (*out.expr, prefix, canonical_prefix);
335 : 17 : break;
336 : 17 : }
337 : 0 : case RegisterType::InOut: {
338 : 0 : auto in_out = operand.get_in_out ();
339 : 0 : ResolveExpr::go (*in_out.expr, prefix, canonical_prefix);
340 : 0 : break;
341 : 0 : }
342 : 0 : case RegisterType::SplitInOut: {
343 : 0 : auto split_in_out = operand.get_split_in_out ();
344 : 0 : ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix);
345 : 0 : ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix);
346 : 0 : break;
347 : 0 : }
348 : 0 : case RegisterType::Const: {
349 : 0 : auto anon_const = operand.get_const ().anon_const;
350 : 0 : ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix);
351 : 0 : break;
352 : 0 : }
353 : 0 : case RegisterType::Sym: {
354 : 0 : auto sym = operand.get_sym ();
355 : 0 : ResolveExpr::go (*sym.expr, prefix, canonical_prefix);
356 : 0 : break;
357 : 0 : }
358 : 0 : case RegisterType::Label: {
359 : 0 : auto label = operand.get_label ();
360 : 0 : ResolveExpr::go (*label.expr, prefix, canonical_prefix);
361 : 0 : break;
362 : 0 : }
363 : : }
364 : : }
365 : 25 : }
366 : : void
367 : 25 : ResolveExpr::visit (AST::InlineAsm &expr)
368 : : {
369 : 25 : translate_operand (expr, prefix, canonical_prefix);
370 : 25 : }
371 : : void
372 : 3161 : ResolveExpr::visit (AST::UnsafeBlockExpr &expr)
373 : : {
374 : 3161 : expr.get_block_expr ().accept_vis (*this);
375 : 3161 : }
376 : :
377 : : void
378 : 210 : ResolveExpr::visit (AST::ArrayElemsValues &elems)
379 : : {
380 : 1381 : for (auto &elem : elems.get_values ())
381 : 1171 : ResolveExpr::go (*elem, prefix, canonical_prefix);
382 : 210 : }
383 : :
384 : : void
385 : 320 : ResolveExpr::visit (AST::ArrayExpr &expr)
386 : : {
387 : 320 : expr.get_array_elems ()->accept_vis (*this);
388 : 320 : }
389 : :
390 : : void
391 : 212 : ResolveExpr::visit (AST::ArrayIndexExpr &expr)
392 : : {
393 : 212 : ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix);
394 : 212 : ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix);
395 : 212 : }
396 : :
397 : : void
398 : 110 : ResolveExpr::visit (AST::ArrayElemsCopied &expr)
399 : : {
400 : 110 : ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix);
401 : 110 : ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix);
402 : 110 : }
403 : :
404 : : // this this an empty struct constructor like 'S {}'
405 : : void
406 : 53 : ResolveExpr::visit (AST::StructExprStruct &struct_expr)
407 : : {
408 : 53 : ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
409 : 53 : }
410 : :
411 : : // this this a struct constructor with fields
412 : : void
413 : 938 : ResolveExpr::visit (AST::StructExprStructFields &struct_expr)
414 : : {
415 : 938 : ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
416 : :
417 : 938 : if (struct_expr.has_struct_base ())
418 : : {
419 : 63 : AST::StructBase &base = struct_expr.get_struct_base ();
420 : 63 : ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix);
421 : : }
422 : :
423 : 938 : auto const &struct_fields = struct_expr.get_fields ();
424 : 2636 : for (auto &struct_field : struct_fields)
425 : : {
426 : 1698 : ResolveStructExprField::go (*struct_field, prefix, canonical_prefix);
427 : : }
428 : 938 : }
429 : :
430 : : void
431 : 204 : ResolveExpr::visit (AST::GroupedExpr &expr)
432 : : {
433 : 204 : ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix);
434 : 204 : }
435 : :
436 : : void
437 : 1611 : ResolveExpr::visit (AST::FieldAccessExpr &expr)
438 : : {
439 : 1611 : ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
440 : 1611 : }
441 : :
442 : : void
443 : 108 : ResolveExpr::visit (AST::LoopExpr &expr)
444 : : {
445 : 108 : if (expr.has_loop_label ())
446 : : {
447 : 28 : auto label = expr.get_loop_label ();
448 : 28 : if (label.get_lifetime ().get_lifetime_type ()
449 : : != AST::Lifetime::LifetimeType::NAMED)
450 : : {
451 : 0 : rust_error_at (label.get_locus (),
452 : : "Labels must be a named lifetime value");
453 : 0 : return;
454 : : }
455 : :
456 : 28 : auto label_name = label.get_lifetime ().get_lifetime_name ();
457 : 28 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
458 : 84 : resolver->get_label_scope ().insert (
459 : 56 : CanonicalPath::new_seg (expr.get_node_id (), label_name),
460 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
461 : 28 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
462 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
463 : 0 : rust_error_at (locus, "was defined here");
464 : 0 : });
465 : 28 : }
466 : 108 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
467 : : }
468 : :
469 : : void
470 : 79 : ResolveExpr::visit (AST::BreakExpr &expr)
471 : : {
472 : 79 : if (expr.has_label ())
473 : : {
474 : 17 : auto label = expr.get_label_unchecked ().get_lifetime ();
475 : 17 : if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
476 : : {
477 : 0 : rust_error_at (label.get_locus (),
478 : : "Labels must be a named lifetime value");
479 : 0 : return;
480 : : }
481 : :
482 : 17 : NodeId resolved_node = UNKNOWN_NODEID;
483 : 34 : if (!resolver->get_label_scope ().lookup (
484 : 34 : CanonicalPath::new_seg (label.get_node_id (),
485 : 34 : label.get_lifetime_name ()),
486 : : &resolved_node))
487 : : {
488 : 1 : rust_error_at (label.get_locus (), ErrorCode::E0426,
489 : : "use of undeclared label %qs",
490 : 1 : label.as_string ().c_str ());
491 : 1 : return;
492 : : }
493 : 16 : resolver->insert_resolved_label (label.get_node_id (), resolved_node);
494 : 17 : }
495 : :
496 : 78 : if (expr.has_break_expr ())
497 : : {
498 : 20 : bool funny_error = false;
499 : 20 : auto &break_expr = expr.get_break_expr ();
500 : 20 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
501 : : {
502 : : /* This is a break with an expression, and the expression is
503 : : just a single identifier. See if the identifier is either
504 : : "rust" or "gcc", in which case we have "break rust" or "break
505 : : gcc", and so may need to emit our funny error. We cannot yet
506 : : emit the error here though, because the identifier may still
507 : : be in scope, and ICE'ing on valid programs would not be very
508 : : funny. */
509 : 11 : std::string ident
510 : 11 : = static_cast<AST::IdentifierExpr &> (break_expr).as_string ();
511 : 11 : if (ident == "rust" || ident == "gcc")
512 : : funny_error = true;
513 : 11 : }
514 : 20 : ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error);
515 : : }
516 : : }
517 : :
518 : : void
519 : 59 : ResolveExpr::visit (AST::WhileLoopExpr &expr)
520 : : {
521 : 59 : if (expr.has_loop_label ())
522 : : {
523 : 2 : auto label = expr.get_loop_label ();
524 : 2 : if (label.get_lifetime ().get_lifetime_type ()
525 : : != AST::Lifetime::LifetimeType::NAMED)
526 : : {
527 : 0 : rust_error_at (label.get_locus (),
528 : : "Labels must be a named lifetime value");
529 : 0 : return;
530 : : }
531 : :
532 : 2 : auto label_name = label.get_lifetime ().get_lifetime_name ();
533 : 2 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
534 : 4 : resolver->get_label_scope ().insert (
535 : 4 : CanonicalPath::new_seg (label.get_node_id (), label_name),
536 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
537 : 2 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
538 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
539 : 0 : rust_error_at (locus, "was defined here");
540 : 0 : });
541 : 2 : }
542 : :
543 : 59 : ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix);
544 : 59 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
545 : : }
546 : :
547 : : void
548 : 0 : ResolveExpr::visit (AST::ForLoopExpr &expr)
549 : : {
550 : 0 : if (expr.has_loop_label ())
551 : : {
552 : 0 : auto label = expr.get_loop_label ();
553 : 0 : if (label.get_lifetime ().get_lifetime_type ()
554 : : != AST::Lifetime::LifetimeType::NAMED)
555 : : {
556 : 0 : rust_error_at (label.get_locus (),
557 : : "Labels must be a named lifetime value");
558 : 0 : return;
559 : : }
560 : :
561 : 0 : auto label_name = label.get_lifetime ().get_lifetime_name ();
562 : 0 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
563 : 0 : resolver->get_label_scope ().insert (
564 : 0 : CanonicalPath::new_seg (label.get_node_id (), label_name),
565 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
566 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
567 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
568 : 0 : rust_error_at (locus, "was defined here");
569 : 0 : });
570 : 0 : }
571 : :
572 : : // this needs a new rib to contain the pattern
573 : 0 : NodeId scope_node_id = expr.get_node_id ();
574 : 0 : resolver->get_name_scope ().push (scope_node_id);
575 : 0 : resolver->get_type_scope ().push (scope_node_id);
576 : 0 : resolver->get_label_scope ().push (scope_node_id);
577 : 0 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
578 : 0 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
579 : 0 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
580 : :
581 : : // resolve the expression
582 : 0 : PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var);
583 : 0 : ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix);
584 : 0 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
585 : :
586 : : // done
587 : 0 : resolver->get_name_scope ().pop ();
588 : 0 : resolver->get_type_scope ().pop ();
589 : 0 : resolver->get_label_scope ().pop ();
590 : : }
591 : :
592 : : void
593 : 10 : ResolveExpr::visit (AST::ContinueExpr &expr)
594 : : {
595 : 10 : if (expr.has_label ())
596 : : {
597 : 1 : auto label = expr.get_label_unchecked ();
598 : 1 : if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
599 : : {
600 : 0 : rust_error_at (label.get_locus (),
601 : : "Labels must be a named lifetime value");
602 : 0 : return;
603 : : }
604 : :
605 : 1 : NodeId resolved_node = UNKNOWN_NODEID;
606 : 2 : if (!resolver->get_label_scope ().lookup (
607 : 2 : CanonicalPath::new_seg (label.get_node_id (),
608 : 2 : label.get_lifetime_name ()),
609 : : &resolved_node))
610 : : {
611 : 1 : rust_error_at (expr.get_label_unchecked ().get_locus (),
612 : : ErrorCode::E0426, "use of undeclared label %qs",
613 : 1 : label.as_string ().c_str ());
614 : 1 : return;
615 : : }
616 : 0 : resolver->insert_resolved_label (label.get_node_id (), resolved_node);
617 : 1 : }
618 : : }
619 : :
620 : : void
621 : 1220 : ResolveExpr::visit (AST::BorrowExpr &expr)
622 : : {
623 : 1220 : ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix);
624 : 1220 : }
625 : :
626 : : void
627 : 1634 : ResolveExpr::visit (AST::DereferenceExpr &expr)
628 : : {
629 : 1634 : ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix);
630 : 1634 : }
631 : :
632 : : void
633 : 412 : ResolveExpr::visit (AST::MatchExpr &expr)
634 : : {
635 : 412 : ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix);
636 : 1330 : for (auto &match_case : expr.get_match_cases ())
637 : : {
638 : : // each arm is in its own scope
639 : 918 : NodeId scope_node_id = match_case.get_node_id ();
640 : 918 : resolver->get_name_scope ().push (scope_node_id);
641 : 918 : resolver->get_type_scope ().push (scope_node_id);
642 : 918 : resolver->get_label_scope ().push (scope_node_id);
643 : 918 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
644 : 918 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
645 : 918 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
646 : :
647 : : // resolve
648 : 918 : AST::MatchArm &arm = match_case.get_arm ();
649 : 918 : if (arm.has_match_arm_guard ())
650 : 1 : ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix);
651 : :
652 : : // We know expr.get_patterns () has one pattern at most
653 : : // so there's no reason to handle it like an AltPattern.
654 : 918 : std::vector<PatternBinding> bindings
655 : 1836 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
656 : :
657 : : // insert any possible new patterns
658 : 1836 : for (auto &pattern : arm.get_patterns ())
659 : : {
660 : 918 : PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
661 : : }
662 : :
663 : : // resolve the body
664 : 918 : ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix);
665 : :
666 : : // done
667 : 918 : resolver->get_name_scope ().pop ();
668 : 918 : resolver->get_type_scope ().pop ();
669 : 918 : resolver->get_label_scope ().pop ();
670 : 918 : }
671 : 412 : }
672 : :
673 : : void
674 : 66 : ResolveExpr::visit (AST::RangeFromToExpr &expr)
675 : : {
676 : 66 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
677 : 66 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
678 : 66 : }
679 : :
680 : : void
681 : 7 : ResolveExpr::visit (AST::RangeFromExpr &expr)
682 : : {
683 : 7 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
684 : 7 : }
685 : :
686 : : void
687 : 7 : ResolveExpr::visit (AST::RangeToExpr &expr)
688 : : {
689 : 7 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
690 : 7 : }
691 : :
692 : : void
693 : 0 : ResolveExpr::visit (AST::RangeFullExpr &)
694 : : {
695 : : // nothing to do
696 : 0 : }
697 : :
698 : : void
699 : 7 : ResolveExpr::visit (AST::RangeFromToInclExpr &expr)
700 : : {
701 : 7 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
702 : 7 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
703 : 7 : }
704 : :
705 : : void
706 : 25 : ResolveExpr::visit (AST::ClosureExprInner &expr)
707 : : {
708 : 25 : NodeId scope_node_id = expr.get_node_id ();
709 : 25 : resolver->get_name_scope ().push (scope_node_id);
710 : 25 : resolver->get_type_scope ().push (scope_node_id);
711 : 25 : resolver->get_label_scope ().push (scope_node_id);
712 : 25 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
713 : 25 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
714 : 25 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
715 : :
716 : 25 : std::vector<PatternBinding> bindings
717 : 50 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
718 : :
719 : 43 : for (auto &p : expr.get_params ())
720 : : {
721 : 18 : resolve_closure_param (p, bindings);
722 : : }
723 : :
724 : 25 : resolver->push_closure_context (expr.get_node_id ());
725 : :
726 : 25 : ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
727 : :
728 : 25 : resolver->pop_closure_context ();
729 : :
730 : 25 : resolver->get_name_scope ().pop ();
731 : 25 : resolver->get_type_scope ().pop ();
732 : 25 : resolver->get_label_scope ().pop ();
733 : 25 : }
734 : :
735 : : void
736 : 30 : ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
737 : : {
738 : 30 : NodeId scope_node_id = expr.get_node_id ();
739 : 30 : resolver->get_name_scope ().push (scope_node_id);
740 : 30 : resolver->get_type_scope ().push (scope_node_id);
741 : 30 : resolver->get_label_scope ().push (scope_node_id);
742 : 30 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
743 : 30 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
744 : 30 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
745 : :
746 : 30 : std::vector<PatternBinding> bindings
747 : 60 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
748 : :
749 : 67 : for (auto &p : expr.get_params ())
750 : : {
751 : 37 : resolve_closure_param (p, bindings);
752 : : }
753 : :
754 : 30 : ResolveType::go (expr.get_return_type ());
755 : :
756 : 30 : resolver->push_closure_context (expr.get_node_id ());
757 : :
758 : 30 : ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
759 : :
760 : 30 : resolver->pop_closure_context ();
761 : :
762 : 30 : resolver->get_name_scope ().pop ();
763 : 30 : resolver->get_type_scope ().pop ();
764 : 30 : resolver->get_label_scope ().pop ();
765 : 30 : }
766 : :
767 : : void
768 : 55 : ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m,
769 : : std::vector<PatternBinding> &bindings)
770 : : {
771 : 55 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings);
772 : :
773 : 55 : if (param.has_type_given ())
774 : 51 : ResolveType::go (param.get_type ());
775 : 55 : }
776 : :
777 : 94227 : ResolveExpr::ResolveExpr (const CanonicalPath &prefix,
778 : : const CanonicalPath &canonical_prefix,
779 : 94227 : bool funny_error)
780 : 94227 : : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
781 : 94227 : funny_error (funny_error)
782 : 94227 : {}
783 : :
784 : : } // namespace Resolver
785 : : } // namespace Rust
|