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 : 94297 : ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix,
33 : : const CanonicalPath &canonical_prefix, bool funny_error)
34 : : {
35 : 94297 : ResolveExpr resolver (prefix, canonical_prefix, funny_error);
36 : 94297 : expr.accept_vis (resolver);
37 : 94294 : }
38 : :
39 : : void
40 : 791 : ResolveExpr::visit (AST::TupleIndexExpr &expr)
41 : : {
42 : 791 : ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix);
43 : 791 : }
44 : :
45 : : void
46 : 471 : ResolveExpr::visit (AST::TupleExpr &expr)
47 : : {
48 : 471 : if (expr.is_unit ())
49 : : return;
50 : :
51 : 1133 : for (auto &elem : expr.get_tuple_elems ())
52 : 793 : ResolveExpr::go (*elem, prefix, canonical_prefix);
53 : : }
54 : :
55 : : void
56 : 15111 : ResolveExpr::visit (AST::PathInExpression &expr)
57 : : {
58 : 15111 : ResolvePath::go (expr);
59 : 15111 : }
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 : 8890 : ResolveExpr::visit (AST::CallExpr &expr)
76 : : {
77 : 8890 : ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix);
78 : 19370 : for (auto ¶m : expr.get_params ())
79 : 10480 : ResolveExpr::go (*param, prefix, canonical_prefix);
80 : 8890 : }
81 : :
82 : : void
83 : 1406 : ResolveExpr::visit (AST::MethodCallExpr &expr)
84 : : {
85 : 1406 : ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
86 : :
87 : 1406 : 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 : 1406 : auto const &in_params = expr.get_params ();
94 : 2058 : for (auto ¶m : in_params)
95 : 652 : ResolveExpr::go (*param, prefix, canonical_prefix);
96 : 1406 : }
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 : 1691 : ResolveExpr::visit (AST::AssignmentExpr &expr)
106 : : {
107 : 1691 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
108 : 1691 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
109 : 1691 : }
110 : :
111 : : void
112 : 17557 : ResolveExpr::visit (AST::IdentifierExpr &expr)
113 : : {
114 : 35114 : if (resolver->get_name_scope ().lookup (
115 : 35114 : CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()),
116 : : &resolved_node))
117 : : {
118 : 17519 : 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 : 17556 : }
144 : :
145 : : void
146 : 2827 : ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr)
147 : : {
148 : 2827 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
149 : 2827 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
150 : 2827 : }
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 : 957 : ResolveExpr::visit (AST::ComparisonExpr &expr)
161 : : {
162 : 957 : ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix);
163 : 957 : ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix);
164 : 957 : }
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 : 318 : ResolveExpr::visit (AST::NegationExpr &expr)
175 : : {
176 : 318 : ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix);
177 : 318 : }
178 : :
179 : : void
180 : 4286 : ResolveExpr::visit (AST::TypeCastExpr &expr)
181 : : {
182 : 4286 : ResolveType::go (expr.get_type_to_cast_to ());
183 : 4286 : ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix);
184 : 4286 : }
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 : 16646 : ResolveExpr::visit (AST::BlockExpr &expr)
264 : : {
265 : 16646 : NodeId scope_node_id = expr.get_node_id ();
266 : 16646 : resolver->get_name_scope ().push (scope_node_id);
267 : 16646 : resolver->get_type_scope ().push (scope_node_id);
268 : 16646 : resolver->get_label_scope ().push (scope_node_id);
269 : 16646 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
270 : 16646 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
271 : 16646 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
272 : :
273 : 16646 : 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 : 35297 : for (auto &s : expr.get_statements ())
296 : : {
297 : 18651 : if (s->is_item ())
298 : 350 : ResolveStmt::go (*s, prefix, canonical_prefix,
299 : 700 : CanonicalPath::create_empty ());
300 : : }
301 : :
302 : 35296 : for (auto &s : expr.get_statements ())
303 : : {
304 : 18651 : if (!s->is_item ())
305 : 18301 : ResolveStmt::go (*s, prefix, canonical_prefix,
306 : 36601 : CanonicalPath::create_empty ());
307 : : }
308 : :
309 : 16645 : if (expr.has_tail_expr ())
310 : 11630 : ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix);
311 : :
312 : 16645 : resolver->get_name_scope ().pop ();
313 : 16645 : resolver->get_type_scope ().pop ();
314 : 16645 : 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 : :
372 : : void
373 : 1 : ResolveExpr::visit (AST::LlvmInlineAsm &expr)
374 : : {
375 : 1 : for (auto &output : expr.get_outputs ())
376 : 0 : ResolveExpr::go (*output.expr, prefix, canonical_prefix);
377 : :
378 : 2 : for (auto &input : expr.get_inputs ())
379 : 1 : ResolveExpr::go (*input.expr, prefix, canonical_prefix);
380 : 1 : }
381 : :
382 : : void
383 : 3163 : ResolveExpr::visit (AST::UnsafeBlockExpr &expr)
384 : : {
385 : 3163 : expr.get_block_expr ().accept_vis (*this);
386 : 3163 : }
387 : :
388 : : void
389 : 211 : ResolveExpr::visit (AST::ArrayElemsValues &elems)
390 : : {
391 : 1383 : for (auto &elem : elems.get_values ())
392 : 1172 : ResolveExpr::go (*elem, prefix, canonical_prefix);
393 : 211 : }
394 : :
395 : : void
396 : 322 : ResolveExpr::visit (AST::ArrayExpr &expr)
397 : : {
398 : 322 : expr.get_array_elems ()->accept_vis (*this);
399 : 322 : }
400 : :
401 : : void
402 : 213 : ResolveExpr::visit (AST::ArrayIndexExpr &expr)
403 : : {
404 : 213 : ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix);
405 : 213 : ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix);
406 : 213 : }
407 : :
408 : : void
409 : 111 : ResolveExpr::visit (AST::ArrayElemsCopied &expr)
410 : : {
411 : 111 : ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix);
412 : 111 : ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix);
413 : 111 : }
414 : :
415 : : // this this an empty struct constructor like 'S {}'
416 : : void
417 : 53 : ResolveExpr::visit (AST::StructExprStruct &struct_expr)
418 : : {
419 : 53 : ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
420 : 53 : }
421 : :
422 : : // this this a struct constructor with fields
423 : : void
424 : 939 : ResolveExpr::visit (AST::StructExprStructFields &struct_expr)
425 : : {
426 : 939 : ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix);
427 : :
428 : 939 : if (struct_expr.has_struct_base ())
429 : : {
430 : 63 : AST::StructBase &base = struct_expr.get_struct_base ();
431 : 63 : ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix);
432 : : }
433 : :
434 : 939 : auto const &struct_fields = struct_expr.get_fields ();
435 : 2638 : for (auto &struct_field : struct_fields)
436 : : {
437 : 1699 : ResolveStructExprField::go (*struct_field, prefix, canonical_prefix);
438 : : }
439 : 939 : }
440 : :
441 : : void
442 : 206 : ResolveExpr::visit (AST::GroupedExpr &expr)
443 : : {
444 : 206 : ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix);
445 : 206 : }
446 : :
447 : : void
448 : 1614 : ResolveExpr::visit (AST::FieldAccessExpr &expr)
449 : : {
450 : 1614 : ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix);
451 : 1614 : }
452 : :
453 : : void
454 : 108 : ResolveExpr::visit (AST::LoopExpr &expr)
455 : : {
456 : 108 : if (expr.has_loop_label ())
457 : : {
458 : 28 : auto label = expr.get_loop_label ();
459 : 28 : if (label.get_lifetime ().get_lifetime_type ()
460 : : != AST::Lifetime::LifetimeType::NAMED)
461 : : {
462 : 0 : rust_error_at (label.get_locus (),
463 : : "Labels must be a named lifetime value");
464 : 0 : return;
465 : : }
466 : :
467 : 28 : auto label_name = label.get_lifetime ().get_lifetime_name ();
468 : 28 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
469 : 56 : resolver->get_label_scope ().insert (
470 : 56 : CanonicalPath::new_seg (expr.get_node_id (), label_name),
471 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
472 : 56 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
473 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
474 : 0 : rust_error_at (locus, "was defined here");
475 : 0 : });
476 : 28 : }
477 : 108 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
478 : : }
479 : :
480 : : void
481 : 79 : ResolveExpr::visit (AST::BreakExpr &expr)
482 : : {
483 : 79 : if (expr.has_label ())
484 : : {
485 : 17 : auto label = expr.get_label_unchecked ().get_lifetime ();
486 : 17 : if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
487 : : {
488 : 0 : rust_error_at (label.get_locus (),
489 : : "Labels must be a named lifetime value");
490 : 0 : return;
491 : : }
492 : :
493 : 17 : NodeId resolved_node = UNKNOWN_NODEID;
494 : 34 : if (!resolver->get_label_scope ().lookup (
495 : 34 : CanonicalPath::new_seg (label.get_node_id (),
496 : 34 : label.get_lifetime_name ()),
497 : : &resolved_node))
498 : : {
499 : 1 : rust_error_at (label.get_locus (), ErrorCode::E0426,
500 : : "use of undeclared label %qs",
501 : 1 : label.as_string ().c_str ());
502 : 1 : return;
503 : : }
504 : 16 : resolver->insert_resolved_label (label.get_node_id (), resolved_node);
505 : 17 : }
506 : :
507 : 78 : if (expr.has_break_expr ())
508 : : {
509 : 20 : bool funny_error = false;
510 : 20 : auto &break_expr = expr.get_break_expr ();
511 : 20 : if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier)
512 : : {
513 : : /* This is a break with an expression, and the expression is
514 : : just a single identifier. See if the identifier is either
515 : : "rust" or "gcc", in which case we have "break rust" or "break
516 : : gcc", and so may need to emit our funny error. We cannot yet
517 : : emit the error here though, because the identifier may still
518 : : be in scope, and ICE'ing on valid programs would not be very
519 : : funny. */
520 : 11 : std::string ident
521 : 11 : = static_cast<AST::IdentifierExpr &> (break_expr).as_string ();
522 : 11 : if (ident == "rust" || ident == "gcc")
523 : : funny_error = true;
524 : 11 : }
525 : 20 : ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error);
526 : : }
527 : : }
528 : :
529 : : void
530 : 59 : ResolveExpr::visit (AST::WhileLoopExpr &expr)
531 : : {
532 : 59 : if (expr.has_loop_label ())
533 : : {
534 : 2 : auto label = expr.get_loop_label ();
535 : 2 : if (label.get_lifetime ().get_lifetime_type ()
536 : : != AST::Lifetime::LifetimeType::NAMED)
537 : : {
538 : 0 : rust_error_at (label.get_locus (),
539 : : "Labels must be a named lifetime value");
540 : 0 : return;
541 : : }
542 : :
543 : 2 : auto label_name = label.get_lifetime ().get_lifetime_name ();
544 : 2 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
545 : 2 : resolver->get_label_scope ().insert (
546 : 4 : CanonicalPath::new_seg (label.get_node_id (), label_name),
547 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
548 : 4 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
549 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
550 : 0 : rust_error_at (locus, "was defined here");
551 : 0 : });
552 : 2 : }
553 : :
554 : 59 : ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix);
555 : 59 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
556 : : }
557 : :
558 : : void
559 : 0 : ResolveExpr::visit (AST::ForLoopExpr &expr)
560 : : {
561 : 0 : if (expr.has_loop_label ())
562 : : {
563 : 0 : auto label = expr.get_loop_label ();
564 : 0 : if (label.get_lifetime ().get_lifetime_type ()
565 : : != AST::Lifetime::LifetimeType::NAMED)
566 : : {
567 : 0 : rust_error_at (label.get_locus (),
568 : : "Labels must be a named lifetime value");
569 : 0 : return;
570 : : }
571 : :
572 : 0 : auto label_name = label.get_lifetime ().get_lifetime_name ();
573 : 0 : auto label_lifetime_node_id = label.get_lifetime ().get_node_id ();
574 : 0 : resolver->get_label_scope ().insert (
575 : 0 : CanonicalPath::new_seg (label.get_node_id (), label_name),
576 : : label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label,
577 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
578 : 0 : rust_error_at (label.get_locus (), "label defined multiple times");
579 : 0 : rust_error_at (locus, "was defined here");
580 : 0 : });
581 : 0 : }
582 : :
583 : : // this needs a new rib to contain the pattern
584 : 0 : NodeId scope_node_id = expr.get_node_id ();
585 : 0 : resolver->get_name_scope ().push (scope_node_id);
586 : 0 : resolver->get_type_scope ().push (scope_node_id);
587 : 0 : resolver->get_label_scope ().push (scope_node_id);
588 : 0 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
589 : 0 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
590 : 0 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
591 : :
592 : : // resolve the expression
593 : 0 : PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var);
594 : 0 : ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix);
595 : 0 : ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix);
596 : :
597 : : // done
598 : 0 : resolver->get_name_scope ().pop ();
599 : 0 : resolver->get_type_scope ().pop ();
600 : 0 : resolver->get_label_scope ().pop ();
601 : : }
602 : :
603 : : void
604 : 10 : ResolveExpr::visit (AST::ContinueExpr &expr)
605 : : {
606 : 10 : if (expr.has_label ())
607 : : {
608 : 1 : auto label = expr.get_label_unchecked ();
609 : 1 : if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
610 : : {
611 : 0 : rust_error_at (label.get_locus (),
612 : : "Labels must be a named lifetime value");
613 : 0 : return;
614 : : }
615 : :
616 : 1 : NodeId resolved_node = UNKNOWN_NODEID;
617 : 2 : if (!resolver->get_label_scope ().lookup (
618 : 2 : CanonicalPath::new_seg (label.get_node_id (),
619 : 2 : label.get_lifetime_name ()),
620 : : &resolved_node))
621 : : {
622 : 1 : rust_error_at (expr.get_label_unchecked ().get_locus (),
623 : : ErrorCode::E0426, "use of undeclared label %qs",
624 : 1 : label.as_string ().c_str ());
625 : 1 : return;
626 : : }
627 : 0 : resolver->insert_resolved_label (label.get_node_id (), resolved_node);
628 : 1 : }
629 : : }
630 : :
631 : : void
632 : 1221 : ResolveExpr::visit (AST::BorrowExpr &expr)
633 : : {
634 : 1221 : ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix);
635 : 1221 : }
636 : :
637 : : void
638 : 1634 : ResolveExpr::visit (AST::DereferenceExpr &expr)
639 : : {
640 : 1634 : ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix);
641 : 1634 : }
642 : :
643 : : void
644 : 412 : ResolveExpr::visit (AST::MatchExpr &expr)
645 : : {
646 : 412 : ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix);
647 : 1330 : for (auto &match_case : expr.get_match_cases ())
648 : : {
649 : : // each arm is in its own scope
650 : 918 : NodeId scope_node_id = match_case.get_node_id ();
651 : 918 : resolver->get_name_scope ().push (scope_node_id);
652 : 918 : resolver->get_type_scope ().push (scope_node_id);
653 : 918 : resolver->get_label_scope ().push (scope_node_id);
654 : 918 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
655 : 918 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
656 : 918 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
657 : :
658 : : // resolve
659 : 918 : AST::MatchArm &arm = match_case.get_arm ();
660 : 918 : if (arm.has_match_arm_guard ())
661 : 1 : ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix);
662 : :
663 : : // We know expr.get_patterns () has one pattern at most
664 : : // so there's no reason to handle it like an AltPattern.
665 : 918 : std::vector<PatternBinding> bindings
666 : 1836 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
667 : :
668 : : // insert any possible new patterns
669 : 1836 : for (auto &pattern : arm.get_patterns ())
670 : : {
671 : 918 : PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings);
672 : : }
673 : :
674 : : // resolve the body
675 : 918 : ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix);
676 : :
677 : : // done
678 : 918 : resolver->get_name_scope ().pop ();
679 : 918 : resolver->get_type_scope ().pop ();
680 : 918 : resolver->get_label_scope ().pop ();
681 : 918 : }
682 : 412 : }
683 : :
684 : : void
685 : 66 : ResolveExpr::visit (AST::RangeFromToExpr &expr)
686 : : {
687 : 66 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
688 : 66 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
689 : 66 : }
690 : :
691 : : void
692 : 7 : ResolveExpr::visit (AST::RangeFromExpr &expr)
693 : : {
694 : 7 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
695 : 7 : }
696 : :
697 : : void
698 : 7 : ResolveExpr::visit (AST::RangeToExpr &expr)
699 : : {
700 : 7 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
701 : 7 : }
702 : :
703 : : void
704 : 0 : ResolveExpr::visit (AST::RangeFullExpr &)
705 : : {
706 : : // nothing to do
707 : 0 : }
708 : :
709 : : void
710 : 7 : ResolveExpr::visit (AST::RangeFromToInclExpr &expr)
711 : : {
712 : 7 : ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix);
713 : 7 : ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix);
714 : 7 : }
715 : :
716 : : void
717 : 26 : ResolveExpr::visit (AST::ClosureExprInner &expr)
718 : : {
719 : 26 : NodeId scope_node_id = expr.get_node_id ();
720 : 26 : resolver->get_name_scope ().push (scope_node_id);
721 : 26 : resolver->get_type_scope ().push (scope_node_id);
722 : 26 : resolver->get_label_scope ().push (scope_node_id);
723 : 26 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
724 : 26 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
725 : 26 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
726 : :
727 : 26 : std::vector<PatternBinding> bindings
728 : 52 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
729 : :
730 : 44 : for (auto &p : expr.get_params ())
731 : : {
732 : 18 : resolve_closure_param (p, bindings);
733 : : }
734 : :
735 : 26 : resolver->push_closure_context (expr.get_node_id ());
736 : :
737 : 26 : ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
738 : :
739 : 26 : resolver->pop_closure_context ();
740 : :
741 : 26 : resolver->get_name_scope ().pop ();
742 : 26 : resolver->get_type_scope ().pop ();
743 : 26 : resolver->get_label_scope ().pop ();
744 : 26 : }
745 : :
746 : : void
747 : 30 : ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
748 : : {
749 : 30 : NodeId scope_node_id = expr.get_node_id ();
750 : 30 : resolver->get_name_scope ().push (scope_node_id);
751 : 30 : resolver->get_type_scope ().push (scope_node_id);
752 : 30 : resolver->get_label_scope ().push (scope_node_id);
753 : 30 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
754 : 30 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
755 : 30 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
756 : :
757 : 30 : std::vector<PatternBinding> bindings
758 : 60 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
759 : :
760 : 67 : for (auto &p : expr.get_params ())
761 : : {
762 : 37 : resolve_closure_param (p, bindings);
763 : : }
764 : :
765 : 30 : ResolveType::go (expr.get_return_type ());
766 : :
767 : 30 : resolver->push_closure_context (expr.get_node_id ());
768 : :
769 : 30 : ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
770 : :
771 : 30 : resolver->pop_closure_context ();
772 : :
773 : 30 : resolver->get_name_scope ().pop ();
774 : 30 : resolver->get_type_scope ().pop ();
775 : 30 : resolver->get_label_scope ().pop ();
776 : 30 : }
777 : :
778 : : void
779 : 55 : ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m,
780 : : std::vector<PatternBinding> &bindings)
781 : : {
782 : 55 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings);
783 : :
784 : 55 : if (param.has_type_given ())
785 : 51 : ResolveType::go (param.get_type ());
786 : 55 : }
787 : :
788 : 94297 : ResolveExpr::ResolveExpr (const CanonicalPath &prefix,
789 : : const CanonicalPath &canonical_prefix,
790 : 94297 : bool funny_error)
791 : 94297 : : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
792 : 94297 : funny_error (funny_error)
793 : 94297 : {}
794 : :
795 : : } // namespace Resolver
796 : : } // namespace Rust
|