Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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-visibility-resolver.h"
20 : : #include "rust-ast.h"
21 : : #include "rust-hir.h"
22 : : #include "rust-hir-item.h"
23 : : #include "rust-name-resolution-context.h"
24 : :
25 : : namespace Rust {
26 : : namespace Privacy {
27 : :
28 : 4081 : VisibilityResolver::VisibilityResolver (
29 : : Analysis::Mappings &mappings,
30 : 4081 : const Resolver2_0::NameResolutionContext &resolver)
31 : 4081 : : mappings (mappings), resolver (resolver)
32 : 4081 : {}
33 : :
34 : : void
35 : 4081 : VisibilityResolver::go (HIR::Crate &crate)
36 : : {
37 : 4081 : mappings.insert_visibility (crate.get_mappings ().get_nodeid (),
38 : : ModuleVisibility::create_public ());
39 : :
40 : 4081 : current_module = crate.get_mappings ().get_defid ();
41 : :
42 : 20986 : for (auto &item : crate.get_items ())
43 : : {
44 : 16905 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
45 : : {
46 : 16905 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
47 : 16905 : vis_item->accept_vis (*this);
48 : : }
49 : : }
50 : 4081 : }
51 : :
52 : : bool
53 : 16 : VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
54 : : DefId &id)
55 : : {
56 : : // We need, from the restriction, to figure out the actual Module it
57 : : // belongs to.
58 : :
59 : 16 : NodeId ast_node_id = restriction.get_mappings ().get_nodeid ();
60 : :
61 : 16 : auto invalid_path
62 : : = Error (restriction.get_locus (),
63 : 16 : "cannot use non-module path as privacy restrictor");
64 : :
65 : 16 : NodeId ref_node_id;
66 : 16 : if (auto id = resolver.lookup (ast_node_id))
67 : : {
68 : 16 : ref_node_id = *id;
69 : : }
70 : : else
71 : : {
72 : 0 : invalid_path.emit ();
73 : 0 : return false;
74 : : }
75 : : // FIXME: Add a hint here if we can find the path in another scope, such as
76 : : // a type or something else
77 : : // TODO: For the hint, can we point to the original item's definition if
78 : : // present?
79 : :
80 : 16 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
81 : 16 : rust_assert (hid.has_value ());
82 : 16 : auto ref = hid.value ();
83 : :
84 : 16 : auto crate = mappings.get_ast_crate (mappings.get_current_crate ());
85 : :
86 : : // we may be dealing with pub(crate)
87 : 16 : if (ref_node_id == crate.get_node_id ())
88 : : // FIXME: What do we do here? There isn't a DefId for the Crate, so can we
89 : : // actually do anything?
90 : : // We basically want to return true always but just when exporting export
91 : : // these items as private?
92 : : return true;
93 : :
94 : 8 : if (auto module = mappings.lookup_module (ref))
95 : : {
96 : : // Fill in the resolved `DefId`
97 : 8 : id = module.value ()->get_mappings ().get_defid ();
98 : :
99 : 8 : return true;
100 : : }
101 : 0 : invalid_path.emit ();
102 : 0 : return false;
103 : 16 : }
104 : :
105 : : bool
106 : 20583 : VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
107 : : ModuleVisibility &to_resolve)
108 : : {
109 : 20583 : switch (visibility.get_vis_type ())
110 : : {
111 : 14302 : case HIR::Visibility::PRIVATE:
112 : 14302 : to_resolve = ModuleVisibility::create_restricted (current_module);
113 : 14302 : return true;
114 : 6265 : case HIR::Visibility::PUBLIC:
115 : 6265 : to_resolve = ModuleVisibility::create_public ();
116 : 6265 : return true;
117 : 16 : case HIR::Visibility::RESTRICTED:
118 : 16 : {
119 : : // FIXME: We also need to handle 2015 vs 2018 edition conflicts
120 : 16 : auto id = UNKNOWN_DEFID;
121 : 16 : auto result = resolve_module_path (visibility.get_path (), id);
122 : 16 : to_resolve = ModuleVisibility::create_restricted (id);
123 : 16 : return result;
124 : : }
125 : 0 : default:
126 : 0 : rust_unreachable ();
127 : : return false;
128 : : }
129 : : }
130 : :
131 : : void
132 : 16589 : VisibilityResolver::resolve_and_update (const HIR::VisItem *item)
133 : : {
134 : 16589 : ModuleVisibility module_vis;
135 : 16589 : if (!resolve_visibility (item->get_visibility (), module_vis))
136 : 0 : return; // we will already have emitted errors
137 : :
138 : 16589 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis);
139 : : }
140 : :
141 : : void
142 : 1186 : VisibilityResolver::visit (HIR::Module &mod)
143 : : {
144 : 1186 : auto old_module = current_module;
145 : 1186 : current_module = mod.get_mappings ().get_defid ();
146 : :
147 : 5095 : for (auto &item : mod.get_items ())
148 : : {
149 : 3909 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
150 : : {
151 : 3909 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
152 : 3909 : vis_item->accept_vis (*this);
153 : : }
154 : : }
155 : :
156 : 1186 : current_module = old_module;
157 : 1186 : }
158 : :
159 : : void
160 : 0 : VisibilityResolver::visit (HIR::ExternCrate &)
161 : 0 : {}
162 : :
163 : : void
164 : 0 : VisibilityResolver::visit (HIR::UseDeclaration &)
165 : 0 : {}
166 : :
167 : : void
168 : 12783 : VisibilityResolver::visit (HIR::Function &func)
169 : : {
170 : 12783 : resolve_and_update (&func);
171 : 12783 : }
172 : :
173 : : void
174 : 1198 : VisibilityResolver::visit (HIR::TypeAlias &type_alias)
175 : : {
176 : 1198 : resolve_and_update (&type_alias);
177 : 1198 : }
178 : :
179 : : void
180 : 1313 : VisibilityResolver::visit (HIR::StructStruct &struct_item)
181 : : {
182 : 1313 : resolve_and_update (&struct_item);
183 : 1313 : }
184 : :
185 : : void
186 : 786 : VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
187 : : {
188 : 786 : resolve_and_update (&tuple_struct);
189 : 786 : }
190 : :
191 : : void
192 : 475 : VisibilityResolver::visit (HIR::Enum &enum_item)
193 : : {
194 : 475 : ModuleVisibility vis;
195 : 475 : if (!resolve_visibility (enum_item.get_visibility (), vis))
196 : 0 : return;
197 : :
198 : 475 : mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis);
199 : 1603 : for (auto &variant : enum_item.get_variants ())
200 : 1128 : mappings.insert_visibility (variant->get_mappings ().get_nodeid (), vis);
201 : : }
202 : :
203 : : void
204 : 97 : VisibilityResolver::visit (HIR::Union &)
205 : 97 : {}
206 : :
207 : : void
208 : 460 : VisibilityResolver::visit (HIR::ConstantItem &const_item)
209 : : {
210 : 460 : resolve_and_update (&const_item);
211 : 460 : }
212 : :
213 : : void
214 : 49 : VisibilityResolver::visit (HIR::StaticItem &static_item)
215 : : {
216 : 49 : resolve_and_update (&static_item);
217 : 49 : }
218 : :
219 : : void
220 : 3519 : VisibilityResolver::visit (HIR::Trait &trait)
221 : : {
222 : 3519 : ModuleVisibility vis;
223 : 3519 : if (!resolve_visibility (trait.get_visibility (), vis))
224 : 0 : return;
225 : :
226 : 3519 : mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis);
227 : 6721 : for (auto &item : trait.get_trait_items ())
228 : 3202 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis);
229 : : }
230 : :
231 : : void
232 : 5531 : VisibilityResolver::visit (HIR::ImplBlock &impl)
233 : : {
234 : 13554 : for (auto &item : impl.get_impl_items ())
235 : : {
236 : 8023 : HIR::VisItem *vis_item;
237 : 8023 : switch (item->get_impl_item_type ())
238 : : {
239 : 6793 : case HIR::ImplItem::FUNCTION:
240 : 6793 : vis_item = static_cast<HIR::Function *> (item.get ());
241 : : break;
242 : 1163 : case HIR::ImplItem::TYPE_ALIAS:
243 : 1163 : vis_item = static_cast<HIR::TypeAlias *> (item.get ());
244 : : break;
245 : 67 : case HIR::ImplItem::CONSTANT:
246 : 67 : vis_item = static_cast<HIR::ConstantItem *> (item.get ());
247 : : break;
248 : 0 : default:
249 : 0 : rust_unreachable ();
250 : 8023 : return;
251 : : }
252 : 8023 : vis_item->accept_vis (*this);
253 : : }
254 : 5531 : }
255 : :
256 : : void
257 : 1440 : VisibilityResolver::visit (HIR::ExternBlock &)
258 : 1440 : {}
259 : :
260 : : } // namespace Privacy
261 : : } // namespace Rust
|