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 : 16328 : ResolvePath::ResolvePath () : ResolverBase () {}
28 : :
29 : : NodeId
30 : 15881 : ResolvePath::go (AST::PathInExpression &expr)
31 : : {
32 : 15881 : ResolvePath resolver;
33 : 15881 : return resolver.resolve_path (expr);
34 : 15881 : }
35 : :
36 : : NodeId
37 : 114 : ResolvePath::go (AST::QualifiedPathInExpression &expr)
38 : : {
39 : 114 : ResolvePath resolver;
40 : 114 : return resolver.resolve_path (expr);
41 : 114 : }
42 : :
43 : : NodeId
44 : 333 : ResolvePath::go (AST::SimplePath &expr)
45 : : {
46 : 333 : ResolvePath resolver;
47 : 333 : return resolver.resolve_path (expr);
48 : 333 : }
49 : :
50 : : NodeId
51 : 15881 : ResolvePath::resolve_path (AST::PathInExpression &expr)
52 : : {
53 : 15881 : if (expr.is_lang_item ())
54 : 88 : return Analysis::Mappings::get ().get_lang_item_node (
55 : 88 : expr.get_lang_item ());
56 : :
57 : 15793 : NodeId resolved_node_id = UNKNOWN_NODEID;
58 : 15793 : NodeId module_scope_id = resolver->peek_current_module_scope ();
59 : 15793 : NodeId previous_resolved_node_id = module_scope_id;
60 : 36529 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
61 : : {
62 : 20739 : auto &segment = expr.get_segments ().at (i);
63 : 20739 : const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
64 : 20739 : bool is_first_segment = i == 0;
65 : 20739 : resolved_node_id = UNKNOWN_NODEID;
66 : :
67 : 20739 : bool in_middle_of_path = i > 0;
68 : 20739 : if (in_middle_of_path && segment.is_lower_self_seg ())
69 : : {
70 : 1 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
71 : : "%qs in paths can only be used in start position",
72 : 1 : segment.as_string ().c_str ());
73 : 1 : return UNKNOWN_NODEID;
74 : : }
75 : :
76 : 20738 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
77 : 20738 : if (segment.is_crate_path_seg ())
78 : : {
79 : : // what is the current crate scope node id?
80 : 258 : module_scope_id = crate_scope_id;
81 : 258 : previous_resolved_node_id = module_scope_id;
82 : :
83 : 258 : NodeId existing = UNKNOWN_NODEID;
84 : 258 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
85 : : &existing);
86 : :
87 : 258 : if (ok)
88 : 0 : rust_assert (existing == module_scope_id);
89 : : else
90 : 258 : resolver->insert_resolved_name (segment.get_node_id (),
91 : : module_scope_id);
92 : 258 : continue;
93 : 258 : }
94 : 20480 : else if (segment.is_super_path_seg ())
95 : : {
96 : 1 : if (module_scope_id == crate_scope_id)
97 : : {
98 : 0 : rust_error_at (segment.get_locus (),
99 : : "cannot use %<super%> at the crate scope");
100 : 0 : return UNKNOWN_NODEID;
101 : : }
102 : :
103 : 1 : module_scope_id = resolver->peek_parent_module_scope ();
104 : 1 : previous_resolved_node_id = module_scope_id;
105 : :
106 : 1 : NodeId existing = UNKNOWN_NODEID;
107 : 1 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
108 : : &existing);
109 : :
110 : 1 : if (ok)
111 : 0 : rust_assert (existing == module_scope_id);
112 : : else
113 : 1 : resolver->insert_resolved_name (segment.get_node_id (),
114 : : module_scope_id);
115 : 1 : continue;
116 : 1 : }
117 : :
118 : : // resolve any generic args
119 : 20479 : if (segment.has_generic_args ())
120 : 774 : ResolveGenericArgs::go (segment.get_generic_args ());
121 : :
122 : : // logic is awkward here there are a few cases
123 : : //
124 : : // T::Default
125 : : // mod::foo::impl_item
126 : : // super::super::module::item
127 : : // self
128 : : // self::foo
129 : : // self::foo::baz
130 : : //
131 : : // T::Default we can only resolve the T and cant do anything about Default
132 : : // its dependant on associated types
133 : : //
134 : : // mod::foo::impl_item
135 : : // we can resolve mod::foo but nothing about impl_item but we need to
136 : : // _always resolve generic arguments
137 : : //
138 : : // self is a simple single lookup
139 : : //
140 : : // we have module_scope_id for the next module_scope to lookup
141 : : // resolved_node_id is the thing we have resolve this segment to
142 : : //
143 : : // new algo?
144 : : // we can only use module resolution when the previous segment is either
145 : : // unknown or equal to this module_scope_id
146 : : //
147 : : // can only use old resolution when previous segment is unkown
148 : :
149 : 20479 : if (is_first_segment)
150 : : {
151 : : // name scope first
152 : 15534 : NodeId resolved_node = UNKNOWN_NODEID;
153 : 15534 : const CanonicalPath path
154 : : = CanonicalPath::new_seg (segment.get_node_id (),
155 : 15534 : ident_seg.as_string ());
156 : 15534 : if (resolver->get_name_scope ().lookup (path, &resolved_node))
157 : : {
158 : 11239 : NodeId existing = UNKNOWN_NODEID;
159 : 11239 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
160 : : &existing);
161 : :
162 : 11239 : if (ok)
163 : 0 : rust_assert (existing == resolved_node);
164 : : else
165 : 11239 : resolver->insert_resolved_name (segment.get_node_id (),
166 : : resolved_node);
167 : 11239 : resolved_node_id = resolved_node;
168 : : }
169 : : // check the type scope
170 : 4295 : else if (resolver->get_type_scope ().lookup (path, &resolved_node))
171 : : {
172 : 3781 : NodeId existing = UNKNOWN_NODEID;
173 : 3781 : bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
174 : : &existing);
175 : :
176 : 3781 : if (ok)
177 : 27 : rust_assert (existing == resolved_node);
178 : : else
179 : 3754 : resolver->insert_resolved_type (segment.get_node_id (),
180 : : resolved_node);
181 : 3781 : resolved_node_id = resolved_node;
182 : : }
183 : 514 : else if (segment.is_lower_self_seg ())
184 : : {
185 : 9 : module_scope_id = crate_scope_id;
186 : 9 : previous_resolved_node_id = module_scope_id;
187 : :
188 : 9 : NodeId existing = UNKNOWN_NODEID;
189 : 9 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
190 : : &existing);
191 : :
192 : 9 : if (ok)
193 : 0 : rust_assert (existing == module_scope_id);
194 : : else
195 : 9 : resolver->insert_resolved_name (segment.get_node_id (),
196 : : module_scope_id);
197 : 9 : continue;
198 : 9 : }
199 : : else
200 : : {
201 : : // no error handling here since we might be able to resolve via
202 : : // the module hierarchy and handle errors at the end
203 : : }
204 : 15534 : }
205 : :
206 : 20470 : if (resolved_node_id == UNKNOWN_NODEID
207 : 20470 : && previous_resolved_node_id == module_scope_id)
208 : : {
209 : 4361 : tl::optional<CanonicalPath &> resolved_child
210 : 8722 : = mappings.lookup_module_child (module_scope_id,
211 : 4361 : ident_seg.as_string ());
212 : 4361 : if (resolved_child.has_value ())
213 : : {
214 : 4353 : NodeId resolved_node = resolved_child->get_node_id ();
215 : 4353 : if (resolver->get_name_scope ().decl_was_declared_here (
216 : : resolved_node))
217 : : {
218 : 2267 : resolved_node_id = resolved_node;
219 : :
220 : 2267 : NodeId existing = UNKNOWN_NODEID;
221 : 2267 : bool ok
222 : 2267 : = resolver->lookup_resolved_name (segment.get_node_id (),
223 : : &existing);
224 : :
225 : 2267 : if (ok)
226 : 0 : rust_assert (existing == resolved_node);
227 : : else
228 : 2267 : resolver->insert_resolved_name (segment.get_node_id (),
229 : : resolved_node);
230 : : }
231 : 2086 : else if (resolver->get_type_scope ().decl_was_declared_here (
232 : : resolved_node))
233 : : {
234 : 2086 : resolved_node_id = resolved_node;
235 : :
236 : 2086 : NodeId existing = UNKNOWN_NODEID;
237 : 2086 : bool ok
238 : 2086 : = resolver->lookup_resolved_type (segment.get_node_id (),
239 : : &existing);
240 : :
241 : 2086 : if (ok)
242 : 27 : rust_assert (existing == resolved_node);
243 : : else
244 : 2059 : resolver->insert_resolved_type (segment.get_node_id (),
245 : : resolved_node);
246 : : }
247 : : else
248 : : {
249 : 0 : rust_error_at (segment.get_locus (),
250 : : "Cannot find path %<%s%> in this scope",
251 : 0 : segment.as_string ().c_str ());
252 : 0 : return UNKNOWN_NODEID;
253 : : }
254 : : }
255 : : }
256 : :
257 : 20470 : bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
258 : 20470 : if (did_resolve_segment)
259 : : {
260 : 19373 : if (mappings.node_is_module (resolved_node_id)
261 : 19373 : || mappings.node_is_crate (resolved_node_id))
262 : : {
263 : : module_scope_id = resolved_node_id;
264 : : }
265 : : previous_resolved_node_id = resolved_node_id;
266 : : }
267 : 1097 : else if (is_first_segment)
268 : : {
269 : 2 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
270 : : "Cannot find path %<%s%> in this scope",
271 : 2 : segment.as_string ().c_str ());
272 : 2 : return UNKNOWN_NODEID;
273 : : }
274 : : }
275 : :
276 : 15790 : resolved_node = resolved_node_id;
277 : 15790 : if (resolved_node_id != UNKNOWN_NODEID)
278 : : {
279 : : // name scope first
280 : 14697 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
281 : : {
282 : 11376 : NodeId existing = UNKNOWN_NODEID;
283 : 11376 : bool ok
284 : 11376 : = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
285 : :
286 : 11376 : if (ok)
287 : 0 : rust_assert (existing == resolved_node_id);
288 : : else
289 : 11376 : resolver->insert_resolved_name (expr.get_node_id (),
290 : : resolved_node_id);
291 : : }
292 : : // check the type scope
293 : 3321 : else if (resolver->get_type_scope ().decl_was_declared_here (
294 : : resolved_node_id))
295 : : {
296 : 3321 : NodeId existing = UNKNOWN_NODEID;
297 : 3321 : bool ok
298 : 3321 : = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
299 : :
300 : 3321 : if (ok)
301 : 0 : rust_assert (existing == resolved_node_id);
302 : : else
303 : 3321 : resolver->insert_resolved_type (expr.get_node_id (),
304 : : resolved_node_id);
305 : : }
306 : : else
307 : : {
308 : 0 : rust_unreachable ();
309 : : }
310 : : }
311 : : return resolved_node_id;
312 : : }
313 : :
314 : : NodeId
315 : 114 : ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr)
316 : : {
317 : 114 : auto &root_segment = expr.get_qualified_path_type ();
318 : 114 : ResolveType::go (root_segment.get_type ());
319 : 114 : if (root_segment.has_as_clause ())
320 : 80 : ResolveType::go (root_segment.get_as_type_path ());
321 : :
322 : 228 : for (auto &segment : expr.get_segments ())
323 : : {
324 : : // we cant actually do anything with the segment itself since this is all
325 : : // the job of the type system to figure it out but we can resolve any
326 : : // generic arguments used
327 : 228 : if (segment.has_generic_args ())
328 : 0 : ResolveGenericArgs::go (segment.get_generic_args ());
329 : : }
330 : :
331 : : // cannot fully resolve a qualified path as it is dependant on associated
332 : : // items
333 : 114 : return UNKNOWN_NODEID;
334 : : }
335 : :
336 : : NodeId
337 : 333 : ResolvePath::resolve_path (AST::SimplePath &expr)
338 : : {
339 : 333 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
340 : 333 : NodeId module_scope_id = resolver->peek_current_module_scope ();
341 : :
342 : 333 : NodeId previous_resolved_node_id = UNKNOWN_NODEID;
343 : 333 : NodeId resolved_node_id = UNKNOWN_NODEID;
344 : 1160 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
345 : : {
346 : 831 : AST::SimplePathSegment &segment = expr.get_segments ().at (i);
347 : 831 : bool is_first_segment = i == 0;
348 : 831 : bool is_final_segment = i >= (expr.get_segments ().size () - 1);
349 : 831 : resolved_node_id = UNKNOWN_NODEID;
350 : :
351 : 831 : if (segment.is_crate_path_seg ())
352 : : {
353 : : // what is the current crate scope node id?
354 : 5 : module_scope_id = crate_scope_id;
355 : 5 : previous_resolved_node_id = module_scope_id;
356 : :
357 : 5 : NodeId existing = UNKNOWN_NODEID;
358 : 5 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
359 : : &existing);
360 : :
361 : 5 : if (ok)
362 : 0 : rust_assert (existing == module_scope_id);
363 : : else
364 : 5 : resolver->insert_resolved_name (segment.get_node_id (),
365 : : module_scope_id);
366 : 5 : resolved_node_id = module_scope_id;
367 : :
368 : 5 : continue;
369 : 5 : }
370 : 826 : else if (segment.is_super_path_seg ())
371 : : {
372 : 125 : if (!is_first_segment)
373 : : {
374 : 1 : rust_error_at (
375 : : segment.get_locus (), ErrorCode::E0433,
376 : : "%<super%> in paths can only be used in start position");
377 : 1 : return UNKNOWN_NODEID;
378 : : }
379 : 124 : 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 : 124 : module_scope_id = resolver->peek_parent_module_scope ();
387 : 124 : previous_resolved_node_id = module_scope_id;
388 : :
389 : 124 : NodeId existing = UNKNOWN_NODEID;
390 : 124 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
391 : : &existing);
392 : :
393 : 124 : if (ok)
394 : 0 : rust_assert (existing == module_scope_id);
395 : : else
396 : 124 : resolver->insert_resolved_name (segment.get_node_id (),
397 : : module_scope_id);
398 : 124 : resolved_node_id = module_scope_id;
399 : :
400 : 124 : continue;
401 : 124 : }
402 : :
403 : 701 : tl::optional<CanonicalPath &> resolved_child
404 : 701 : = mappings.lookup_module_child (module_scope_id,
405 : : segment.get_segment_name ());
406 : 701 : if (resolved_child.has_value ())
407 : : {
408 : 616 : NodeId resolved_node = resolved_child->get_node_id ();
409 : 616 : if (resolver->get_name_scope ().decl_was_declared_here (
410 : : resolved_node))
411 : : {
412 : 211 : resolved_node_id = resolved_node;
413 : :
414 : 211 : NodeId existing = UNKNOWN_NODEID;
415 : 211 : bool ok = resolver->lookup_resolved_name (segment.get_node_id (),
416 : : &existing);
417 : :
418 : 211 : if (ok)
419 : 0 : rust_assert (existing == resolved_node);
420 : : else
421 : 211 : resolver->insert_resolved_name (segment.get_node_id (),
422 : : resolved_node);
423 : : }
424 : 405 : else if (resolver->get_type_scope ().decl_was_declared_here (
425 : : resolved_node))
426 : : {
427 : 405 : resolved_node_id = resolved_node;
428 : :
429 : 405 : NodeId existing = UNKNOWN_NODEID;
430 : 405 : bool ok = resolver->lookup_resolved_type (segment.get_node_id (),
431 : : &existing);
432 : :
433 : 405 : if (ok)
434 : 0 : rust_assert (existing == resolved_node);
435 : : else
436 : 405 : 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 : 701 : if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
449 : : {
450 : : // name scope first
451 : 31 : NodeId resolved_node = UNKNOWN_NODEID;
452 : 31 : const CanonicalPath path
453 : : = CanonicalPath::new_seg (segment.get_node_id (),
454 : 31 : segment.get_segment_name ());
455 : 31 : 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 : 25 : 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 : 31 : }
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 : 701 : if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
499 : 701 : && is_final_segment && segment.is_lower_self_seg ())
500 : : resolved_node_id = previous_resolved_node_id;
501 : :
502 : : // final check
503 : 701 : if (resolved_node_id == UNKNOWN_NODEID)
504 : : {
505 : 3 : rust_error_at (segment.get_locus (),
506 : : "cannot find simple path segment %<%s%> in this scope",
507 : 3 : segment.as_string ().c_str ());
508 : 3 : return UNKNOWN_NODEID;
509 : : }
510 : :
511 : 698 : if (mappings.node_is_module (resolved_node_id))
512 : : {
513 : 441 : module_scope_id = resolved_node_id;
514 : : }
515 : :
516 : 698 : previous_resolved_node_id = resolved_node_id;
517 : : }
518 : :
519 : 329 : resolved_node = resolved_node_id;
520 : 329 : if (resolved_node_id != UNKNOWN_NODEID)
521 : : {
522 : : // name scope first
523 : 329 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
524 : : {
525 : 30 : NodeId existing = UNKNOWN_NODEID;
526 : 30 : bool ok
527 : 30 : = resolver->lookup_resolved_name (expr.get_node_id (), &existing);
528 : :
529 : 30 : if (ok)
530 : 0 : rust_assert (existing == resolved_node_id);
531 : : else
532 : 30 : resolver->insert_resolved_name (expr.get_node_id (),
533 : : resolved_node_id);
534 : : }
535 : : // check the type scope
536 : 299 : else if (resolver->get_type_scope ().decl_was_declared_here (
537 : : resolved_node_id))
538 : : {
539 : 299 : NodeId existing = UNKNOWN_NODEID;
540 : 299 : bool ok
541 : 299 : = resolver->lookup_resolved_type (expr.get_node_id (), &existing);
542 : :
543 : 299 : if (ok)
544 : 0 : rust_assert (existing == resolved_node_id);
545 : : else
546 : 299 : 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
|