Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : 32717 : BindingLayer::BindingLayer (BindingSource source) : source (source)
27 : : {
28 : 32717 : push (Binding::Kind::Product);
29 : 32717 : }
30 : :
31 : : bool
32 : 47696 : BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
33 : : {
34 : 95732 : for (auto &bind : bindings)
35 : : {
36 : 48102 : if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
37 : 48102 : && bind.kind == kind)
38 : : {
39 : 47696 : return true;
40 : : }
41 : : }
42 : : return false;
43 : : }
44 : :
45 : : void
46 : 33299 : BindingLayer::push (Binding::Kind kind)
47 : : {
48 : 33299 : bindings.push_back (Binding (kind));
49 : 33299 : }
50 : :
51 : : bool
52 : 23852 : BindingLayer::is_and_bound (Identifier ident)
53 : : {
54 : 23852 : return bind_test (ident, Binding::Kind::Product);
55 : : }
56 : :
57 : : bool
58 : 23844 : BindingLayer::is_or_bound (Identifier ident)
59 : : {
60 : 23844 : return bind_test (ident, Binding::Kind::Or);
61 : : }
62 : :
63 : : void
64 : 23844 : BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
65 : : bool is_mut)
66 : : {
67 : 23844 : bindings.back ().idents.emplace (
68 : 23844 : std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
69 : 23844 : }
70 : :
71 : : void
72 : 582 : BindingLayer::merge ()
73 : : {
74 : 582 : auto last_binding = std::move (bindings.back ());
75 : 582 : bindings.pop_back ();
76 : :
77 : 582 : if (bindings.back ().has_expected_bindings)
78 : : {
79 : 262 : 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 : 756 : 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 : 582 : if (bindings.back ().kind == Binding::Kind::Or)
123 : 393 : bindings.back ().has_expected_bindings = true;
124 : 582 : }
125 : :
126 : : BindingSource
127 : 8 : BindingLayer::get_source () const
128 : : {
129 : 8 : return source;
130 : : }
131 : :
132 : : Resolver::CanonicalPath
133 : 73606 : CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
134 : : {
135 : 147212 : auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
136 : 73606 : ret.set_crate_num (crate_num);
137 : 73606 : return ret;
138 : : }
139 : :
140 : : Resolver::CanonicalPath
141 : 145997 : CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
142 : : {
143 : 145997 : auto parent_path = get_parent ().as_path (ctx);
144 : 291994 : return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
145 : 145997 : }
146 : :
147 : : Resolver::CanonicalPath
148 : 27217 : CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
149 : : {
150 : 27217 : if (!cache)
151 : : {
152 : 17100 : auto res = ctx.lookup (lookup_id).and_then (
153 : 33104 : [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
154 : :
155 : 17100 : 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 : 12178 : return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
162 : : }
163 : :
164 : 4922 : cache = res.value ();
165 : : }
166 : 15039 : return cache->as_path (ctx);
167 : : }
168 : :
169 : : Resolver::CanonicalPath
170 : 6767 : CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
171 : : {
172 : 6767 : auto parent_path = get_parent ().as_path (ctx);
173 : 6767 : return parent_path.append (
174 : 13534 : Resolver::CanonicalPath::inherent_impl_seg (impl_id,
175 : 20301 : type_record.as_path (ctx)));
176 : 6767 : }
177 : :
178 : : Resolver::CanonicalPath
179 : 10225 : CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
180 : : {
181 : 10225 : auto parent_path = get_parent ().as_path (ctx);
182 : 10225 : return parent_path.append (
183 : 20450 : Resolver::CanonicalPath::trait_impl_projection_seg (
184 : 30675 : impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
185 : 10225 : }
186 : :
187 : 4290 : NameResolutionContext::NameResolutionContext ()
188 : 4290 : : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
189 : 4290 : {}
190 : :
191 : : tl::expected<NodeId, DuplicateNameError>
192 : 146810 : NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
193 : : {
194 : 146810 : switch (ns)
195 : : {
196 : 67638 : case Namespace::Values:
197 : 67638 : return values.insert (name, id);
198 : 79005 : case Namespace::Types:
199 : 79005 : 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 : 3280 : NameResolutionContext::insert_variant (Identifier name, NodeId id)
211 : : {
212 : 3280 : 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 : 28 : NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns)
236 : : {
237 : 28 : switch (ns)
238 : : {
239 : 10 : case Namespace::Values:
240 : 10 : return values.insert_globbed (name, id);
241 : 18 : case Namespace::Types:
242 : 18 : 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 : 194128 : NameResolutionContext::map_usage (Usage usage, Definition definition)
254 : : {
255 : 194128 : auto inserted = resolved_nodes.emplace (usage, definition).second;
256 : :
257 : : // is that valid?
258 : 194128 : rust_assert (inserted);
259 : 194128 : }
260 : :
261 : : tl::optional<NodeId>
262 : 1265849 : NameResolutionContext::lookup (NodeId usage) const
263 : : {
264 : 1265849 : auto it = resolved_nodes.find (Usage (usage));
265 : :
266 : 1265849 : if (it == resolved_nodes.end ())
267 : 8472 : return tl::nullopt;
268 : :
269 : 1257377 : return it->second.id;
270 : : }
271 : :
272 : : void
273 : 492586 : 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 : 492586 : values.push (rib_kind, id, path);
279 : 492586 : types.push (rib_kind, id, path);
280 : 492586 : macros.push (rib_kind, id, path);
281 : : // labels.push (rib, id);
282 : :
283 : 492586 : lambda ();
284 : :
285 : 492584 : values.pop ();
286 : 492584 : types.pop ();
287 : 492584 : macros.pop ();
288 : : // labels.pop (rib);
289 : 492584 : }
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
|