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-path.h"
22 : :
23 : : namespace Rust {
24 : : namespace Resolver {
25 : :
26 : 11497 : ResolvePath::ResolvePath () : ResolverBase () {}
27 : :
28 : : NodeId
29 : 11324 : ResolvePath::go (AST::PathInExpression &expr)
30 : : {
31 : 11324 : ResolvePath resolver;
32 : 11324 : return resolver.resolve_path (expr);
33 : 11324 : }
34 : :
35 : : NodeId
36 : 80 : ResolvePath::go (AST::QualifiedPathInExpression &expr)
37 : : {
38 : 80 : ResolvePath resolver;
39 : 80 : return resolver.resolve_path (expr);
40 : 80 : }
41 : :
42 : : NodeId
43 : 93 : ResolvePath::go (AST::SimplePath &expr)
44 : : {
45 : 93 : ResolvePath resolver;
46 : 93 : return resolver.resolve_path (expr);
47 : 93 : }
48 : :
49 : : NodeId
50 : 11324 : ResolvePath::resolve_path (AST::PathInExpression &expr)
51 : : {
52 : 11324 : NodeId resolved_node_id = UNKNOWN_NODEID;
53 : 11324 : NodeId module_scope_id = resolver->peek_current_module_scope ();
54 : 11324 : NodeId previous_resolved_node_id = module_scope_id;
55 : 25176 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
56 : : {
57 : 13855 : auto &segment = expr.get_segments ().at (i);
58 : 13855 : const AST::PathIdentSegment &ident_seg = segment.get_ident_segment ();
59 : 13855 : bool is_first_segment = i == 0;
60 : 13855 : resolved_node_id = UNKNOWN_NODEID;
61 : :
62 : 13855 : bool in_middle_of_path = i > 0;
63 : 13855 : if (in_middle_of_path && segment.is_lower_self_seg ())
64 : : {
65 : 1 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
66 : : "failed to resolve: %qs in paths can only be used "
67 : : "in start position",
68 : 1 : segment.as_string ().c_str ());
69 : 1 : return UNKNOWN_NODEID;
70 : : }
71 : :
72 : 13854 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
73 : 13854 : if (segment.is_crate_path_seg ())
74 : : {
75 : : // what is the current crate scope node id?
76 : 7 : module_scope_id = crate_scope_id;
77 : 7 : previous_resolved_node_id = module_scope_id;
78 : 7 : resolver->insert_resolved_name (segment.get_node_id (),
79 : : module_scope_id);
80 : 7 : continue;
81 : : }
82 : 13847 : else if (segment.is_super_path_seg ())
83 : : {
84 : 1 : if (module_scope_id == crate_scope_id)
85 : : {
86 : 0 : rust_error_at (segment.get_locus (),
87 : : "cannot use %<super%> at the crate scope");
88 : 0 : return UNKNOWN_NODEID;
89 : : }
90 : :
91 : 1 : module_scope_id = resolver->peek_parent_module_scope ();
92 : 1 : previous_resolved_node_id = module_scope_id;
93 : 1 : resolver->insert_resolved_name (segment.get_node_id (),
94 : : module_scope_id);
95 : 1 : continue;
96 : : }
97 : :
98 : : // resolve any generic args
99 : 13846 : if (segment.has_generic_args ())
100 : 570 : ResolveGenericArgs::go (segment.get_generic_args ());
101 : :
102 : : // logic is awkward here there are a few cases
103 : : //
104 : : // T::Default
105 : : // mod::foo::impl_item
106 : : // super::super::module::item
107 : : // self
108 : : // self::foo
109 : : // self::foo::baz
110 : : //
111 : : // T::Default we can only resolve the T and cant do anything about Default
112 : : // its dependant on associated types
113 : : //
114 : : // mod::foo::impl_item
115 : : // we can resolve mod::foo but nothing about impl_item but we need to
116 : : // _always resolve generic arguments
117 : : //
118 : : // self is a simple single lookup
119 : : //
120 : : // we have module_scope_id for the next module_scope to lookup
121 : : // resolved_node_id is the thing we have resolve this segment to
122 : : //
123 : : // new algo?
124 : : // we can only use module resolution when the previous segment is either
125 : : // unknown or equal to this module_scope_id
126 : : //
127 : : // can only use old resolution when previous segment is unkown
128 : :
129 : 13846 : if (is_first_segment)
130 : : {
131 : : // name scope first
132 : 11316 : NodeId resolved_node = UNKNOWN_NODEID;
133 : 11316 : const CanonicalPath path
134 : : = CanonicalPath::new_seg (segment.get_node_id (),
135 : 11316 : ident_seg.as_string ());
136 : 11316 : if (resolver->get_name_scope ().lookup (path, &resolved_node))
137 : : {
138 : 8207 : resolver->insert_resolved_name (segment.get_node_id (),
139 : : resolved_node);
140 : 8207 : resolved_node_id = resolved_node;
141 : : }
142 : : // check the type scope
143 : 3109 : else if (resolver->get_type_scope ().lookup (path, &resolved_node))
144 : : {
145 : 2908 : resolver->insert_resolved_type (segment.get_node_id (),
146 : : resolved_node);
147 : 2908 : resolved_node_id = resolved_node;
148 : : }
149 : 201 : else if (segment.is_lower_self_seg ())
150 : : {
151 : 9 : module_scope_id = crate_scope_id;
152 : 9 : previous_resolved_node_id = module_scope_id;
153 : 9 : resolver->insert_resolved_name (segment.get_node_id (),
154 : : module_scope_id);
155 : 9 : continue;
156 : : }
157 : : else
158 : : {
159 : : // no error handling here since we might be able to resolve via
160 : : // the module hierarchy and handle errors at the end
161 : : }
162 : 11316 : }
163 : :
164 : 13837 : if (resolved_node_id == UNKNOWN_NODEID
165 : 13837 : && previous_resolved_node_id == module_scope_id)
166 : : {
167 : 1922 : tl::optional<CanonicalPath &> resolved_child
168 : 3844 : = mappings->lookup_module_child (module_scope_id,
169 : 1922 : ident_seg.as_string ());
170 : 1922 : if (resolved_child.has_value ())
171 : : {
172 : 1918 : NodeId resolved_node = resolved_child->get_node_id ();
173 : 1918 : if (resolver->get_name_scope ().decl_was_declared_here (
174 : : resolved_node))
175 : : {
176 : 959 : resolved_node_id = resolved_node;
177 : 959 : resolver->insert_resolved_name (segment.get_node_id (),
178 : : resolved_node);
179 : : }
180 : 959 : else if (resolver->get_type_scope ().decl_was_declared_here (
181 : : resolved_node))
182 : : {
183 : 959 : resolved_node_id = resolved_node;
184 : 959 : resolver->insert_resolved_type (segment.get_node_id (),
185 : : resolved_node);
186 : : }
187 : : else
188 : : {
189 : 0 : rust_error_at (segment.get_locus (),
190 : : "Cannot find path %qs in this scope",
191 : 0 : segment.as_string ().c_str ());
192 : 0 : return UNKNOWN_NODEID;
193 : : }
194 : : }
195 : : }
196 : :
197 : 13837 : bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID;
198 : 13837 : if (did_resolve_segment)
199 : : {
200 : 13033 : if (mappings->node_is_module (resolved_node_id)
201 : 13033 : || mappings->node_is_crate (resolved_node_id))
202 : : {
203 : : module_scope_id = resolved_node_id;
204 : : }
205 : : previous_resolved_node_id = resolved_node_id;
206 : : }
207 : 804 : else if (is_first_segment)
208 : : {
209 : 2 : rust_error_at (segment.get_locus (), ErrorCode::E0433,
210 : : "Cannot find path %qs in this scope",
211 : 2 : segment.as_string ().c_str ());
212 : 2 : return UNKNOWN_NODEID;
213 : : }
214 : : }
215 : :
216 : 11321 : resolved_node = resolved_node_id;
217 : 11321 : if (resolved_node_id != UNKNOWN_NODEID)
218 : : {
219 : : // name scope first
220 : 10519 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
221 : : {
222 : 8183 : resolver->insert_resolved_name (expr.get_node_id (),
223 : : resolved_node_id);
224 : : }
225 : : // check the type scope
226 : 2336 : else if (resolver->get_type_scope ().decl_was_declared_here (
227 : : resolved_node_id))
228 : : {
229 : 2336 : resolver->insert_resolved_type (expr.get_node_id (),
230 : : resolved_node_id);
231 : : }
232 : : else
233 : : {
234 : 0 : rust_unreachable ();
235 : : }
236 : : }
237 : : return resolved_node_id;
238 : : }
239 : :
240 : : NodeId
241 : 80 : ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr)
242 : : {
243 : 80 : auto &root_segment = expr.get_qualified_path_type ();
244 : 80 : ResolveType::go (root_segment.get_type ());
245 : 80 : if (root_segment.has_as_clause ())
246 : 63 : ResolveType::go (root_segment.get_as_type_path ());
247 : :
248 : 160 : for (auto &segment : expr.get_segments ())
249 : : {
250 : : // we cant actually do anything with the segment itself since this is all
251 : : // the job of the type system to figure it out but we can resolve any
252 : : // generic arguments used
253 : 160 : if (segment.has_generic_args ())
254 : 0 : ResolveGenericArgs::go (segment.get_generic_args ());
255 : : }
256 : :
257 : : // cannot fully resolve a qualified path as it is dependant on associated
258 : : // items
259 : 80 : return UNKNOWN_NODEID;
260 : : }
261 : :
262 : : NodeId
263 : 93 : ResolvePath::resolve_path (AST::SimplePath &expr)
264 : : {
265 : 93 : NodeId crate_scope_id = resolver->peek_crate_module_scope ();
266 : 93 : NodeId module_scope_id = resolver->peek_current_module_scope ();
267 : :
268 : 93 : NodeId previous_resolved_node_id = UNKNOWN_NODEID;
269 : 93 : NodeId resolved_node_id = UNKNOWN_NODEID;
270 : 325 : for (size_t i = 0; i < expr.get_segments ().size (); i++)
271 : : {
272 : 239 : AST::SimplePathSegment &segment = expr.get_segments ().at (i);
273 : 239 : bool is_first_segment = i == 0;
274 : 239 : bool is_final_segment = i >= (expr.get_segments ().size () - 1);
275 : 239 : resolved_node_id = UNKNOWN_NODEID;
276 : :
277 : 239 : if (segment.is_crate_path_seg ())
278 : : {
279 : : // what is the current crate scope node id?
280 : 1 : module_scope_id = crate_scope_id;
281 : 1 : previous_resolved_node_id = module_scope_id;
282 : 1 : resolver->insert_resolved_name (segment.get_node_id (),
283 : : module_scope_id);
284 : 1 : resolved_node_id = module_scope_id;
285 : :
286 : 232 : continue;
287 : : }
288 : 238 : else if (segment.is_super_path_seg ())
289 : : {
290 : 1 : if (module_scope_id == crate_scope_id)
291 : : {
292 : 0 : rust_error_at (segment.get_locus (),
293 : : "cannot use %<super%> at the crate scope");
294 : 0 : return UNKNOWN_NODEID;
295 : : }
296 : :
297 : 1 : module_scope_id = resolver->peek_parent_module_scope ();
298 : 1 : previous_resolved_node_id = module_scope_id;
299 : 1 : resolver->insert_resolved_name (segment.get_node_id (),
300 : : module_scope_id);
301 : 1 : resolved_node_id = module_scope_id;
302 : :
303 : 1 : continue;
304 : : }
305 : :
306 : 237 : tl::optional<CanonicalPath &> resolved_child
307 : 237 : = mappings->lookup_module_child (module_scope_id,
308 : : segment.get_segment_name ());
309 : 237 : if (resolved_child.has_value ())
310 : : {
311 : 196 : NodeId resolved_node = resolved_child->get_node_id ();
312 : 196 : if (resolver->get_name_scope ().decl_was_declared_here (
313 : : resolved_node))
314 : : {
315 : 90 : resolved_node_id = resolved_node;
316 : 90 : resolver->insert_resolved_name (segment.get_node_id (),
317 : : resolved_node);
318 : : }
319 : 106 : else if (resolver->get_type_scope ().decl_was_declared_here (
320 : : resolved_node))
321 : : {
322 : 106 : resolved_node_id = resolved_node;
323 : 106 : resolver->insert_resolved_type (segment.get_node_id (),
324 : : resolved_node);
325 : : }
326 : : else
327 : : {
328 : 0 : rust_error_at (segment.get_locus (),
329 : : "Cannot find path %qs in this scope",
330 : 0 : segment.as_string ().c_str ());
331 : 0 : return UNKNOWN_NODEID;
332 : : }
333 : : }
334 : :
335 : 237 : if (resolved_node_id == UNKNOWN_NODEID && is_first_segment)
336 : : {
337 : : // name scope first
338 : 17 : NodeId resolved_node = UNKNOWN_NODEID;
339 : 17 : const CanonicalPath path
340 : : = CanonicalPath::new_seg (segment.get_node_id (),
341 : 17 : segment.get_segment_name ());
342 : 17 : if (resolver->get_name_scope ().lookup (path, &resolved_node))
343 : : {
344 : 6 : resolved_node_id = resolved_node;
345 : 6 : resolver->insert_resolved_name (segment.get_node_id (),
346 : : resolved_node);
347 : : }
348 : : // check the type scope
349 : 11 : else if (resolver->get_type_scope ().lookup (path, &resolved_node))
350 : : {
351 : 8 : resolved_node_id = resolved_node;
352 : 8 : resolver->insert_resolved_type (segment.get_node_id (),
353 : : resolved_node);
354 : : }
355 : 17 : }
356 : :
357 : : // if we still have not resolved and this is the final segment and the
358 : : // final segment is self its likely the case: pub use
359 : : //
360 : : // result::Result::{self, Err, Ok};
361 : : //
362 : : // Then the resolved_node_id is just the previous one so long as it is a
363 : : // resolved node id
364 : : // rust_debug_loc (segment.get_locus (),
365 : : // "trying to resolve seg: [%s] first [%s] last [%s]",
366 : : // segment.get_segment_name ().c_str (),
367 : : // is_first_segment ? "true" : "false",
368 : : // is_final_segment ? "true" : "false");
369 : 237 : if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
370 : 237 : && is_final_segment && segment.is_lower_self_seg ())
371 : : resolved_node_id = previous_resolved_node_id;
372 : :
373 : : // final check
374 : 237 : if (resolved_node_id == UNKNOWN_NODEID)
375 : : {
376 : 7 : rust_error_at (segment.get_locus (),
377 : : "cannot find simple path segment %qs in this scope",
378 : 7 : segment.as_string ().c_str ());
379 : 7 : return UNKNOWN_NODEID;
380 : : }
381 : :
382 : 230 : if (mappings->node_is_module (resolved_node_id))
383 : : {
384 : 172 : module_scope_id = resolved_node_id;
385 : : }
386 : :
387 : : previous_resolved_node_id = resolved_node_id;
388 : : }
389 : :
390 : 86 : resolved_node = resolved_node_id;
391 : 86 : if (resolved_node_id != UNKNOWN_NODEID)
392 : : {
393 : : // name scope first
394 : 86 : if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id))
395 : : {
396 : 22 : resolver->insert_resolved_name (expr.get_node_id (),
397 : : resolved_node_id);
398 : : }
399 : : // check the type scope
400 : 64 : else if (resolver->get_type_scope ().decl_was_declared_here (
401 : : resolved_node_id))
402 : : {
403 : 64 : resolver->insert_resolved_type (expr.get_node_id (),
404 : : resolved_node_id);
405 : : }
406 : : else
407 : : {
408 : 0 : rust_unreachable ();
409 : : }
410 : : }
411 : : return resolved_node_id;
412 : : }
413 : :
414 : : } // namespace Resolver
415 : : } // namespace Rust
|