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-path.h"
20 : : #include "rust-ast-resolve-type.h"
21 : : #include "rust-hir-map.h"
22 : : #include "rust-path.h"
23 : :
24 : : namespace Rust {
25 : : namespace Resolver {
26 : :
27 : 18054 : ResolvePath::ResolvePath () : ResolverBase () {}
28 : :
29 : : NodeId
30 : 17556 : ResolvePath::go (AST::PathInExpression &expr)
31 : : {
32 : 17556 : ResolvePath resolver;
33 : 17556 : return resolver.resolve_path (expr);
34 : 17556 : }
35 : :
36 : : NodeId
37 : 128 : ResolvePath::go (AST::QualifiedPathInExpression &expr)
38 : : {
39 : 128 : ResolvePath resolver;
40 : 128 : return resolver.resolve_path (expr);
41 : 128 : }
42 : :
43 : : NodeId
44 : 370 : ResolvePath::go (AST::SimplePath &expr)
45 : : {
46 : 370 : ResolvePath resolver;
47 : 370 : return resolver.resolve_path (expr);
48 : 370 : }
49 : :
50 : : NodeId
51 : 17556 : ResolvePath::resolve_path (AST::PathInExpression &expr)
52 : : {
53 : 17556 : if (expr.is_lang_item ())
54 : 88 : return Analysis::Mappings::get ().get_lang_item_node (
55 : 88 : expr.get_lang_item ());
56 : :
57 : 17468 : NodeId resolved_node_id = UNKNOWN_NODEID;
58 : 17468 : NodeId module_scope_id = resolver->peek_current_module_scope ();
59 : 17468 : NodeId previous_resolved_node_id = module_scope_id;
60 : 40191 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
61 : : {
62 : 22726 : auto &segment = expr.get_segments ().at (i);
63 : 22726 : const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
64 : 22726 : bool is_first_segment = i == 0;
65 : 22726 : resolved_node_id = UNKNOWN_NODEID;
66 : :
67 : 22726 : bool in_middle_of_path = i > 0;
68 : 22726 : if (in_middle_of_path && segment.is_lower_self_seg ())
69 : : {
70 : 1 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
71 : : "leading path segment %qs can only be used at the "
72 : : "beginning of a path",
73 : 1 : segment.as_string ().c_str ());
74 : 1 : return UNKNOWN_NODEID;
75 : : }
76 : :
77 : 22725 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
78 : 22725 : if (segment.is_crate_path_seg ())
79 : : {
80 : : // what is the current crate scope node id?
81 : 258 : module_scope_id = crate_scope_id;
82 : 258 : previous_resolved_node_id = module_scope_id;
83 : :
84 : 258 : NodeId existing = UNKNOWN_NODEID;
85 : 258 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
86 : : &existing);
87 : :
88 : 258 : if (ok)
89 : 0 : rust_assert (existing == module_scope_id);
90 : : else
91 : 258 : resolver->insert_resolved_name (segment.get_node_id (),
92 : : module_scope_id);
93 : 258 : continue;
94 : 258 : }
95 : 22467 : else if (segment.is_super_path_seg ())
96 : : {
97 : 1 : if (module_scope_id == crate_scope_id)
98 : : {
99 : 0 : rust_error_at (segment.get_locus (),
100 : : "cannot use %<super%> at the crate scope");
101 : 0 : return UNKNOWN_NODEID;
102 : : }
103 : :
104 : 1 : module_scope_id = resolver->peek_parent_module_scope ();
105 : 1 : previous_resolved_node_id = module_scope_id;
106 : :
107 : 1 : NodeId existing = UNKNOWN_NODEID;
108 : 1 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
109 : : &existing);
110 : :
111 : 1 : if (ok)
112 : 0 : rust_assert (existing == module_scope_id);
113 : : else
114 : 1 : resolver->insert_resolved_name (segment.get_node_id (),
115 : : module_scope_id);
116 : 1 : continue;
117 : 1 : }
118 : :
119 : : // resolve any generic args
120 : 22466 : if (segment.has_generic_args ())
121 : 831 : ResolveGenericArgs::go (segment.get_generic_args ());
122 : :
123 : : // logic is awkward here there are a few cases
124 : : //
125 : : // T::Default
126 : : // mod::foo::impl_item
127 : : // super::super::module::item
128 : : // self
129 : : // self::foo
130 : : // self::foo::baz
131 : : //
132 : : // T::Default we can only resolve the T and cant do anything about Default
133 : : // its dependant on associated types
134 : : //
135 : : // mod::foo::impl_item
136 : : // we can resolve mod::foo but nothing about impl_item but we need to
137 : : // _always resolve generic arguments
138 : : //
139 : : // self is a simple single lookup
140 : : //
141 : : // we have module_scope_id for the next module_scope to lookup
142 : : // resolved_node_id is the thing we have resolve this segment to
143 : : //
144 : : // new algo?
145 : : // we can only use module resolution when the previous segment is either
146 : : // unknown or equal to this module_scope_id
147 : : //
148 : : // can only use old resolution when previous segment is unkown
149 : :
150 : 22466 : if (is_first_segment)
151 : : {
152 : : // name scope first
153 : 17209 : NodeId resolved_node = UNKNOWN_NODEID;
154 : 17209 : const CanonicalPath path
155 : : = CanonicalPath::new_seg (segment.get_node_id (),
156 : 17209 : ident_seg.as_string ());
157 : 17209 : if (resolver->get_name_scope ().lookup (path, &resolved_node))
158 : : {
159 : 12400 : NodeId existing = UNKNOWN_NODEID;
160 : 12400 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
161 : : &existing);
162 : :
163 : 12400 : if (ok)
164 : 0 : rust_assert (existing == resolved_node);
165 : : else
166 : 12400 : resolver->insert_resolved_name (segment.get_node_id (),
167 : : resolved_node);
168 : 12400 : resolved_node_id = resolved_node;
169 : : }
170 : : // check the type scope
171 : 4809 : else if (resolver->get_type_scope ().lookup (path, &resolved_node))
172 : : {
173 : 4288 : NodeId existing = UNKNOWN_NODEID;
174 : 4288 : bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
175 : : &existing);
176 : :
177 : 4288 : if (ok)
178 : 48 : rust_assert (existing == resolved_node);
179 : : else
180 : 4240 : resolver->insert_resolved_type (segment.get_node_id (),
181 : : resolved_node);
182 : 4288 : resolved_node_id = resolved_node;
183 : : }
184 : 521 : else if (segment.is_lower_self_seg ())
185 : : {
186 : 9 : module_scope_id = crate_scope_id;
187 : 9 : previous_resolved_node_id = module_scope_id;
188 : :
189 : 9 : NodeId existing = UNKNOWN_NODEID;
190 : 9 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
191 : : &existing);
192 : :
193 : 9 : if (ok)
194 : 0 : rust_assert (existing == module_scope_id);
195 : : else
196 : 9 : resolver->insert_resolved_name (segment.get_node_id (),
197 : : module_scope_id);
198 : 9 : continue;
199 : 9 : }
200 : : else
201 : : {
202 : : // no error handling here since we might be able to resolve via
203 : : // the module hierarchy and handle errors at the end
204 : : }
205 : 17209 : }
206 : :
207 : 22457 : if (resolved_node_id == UNKNOWN_NODEID
208 : 22457 : && previous_resolved_node_id == module_scope_id)
209 : : {
210 : 4569 : tl::optional<CanonicalPath &> resolved_child
211 : 9138 : = mappings.lookup_module_child (module_scope_id,
212 : 4569 : ident_seg.as_string ());
213 : 4569 : if (resolved_child.has_value ())
214 : : {
215 : 4561 : NodeId resolved_node = resolved_child->get_node_id ();
216 : 4561 : if (resolver->get_name_scope ().decl_was_declared_here (
217 : : resolved_node))
218 : : {
219 : 2309 : resolved_node_id = resolved_node;
220 : :
221 : 2309 : NodeId existing = UNKNOWN_NODEID;
222 : 2309 : bool ok
223 : 2309 : = resolver->lookup_resolved_name (segment.get_node_id (),
224 : : &existing);
225 : :
226 : 2309 : if (ok)
227 : 0 : rust_assert (existing == resolved_node);
228 : : else
229 : 2309 : resolver->insert_resolved_name (segment.get_node_id (),
230 : : resolved_node);
231 : : }
232 : 2252 : else if (resolver->get_type_scope ().decl_was_declared_here (
233 : : resolved_node))
234 : : {
235 : 2252 : resolved_node_id = resolved_node;
236 : :
237 : 2252 : NodeId existing = UNKNOWN_NODEID;
238 : 2252 : bool ok
239 : 2252 : = resolver->lookup_resolved_type (segment.get_node_id (),
240 : : &existing);
241 : :
242 : 2252 : if (ok)
243 : 48 : rust_assert (existing == resolved_node);
244 : : else
245 : 2204 : resolver->insert_resolved_type (segment.get_node_id (),
246 : : resolved_node);
247 : : }
248 : : else
249 : : {
250 : 0 : rust_error_at (segment.get_locus (),
251 : : "Cannot find path %<%s%> in this scope",
252 : 0 : segment.as_string ().c_str ());
253 : 0 : return UNKNOWN_NODEID;
254 : : }
255 : : }
256 : : }
257 : :
258 : 22457 : bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
259 : 22457 : if (did_resolve_segment)
260 : : {
261 : 21249 : if (mappings.node_is_module (resolved_node_id)
262 : 21249 : || mappings.node_is_crate (resolved_node_id))
263 : : {
264 : : module_scope_id = resolved_node_id;
265 : : }
266 : : previous_resolved_node_id = resolved_node_id;
267 : : }
268 : 1208 : else if (is_first_segment)
269 : : {
270 : 2 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
271 : : "Cannot find path %<%s%> in this scope",
272 : 2 : segment.as_string ().c_str ());
273 : 2 : return UNKNOWN_NODEID;
274 : : }
275 : : }
276 : :
277 : 17465 : resolved_node = resolved_node_id;
278 : 17465 : if (resolved_node_id != UNKNOWN_NODEID)
279 : : {
280 : : // name scope first
281 : 16261 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
282 : : {
283 : 12544 : NodeId existing = UNKNOWN_NODEID;
284 : 12544 : bool ok
285 : 12544 : = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
286 : :
287 : 12544 : if (ok)
288 : 0 : rust_assert (existing == resolved_node_id);
289 : : else
290 : 12544 : resolver->insert_resolved_name (expr.get_node_id (),
291 : : resolved_node_id);
292 : : }
293 : : // check the type scope
294 : 3717 : else if (resolver->get_type_scope ().decl_was_declared_here (
295 : : resolved_node_id))
296 : : {
297 : 3717 : NodeId existing = UNKNOWN_NODEID;
298 : 3717 : bool ok
299 : 3717 : = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
300 : :
301 : 3717 : if (ok)
302 : 16 : rust_assert (existing == resolved_node_id);
303 : : else
304 : 3701 : resolver->insert_resolved_type (expr.get_node_id (),
305 : : resolved_node_id);
306 : : }
307 : : else
308 : : {
309 : 0 : rust_unreachable ();
310 : : }
311 : : }
312 : : return resolved_node_id;
313 : : }
314 : :
315 : : NodeId
316 : 128 : ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr)
317 : : {
318 : 128 : auto &root_segment = expr.get_qualified_path_type ();
319 : 128 : ResolveType::go (root_segment.get_type ());
320 : 128 : if (root_segment.has_as_clause ())
321 : 94 : ResolveType::go (root_segment.get_as_type_path ());
322 : :
323 : 256 : for (auto &segment : expr.get_segments ())
324 : : {
325 : : // we cant actually do anything with the segment itself since this is all
326 : : // the job of the type system to figure it out but we can resolve any
327 : : // generic arguments used
328 : 256 : if (segment.has_generic_args ())
329 : 0 : ResolveGenericArgs::go (segment.get_generic_args ());
330 : : }
331 : :
332 : : // cannot fully resolve a qualified path as it is dependant on associated
333 : : // items
334 : 128 : return UNKNOWN_NODEID;
335 : : }
336 : :
337 : : NodeId
338 : 370 : ResolvePath::resolve_path (AST::SimplePath &expr)
339 : : {
340 : 370 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
341 : 370 : NodeId module_scope_id = resolver->peek_current_module_scope ();
342 : :
343 : 370 : NodeId previous_resolved_node_id = UNKNOWN_NODEID;
344 : 370 : NodeId resolved_node_id = UNKNOWN_NODEID;
345 : 1264 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
346 : : {
347 : 902 : AST::SimplePathSegment &segment = expr.get_segments ().at (i);
348 : 902 : bool is_first_segment = i == 0;
349 : 902 : bool is_final_segment = i >= (expr.get_segments ().size () - 1);
350 : 902 : resolved_node_id = UNKNOWN_NODEID;
351 : :
352 : 902 : if (segment.is_crate_path_seg ())
353 : : {
354 : : // what is the current crate scope node id?
355 : 5 : module_scope_id = crate_scope_id;
356 : 5 : previous_resolved_node_id = module_scope_id;
357 : :
358 : 5 : NodeId existing = UNKNOWN_NODEID;
359 : 5 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
360 : : &existing);
361 : :
362 : 5 : if (ok)
363 : 0 : rust_assert (existing == module_scope_id);
364 : : else
365 : 5 : resolver->insert_resolved_name (segment.get_node_id (),
366 : : module_scope_id);
367 : 5 : resolved_node_id = module_scope_id;
368 : :
369 : 5 : continue;
370 : 5 : }
371 : 897 : else if (segment.is_super_path_seg ())
372 : : {
373 : 153 : if (!is_first_segment)
374 : : {
375 : 1 : rust_error_at (segment.get_locus (),
376 : : "%<super%> can only be used in start position");
377 : 1 : return UNKNOWN_NODEID;
378 : : }
379 : 152 : if (module_scope_id == crate_scope_id)
380 : : {
381 : 0 : rust_error_at (segment.get_locus (),
382 : : "cannot use %<super%> at the crate scope");
383 : 0 : return UNKNOWN_NODEID;
384 : : }
385 : :
386 : 152 : module_scope_id = resolver->peek_parent_module_scope ();
387 : 152 : previous_resolved_node_id = module_scope_id;
388 : :
389 : 152 : NodeId existing = UNKNOWN_NODEID;
390 : 152 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
391 : : &existing);
392 : :
393 : 152 : if (ok)
394 : 0 : rust_assert (existing == module_scope_id);
395 : : else
396 : 152 : resolver->insert_resolved_name (segment.get_node_id (),
397 : : module_scope_id);
398 : 152 : resolved_node_id = module_scope_id;
399 : :
400 : 152 : continue;
401 : 152 : }
402 : :
403 : 744 : tl::optional<CanonicalPath &> resolved_child
404 : 744 : = mappings.lookup_module_child (module_scope_id,
405 : : segment.get_segment_name ());
406 : 744 : if (resolved_child.has_value ())
407 : : {
408 : 655 : NodeId resolved_node = resolved_child->get_node_id ();
409 : 655 : if (resolver->get_name_scope ().decl_was_declared_here (
410 : : resolved_node))
411 : : {
412 : 222 : resolved_node_id = resolved_node;
413 : :
414 : 222 : NodeId existing = UNKNOWN_NODEID;
415 : 222 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
416 : : &existing);
417 : :
418 : 222 : if (ok)
419 : 0 : rust_assert (existing == resolved_node);
420 : : else
421 : 222 : resolver->insert_resolved_name (segment.get_node_id (),
422 : : resolved_node);
423 : : }
424 : 433 : else if (resolver->get_type_scope ().decl_was_declared_here (
425 : : resolved_node))
426 : : {
427 : 433 : resolved_node_id = resolved_node;
428 : :
429 : 433 : NodeId existing = UNKNOWN_NODEID;
430 : 433 : bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
431 : : &existing);
432 : :
433 : 433 : if (ok)
434 : 0 : rust_assert (existing == resolved_node);
435 : : else
436 : 433 : resolver->insert_resolved_type (segment.get_node_id (),
437 : : resolved_node);
438 : : }
439 : : else
440 : : {
441 : 0 : rust_error_at (segment.get_locus (),
442 : : "Cannot find path %<%s%> in this scope",
443 : 0 : segment.as_string ().c_str ());
444 : 0 : return UNKNOWN_NODEID;
445 : : }
446 : : }
447 : :
448 : 744 : if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
449 : : {
450 : : // name scope first
451 : 33 : NodeId resolved_node = UNKNOWN_NODEID;
452 : 33 : const CanonicalPath path
453 : : = CanonicalPath::new_seg (segment.get_node_id (),
454 : 33 : segment.get_segment_name ());
455 : 33 : if (resolver->get_name_scope ().lookup (path, &resolved_node))
456 : : {
457 : 6 : resolved_node_id = resolved_node;
458 : :
459 : 6 : NodeId existing = UNKNOWN_NODEID;
460 : 6 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
461 : : &existing);
462 : :
463 : 6 : if (ok)
464 : 0 : rust_assert (existing == resolved_node);
465 : : else
466 : 6 : resolver->insert_resolved_name (segment.get_node_id (),
467 : : resolved_node);
468 : : }
469 : : // check the type scope
470 : 27 : else if (resolver->get_type_scope ().lookup (path, &resolved_node))
471 : : {
472 : 24 : resolved_node_id = resolved_node;
473 : :
474 : 24 : NodeId existing = UNKNOWN_NODEID;
475 : 24 : bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
476 : : &existing);
477 : :
478 : 24 : if (ok)
479 : 0 : rust_assert (existing == resolved_node);
480 : : else
481 : 24 : resolver->insert_resolved_type (segment.get_node_id (),
482 : : resolved_node);
483 : : }
484 : 33 : }
485 : :
486 : : // if we still have not resolved and this is the final segment and the
487 : : // final segment is self its likely the case: pub use
488 : : //
489 : : // result::Result::{self, Err, Ok};
490 : : //
491 : : // Then the resolved_node_id is just the previous one so long as it is a
492 : : // resolved node id
493 : : // rust_debug_loc (segment.get_locus (),
494 : : // "trying to resolve seg: [%s] first [%s] last [%s]",
495 : : // segment.get_segment_name ().c_str (),
496 : : // is_first_segment ? "true" : "false",
497 : : // is_final_segment ? "true" : "false");
498 : 744 : if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
499 : 744 : && is_final_segment && segment.is_lower_self_seg ())
500 : : resolved_node_id = previous_resolved_node_id;
501 : :
502 : : // final check
503 : 744 : if (resolved_node_id == UNKNOWN_NODEID)
504 : : {
505 : 7 : rust_error_at (segment.get_locus (),
506 : : "cannot find simple path segment %<%s%> in this scope",
507 : 7 : segment.as_string ().c_str ());
508 : 7 : return UNKNOWN_NODEID;
509 : : }
510 : :
511 : 737 : if (mappings.node_is_module (resolved_node_id))
512 : : {
513 : 447 : module_scope_id = resolved_node_id;
514 : : }
515 : :
516 : 737 : previous_resolved_node_id = resolved_node_id;
517 : : }
518 : :
519 : 362 : resolved_node = resolved_node_id;
520 : 362 : if (resolved_node_id != UNKNOWN_NODEID)
521 : : {
522 : : // name scope first
523 : 362 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
524 : : {
525 : 35 : NodeId existing = UNKNOWN_NODEID;
526 : 35 : bool ok
527 : 35 : = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
528 : :
529 : 35 : if (ok)
530 : 0 : rust_assert (existing == resolved_node_id);
531 : : else
532 : 35 : resolver->insert_resolved_name (expr.get_node_id (),
533 : : resolved_node_id);
534 : : }
535 : : // check the type scope
536 : 327 : else if (resolver->get_type_scope ().decl_was_declared_here (
537 : : resolved_node_id))
538 : : {
539 : 327 : NodeId existing = UNKNOWN_NODEID;
540 : 327 : bool ok
541 : 327 : = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
542 : :
543 : 327 : if (ok)
544 : 0 : rust_assert (existing == resolved_node_id);
545 : : else
546 : 327 : resolver->insert_resolved_type (expr.get_node_id (),
547 : : resolved_node_id);
548 : : }
549 : : else
550 : : {
551 : 0 : rust_unreachable ();
552 : : }
553 : : }
554 : : return resolved_node_id;
555 : : }
556 : :
557 : : } // namespace Resolver
558 : : } // namespace Rust
|