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