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-rib.h"
20 : #include "rust-name-resolution-context.h"
21 :
22 : namespace Rust {
23 : namespace Resolver2_0 {
24 :
25 270818 : Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26 270818 : : enum_variant (enum_variant)
27 : {
28 270818 : switch (mode)
29 : {
30 24478 : case Mode::SHADOWABLE:
31 24478 : ids_shadowable.push_back (id);
32 24478 : return;
33 246306 : case Mode::NON_SHADOWABLE:
34 246306 : ids_non_shadowable.push_back (id);
35 246306 : return;
36 34 : case Mode::GLOBBED:
37 34 : ids_globbed.push_back (id);
38 34 : return;
39 0 : default:
40 0 : gcc_unreachable ();
41 : }
42 : }
43 :
44 : bool
45 407657 : Rib::Definition::is_ambiguous () const
46 : {
47 407657 : if (!ids_shadowable.empty ())
48 : return false;
49 381055 : else if (!ids_non_shadowable.empty ())
50 381018 : return ids_non_shadowable.size () > 1;
51 : else
52 37 : return ids_globbed.size () > 1;
53 : }
54 :
55 : bool
56 69528 : Rib::Definition::is_variant () const
57 : {
58 69528 : return enum_variant;
59 : }
60 :
61 : std::string
62 1697588 : Rib::Definition::to_string () const
63 : {
64 1697588 : std::stringstream out;
65 1697588 : const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
66 1697588 : const std::vector<NodeId> *id_lists[3]
67 1697588 : = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
68 6790352 : for (int i = 0; i < 3; i++)
69 : {
70 5092764 : out << headers[i];
71 5092764 : std::string sep;
72 6790844 : for (auto id : *id_lists[i])
73 : {
74 3396160 : out << sep << id;
75 1698080 : sep = ",";
76 : }
77 5092764 : }
78 1697588 : out << "]";
79 1697588 : if (enum_variant)
80 10164 : out << "(enum variant)";
81 1697588 : return out.str ();
82 1697588 : }
83 :
84 : Rib::Definition
85 24478 : Rib::Definition::Shadowable (NodeId id)
86 : {
87 24478 : return Definition (id, Mode::SHADOWABLE, false);
88 : }
89 :
90 : Rib::Definition
91 246306 : Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
92 : {
93 246306 : return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
94 : }
95 :
96 : Rib::Definition
97 34 : Rib::Definition::Globbed (NodeId id)
98 : {
99 34 : return Definition (id, Mode::GLOBBED, false);
100 : }
101 :
102 107597 : DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
103 107597 : : name (name), existing (existing)
104 107597 : {}
105 :
106 1613301 : Rib::Rib (Kind kind) : kind (kind) {}
107 :
108 0 : Rib::Rib (Kind kind, std::string identifier, NodeId id)
109 0 : : Rib (kind, {{identifier, id}})
110 0 : {}
111 :
112 0 : Rib::Rib (Kind kind, std::unordered_map<std::string, NodeId> to_insert)
113 0 : : kind (kind)
114 : {
115 0 : for (auto &value : to_insert)
116 0 : values.insert ({value.first, Definition::NonShadowable (value.second)});
117 0 : }
118 :
119 : tl::expected<NodeId, DuplicateNameError>
120 267304 : Rib::insert (std::string name, Definition def)
121 : {
122 267304 : auto it = values.find (name);
123 267304 : if (it == values.end ())
124 : {
125 : /* No old value */
126 159400 : values[name] = def;
127 : }
128 107904 : else if (it->second.ids_non_shadowable.empty ()
129 107904 : || def.ids_non_shadowable.empty ())
130 : { /* No non-shadowable conflict */
131 441 : auto ¤t = values[name];
132 444 : for (auto id : def.ids_non_shadowable)
133 : {
134 6 : if (std::find (current.ids_non_shadowable.cbegin (),
135 : current.ids_non_shadowable.cend (), id)
136 6 : == current.ids_non_shadowable.cend ())
137 3 : current.ids_non_shadowable.push_back (id);
138 : else
139 : // TODO: should this produce an error?
140 0 : return tl::make_unexpected (DuplicateNameError (name, id));
141 : }
142 742 : for (auto id : def.ids_shadowable)
143 : {
144 838 : if (std::find (current.ids_shadowable.cbegin (),
145 : current.ids_shadowable.cend (), id)
146 838 : == current.ids_shadowable.cend ())
147 301 : current.ids_shadowable.push_back (id);
148 : else
149 : // TODO: should this produce an error?
150 236 : return tl::make_unexpected (DuplicateNameError (name, id));
151 : }
152 326 : for (auto id : def.ids_globbed)
153 : {
154 38 : if (std::find (current.ids_globbed.cbegin (),
155 : current.ids_globbed.cend (), id)
156 38 : == current.ids_globbed.cend ())
157 3 : current.ids_globbed.push_back (id);
158 : else
159 : // TODO: should this produce an error?
160 32 : return tl::make_unexpected (DuplicateNameError (name, id));
161 : }
162 : }
163 : else /* Multiple non-shadowable */
164 : {
165 322389 : return tl::make_unexpected (
166 429852 : DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
167 : }
168 :
169 159707 : if (!def.ids_shadowable.empty ())
170 24360 : return def.ids_shadowable.back ();
171 135347 : else if (!def.ids_non_shadowable.empty ())
172 135329 : return def.ids_non_shadowable.back ();
173 18 : rust_assert (!def.ids_globbed.empty ());
174 18 : return def.ids_globbed.back ();
175 : }
176 :
177 : tl::optional<Rib::Definition>
178 338085 : Rib::get (const std::string &name)
179 : {
180 338085 : auto it = values.find (name);
181 :
182 338085 : if (it == values.end ())
183 229755 : return tl::nullopt;
184 :
185 108330 : return it->second;
186 : }
187 :
188 : const std::unordered_map<std::string, Rib::Definition> &
189 3118129 : Rib::get_values () const
190 : {
191 3118129 : return values;
192 : }
193 :
194 : } // namespace Resolver2_0
195 : } // namespace Rust
|