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