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 270466 : Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26 270466 : : enum_variant (enum_variant)
27 : {
28 270466 : switch (mode)
29 : {
30 24460 : case Mode::SHADOWABLE:
31 24460 : ids_shadowable.push_back (id);
32 24460 : return;
33 245976 : case Mode::NON_SHADOWABLE:
34 245976 : ids_non_shadowable.push_back (id);
35 245976 : return;
36 30 : case Mode::GLOBBED:
37 30 : ids_globbed.push_back (id);
38 30 : return;
39 0 : default:
40 0 : gcc_unreachable ();
41 : }
42 : }
43 :
44 : bool
45 404111 : Rib::Definition::is_ambiguous () const
46 : {
47 404111 : if (!ids_shadowable.empty ())
48 : return false;
49 377589 : else if (!ids_non_shadowable.empty ())
50 377555 : return ids_non_shadowable.size () > 1;
51 : else
52 34 : return ids_globbed.size () > 1;
53 : }
54 :
55 : bool
56 69384 : Rib::Definition::is_variant () const
57 : {
58 69384 : return enum_variant;
59 : }
60 :
61 : std::string
62 1694418 : Rib::Definition::to_string () const
63 : {
64 1694418 : std::stringstream out;
65 1694418 : const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
66 1694418 : const std::vector<NodeId> *id_lists[3]
67 1694418 : = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
68 6777672 : for (int i = 0; i < 3; i++)
69 : {
70 5083254 : out << headers[i];
71 5083254 : std::string sep;
72 6778263 : for (auto id : *id_lists[i])
73 : {
74 3390018 : out << sep << id;
75 1695009 : sep = ",";
76 : }
77 5083254 : }
78 1694418 : out << "]";
79 1694418 : if (enum_variant)
80 10164 : out << "(enum variant)";
81 1694418 : return out.str ();
82 1694418 : }
83 :
84 : Rib::Definition
85 24460 : Rib::Definition::Shadowable (NodeId id)
86 : {
87 24460 : return Definition (id, Mode::SHADOWABLE, false);
88 : }
89 :
90 : Rib::Definition
91 245976 : Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
92 : {
93 245976 : return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
94 : }
95 :
96 : Rib::Definition
97 30 : Rib::Definition::Globbed (NodeId id)
98 : {
99 30 : return Definition (id, Mode::GLOBBED, false);
100 : }
101 :
102 107533 : DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
103 107533 : : name (name), existing (existing)
104 107533 : {}
105 :
106 1562553 : 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 266959 : Rib::insert (std::string name, Definition def)
121 : {
122 266959 : auto it = values.find (name);
123 266959 : if (it == values.end ())
124 : {
125 : /* No old value */
126 159021 : values[name] = def;
127 : }
128 107938 : else if (it->second.ids_non_shadowable.empty ()
129 107938 : || def.ids_non_shadowable.empty ())
130 : { /* No non-shadowable conflict */
131 539 : auto ¤t = values[name];
132 542 : 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 940 : for (auto id : def.ids_shadowable)
143 : {
144 1038 : if (std::find (current.ids_shadowable.cbegin (),
145 : current.ids_shadowable.cend (), id)
146 1038 : == current.ids_shadowable.cend ())
147 401 : 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 422 : for (auto id : def.ids_globbed)
153 : {
154 34 : if (std::find (current.ids_globbed.cbegin (),
155 : current.ids_globbed.cend (), id)
156 34 : == current.ids_globbed.cend ())
157 1 : 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 322197 : return tl::make_unexpected (
166 429596 : DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
167 : }
168 :
169 159426 : if (!def.ids_shadowable.empty ())
170 24342 : return def.ids_shadowable.back ();
171 135084 : else if (!def.ids_non_shadowable.empty ())
172 135070 : return def.ids_non_shadowable.back ();
173 14 : rust_assert (!def.ids_globbed.empty ());
174 14 : return def.ids_globbed.back ();
175 : }
176 :
177 : tl::optional<Rib::Definition>
178 330352 : Rib::get (const std::string &name)
179 : {
180 330352 : auto it = values.find (name);
181 :
182 330352 : if (it == values.end ())
183 222178 : return tl::nullopt;
184 :
185 108174 : return it->second;
186 : }
187 :
188 : const std::unordered_map<std::string, Rib::Definition> &
189 3016921 : Rib::get_values () const
190 : {
191 3016921 : return values;
192 : }
193 :
194 : } // namespace Resolver2_0
195 : } // namespace Rust
|