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 : 3819 : VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings,
32 : 3819 : Resolver::Resolver &resolver)
33 : 3819 : : mappings (mappings), resolver (resolver)
34 : 3819 : {}
35 : :
36 : : void
37 : 3819 : VisibilityResolver::go (HIR::Crate &crate)
38 : : {
39 : 3819 : mappings.insert_visibility (crate.get_mappings ().get_nodeid (),
40 : : ModuleVisibility::create_public ());
41 : :
42 : 3819 : current_module = crate.get_mappings ().get_defid ();
43 : :
44 : 18168 : for (auto &item : crate.get_items ())
45 : : {
46 : 14349 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
47 : : {
48 : 14349 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
49 : 14349 : vis_item->accept_vis (*this);
50 : : }
51 : : }
52 : 3819 : }
53 : :
54 : : bool
55 : 20 : 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 : 20 : NodeId ast_node_id = restriction.get_mappings ().get_nodeid ();
62 : :
63 : 20 : auto invalid_path
64 : : = Error (restriction.get_locus (),
65 : 20 : "cannot use non-module path as privacy restrictor");
66 : :
67 : 20 : NodeId ref_node_id = UNKNOWN_NODEID;
68 : 20 : if (flag_name_resolution_2_0)
69 : : {
70 : 11 : auto &nr_ctx
71 : 11 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
72 : :
73 : 11 : if (auto id = nr_ctx.lookup (ast_node_id))
74 : : {
75 : 0 : ref_node_id = *id;
76 : : }
77 : : else
78 : : {
79 : 11 : invalid_path.emit ();
80 : 11 : return false;
81 : : }
82 : : }
83 : 9 : 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 : 9 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
94 : 9 : rust_assert (hid.has_value ());
95 : 9 : auto ref = hid.value ();
96 : :
97 : 9 : auto crate = mappings.get_ast_crate (mappings.get_current_crate ());
98 : :
99 : : // we may be dealing with pub(crate)
100 : 9 : 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 : 9 : }
117 : :
118 : : bool
119 : 14438 : VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
120 : : ModuleVisibility &to_resolve)
121 : : {
122 : 14438 : switch (visibility.get_vis_type ())
123 : : {
124 : 10546 : case HIR::Visibility::PRIVATE:
125 : 10546 : to_resolve = ModuleVisibility::create_restricted (current_module);
126 : 10546 : return true;
127 : 3872 : case HIR::Visibility::PUBLIC:
128 : 3872 : to_resolve = ModuleVisibility::create_public ();
129 : 3872 : return true;
130 : 20 : case HIR::Visibility::RESTRICTED: {
131 : : // FIXME: We also need to handle 2015 vs 2018 edition conflicts
132 : 20 : auto id = UNKNOWN_DEFID;
133 : 20 : auto result = resolve_module_path (visibility.get_path (), id);
134 : 20 : to_resolve = ModuleVisibility::create_restricted (id);
135 : 20 : return result;
136 : : }
137 : 0 : default:
138 : 0 : rust_unreachable ();
139 : : return false;
140 : : }
141 : : }
142 : :
143 : : void
144 : 11942 : VisibilityResolver::resolve_and_update (const HIR::VisItem *item)
145 : : {
146 : 11942 : ModuleVisibility module_vis;
147 : 11942 : if (!resolve_visibility (item->get_visibility (), module_vis))
148 : 11 : return; // we will already have emitted errors
149 : :
150 : 11931 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis);
151 : : }
152 : :
153 : : void
154 : 492 : VisibilityResolver::visit (HIR::Module &mod)
155 : : {
156 : 492 : auto old_module = current_module;
157 : 492 : current_module = mod.get_mappings ().get_defid ();
158 : :
159 : 1130 : for (auto &item : mod.get_items ())
160 : : {
161 : 638 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
162 : : {
163 : 638 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
164 : 638 : vis_item->accept_vis (*this);
165 : : }
166 : : }
167 : :
168 : 492 : current_module = old_module;
169 : 492 : }
170 : :
171 : : void
172 : 0 : VisibilityResolver::visit (HIR::ExternCrate &)
173 : 0 : {}
174 : :
175 : : void
176 : 0 : VisibilityResolver::visit (HIR::UseDeclaration &)
177 : 0 : {}
178 : :
179 : : void
180 : 8976 : VisibilityResolver::visit (HIR::Function &func)
181 : : {
182 : 8976 : resolve_and_update (&func);
183 : 8976 : }
184 : :
185 : : void
186 : 833 : VisibilityResolver::visit (HIR::TypeAlias &type_alias)
187 : : {
188 : 833 : resolve_and_update (&type_alias);
189 : 833 : }
190 : :
191 : : void
192 : 955 : VisibilityResolver::visit (HIR::StructStruct &struct_item)
193 : : {
194 : 955 : resolve_and_update (&struct_item);
195 : 955 : }
196 : :
197 : : void
198 : 699 : VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
199 : : {
200 : 699 : resolve_and_update (&tuple_struct);
201 : 699 : }
202 : :
203 : : void
204 : 203 : VisibilityResolver::visit (HIR::Enum &enum_item)
205 : : {
206 : 203 : ModuleVisibility vis;
207 : 203 : if (!resolve_visibility (enum_item.get_visibility (), vis))
208 : 0 : return;
209 : :
210 : 203 : mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis);
211 : 669 : for (auto &variant : enum_item.get_variants ())
212 : 466 : mappings.insert_visibility (variant->get_mappings ().get_nodeid (), vis);
213 : : }
214 : :
215 : : void
216 : 94 : VisibilityResolver::visit (HIR::Union &)
217 : 94 : {}
218 : :
219 : : void
220 : 431 : VisibilityResolver::visit (HIR::ConstantItem &const_item)
221 : : {
222 : 431 : resolve_and_update (&const_item);
223 : 431 : }
224 : :
225 : : void
226 : 48 : VisibilityResolver::visit (HIR::StaticItem &static_item)
227 : : {
228 : 48 : resolve_and_update (&static_item);
229 : 48 : }
230 : :
231 : : void
232 : 2293 : VisibilityResolver::visit (HIR::Trait &trait)
233 : : {
234 : 2293 : ModuleVisibility vis;
235 : 2293 : if (!resolve_visibility (trait.get_visibility (), vis))
236 : 0 : return;
237 : :
238 : 2293 : mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis);
239 : 3963 : for (auto &item : trait.get_trait_items ())
240 : 1670 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis);
241 : : }
242 : :
243 : : void
244 : 3290 : VisibilityResolver::visit (HIR::ImplBlock &impl)
245 : : {
246 : 7699 : for (auto &item : impl.get_impl_items ())
247 : : {
248 : 4409 : HIR::VisItem *vis_item;
249 : 4409 : switch (item->get_impl_item_type ())
250 : : {
251 : 3574 : case HIR::ImplItem::FUNCTION:
252 : 3574 : vis_item = static_cast<HIR::Function *> (item.get ());
253 : : break;
254 : 797 : case HIR::ImplItem::TYPE_ALIAS:
255 : 797 : vis_item = static_cast<HIR::TypeAlias *> (item.get ());
256 : : break;
257 : 38 : case HIR::ImplItem::CONSTANT:
258 : 38 : vis_item = static_cast<HIR::ConstantItem *> (item.get ());
259 : : break;
260 : 0 : default:
261 : 0 : rust_unreachable ();
262 : 4409 : return;
263 : : }
264 : 4409 : vis_item->accept_vis (*this);
265 : : }
266 : 3290 : }
267 : :
268 : : void
269 : 1082 : VisibilityResolver::visit (HIR::ExternBlock &)
270 : 1082 : {}
271 : :
272 : : } // namespace Privacy
273 : : } // namespace Rust
|