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 : #ifndef RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
20 : #define RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
21 :
22 : #include "optional.h"
23 : #include "rust-ast-visitor.h"
24 : #include "rust-ast.h"
25 : #include "rust-item.h"
26 : #include "rust-name-resolution-context.h"
27 : #include "rust-default-resolver.h"
28 :
29 : namespace Rust {
30 : namespace Resolver2_0 {
31 :
32 : /**
33 : * The `TopLevel` visitor takes care of collecting all the definitions in a
34 : * crate, and inserting them into the proper namespaces. These definitions can
35 : * then be accessed by subsequent resolvers, such as `Early` or `Late`.
36 : */
37 : class TopLevel : public DefaultResolver
38 : {
39 : using DefaultResolver::visit;
40 :
41 : public:
42 : TopLevel (NameResolutionContext &resolver);
43 :
44 : void go (AST::Crate &crate);
45 :
46 10411 : bool is_dirty () { return dirty; }
47 :
48 : // Each import will be transformed into an instance of `ImportKind`, a class
49 : // representing some of the data we need to resolve in the
50 : // `EarlyNameResolver`. Basically, for each `UseTree` that we see in
51 : // `TopLevel`, create one of these. `TopLevel` should build a list of these
52 : // `ImportKind`s, which `Early` can then resolve to their proper definitions.
53 : // Then, a final pass will insert the definitions into the `ForeverStack` -
54 : // `FinalizeImports`.
55 : //
56 : // Using this struct should be very simple - each path within a `UseTree`
57 : // becomes one `ImportKind`. The complex case is glob imports, in which case
58 : // one glob import will become one `ImportKind` which will later become
59 : // multiple definitions thanks to the `GlobbingVisitor`.
60 : struct ImportKind
61 : {
62 : enum class Kind
63 : {
64 : Glob,
65 : Simple,
66 : Rebind,
67 : } kind;
68 :
69 25 : static ImportKind Glob (AST::SimplePath &&to_resolve, Rib &values_rib,
70 : Rib &types_rib, Rib ¯os_rib, bool is_prelude)
71 : {
72 25 : return ImportKind (Kind::Glob, std::move (to_resolve), values_rib,
73 25 : types_rib, macros_rib, is_prelude);
74 : }
75 :
76 0 : static ImportKind Simple (AST::SimplePath &&to_resolve, Rib &values_rib,
77 : Rib &types_rib, Rib ¯os_rib)
78 : {
79 0 : return ImportKind (Kind::Simple, std::move (to_resolve), values_rib,
80 0 : types_rib, macros_rib);
81 : }
82 :
83 4121 : static ImportKind Rebind (AST::SimplePath &&to_resolve,
84 : AST::UseTreeRebind &&rebind, Rib &values_rib,
85 : Rib &types_rib, Rib ¯os_rib)
86 : {
87 4121 : return ImportKind (
88 : Kind::Rebind, std::move (to_resolve), values_rib, types_rib, macros_rib,
89 : false /* is_prelude: rebind imports can never be preludes */,
90 4121 : std::move (rebind));
91 : }
92 :
93 : // The path for `Early` to resolve.
94 : AST::SimplePath to_resolve;
95 :
96 : // The path to rebind an import to - only present if kind is Kind::Rebind
97 : tl::optional<AST::UseTreeRebind> rebind;
98 :
99 : Rib &values_rib;
100 : Rib &types_rib;
101 : Rib ¯os_rib;
102 :
103 : // Can only be true if we are dealing with a glob import with the
104 : // #[prelude_import] attribute
105 : bool is_prelude = false;
106 :
107 : private:
108 4146 : ImportKind (Kind kind, AST::SimplePath &&to_resolve, Rib &values_rib,
109 : Rib &types_rib, Rib ¯os_rib, bool is_prelude = false,
110 25 : tl::optional<AST::UseTreeRebind> &&rebind = tl::nullopt)
111 4146 : : kind (kind), to_resolve (std::move (to_resolve)),
112 4146 : rebind (std::move (rebind)), values_rib (values_rib),
113 4146 : types_rib (types_rib), macros_rib (macros_rib), is_prelude (is_prelude)
114 4146 : {}
115 : };
116 :
117 : std::unordered_map<NodeId, std::vector<ImportKind>> &get_imports_to_resolve ()
118 : {
119 1842 : return imports_to_resolve;
120 : }
121 :
122 : void check_multiple_insertion_error (
123 : tl::expected<NodeId, DuplicateNameError> result,
124 : const Identifier &identifier, const location_t &locus,
125 : const NodeId node_id);
126 :
127 : /**
128 : * Insert a new definition or error out if a definition with the same name
129 : * was already present in the same namespace in the same scope.
130 : *
131 : * @param identifier The identifier of the definition to add.
132 : * @param node A reference to the node, so we can get its `NodeId` and
133 : * location.
134 : * @param ns The namespace in which to add the definition.
135 : */
136 : template <typename T>
137 : void insert_or_error_out (const Identifier &identifier, const T &node,
138 : Namespace ns);
139 : void insert_or_error_out (const Identifier &identifier,
140 : const location_t &locus, const NodeId &id,
141 : Namespace ns);
142 :
143 : template <typename T>
144 : void insert_enum_variant_or_error_out (const Identifier &identifier,
145 : const T &node);
146 :
147 : void insert_enum_variant_or_error_out (const Identifier &identifier,
148 : const location_t &locus,
149 : const NodeId node_id);
150 :
151 : private:
152 : // If a new export has been defined whilst visiting the visitor is considered
153 : // dirty
154 : bool dirty;
155 :
156 : // FIXME: Do we move these to our mappings?
157 : std::unordered_map<NodeId, location_t> node_locations;
158 :
159 : // Store node forwarding for use declaration, the link between a
160 : // definition and its new local name.
161 : std::unordered_map<NodeId, NodeId> node_forwarding;
162 :
163 : // One of the outputs of the `TopLevel` visitor - the list of imports that
164 : // `Early` should take care of resolving
165 : std::unordered_map<NodeId, std::vector<ImportKind>> imports_to_resolve;
166 :
167 : void visit (AST::Module &module) override;
168 : void visit (AST::Trait &trait) override;
169 : void maybe_insert_big_self (AST::Impl &impl) override;
170 : void visit (AST::TraitItemType &trait_item) override;
171 : void visit (AST::MacroRulesDefinition ¯o) override;
172 : void visit (AST::Function &function) override;
173 : void visit (AST::StaticItem &static_item) override;
174 : void visit (AST::ExternalStaticItem &static_item) override;
175 : void visit (AST::StructStruct &struct_item) override;
176 : void visit (AST::TupleStruct &tuple_struct) override;
177 : void visit (AST::EnumItem &variant) override;
178 : void visit (AST::EnumItemTuple &variant) override;
179 : void visit (AST::EnumItemStruct &variant) override;
180 : void visit (AST::EnumItemDiscriminant &variant) override;
181 : void visit (AST::Enum &enum_item) override;
182 : void visit (AST::Union &union_item) override;
183 : void visit (AST::ConstantItem &const_item) override;
184 : void visit (AST::TypeAlias &type_item) override;
185 : void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override;
186 : void visit (AST::TypeParam &type_param) override;
187 : void visit (AST::ConstGenericParam &const_param) override;
188 :
189 : void visit (AST::UseDeclaration &use) override;
190 : };
191 :
192 : } // namespace Resolver2_0
193 : } // namespace Rust
194 :
195 : // For storing Imports as keys in maps
196 : namespace std {
197 : template <> struct less<Rust::Resolver2_0::TopLevel::ImportKind>
198 : {
199 : bool operator() (const Rust::Resolver2_0::TopLevel::ImportKind &lhs,
200 : const Rust::Resolver2_0::TopLevel::ImportKind &rhs) const
201 : {
202 : return lhs.to_resolve.as_string () < rhs.to_resolve.as_string ()
203 : && lhs.kind < rhs.kind;
204 : }
205 : };
206 : } // namespace std
207 :
208 : #endif // !RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
|