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 :
23 : namespace Rust {
24 : namespace Resolver2_0 {
25 :
26 33542 : BindingLayer::BindingLayer (BindingSource source) : source (source)
27 : {
28 33542 : push (Binding::Kind::Product);
29 33542 : }
30 :
31 : bool
32 48584 : BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
33 : {
34 97508 : for (auto &bind : bindings)
35 : {
36 48990 : if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
37 48990 : && bind.kind == kind)
38 : {
39 48584 : return true;
40 : }
41 : }
42 : return false;
43 : }
44 :
45 : void
46 34133 : BindingLayer::push (Binding::Kind kind)
47 : {
48 34133 : bindings.push_back (Binding (kind));
49 34133 : }
50 :
51 : bool
52 24296 : BindingLayer::is_and_bound (Identifier ident)
53 : {
54 24296 : return bind_test (ident, Binding::Kind::Product);
55 : }
56 :
57 : bool
58 24288 : BindingLayer::is_or_bound (Identifier ident)
59 : {
60 24288 : return bind_test (ident, Binding::Kind::Or);
61 : }
62 :
63 : void
64 24288 : BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
65 : bool is_mut)
66 : {
67 24288 : bindings.back ().idents.emplace (
68 24288 : std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
69 24288 : }
70 :
71 : void
72 591 : BindingLayer::merge ()
73 : {
74 591 : auto last_binding = std::move (bindings.back ());
75 591 : bindings.pop_back ();
76 :
77 591 : if (bindings.back ().has_expected_bindings)
78 : {
79 267 : for (auto &value : bindings.back ().idents)
80 : {
81 58 : auto ident = value.first;
82 58 : if (last_binding.idents.find (ident) == last_binding.idents.end ())
83 : {
84 0 : location_t locus = value.second.first;
85 0 : rust_error_at (locus, ErrorCode::E0408,
86 : "variable %qs is not bound in all patterns",
87 : ident.c_str ());
88 : }
89 58 : }
90 : }
91 :
92 765 : for (auto &value : last_binding.idents)
93 : {
94 174 : auto res = bindings.back ().idents.emplace (value);
95 174 : if (res.second)
96 : {
97 116 : if (bindings.back ().has_expected_bindings)
98 : {
99 14 : auto &ident = value.first;
100 14 : location_t locus = value.second.first;
101 14 : rust_error_at (locus, ErrorCode::E0408,
102 : "variable %qs is not bound in all patterns",
103 : ident.c_str ());
104 : }
105 : }
106 : else
107 : {
108 58 : auto this_mode = value.second.second;
109 58 : auto other_mode = res.first->second.second;
110 232 : if (this_mode != other_mode)
111 : {
112 7 : auto &ident = value.first;
113 7 : location_t locus = value.second.first;
114 7 : rust_error_at (locus, ErrorCode::E0409,
115 : "variable %qs is bound inconsistently across "
116 : "pattern alternatives",
117 : ident.c_str ());
118 : }
119 : }
120 : }
121 :
122 591 : if (bindings.back ().kind == Binding::Kind::Or)
123 400 : bindings.back ().has_expected_bindings = true;
124 591 : }
125 :
126 : BindingSource
127 8 : BindingLayer::get_source () const
128 : {
129 8 : return source;
130 : }
131 :
132 : Resolver::CanonicalPath
133 74527 : CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
134 : {
135 149054 : auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
136 74527 : ret.set_crate_num (crate_num);
137 74527 : return ret;
138 : }
139 :
140 : Resolver::CanonicalPath
141 147394 : CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
142 : {
143 147394 : auto parent_path = get_parent ().as_path (ctx);
144 294788 : return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
145 147394 : }
146 :
147 : Resolver::CanonicalPath
148 27377 : CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
149 : {
150 27377 : if (!cache)
151 : {
152 17165 : auto res = ctx.lookup (lookup_id).and_then (
153 33226 : [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
154 :
155 17165 : if (!res)
156 : {
157 : // HACK: use a dummy value
158 : // this should bring us roughly to parity with nr1.0
159 : // since nr1.0 doesn't seem to handle canonical paths for generics
160 : // quite right anyways
161 12189 : return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
162 : }
163 :
164 4976 : cache = res.value ();
165 : }
166 15188 : return cache->as_path (ctx);
167 : }
168 :
169 : Resolver::CanonicalPath
170 6855 : CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
171 : {
172 6855 : auto parent_path = get_parent ().as_path (ctx);
173 6855 : return parent_path.append (
174 13710 : Resolver::CanonicalPath::inherent_impl_seg (impl_id,
175 20565 : type_record.as_path (ctx)));
176 6855 : }
177 :
178 : Resolver::CanonicalPath
179 10261 : CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
180 : {
181 10261 : auto parent_path = get_parent ().as_path (ctx);
182 10261 : return parent_path.append (
183 20522 : Resolver::CanonicalPath::trait_impl_projection_seg (
184 30783 : impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
185 10261 : }
186 :
187 4510 : NameResolutionContext::NameResolutionContext ()
188 4510 : : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
189 4510 : {}
190 :
191 : tl::expected<NodeId, DuplicateNameError>
192 149873 : NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
193 : {
194 149873 : switch (ns)
195 : {
196 69245 : case Namespace::Values:
197 69245 : return values.insert (name, id);
198 80461 : case Namespace::Types:
199 80461 : return types.insert (name, id);
200 167 : case Namespace::Macros:
201 167 : return macros.insert (name, id);
202 0 : case Namespace::Labels:
203 0 : default:
204 : // return labels.insert (name, id);
205 0 : rust_unreachable ();
206 : }
207 : }
208 :
209 : tl::expected<NodeId, DuplicateNameError>
210 3332 : NameResolutionContext::insert_variant (Identifier name, NodeId id)
211 : {
212 3332 : return types.insert_variant (name, id);
213 : }
214 :
215 : tl::expected<NodeId, DuplicateNameError>
216 0 : NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
217 : Namespace ns)
218 : {
219 0 : switch (ns)
220 : {
221 0 : case Namespace::Values:
222 0 : return values.insert_shadowable (name, id);
223 0 : case Namespace::Types:
224 0 : return types.insert_shadowable (name, id);
225 0 : case Namespace::Macros:
226 0 : return macros.insert_shadowable (name, id);
227 0 : case Namespace::Labels:
228 0 : default:
229 : // return labels.insert (name, id);
230 0 : rust_unreachable ();
231 : }
232 : }
233 :
234 : tl::expected<NodeId, DuplicateNameError>
235 30 : NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
236 : {
237 30 : switch (ns)
238 : {
239 10 : case Namespace::Values:
240 10 : return values.insert_globbed (name, id);
241 20 : case Namespace::Types:
242 20 : return types.insert_globbed (name, id);
243 0 : case Namespace::Macros:
244 0 : return macros.insert_globbed (name, id);
245 0 : case Namespace::Labels:
246 0 : default:
247 : // return labels.insert (name, id);
248 0 : rust_unreachable ();
249 : }
250 : }
251 :
252 : void
253 199723 : NameResolutionContext::map_usage (Usage usage, Definition definition)
254 : {
255 199723 : auto inserted = resolved_nodes.emplace (usage, definition).second;
256 :
257 : // is that valid?
258 199723 : rust_assert (inserted);
259 199723 : }
260 :
261 : tl::optional<NodeId>
262 2603282 : NameResolutionContext::lookup (NodeId usage) const
263 : {
264 2603282 : auto it = resolved_nodes.find (Usage (usage));
265 :
266 2603282 : if (it == resolved_nodes.end ())
267 6099 : return tl::nullopt;
268 :
269 2597183 : return it->second.id;
270 : }
271 :
272 : void
273 502811 : NameResolutionContext::scoped (Rib::Kind rib_kind, NodeId id,
274 : std::function<void (void)> lambda,
275 : tl::optional<Identifier> path)
276 : {
277 : // NOTE: You must be at the root node when pushing the prelude rib.
278 502811 : values.push (rib_kind, id, path);
279 502811 : types.push (rib_kind, id, path);
280 502811 : macros.push (rib_kind, id, path);
281 : // labels.push (rib, id);
282 :
283 502811 : lambda ();
284 :
285 502809 : values.pop ();
286 502809 : types.pop ();
287 502809 : macros.pop ();
288 : // labels.pop (rib);
289 502809 : }
290 :
291 : void
292 0 : NameResolutionContext::scoped (Rib::Kind rib_kind, Namespace ns,
293 : NodeId scope_id,
294 : std::function<void (void)> lambda,
295 : tl::optional<Identifier> path)
296 : {
297 : // This could work... I'm not sure why you would want to do this though.
298 0 : rust_assert (rib_kind != Rib::Kind::Prelude);
299 :
300 0 : switch (ns)
301 : {
302 0 : case Namespace::Values:
303 0 : values.push (rib_kind, scope_id, path);
304 0 : break;
305 0 : case Namespace::Types:
306 0 : types.push (rib_kind, scope_id, path);
307 0 : break;
308 0 : case Namespace::Labels:
309 0 : case Namespace::Macros:
310 0 : gcc_unreachable ();
311 : }
312 :
313 0 : lambda ();
314 :
315 0 : switch (ns)
316 : {
317 0 : case Namespace::Values:
318 0 : values.pop ();
319 0 : break;
320 0 : case Namespace::Types:
321 0 : types.pop ();
322 0 : break;
323 : case Namespace::Labels:
324 : case Namespace::Macros:
325 : gcc_unreachable ();
326 : }
327 0 : }
328 :
329 : } // namespace Resolver2_0
330 : } // namespace Rust
|