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 : : #ifndef RUST_AST_RESOLVE_STMT_H
20 : : #define RUST_AST_RESOLVE_STMT_H
21 : :
22 : : #include "rust-ast-resolve-base.h"
23 : : #include "rust-ast-resolve-type.h"
24 : : #include "rust-ast-resolve-pattern.h"
25 : : #include "rust-ast-resolve-expr.h"
26 : : #include "rust-item.h"
27 : :
28 : : namespace Rust {
29 : : namespace Resolver {
30 : :
31 : 0 : class ResolveStmt : public ResolverBase
32 : : {
33 : : using Rust::Resolver::ResolverBase::visit;
34 : :
35 : : public:
36 : 0 : static void go (AST::Stmt &stmt, const CanonicalPath &prefix,
37 : : const CanonicalPath &canonical_prefix,
38 : : const CanonicalPath &enum_prefix)
39 : : {
40 : 0 : if (stmt.is_marked_for_strip ())
41 : 0 : return;
42 : :
43 : 0 : ResolveStmt resolver (prefix, canonical_prefix, enum_prefix);
44 : 0 : stmt.accept_vis (resolver);
45 : 0 : }
46 : :
47 : 0 : void visit (AST::ExprStmt &stmt) override
48 : : {
49 : 0 : ResolveExpr::go (stmt.get_expr (), prefix, canonical_prefix);
50 : 0 : }
51 : :
52 : 0 : void visit (AST::ConstantItem &constant) override
53 : : {
54 : 0 : auto decl = CanonicalPath::new_seg (constant.get_node_id (),
55 : 0 : constant.get_identifier ());
56 : 0 : auto path = decl; // this ensures we have the correct relative resolution
57 : 0 : auto cpath = canonical_prefix.append (decl);
58 : 0 : mappings.insert_canonical_path (constant.get_node_id (), cpath);
59 : :
60 : 0 : resolver->get_name_scope ().insert (
61 : : path, constant.get_node_id (), constant.get_locus (), false,
62 : : Rib::ItemType::Const,
63 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
64 : 0 : rich_location r (line_table, constant.get_locus ());
65 : 0 : r.add_range (locus);
66 : 0 : redefined_error (r);
67 : 0 : });
68 : :
69 : 0 : ResolveType::go (constant.get_type ());
70 : 0 : if (constant.has_expr ())
71 : 0 : ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
72 : 0 : }
73 : :
74 : 0 : void visit (AST::LetStmt &stmt) override
75 : : {
76 : 0 : if (stmt.has_init_expr ())
77 : 0 : ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix);
78 : :
79 : 0 : if (stmt.has_else_expr ())
80 : 0 : ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix);
81 : :
82 : 0 : PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var);
83 : 0 : if (stmt.has_type ())
84 : 0 : ResolveType::go (stmt.get_type ());
85 : 0 : }
86 : :
87 : 0 : void visit (AST::TupleStruct &struct_decl) override
88 : : {
89 : 0 : auto decl
90 : 0 : = CanonicalPath::new_seg (struct_decl.get_node_id (),
91 : 0 : struct_decl.get_identifier ().as_string ());
92 : 0 : auto path = decl; // this ensures we have the correct relative resolution
93 : 0 : auto cpath = canonical_prefix.append (decl);
94 : 0 : mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
95 : :
96 : 0 : resolver->get_type_scope ().insert (
97 : : path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
98 : : Rib::ItemType::Type,
99 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
100 : 0 : rich_location r (line_table, struct_decl.get_locus ());
101 : 0 : r.add_range (locus);
102 : 0 : redefined_error (r);
103 : 0 : });
104 : :
105 : 0 : NodeId scope_node_id = struct_decl.get_node_id ();
106 : 0 : resolver->get_type_scope ().push (scope_node_id);
107 : :
108 : 0 : if (struct_decl.has_generics ())
109 : 0 : ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
110 : : canonical_prefix);
111 : :
112 : 0 : for (AST::TupleField &field : struct_decl.get_fields ())
113 : 0 : ResolveType::go (field.get_field_type ());
114 : :
115 : 0 : resolver->get_type_scope ().pop ();
116 : 0 : }
117 : :
118 : 0 : void visit (AST::Enum &enum_decl) override
119 : : {
120 : 0 : auto decl
121 : 0 : = CanonicalPath::new_seg (enum_decl.get_node_id (),
122 : 0 : enum_decl.get_identifier ().as_string ());
123 : 0 : auto path = decl; // this ensures we have the correct relative resolution
124 : 0 : auto cpath = canonical_prefix.append (decl);
125 : 0 : mappings.insert_canonical_path (enum_decl.get_node_id (), cpath);
126 : :
127 : 0 : resolver->get_type_scope ().insert (
128 : : path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
129 : : Rib::ItemType::Type,
130 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
131 : 0 : rich_location r (line_table, enum_decl.get_locus ());
132 : 0 : r.add_range (locus);
133 : 0 : redefined_error (r);
134 : 0 : });
135 : :
136 : 0 : NodeId scope_node_id = enum_decl.get_node_id ();
137 : 0 : resolver->get_type_scope ().push (scope_node_id);
138 : :
139 : 0 : if (enum_decl.has_generics ())
140 : 0 : ResolveGenericParams::go (enum_decl.get_generic_params (), prefix,
141 : : canonical_prefix);
142 : :
143 : 0 : for (auto &variant : enum_decl.get_variants ())
144 : 0 : ResolveStmt::go (*variant, path, canonical_prefix, path);
145 : :
146 : 0 : resolver->get_type_scope ().pop ();
147 : 0 : }
148 : :
149 : 0 : void visit (AST::EnumItem &item) override
150 : : {
151 : 0 : auto decl = enum_prefix.append (
152 : 0 : CanonicalPath::new_seg (item.get_node_id (),
153 : 0 : item.get_identifier ().as_string ()));
154 : 0 : auto path = decl; // this ensures we have the correct relative resolution
155 : 0 : auto cpath = canonical_prefix.append (decl);
156 : 0 : mappings.insert_canonical_path (item.get_node_id (), cpath);
157 : :
158 : 0 : resolver->get_type_scope ().insert (
159 : 0 : path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
160 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
161 : 0 : rich_location r (line_table, item.get_locus ());
162 : 0 : r.add_range (locus);
163 : 0 : redefined_error (r);
164 : 0 : });
165 : :
166 : : // Done, no fields.
167 : 0 : }
168 : :
169 : 0 : void visit (AST::EnumItemTuple &item) override
170 : : {
171 : 0 : auto decl = enum_prefix.append (
172 : 0 : CanonicalPath::new_seg (item.get_node_id (),
173 : 0 : item.get_identifier ().as_string ()));
174 : 0 : auto path = decl; // this ensures we have the correct relative resolution
175 : 0 : auto cpath = canonical_prefix.append (decl);
176 : 0 : mappings.insert_canonical_path (item.get_node_id (), cpath);
177 : :
178 : 0 : resolver->get_type_scope ().insert (
179 : 0 : path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
180 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
181 : 0 : rich_location r (line_table, item.get_locus ());
182 : 0 : r.add_range (locus);
183 : 0 : redefined_error (r);
184 : 0 : });
185 : :
186 : 0 : for (auto &field : item.get_tuple_fields ())
187 : : {
188 : 0 : if (field.get_field_type ().is_marked_for_strip ())
189 : 0 : continue;
190 : :
191 : 0 : ResolveType::go (field.get_field_type ());
192 : : }
193 : 0 : }
194 : :
195 : 0 : void visit (AST::EnumItemStruct &item) override
196 : : {
197 : 0 : auto decl = enum_prefix.append (
198 : 0 : CanonicalPath::new_seg (item.get_node_id (),
199 : 0 : item.get_identifier ().as_string ()));
200 : 0 : auto path = decl; // this ensures we have the correct relative resolution
201 : 0 : auto cpath = canonical_prefix.append (decl);
202 : 0 : mappings.insert_canonical_path (item.get_node_id (), cpath);
203 : :
204 : 0 : resolver->get_type_scope ().insert (
205 : 0 : path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
206 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
207 : 0 : rich_location r (line_table, item.get_locus ());
208 : 0 : r.add_range (locus);
209 : 0 : redefined_error (r);
210 : 0 : });
211 : :
212 : 0 : for (auto &field : item.get_struct_fields ())
213 : : {
214 : 0 : if (field.get_field_type ().is_marked_for_strip ())
215 : 0 : continue;
216 : :
217 : 0 : ResolveType::go (field.get_field_type ());
218 : : }
219 : 0 : }
220 : :
221 : 0 : void visit (AST::EnumItemDiscriminant &item) override
222 : : {
223 : 0 : auto decl = enum_prefix.append (
224 : 0 : CanonicalPath::new_seg (item.get_node_id (),
225 : 0 : item.get_identifier ().as_string ()));
226 : 0 : auto path = decl; // this ensures we have the correct relative resolution
227 : 0 : auto cpath = canonical_prefix.append (decl);
228 : 0 : mappings.insert_canonical_path (item.get_node_id (), cpath);
229 : :
230 : 0 : resolver->get_type_scope ().insert (
231 : 0 : path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
232 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
233 : 0 : rich_location r (line_table, item.get_locus ());
234 : 0 : r.add_range (locus);
235 : 0 : redefined_error (r);
236 : 0 : });
237 : :
238 : : // Done, no fields.
239 : 0 : }
240 : :
241 : 0 : void visit (AST::StructStruct &struct_decl) override
242 : : {
243 : 0 : auto decl
244 : 0 : = CanonicalPath::new_seg (struct_decl.get_node_id (),
245 : 0 : struct_decl.get_identifier ().as_string ());
246 : 0 : auto path = decl; // this ensures we have the correct relative resolution
247 : 0 : auto cpath = canonical_prefix.append (decl);
248 : 0 : mappings.insert_canonical_path (struct_decl.get_node_id (), cpath);
249 : :
250 : 0 : resolver->get_type_scope ().insert (
251 : : path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
252 : : Rib::ItemType::Type,
253 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
254 : 0 : rich_location r (line_table, struct_decl.get_locus ());
255 : 0 : r.add_range (locus);
256 : 0 : redefined_error (r);
257 : 0 : });
258 : :
259 : 0 : NodeId scope_node_id = struct_decl.get_node_id ();
260 : 0 : resolver->get_type_scope ().push (scope_node_id);
261 : :
262 : 0 : if (struct_decl.has_generics ())
263 : 0 : ResolveGenericParams::go (struct_decl.get_generic_params (), prefix,
264 : : canonical_prefix);
265 : :
266 : 0 : for (AST::StructField &field : struct_decl.get_fields ())
267 : : {
268 : 0 : if (field.get_field_type ().is_marked_for_strip ())
269 : 0 : continue;
270 : :
271 : 0 : ResolveType::go (field.get_field_type ());
272 : : }
273 : :
274 : 0 : resolver->get_type_scope ().pop ();
275 : 0 : }
276 : :
277 : 0 : void visit (AST::Union &union_decl) override
278 : : {
279 : 0 : auto decl
280 : 0 : = CanonicalPath::new_seg (union_decl.get_node_id (),
281 : 0 : union_decl.get_identifier ().as_string ());
282 : 0 : auto path = decl; // this ensures we have the correct relative resolution
283 : 0 : auto cpath = canonical_prefix.append (decl);
284 : 0 : mappings.insert_canonical_path (union_decl.get_node_id (), cpath);
285 : :
286 : 0 : resolver->get_type_scope ().insert (
287 : : path, union_decl.get_node_id (), union_decl.get_locus (), false,
288 : : Rib::ItemType::Type,
289 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
290 : 0 : rich_location r (line_table, union_decl.get_locus ());
291 : 0 : r.add_range (locus);
292 : 0 : redefined_error (r);
293 : 0 : });
294 : :
295 : 0 : NodeId scope_node_id = union_decl.get_node_id ();
296 : 0 : resolver->get_type_scope ().push (scope_node_id);
297 : :
298 : 0 : if (union_decl.has_generics ())
299 : 0 : ResolveGenericParams::go (union_decl.get_generic_params (), prefix,
300 : : canonical_prefix);
301 : :
302 : 0 : for (AST::StructField &field : union_decl.get_variants ())
303 : : {
304 : 0 : if (field.get_field_type ().is_marked_for_strip ())
305 : 0 : continue;
306 : :
307 : 0 : ResolveType::go (field.get_field_type ());
308 : : }
309 : :
310 : 0 : resolver->get_type_scope ().pop ();
311 : 0 : }
312 : :
313 : 0 : void visit (AST::Function &function) override
314 : : {
315 : 0 : auto decl
316 : 0 : = CanonicalPath::new_seg (function.get_node_id (),
317 : 0 : function.get_function_name ().as_string ());
318 : 0 : auto path = decl; // this ensures we have the correct relative resolution
319 : 0 : auto cpath = canonical_prefix.append (decl);
320 : 0 : mappings.insert_canonical_path (function.get_node_id (), cpath);
321 : :
322 : 0 : resolver->get_name_scope ().insert (
323 : 0 : path, function.get_node_id (), function.get_locus (), false,
324 : : Rib::ItemType::Function,
325 : 0 : [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
326 : 0 : rich_location r (line_table, function.get_locus ());
327 : 0 : r.add_range (locus);
328 : 0 : redefined_error (r);
329 : 0 : });
330 : :
331 : 0 : NodeId scope_node_id = function.get_node_id ();
332 : 0 : resolver->get_name_scope ().push (scope_node_id);
333 : 0 : resolver->get_type_scope ().push (scope_node_id);
334 : 0 : resolver->get_label_scope ().push (scope_node_id);
335 : 0 : resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
336 : 0 : resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
337 : 0 : resolver->push_new_label_rib (resolver->get_label_scope ().peek ());
338 : :
339 : 0 : if (function.has_generics ())
340 : 0 : ResolveGenericParams::go (function.get_generic_params (), prefix,
341 : : canonical_prefix);
342 : :
343 : 0 : if (function.has_return_type ())
344 : 0 : ResolveType::go (function.get_return_type ());
345 : :
346 : 0 : std::vector<PatternBinding> bindings
347 : 0 : = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())};
348 : :
349 : : // we make a new scope so the names of parameters are resolved and shadowed
350 : : // correctly
351 : 0 : for (auto &p : function.get_function_params ())
352 : : {
353 : 0 : if (p->is_variadic ())
354 : : {
355 : 0 : auto ¶m = static_cast<AST::VariadicParam &> (*p);
356 : 0 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
357 : : bindings);
358 : : }
359 : :
360 : 0 : else if (p->is_self ())
361 : : {
362 : 0 : auto ¶m = static_cast<AST::SelfParam &> (*p);
363 : 0 : ResolveType::go (param.get_type ());
364 : : }
365 : : else
366 : : {
367 : 0 : auto ¶m = static_cast<AST::FunctionParam &> (*p);
368 : :
369 : 0 : ResolveType::go (param.get_type ());
370 : 0 : PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param,
371 : : bindings);
372 : : }
373 : : }
374 : :
375 : : // resolve the function body
376 : 0 : ResolveExpr::go (*function.get_definition ().value (), path, cpath);
377 : :
378 : 0 : resolver->get_name_scope ().pop ();
379 : 0 : resolver->get_type_scope ().pop ();
380 : 0 : resolver->get_label_scope ().pop ();
381 : 0 : }
382 : :
383 : : void visit (AST::ExternBlock &extern_block) override;
384 : : void visit (AST::Trait &trait) override;
385 : : void visit (AST::InherentImpl &impl_block) override;
386 : : void visit (AST::TraitImpl &impl_block) override;
387 : : void visit (AST::StaticItem &var) override;
388 : :
389 : : private:
390 : 0 : ResolveStmt (const CanonicalPath &prefix,
391 : : const CanonicalPath &canonical_prefix,
392 : : const CanonicalPath &enum_prefix)
393 : 0 : : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix),
394 : 0 : enum_prefix (enum_prefix)
395 : : {}
396 : :
397 : : const CanonicalPath &prefix;
398 : : const CanonicalPath &canonical_prefix;
399 : :
400 : : /* item declaration statements are not given a canonical path, but enum items
401 : : * (variants) do inherit the enum path/identifier name. */
402 : : const CanonicalPath &enum_prefix;
403 : : };
404 : :
405 : : } // namespace Resolver
406 : : } // namespace Rust
407 : :
408 : : #endif // RUST_AST_RESOLVE_STMT_H
|