1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #include "rust-toplevel-name-resolver-2.0.h"
21 #include "rust-ast-full.h"
22 #include "rust-hir-map.h"
23 #include "rust-attribute-values.h"
26 namespace Resolver2_0
{
28 TopLevel::TopLevel (NameResolutionContext
&resolver
)
29 : DefaultResolver (resolver
)
34 TopLevel::insert_or_error_out (const Identifier
&identifier
, const T
&node
,
37 insert_or_error_out (identifier
, node
.get_locus (), node
.get_node_id (), ns
);
41 TopLevel::insert_or_error_out (const Identifier
&identifier
,
42 const location_t
&locus
, const NodeId
&node_id
,
45 // keep track of each node's location to provide useful errors
46 node_locations
.emplace (node_id
, locus
);
48 auto result
= ctx
.insert (identifier
, node_id
, ns
);
52 // can we do something like check if the node id is the same? if it is the
53 // same, it's not an error, just the resolver running multiple times?
55 rich_location
rich_loc (line_table
, locus
);
56 rich_loc
.add_range (node_locations
[result
.error ().existing
]);
58 rust_error_at (rich_loc
, ErrorCode::E0428
, "%qs defined multiple times",
59 identifier
.as_string ().c_str ());
64 TopLevel::go (AST::Crate
&crate
)
66 // we do not include builtin types in the top-level definition collector, as
67 // they are not used until `Late`. furthermore, we run this visitor multiple
68 // times in a row in a fixed-point fashion, so it would make the code
69 // responsible for this ugly and perfom a lot of error checking.
71 for (auto &item
: crate
.items
)
72 item
->accept_vis (*this);
76 TopLevel::visit (AST::Module
&module
)
78 // FIXME: Do we need to insert the module in the type namespace?
80 auto sub_visitor
= [this, &module
] () {
81 for (auto &item
: module
.get_items ())
82 item
->accept_vis (*this);
85 ctx
.scoped (Rib::Kind::Module
, module
.get_node_id (), sub_visitor
,
89 template <typename PROC_MACRO
>
91 insert_macros (std::vector
<PROC_MACRO
> ¯os
, NameResolutionContext
&ctx
)
93 for (auto ¯o
: macros
)
95 auto res
= ctx
.macros
.insert (macro
.get_name (), macro
.get_node_id ());
99 rust_error_at (UNKNOWN_LOCATION
, ErrorCode::E0428
,
100 "macro %qs defined multiple times",
101 macro
.get_name ().c_str ());
107 TopLevel::visit (AST::ExternCrate
&crate
)
110 rust_assert (Analysis::Mappings::get ()->lookup_crate_name (
111 crate
.get_referenced_crate (), num
));
113 auto attribute_macros
114 = Analysis::Mappings::get ()->lookup_attribute_proc_macros (num
);
116 auto bang_macros
= Analysis::Mappings::get ()->lookup_bang_proc_macros (num
);
119 = Analysis::Mappings::get ()->lookup_derive_proc_macros (num
);
121 auto sub_visitor
= [&] () {
122 // TODO: Find a way to keep this part clean without the double dispatch.
123 if (derive_macros
.has_value ())
125 insert_macros (derive_macros
.value (), ctx
);
126 for (auto ¯o
: derive_macros
.value ())
127 Analysis::Mappings::get ()->insert_derive_proc_macro_def (macro
);
129 if (attribute_macros
.has_value ())
131 insert_macros (attribute_macros
.value (), ctx
);
132 for (auto ¯o
: attribute_macros
.value ())
133 Analysis::Mappings::get ()->insert_attribute_proc_macro_def (macro
);
135 if (bang_macros
.has_value ())
137 insert_macros (bang_macros
.value (), ctx
);
138 for (auto ¯o
: bang_macros
.value ())
139 Analysis::Mappings::get ()->insert_bang_proc_macro_def (macro
);
143 if (crate
.has_as_clause ())
144 ctx
.scoped (Rib::Kind::Module
, crate
.get_node_id (), sub_visitor
,
145 crate
.get_as_clause ());
147 ctx
.scoped (Rib::Kind::Module
, crate
.get_node_id (), sub_visitor
,
148 crate
.get_referenced_crate ());
152 is_macro_export (AST::MacroRulesDefinition
&def
)
154 for (const auto &attr
: def
.get_outer_attrs ())
155 if (attr
.get_path ().as_string () == Values::Attributes::MACRO_EXPORT
)
162 TopLevel::visit (AST::MacroRulesDefinition
¯o
)
164 // we do not insert macros in the current rib as that needs to be done in the
165 // textual scope of the Early pass. we only insert them in the root of the
166 // crate if they are marked with #[macro_export]. The execption to this is
167 // macros 2.0, which get resolved and inserted like regular items.
169 if (is_macro_export (macro
))
171 auto res
= ctx
.macros
.insert_at_root (macro
.get_rule_name (),
172 macro
.get_node_id ());
176 rich_location
rich_loc (line_table
, macro
.get_locus ());
177 rich_loc
.add_range (node_locations
[res
.error ().existing
]);
179 rust_error_at (rich_loc
, ErrorCode::E0428
,
180 "macro %qs defined multiple times",
181 macro
.get_rule_name ().as_string ().c_str ());
185 if (macro
.get_kind () == AST::MacroRulesDefinition::MacroKind::DeclMacro
)
186 insert_or_error_out (macro
.get_rule_name (), macro
, Namespace::Macros
);
188 auto mappings
= Analysis::Mappings::get ();
189 AST::MacroRulesDefinition
*tmp
= nullptr;
190 if (mappings
->lookup_macro_def (macro
.get_node_id (), &tmp
))
193 mappings
->insert_macro_def (¯o
);
197 TopLevel::visit (AST::Function
&function
)
199 insert_or_error_out (function
.get_function_name (), function
,
202 DefaultResolver::visit (function
);
206 TopLevel::visit (AST::BlockExpr
&expr
)
208 // extracting the lambda from the `scoped` call otherwise the code looks like
209 // a hot turd thanks to our .clang-format
211 auto sub_vis
= [this, &expr
] () {
212 for (auto &stmt
: expr
.get_statements ())
213 stmt
->accept_vis (*this);
215 if (expr
.has_tail_expr ())
216 expr
.get_tail_expr ()->accept_vis (*this);
219 ctx
.scoped (Rib::Kind::Normal
, expr
.get_node_id (), sub_vis
);
223 TopLevel::visit (AST::StaticItem
&static_item
)
226 = [this, &static_item
] () { static_item
.get_expr ()->accept_vis (*this); };
228 ctx
.scoped (Rib::Kind::Item
, static_item
.get_node_id (), sub_vis
);
232 TopLevel::visit (AST::TraitItemFunc
&item
)
235 = [this, &item
] () { item
.get_definition ()->accept_vis (*this); };
237 if (item
.has_definition ())
238 ctx
.scoped (Rib::Kind::Function
, item
.get_node_id (), def_vis
);
242 TopLevel::visit (AST::StructStruct
&struct_item
)
244 insert_or_error_out (struct_item
.get_struct_name (), struct_item
,
247 // Do we need to insert the constructor in the value namespace as well?
249 // Do we need to do anything if the struct is a unit struct?
250 if (struct_item
.is_unit_struct ())
251 insert_or_error_out (struct_item
.get_struct_name (), struct_item
,
256 TopLevel::visit (AST::TupleStruct
&tuple_struct
)
258 insert_or_error_out (tuple_struct
.get_struct_name (), tuple_struct
,
263 TopLevel::visit (AST::EnumItem
&variant
)
265 insert_or_error_out (variant
.get_identifier (), variant
, Namespace::Types
);
269 TopLevel::visit (AST::EnumItemTuple
&variant
)
271 insert_or_error_out (variant
.get_identifier (), variant
, Namespace::Types
);
275 TopLevel::visit (AST::EnumItemStruct
&variant
)
277 insert_or_error_out (variant
.get_identifier (), variant
, Namespace::Types
);
281 TopLevel::visit (AST::EnumItemDiscriminant
&variant
)
283 insert_or_error_out (variant
.get_identifier (), variant
, Namespace::Types
);
287 TopLevel::visit (AST::Enum
&enum_item
)
289 insert_or_error_out (enum_item
.get_identifier (), enum_item
,
292 auto field_vis
= [this, &enum_item
] () {
293 for (auto &variant
: enum_item
.get_variants ())
294 variant
->accept_vis (*this);
297 ctx
.scoped (Rib::Kind::Item
/* FIXME: Is that correct? */,
298 enum_item
.get_node_id (), field_vis
, enum_item
.get_identifier ());
302 TopLevel::visit (AST::Union
&union_item
)
304 insert_or_error_out (union_item
.get_identifier (), union_item
,
309 TopLevel::visit (AST::ConstantItem
&const_item
)
312 = [this, &const_item
] () { const_item
.get_expr ()->accept_vis (*this); };
314 ctx
.scoped (Rib::Kind::ConstantItem
, const_item
.get_node_id (), expr_vis
);
318 TopLevel::handle_use_dec (AST::SimplePath path
)
320 // TODO: Glob imports can get shadowed by regular imports and regular items.
321 // So we need to store them in a specific way in the ForeverStack - which can
322 // also probably be used by labels and macros etc. Like store it as a
323 // `Shadowable(NodeId)` instead of just a `NodeId`
325 auto locus
= path
.get_final_segment ().get_locus ();
326 auto declared_name
= path
.get_final_segment ().as_string ();
328 // in what namespace do we perform path resolution? All of them? see which one
329 // matches? Error out on ambiguities?
330 // so, apparently, for each one that matches, add it to the proper namespace
335 auto resolve_and_insert
= [this, &found
, &declared_name
,
336 locus
] (Namespace ns
,
337 const AST::SimplePath
&path
) {
338 tl::optional
<NodeId
> resolved
= tl::nullopt
;
340 // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
341 // that we can improve it with hints or location or w/ever. and maybe
342 // only emit it the first time.
345 case Namespace::Values
:
346 resolved
= ctx
.values
.resolve_path (path
.get_segments ());
348 case Namespace::Types
:
349 resolved
= ctx
.types
.resolve_path (path
.get_segments ());
351 case Namespace::Macros
:
352 resolved
= ctx
.macros
.resolve_path (path
.get_segments ());
354 case Namespace::Labels
:
355 // TODO: Is that okay?
360 (void) resolved
.map ([this, &found
, &declared_name
, locus
, ns
] (NodeId id
) {
363 // what do we do with the id?
364 insert_or_error_out (declared_name
, locus
, id
, ns
);
370 // do this for all namespaces (even Labels?)
372 resolve_and_insert (Namespace::Values
, path
);
373 resolve_and_insert (Namespace::Types
, path
);
374 resolve_and_insert (Namespace::Macros
, path
);
376 // TODO: No labels? No, right?
382 flatten_rebind (const AST::UseTreeRebind
&glob
,
383 std::vector
<AST::SimplePath
> &paths
);
385 flatten_list (const AST::UseTreeList
&glob
,
386 std::vector
<AST::SimplePath
> &paths
);
388 flatten_glob (const AST::UseTreeGlob
&glob
,
389 std::vector
<AST::SimplePath
> &paths
);
392 flatten (const AST::UseTree
*tree
, std::vector
<AST::SimplePath
> &paths
)
394 switch (tree
->get_kind ())
396 case AST::UseTree::Rebind
: {
397 auto rebind
= static_cast<const AST::UseTreeRebind
*> (tree
);
398 flatten_rebind (*rebind
, paths
);
401 case AST::UseTree::List
: {
402 auto list
= static_cast<const AST::UseTreeList
*> (tree
);
403 flatten_list (*list
, paths
);
406 case AST::UseTree::Glob
: {
407 rust_sorry_at (tree
->get_locus (), "cannot resolve glob imports yet");
408 auto glob
= static_cast<const AST::UseTreeGlob
*> (tree
);
409 flatten_glob (*glob
, paths
);
417 flatten_rebind (const AST::UseTreeRebind
&rebind
,
418 std::vector
<AST::SimplePath
> &paths
)
420 auto path
= rebind
.get_path ();
422 // FIXME: Do we want to emplace the rebind here as well?
423 if (rebind
.has_identifier ())
425 auto rebind_path
= path
;
426 auto new_seg
= rebind
.get_identifier ();
428 // Add the identifier as a new path
429 rebind_path
.get_segments ().back ()
430 = AST::SimplePathSegment (new_seg
.as_string (), UNDEF_LOCATION
);
432 paths
.emplace_back (rebind_path
);
436 paths
.emplace_back (path
);
441 flatten_list (const AST::UseTreeList
&list
, std::vector
<AST::SimplePath
> &paths
)
443 auto prefix
= AST::SimplePath::create_empty ();
444 if (list
.has_path ())
445 prefix
= list
.get_path ();
447 for (const auto &tree
: list
.get_trees ())
449 auto sub_paths
= std::vector
<AST::SimplePath
> ();
450 flatten (tree
.get (), sub_paths
);
452 for (auto &sub_path
: sub_paths
)
454 auto new_path
= prefix
;
455 std::copy (sub_path
.get_segments ().begin (),
456 sub_path
.get_segments ().end (),
457 std::back_inserter (new_path
.get_segments ()));
459 paths
.emplace_back (new_path
);
465 flatten_glob (const AST::UseTreeGlob
&glob
, std::vector
<AST::SimplePath
> &paths
)
467 if (glob
.has_path ())
468 paths
.emplace_back (glob
.get_path ());
472 TopLevel::visit (AST::UseDeclaration
&use
)
474 auto paths
= std::vector
<AST::SimplePath
> ();
476 // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup?
477 // How do we handle module imports in general? Should they get added to all
480 const auto &tree
= use
.get_tree ();
481 flatten (tree
.get (), paths
);
483 for (auto &path
: paths
)
484 if (!handle_use_dec (path
))
485 rust_error_at (path
.get_final_segment ().get_locus (), ErrorCode::E0433
,
486 "could not resolve import %qs",
487 path
.as_string ().c_str ());
490 } // namespace Resolver2_0