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 4339 : VisibilityResolver::VisibilityResolver (
30 : Analysis::Mappings &mappings,
31 4339 : const Resolver2_0::FinalizedNameResolutionContext &resolver)
32 4339 : : mappings (mappings), resolver (resolver)
33 4339 : {}
34 :
35 : void
36 4339 : VisibilityResolver::go (HIR::Crate &crate)
37 : {
38 4339 : mappings.insert_visibility (crate.get_mappings ().get_nodeid (),
39 : ModuleVisibility::create_public ());
40 :
41 4339 : current_module = crate.get_mappings ().get_defid ();
42 :
43 22168 : for (auto &item : crate.get_items ())
44 : {
45 17829 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
46 : {
47 17829 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
48 17829 : vis_item->accept_vis (*this);
49 : }
50 : }
51 4339 : }
52 :
53 : bool
54 16 : 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 16 : NodeId ast_node_id = restriction.get_mappings ().get_nodeid ();
61 :
62 16 : auto invalid_path
63 : = Error (restriction.get_locus (),
64 16 : "cannot use non-module path as privacy restrictor");
65 :
66 16 : NodeId ref_node_id;
67 16 : if (auto id = resolver.lookup (ast_node_id, Resolver2_0::Namespace::Types))
68 : {
69 16 : 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 16 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
82 16 : rust_assert (hid.has_value ());
83 16 : auto ref = hid.value ();
84 :
85 16 : auto crate = mappings.get_ast_crate (mappings.get_current_crate ());
86 :
87 : // we may be dealing with pub(crate)
88 16 : if (ref_node_id == crate.get_node_id ())
89 : // FIXME: What do we do here? There isn't a DefId for the Crate, so can we
90 : // actually do anything?
91 : // We basically want to return true always but just when exporting export
92 : // these items as private?
93 : return true;
94 :
95 8 : if (auto module = mappings.lookup_module (ref))
96 : {
97 : // Fill in the resolved `DefId`
98 8 : id = module.value ()->get_mappings ().get_defid ();
99 :
100 8 : return true;
101 : }
102 0 : invalid_path.emit ();
103 0 : return false;
104 16 : }
105 :
106 : bool
107 21341 : VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
108 : ModuleVisibility &to_resolve)
109 : {
110 21341 : switch (visibility.get_vis_type ())
111 : {
112 14734 : case HIR::Visibility::VisType::Private:
113 14734 : to_resolve = ModuleVisibility::create_restricted (current_module);
114 14734 : return true;
115 6591 : case HIR::Visibility::VisType::Public:
116 6591 : to_resolve = ModuleVisibility::create_public ();
117 6591 : return true;
118 16 : case HIR::Visibility::VisType::Restricted:
119 16 : {
120 : // FIXME: We also need to handle 2015 vs 2018 edition conflicts
121 16 : auto id = UNKNOWN_DEFID;
122 16 : auto result = resolve_module_path (visibility.get_path (), id);
123 16 : to_resolve = ModuleVisibility::create_restricted (id);
124 16 : return result;
125 : }
126 0 : default:
127 0 : rust_unreachable ();
128 : return false;
129 : }
130 : }
131 :
132 : void
133 17096 : VisibilityResolver::resolve_and_update (const HIR::VisItem *item)
134 : {
135 17096 : ModuleVisibility module_vis;
136 17096 : if (!resolve_visibility (item->get_visibility (), module_vis))
137 0 : return; // we will already have emitted errors
138 :
139 17096 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis);
140 : }
141 :
142 : void
143 1200 : VisibilityResolver::visit (HIR::Module &mod)
144 : {
145 1200 : auto old_module = current_module;
146 1200 : current_module = mod.get_mappings ().get_defid ();
147 :
148 5130 : for (auto &item : mod.get_items ())
149 : {
150 3930 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
151 : {
152 3930 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
153 3930 : vis_item->accept_vis (*this);
154 : }
155 : }
156 :
157 1200 : current_module = old_module;
158 1200 : }
159 :
160 : void
161 0 : VisibilityResolver::visit (HIR::ExternCrate &)
162 0 : {}
163 :
164 : void
165 0 : VisibilityResolver::visit (HIR::UseDeclaration &)
166 0 : {}
167 :
168 : void
169 13168 : VisibilityResolver::visit (HIR::Function &func)
170 : {
171 13168 : resolve_and_update (&func);
172 13168 : }
173 :
174 : void
175 1235 : VisibilityResolver::visit (HIR::TypeAlias &type_alias)
176 : {
177 1235 : resolve_and_update (&type_alias);
178 1235 : }
179 :
180 : void
181 1377 : VisibilityResolver::visit (HIR::StructStruct &struct_item)
182 : {
183 1377 : resolve_and_update (&struct_item);
184 1377 : }
185 :
186 : void
187 797 : VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
188 : {
189 797 : resolve_and_update (&tuple_struct);
190 797 : }
191 :
192 : void
193 486 : VisibilityResolver::visit (HIR::Enum &enum_item)
194 : {
195 486 : ModuleVisibility vis;
196 486 : if (!resolve_visibility (enum_item.get_visibility (), vis))
197 0 : return;
198 :
199 486 : mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis);
200 1637 : for (auto &variant : enum_item.get_variants ())
201 1151 : mappings.insert_visibility (variant->get_mappings ().get_nodeid (), vis);
202 : }
203 :
204 : void
205 101 : VisibilityResolver::visit (HIR::Union &)
206 101 : {}
207 :
208 : void
209 468 : VisibilityResolver::visit (HIR::ConstantItem &const_item)
210 : {
211 468 : resolve_and_update (&const_item);
212 468 : }
213 :
214 : void
215 51 : VisibilityResolver::visit (HIR::StaticItem &static_item)
216 : {
217 51 : resolve_and_update (&static_item);
218 51 : }
219 :
220 : void
221 3759 : VisibilityResolver::visit (HIR::Trait &trait)
222 : {
223 3759 : ModuleVisibility vis;
224 3759 : if (!resolve_visibility (trait.get_visibility (), vis))
225 0 : return;
226 :
227 3759 : mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis);
228 7013 : for (auto &item : trait.get_trait_items ())
229 3254 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis);
230 : }
231 :
232 : void
233 5628 : VisibilityResolver::visit (HIR::ImplBlock &impl)
234 : {
235 13758 : for (auto &item : impl.get_impl_items ())
236 : {
237 8130 : HIR::VisItem *vis_item;
238 8130 : switch (item->get_impl_item_type ())
239 : {
240 6884 : case HIR::ImplItem::FUNCTION:
241 6884 : vis_item = static_cast<HIR::Function *> (item.get ());
242 : break;
243 1178 : case HIR::ImplItem::TYPE_ALIAS:
244 1178 : vis_item = static_cast<HIR::TypeAlias *> (item.get ());
245 : break;
246 68 : case HIR::ImplItem::CONSTANT:
247 68 : vis_item = static_cast<HIR::ConstantItem *> (item.get ());
248 : break;
249 0 : default:
250 0 : rust_unreachable ();
251 8130 : return;
252 : }
253 8130 : vis_item->accept_vis (*this);
254 : }
255 5628 : }
256 :
257 : void
258 1619 : VisibilityResolver::visit (HIR::ExternBlock &)
259 1619 : {}
260 :
261 : } // namespace Privacy
262 : } // namespace Rust
|