Line data Source code
1 : // Copyright (C) 2020-2026 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-name-resolution-context.h"
20 : #include "optional.h"
21 : #include "rust-mapping-common.h"
22 : #include "rust-rib.h"
23 : #include "rust-system.h"
24 :
25 : namespace Rust {
26 : namespace Resolver2_0 {
27 :
28 100005 : BindingLayer::BindingLayer (BindingSource source) : source (source)
29 : {
30 100005 : push (Binding::Kind::Product);
31 100005 : }
32 :
33 : bool
34 91362 : BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
35 : {
36 183070 : for (auto &bind : bindings)
37 : {
38 91775 : if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
39 91775 : && bind.kind == kind)
40 : {
41 91362 : return true;
42 : }
43 : }
44 : return false;
45 : }
46 :
47 : void
48 100736 : BindingLayer::push (Binding::Kind kind)
49 : {
50 100736 : bindings.push_back (Binding (kind));
51 100736 : }
52 :
53 : bool
54 45685 : BindingLayer::is_and_bound (Identifier ident)
55 : {
56 45685 : return bind_test (ident, Binding::Kind::Product);
57 : }
58 :
59 : bool
60 45677 : BindingLayer::is_or_bound (Identifier ident)
61 : {
62 45677 : return bind_test (ident, Binding::Kind::Or);
63 : }
64 :
65 : void
66 45677 : BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
67 : bool is_mut)
68 : {
69 45677 : bindings.back ().idents.emplace (
70 45677 : std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
71 45677 : }
72 :
73 : void
74 731 : BindingLayer::merge ()
75 : {
76 731 : auto last_binding = std::move (bindings.back ());
77 731 : bindings.pop_back ();
78 :
79 731 : if (bindings.back ().has_expected_bindings)
80 : {
81 330 : for (auto &value : bindings.back ().idents)
82 : {
83 59 : auto ident = value.first;
84 59 : if (last_binding.idents.find (ident) == last_binding.idents.end ())
85 : {
86 0 : location_t locus = value.second.first;
87 0 : rust_error_at (locus, ErrorCode::E0408,
88 : "variable %qs is not bound in all patterns",
89 : ident.c_str ());
90 : }
91 59 : }
92 : }
93 :
94 908 : for (auto &value : last_binding.idents)
95 : {
96 177 : auto res = bindings.back ().idents.emplace (value);
97 177 : if (res.second)
98 : {
99 118 : if (bindings.back ().has_expected_bindings)
100 : {
101 14 : auto &ident = value.first;
102 14 : location_t locus = value.second.first;
103 14 : rust_error_at (locus, ErrorCode::E0408,
104 : "variable %qs is not bound in all patterns",
105 : ident.c_str ());
106 : }
107 : }
108 : else
109 : {
110 59 : auto this_mode = value.second.second;
111 59 : auto other_mode = res.first->second.second;
112 236 : if (this_mode != other_mode)
113 : {
114 7 : auto &ident = value.first;
115 7 : location_t locus = value.second.first;
116 7 : rust_error_at (locus, ErrorCode::E0409,
117 : "variable %qs is bound inconsistently across "
118 : "pattern alternatives",
119 : ident.c_str ());
120 : }
121 : }
122 : }
123 :
124 731 : if (bindings.back ().kind == Binding::Kind::Or)
125 501 : bindings.back ().has_expected_bindings = true;
126 731 : }
127 :
128 : BindingSource
129 8 : BindingLayer::get_source () const
130 : {
131 8 : return source;
132 : }
133 :
134 : Resolver::CanonicalPath
135 76239 : CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &,
136 : Namespace ns)
137 : {
138 152478 : auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
139 76239 : ret.set_crate_num (crate_num);
140 76239 : return ret;
141 : }
142 :
143 : Resolver::CanonicalPath
144 136171 : CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx,
145 : Namespace ns)
146 : {
147 136171 : auto &parent = ctx.canonical_ctx.get_record (get_parent ());
148 136171 : auto parent_path = parent.as_path (ctx, ns);
149 272342 : return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
150 136171 : }
151 :
152 : Resolver::CanonicalPath
153 27831 : CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx,
154 : Namespace ns)
155 : {
156 27831 : if (!cache)
157 : {
158 : // TODO: what namespace do we use here? can the caller give one?
159 17428 : auto res = ctx.lookup (lookup_id, ns).and_then ([&ctx] (NodeId id) {
160 9396 : return ctx.canonical_ctx.get_record_opt (id);
161 : });
162 :
163 17428 : if (!res)
164 : {
165 : // HACK: use a dummy value
166 : // this should bring us roughly to parity with nr1.0
167 : // since nr1.0 doesn't seem to handle canonical paths for generics
168 : // quite right anyways
169 12380 : return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
170 : }
171 :
172 5048 : cache = res.value ();
173 : }
174 15451 : return cache->as_path (ctx, ns);
175 : }
176 :
177 : Resolver::CanonicalPath
178 6963 : CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx,
179 : Namespace ns)
180 : {
181 6963 : auto parent_path
182 6963 : = ctx.canonical_ctx.get_record (get_parent ()).as_path (ctx, ns);
183 6963 : return parent_path.append (
184 13926 : Resolver::CanonicalPath::inherent_impl_seg (impl_id,
185 20889 : type_record.as_path (ctx, ns)));
186 6963 : }
187 :
188 : Resolver::CanonicalPath
189 10434 : CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx,
190 : Namespace ns)
191 : {
192 : // Maybe this doesn't need the namespace and will always be in the types NS?
193 10434 : auto parent_path
194 10434 : = ctx.canonical_ctx.get_record (get_parent ()).as_path (ctx, ns);
195 10434 : return parent_path.append (
196 20868 : Resolver::CanonicalPath::trait_impl_projection_seg (
197 20868 : impl_id, trait_path_record.as_path (ctx, ns),
198 31302 : type_record.as_path (ctx, ns)));
199 10434 : }
200 :
201 4869 : NameResolutionContext::NameResolutionContext ()
202 4869 : : root (std::make_unique<Node> (Rib::Kind::Normal, UNKNOWN_NODEID)),
203 4869 : lang_prelude (
204 4869 : std::make_unique<Node> (Rib::Kind::Prelude, UNKNOWN_NODEID, *root)),
205 4869 : extern_prelude (
206 4869 : std::make_unique<Node> (Rib::Kind::Prelude, UNKNOWN_NODEID)),
207 4869 : values (*root, *lang_prelude, *extern_prelude),
208 4869 : types (*root, *lang_prelude, *extern_prelude),
209 4869 : macros (*root, *lang_prelude, *extern_prelude),
210 4869 : labels (*root, *lang_prelude, *extern_prelude),
211 4869 : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
212 4869 : {}
213 :
214 : tl::expected<NodeId, DuplicateNameError>
215 1268254 : NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
216 : {
217 1268254 : switch (ns)
218 : {
219 547758 : case Namespace::Values:
220 547758 : return values.insert (name, id);
221 718442 : case Namespace::Types:
222 718442 : return types.insert (name, id);
223 2054 : case Namespace::Macros:
224 2054 : return macros.insert (name, id);
225 0 : case Namespace::Labels:
226 0 : default:
227 0 : return labels.insert (name, id);
228 : rust_unreachable ();
229 : }
230 : }
231 :
232 : tl::expected<NodeId, DuplicateNameError>
233 7606 : NameResolutionContext::insert_variant (Identifier name, NodeId id,
234 : bool is_also_value)
235 : {
236 7606 : auto res = types.insert_variant (name, id);
237 7606 : if (res.has_value () && is_also_value)
238 1301 : res = values.insert_variant (name, id);
239 7606 : return res;
240 : }
241 :
242 : tl::expected<NodeId, DuplicateNameError>
243 0 : NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
244 : Namespace ns)
245 : {
246 0 : switch (ns)
247 : {
248 0 : case Namespace::Values:
249 0 : return values.insert_shadowable (name, id);
250 0 : case Namespace::Types:
251 0 : return types.insert_shadowable (name, id);
252 0 : case Namespace::Macros:
253 0 : return macros.insert_shadowable (name, id);
254 0 : case Namespace::Labels:
255 0 : return labels.insert (name, id);
256 0 : default:
257 0 : rust_unreachable ();
258 : }
259 : }
260 :
261 : tl::expected<NodeId, DuplicateNameError>
262 0 : NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
263 : {
264 0 : switch (ns)
265 : {
266 0 : case Namespace::Values:
267 0 : return values.insert_globbed (name, id);
268 0 : case Namespace::Types:
269 0 : return types.insert_globbed (name, id);
270 0 : case Namespace::Macros:
271 0 : return macros.insert_globbed (name, id);
272 0 : case Namespace::Labels:
273 0 : return labels.insert (name, id);
274 0 : default:
275 0 : rust_unreachable ();
276 : }
277 : }
278 :
279 : // TODO: Maybe this should take a NamespacedDefinition as argument?
280 : void
281 772387 : NameResolutionContext::map_usage (Usage usage, Definition definition,
282 : Namespace ns)
283 : {
284 772387 : switch (ns)
285 : {
286 356320 : case Namespace::Values:
287 356320 : values.map_usage (usage, definition);
288 356320 : break;
289 366807 : case Namespace::Types:
290 366807 : types.map_usage (usage, definition);
291 366807 : break;
292 45 : case Namespace::Labels:
293 45 : labels.map_usage (usage, definition);
294 45 : break;
295 49215 : case Namespace::Macros:
296 49215 : macros.map_usage (usage, definition);
297 49215 : break;
298 : }
299 772387 : }
300 :
301 : tl::optional<NodeId>
302 3259834 : NameResolutionContext::lookup (NodeId usage, Namespace ns) const
303 : {
304 3259834 : switch (ns)
305 : {
306 320505 : case Namespace::Values:
307 320505 : return values.lookup (usage);
308 2939189 : case Namespace::Types:
309 2939189 : return types.lookup (usage);
310 140 : case Namespace::Labels:
311 140 : return labels.lookup (usage);
312 0 : case Namespace::Macros:
313 0 : return macros.lookup (usage);
314 0 : default:
315 0 : rust_unreachable ();
316 : }
317 : }
318 :
319 : tl::optional<NameResolutionContext::NSLookup>
320 198147 : NameResolutionContext::lookup (NodeId usage, Namespace ns1, Namespace ns2) const
321 : {
322 198147 : if (auto result = lookup (usage, ns1))
323 133877 : return NSLookup (*result, ns1);
324 :
325 64270 : return lookup (usage, ns2).map ([&ns2] (NodeId id) {
326 60403 : return NSLookup (id, ns2);
327 : });
328 : }
329 :
330 : tl::optional<NameResolutionContext::NSLookup>
331 0 : NameResolutionContext::lookup (NodeId usage, Namespace ns1, Namespace ns2,
332 : Namespace ns3) const
333 : {
334 0 : if (auto result = lookup (usage, ns1, ns2))
335 0 : return result;
336 :
337 0 : return lookup (usage, ns3).map ([&ns3] (NodeId id) {
338 0 : return NSLookup (id, ns3);
339 : });
340 : }
341 :
342 : void
343 7686477 : NameResolutionContext::scoped (Rib::Kind rib_kind, NodeId id,
344 : std::function<void (void)> lambda,
345 : tl::optional<Identifier> path)
346 : {
347 : // NOTE: You must be at the root node when pushing the prelude rib.
348 7686477 : values.push (rib_kind, id, path);
349 7686477 : types.push (rib_kind, id, path);
350 7686477 : macros.push (rib_kind, id, path);
351 7686477 : labels.push (rib_kind, id, path);
352 :
353 7686477 : lambda ();
354 :
355 7686468 : values.pop ();
356 7686468 : types.pop ();
357 7686468 : macros.pop ();
358 7686468 : labels.pop ();
359 7686468 : }
360 :
361 : void
362 0 : NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns,
363 : NodeId scope_id,
364 : std::function<void (void)> lambda,
365 : tl::optional<Identifier> path)
366 : {
367 : // This could work... I'm not sure why you would want to do this though.
368 0 : rust_assert (rib_kind != Rib::Kind::Prelude);
369 :
370 0 : switch (ns)
371 : {
372 0 : case Namespace::Values:
373 0 : values.push (rib_kind, scope_id, path);
374 0 : break;
375 0 : case Namespace::Types:
376 0 : types.push (rib_kind, scope_id, path);
377 0 : break;
378 0 : case Namespace::Labels:
379 0 : labels.push (rib_kind, scope_id, path);
380 0 : break;
381 0 : case Namespace::Macros:
382 0 : gcc_unreachable ();
383 : }
384 :
385 0 : lambda ();
386 :
387 0 : switch (ns)
388 : {
389 0 : case Namespace::Values:
390 0 : values.pop ();
391 0 : break;
392 0 : case Namespace::Types:
393 0 : types.pop ();
394 0 : break;
395 0 : case Namespace::Labels:
396 0 : labels.pop ();
397 0 : break;
398 : case Namespace::Macros:
399 : gcc_unreachable ();
400 : }
401 0 : }
402 :
403 : void
404 24 : NameResolutionContext::merge (NameResolutionContext &other, NodeId at)
405 : {
406 : // TODO: merge once, for all namespaces at once
407 :
408 120 : auto merge_fstack = [&] (auto &stack, auto &other_stack, Namespace ns) {
409 96 : auto node = stack.dfs_node (stack.root, at);
410 96 : if (node)
411 : {
412 96 : auto &extern_crate_node = node.value ();
413 416 : for (auto kv : other_stack.root.children)
414 : {
415 160 : auto link = kv.first;
416 160 : auto child = kv.second;
417 320 : extern_crate_node.insert_child (link, child);
418 160 : child.parent = extern_crate_node;
419 : }
420 176 : for (auto kv : other_stack.root.rib (ns).get_values ())
421 : {
422 40 : auto name = kv.first;
423 40 : auto def = kv.second;
424 80 : extern_crate_node.rib (ns).insert (name, def);
425 : }
426 : }
427 96 : stack.resolved_nodes.insert (other_stack.resolved_nodes.begin (),
428 : other_stack.resolved_nodes.end ());
429 120 : };
430 :
431 24 : merge_fstack (values, other.values, Namespace::Values);
432 24 : merge_fstack (types, other.types, Namespace::Types);
433 24 : merge_fstack (macros, other.macros, Namespace::Macros);
434 24 : merge_fstack (labels, other.labels, Namespace::Labels);
435 24 : canonical_ctx.merge (std::move (other.canonical_ctx));
436 24 : }
437 :
438 : #if 0
439 : void
440 : NameResolutionContext::flatten ()
441 : {
442 : values.flatten ();
443 : types.flatten ();
444 : macros.flatten ();
445 : labels.flatten ();
446 : }
447 : #endif
448 :
449 : } // namespace Resolver2_0
450 : } // namespace Rust
|