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 284877 : Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26 284877 : : enum_variant (enum_variant)
27 : {
28 284877 : switch (mode)
29 : {
30 24901 : case Mode::SHADOWABLE:
31 24901 : ids_shadowable.push_back (id);
32 24901 : return;
33 259892 : case Mode::NON_SHADOWABLE:
34 259892 : ids_non_shadowable.push_back (id);
35 259892 : return;
36 84 : case Mode::GLOBBED:
37 84 : ids_globbed.push_back (id);
38 84 : return;
39 0 : default:
40 0 : gcc_unreachable ();
41 : }
42 : }
43 :
44 : bool
45 474354 : Rib::Definition::is_ambiguous () const
46 : {
47 474354 : if (!ids_shadowable.empty ())
48 : return false;
49 447506 : else if (!ids_non_shadowable.empty ())
50 447445 : return ids_non_shadowable.size () > 1;
51 : else
52 61 : return ids_globbed.size () > 1;
53 : }
54 :
55 : bool
56 72297 : Rib::Definition::is_variant () const
57 : {
58 72297 : return enum_variant;
59 : }
60 :
61 : std::string
62 1907993 : Rib::Definition::to_string () const
63 : {
64 1907993 : std::stringstream out;
65 1907993 : const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
66 1907993 : const std::vector<NodeId> *id_lists[3]
67 1907993 : = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
68 7631972 : for (int i = 0; i < 3; i++)
69 : {
70 5723979 : out << headers[i];
71 5723979 : std::string sep;
72 7632472 : for (auto id : *id_lists[i])
73 : {
74 3816986 : out << sep << id;
75 1908493 : sep = ",";
76 : }
77 5723979 : }
78 1907993 : out << "]";
79 1907993 : if (enum_variant)
80 23880 : out << "(enum variant)";
81 1907993 : return out.str ();
82 1907993 : }
83 :
84 : Rib::Definition
85 24901 : Rib::Definition::Shadowable (NodeId id)
86 : {
87 24901 : return Definition (id, Mode::SHADOWABLE, false);
88 : }
89 :
90 : Rib::Definition
91 259892 : Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
92 : {
93 259892 : return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
94 : }
95 :
96 : Rib::Definition
97 84 : Rib::Definition::Globbed (NodeId id)
98 : {
99 84 : return Definition (id, Mode::GLOBBED, false);
100 : }
101 :
102 112449 : DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
103 112449 : : name (name), existing (existing)
104 112449 : {}
105 :
106 1677714 : 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 281563 : Rib::insert (std::string name, Definition def)
121 : {
122 281563 : auto it = values.find (name);
123 281563 : if (it == values.end ())
124 : {
125 : /* No old value */
126 168826 : values[name] = def;
127 : }
128 112737 : else if (it->second.ids_non_shadowable.empty ()
129 112737 : || def.ids_non_shadowable.empty ())
130 : { /* No non-shadowable conflict */
131 447 : auto ¤t = values[name];
132 450 : 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 729 : for (auto id : def.ids_shadowable)
143 : {
144 794 : if (std::find (current.ids_shadowable.cbegin (),
145 : current.ids_shadowable.cend (), id)
146 794 : == current.ids_shadowable.cend ())
147 282 : current.ids_shadowable.push_back (id);
148 : else
149 : // TODO: should this produce an error?
150 230 : return tl::make_unexpected (DuplicateNameError (name, id));
151 : }
152 335 : for (auto id : def.ids_globbed)
153 : {
154 94 : if (std::find (current.ids_globbed.cbegin (),
155 : current.ids_globbed.cend (), id)
156 94 : == current.ids_globbed.cend ())
157 3 : current.ids_globbed.push_back (id);
158 : else
159 : // TODO: should this produce an error?
160 88 : return tl::make_unexpected (DuplicateNameError (name, id));
161 : }
162 : }
163 : else /* Multiple non-shadowable */
164 : {
165 336870 : return tl::make_unexpected (
166 449160 : DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
167 : }
168 :
169 169114 : if (!def.ids_shadowable.empty ())
170 24786 : return def.ids_shadowable.back ();
171 144328 : else if (!def.ids_non_shadowable.empty ())
172 144288 : return def.ids_non_shadowable.back ();
173 40 : rust_assert (!def.ids_globbed.empty ());
174 40 : return def.ids_globbed.back ();
175 : }
176 :
177 : tl::optional<Rib::Definition>
178 485973 : Rib::get (const std::string &name)
179 : {
180 485973 : auto it = values.find (name);
181 :
182 485973 : if (it == values.end ())
183 375518 : return tl::nullopt;
184 :
185 110455 : return it->second;
186 : }
187 :
188 : const std::unordered_map<std::string, Rib::Definition> &
189 3240943 : Rib::get_values () const
190 : {
191 3240943 : return values;
192 : }
193 :
194 : } // namespace Resolver2_0
195 : } // namespace Rust
|