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