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-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 4121 : VisibilityResolver::VisibilityResolver (
29 : Analysis::Mappings &mappings,
30 4121 : const Resolver2_0::NameResolutionContext &resolver)
31 4121 : : mappings (mappings), resolver (resolver)
32 4121 : {}
33 :
34 : void
35 4121 : VisibilityResolver::go (HIR::Crate &crate)
36 : {
37 4121 : mappings.insert_visibility (crate.get_mappings ().get_nodeid (),
38 : ModuleVisibility::create_public ());
39 :
40 4121 : current_module = crate.get_mappings ().get_defid ();
41 :
42 21141 : for (auto &item : crate.get_items ())
43 : {
44 17020 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
45 : {
46 17020 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
47 17020 : vis_item->accept_vis (*this);
48 : }
49 : }
50 4121 : }
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 20694 : VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
107 : ModuleVisibility &to_resolve)
108 : {
109 20694 : switch (visibility.get_vis_type ())
110 : {
111 14369 : case HIR::Visibility::PRIVATE:
112 14369 : to_resolve = ModuleVisibility::create_restricted (current_module);
113 14369 : return true;
114 6309 : case HIR::Visibility::PUBLIC:
115 6309 : to_resolve = ModuleVisibility::create_public ();
116 6309 : 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 16680 : VisibilityResolver::resolve_and_update (const HIR::VisItem *item)
133 : {
134 16680 : ModuleVisibility module_vis;
135 16680 : if (!resolve_visibility (item->get_visibility (), module_vis))
136 0 : return; // we will already have emitted errors
137 :
138 16680 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis);
139 : }
140 :
141 : void
142 1189 : VisibilityResolver::visit (HIR::Module &mod)
143 : {
144 1189 : auto old_module = current_module;
145 1189 : current_module = mod.get_mappings ().get_defid ();
146 :
147 5099 : for (auto &item : mod.get_items ())
148 : {
149 3910 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
150 : {
151 3910 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
152 3910 : vis_item->accept_vis (*this);
153 : }
154 : }
155 :
156 1189 : current_module = old_module;
157 1189 : }
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 12841 : VisibilityResolver::visit (HIR::Function &func)
169 : {
170 12841 : resolve_and_update (&func);
171 12841 : }
172 :
173 : void
174 1212 : VisibilityResolver::visit (HIR::TypeAlias &type_alias)
175 : {
176 1212 : resolve_and_update (&type_alias);
177 1212 : }
178 :
179 : void
180 1322 : VisibilityResolver::visit (HIR::StructStruct &struct_item)
181 : {
182 1322 : resolve_and_update (&struct_item);
183 1322 : }
184 :
185 : void
186 794 : VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
187 : {
188 794 : resolve_and_update (&tuple_struct);
189 794 : }
190 :
191 : void
192 478 : VisibilityResolver::visit (HIR::Enum &enum_item)
193 : {
194 478 : ModuleVisibility vis;
195 478 : if (!resolve_visibility (enum_item.get_visibility (), vis))
196 0 : return;
197 :
198 478 : mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis);
199 1614 : for (auto &variant : enum_item.get_variants ())
200 1136 : 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 51 : VisibilityResolver::visit (HIR::StaticItem &static_item)
215 : {
216 51 : resolve_and_update (&static_item);
217 51 : }
218 :
219 : void
220 3536 : VisibilityResolver::visit (HIR::Trait &trait)
221 : {
222 3536 : ModuleVisibility vis;
223 3536 : if (!resolve_visibility (trait.get_visibility (), vis))
224 0 : return;
225 :
226 3536 : mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis);
227 6747 : for (auto &item : trait.get_trait_items ())
228 3211 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis);
229 : }
230 :
231 : void
232 5538 : VisibilityResolver::visit (HIR::ImplBlock &impl)
233 : {
234 13568 : for (auto &item : impl.get_impl_items ())
235 : {
236 8030 : HIR::VisItem *vis_item;
237 8030 : 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 1170 : case HIR::ImplItem::TYPE_ALIAS:
243 1170 : 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 8030 : return;
251 : }
252 8030 : vis_item->accept_vis (*this);
253 : }
254 5538 : }
255 :
256 : void
257 1442 : VisibilityResolver::visit (HIR::ExternBlock &)
258 1442 : {}
259 :
260 : } // namespace Privacy
261 : } // namespace Rust
|