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