1 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
3 #![deny(rust_2018_idioms)]
6 #![feature(rustc_diagnostic_macros)]
8 #![recursion_limit="256"]
10 #[macro_use] extern crate syntax;
13 use rustc
::hir
::{self, Node, PatKind, AssociatedItemKind}
;
14 use rustc
::hir
::def
::Def
;
15 use rustc
::hir
::def_id
::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}
;
16 use rustc
::hir
::intravisit
::{self, Visitor, NestedVisitorMap}
;
17 use rustc
::hir
::itemlikevisit
::DeepVisitor
;
19 use rustc
::middle
::privacy
::{AccessLevel, AccessLevels}
;
20 use rustc
::ty
::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}
;
21 use rustc
::ty
::fold
::TypeVisitor
;
22 use rustc
::ty
::query
::Providers
;
23 use rustc
::ty
::subst
::Substs
;
24 use rustc
::util
::nodemap
::NodeSet
;
25 use rustc_data_structures
::fx
::FxHashSet
;
26 use rustc_data_structures
::sync
::Lrc
;
27 use syntax
::ast
::{self, DUMMY_NODE_ID, Ident}
;
29 use syntax
::symbol
::keywords
;
32 use std
::{cmp, fmt, mem}
;
33 use std
::marker
::PhantomData
;
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Generic infrastructure used to implement specific visitors below.
39 ////////////////////////////////////////////////////////////////////////////////
41 /// Implemented to visit all `DefId`s in a type.
42 /// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them.
43 /// The idea is to visit "all components of a type", as documented in
44 /// https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type.
45 /// The default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings.
46 /// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
47 /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
48 /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
49 trait DefIdVisitor
<'a
, 'tcx
: 'a
> {
50 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
>;
51 fn shallow(&self) -> bool { false }
52 fn skip_assoc_tys(&self) -> bool { false }
53 fn visit_def_id(&mut self, def_id
: DefId
, kind
: &str, descr
: &dyn fmt
::Display
) -> bool
;
55 /// Not overridden, but used to actually visit types and traits.
56 fn skeleton(&mut self) -> DefIdVisitorSkeleton
<'_
, 'a
, 'tcx
, Self> {
57 DefIdVisitorSkeleton
{
59 visited_opaque_tys
: Default
::default(),
60 dummy
: Default
::default(),
63 fn visit(&mut self, ty_fragment
: impl TypeFoldable
<'tcx
>) -> bool
{
64 ty_fragment
.visit_with(&mut self.skeleton())
66 fn visit_trait(&mut self, trait_ref
: TraitRef
<'tcx
>) -> bool
{
67 self.skeleton().visit_trait(trait_ref
)
69 fn visit_predicates(&mut self, predicates
: Lrc
<ty
::GenericPredicates
<'tcx
>>) -> bool
{
70 self.skeleton().visit_predicates(predicates
)
74 struct DefIdVisitorSkeleton
<'v
, 'a
, 'tcx
, V
>
75 where V
: DefIdVisitor
<'a
, 'tcx
> + ?Sized
77 def_id_visitor
: &'v
mut V
,
78 visited_opaque_tys
: FxHashSet
<DefId
>,
79 dummy
: PhantomData
<TyCtxt
<'a
, 'tcx
, 'tcx
>>,
82 impl<'a
, 'tcx
, V
> DefIdVisitorSkeleton
<'_
, 'a
, 'tcx
, V
>
83 where V
: DefIdVisitor
<'a
, 'tcx
> + ?Sized
85 fn visit_trait(&mut self, trait_ref
: TraitRef
<'tcx
>) -> bool
{
86 let TraitRef { def_id, substs }
= trait_ref
;
87 self.def_id_visitor
.visit_def_id(def_id
, "trait", &trait_ref
) ||
88 (!self.def_id_visitor
.shallow() && substs
.visit_with(self))
91 fn visit_predicates(&mut self, predicates
: Lrc
<ty
::GenericPredicates
<'tcx
>>) -> bool
{
92 let ty
::GenericPredicates { parent: _, predicates }
= &*predicates
;
93 for (predicate
, _span
) in predicates
{
95 ty
::Predicate
::Trait(poly_predicate
) => {
96 let ty
::TraitPredicate { trait_ref }
= *poly_predicate
.skip_binder();
97 if self.visit_trait(trait_ref
) {
101 ty
::Predicate
::Projection(poly_predicate
) => {
102 let ty
::ProjectionPredicate { projection_ty, ty }
=
103 *poly_predicate
.skip_binder();
104 if ty
.visit_with(self) {
107 if self.visit_trait(projection_ty
.trait_ref(self.def_id_visitor
.tcx())) {
111 ty
::Predicate
::TypeOutlives(poly_predicate
) => {
112 let ty
::OutlivesPredicate(ty
, _region
) = *poly_predicate
.skip_binder();
113 if ty
.visit_with(self) {
117 ty
::Predicate
::RegionOutlives(..) => {}
,
118 _
=> bug
!("unexpected predicate: {:?}", predicate
),
125 impl<'a
, 'tcx
, V
> TypeVisitor
<'tcx
> for DefIdVisitorSkeleton
<'_
, 'a
, 'tcx
, V
>
126 where V
: DefIdVisitor
<'a
, 'tcx
> + ?Sized
128 fn visit_ty(&mut self, ty
: Ty
<'tcx
>) -> bool
{
129 let tcx
= self.def_id_visitor
.tcx();
130 // Substs are not visited here because they are visited below in `super_visit_with`.
132 ty
::Adt(&ty
::AdtDef { did: def_id, .. }
, ..) |
133 ty
::Foreign(def_id
) |
134 ty
::FnDef(def_id
, ..) |
135 ty
::Closure(def_id
, ..) |
136 ty
::Generator(def_id
, ..) => {
137 if self.def_id_visitor
.visit_def_id(def_id
, "type", ty
) {
140 if self.def_id_visitor
.shallow() {
143 // Default type visitor doesn't visit signatures of fn types.
144 // Something like `fn() -> Priv {my_func}` is considered a private type even if
145 // `my_func` is public, so we need to visit signatures.
146 if let ty
::FnDef(..) = ty
.sty
{
147 if tcx
.fn_sig(def_id
).visit_with(self) {
151 // Inherent static methods don't have self type in substs.
152 // Something like `fn() {my_method}` type of the method
153 // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
154 // so we need to visit the self type additionally.
155 if let Some(assoc_item
) = tcx
.opt_associated_item(def_id
) {
156 if let ty
::ImplContainer(impl_def_id
) = assoc_item
.container
{
157 if tcx
.type_of(impl_def_id
).visit_with(self) {
163 ty
::Projection(proj
) | ty
::UnnormalizedProjection(proj
) => {
164 if self.def_id_visitor
.skip_assoc_tys() {
165 // Visitors searching for minimal visibility/reachability want to
166 // conservatively approximate associated types like `<Type as Trait>::Alias`
167 // as visible/reachable even if both `Type` and `Trait` are private.
168 // Ideally, associated types should be substituted in the same way as
169 // free type aliases, but this isn't done yet.
172 // This will also visit substs if necessary, so we don't need to recurse.
173 return self.visit_trait(proj
.trait_ref(tcx
));
175 ty
::Dynamic(predicates
, ..) => {
176 // All traits in the list are considered the "primary" part of the type
177 // and are visited by shallow visitors.
178 for predicate
in *predicates
.skip_binder() {
179 let trait_ref
= match *predicate
{
180 ty
::ExistentialPredicate
::Trait(trait_ref
) => trait_ref
,
181 ty
::ExistentialPredicate
::Projection(proj
) => proj
.trait_ref(tcx
),
182 ty
::ExistentialPredicate
::AutoTrait(def_id
) =>
183 ty
::ExistentialTraitRef { def_id, substs: Substs::empty() }
,
185 let ty
::ExistentialTraitRef { def_id, substs: _ }
= trait_ref
;
186 if self.def_id_visitor
.visit_def_id(def_id
, "trait", &trait_ref
) {
191 ty
::Opaque(def_id
, ..) => {
192 // Skip repeated `Opaque`s to avoid infinite recursion.
193 if self.visited_opaque_tys
.insert(def_id
) {
194 // The intent is to treat `impl Trait1 + Trait2` identically to
195 // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
196 // (it either has no visibility, or its visibility is insignificant, like
197 // visibilities of type aliases) and recurse into predicates instead to go
198 // through the trait list (default type visitor doesn't visit those traits).
199 // All traits in the list are considered the "primary" part of the type
200 // and are visited by shallow visitors.
201 if self.visit_predicates(tcx
.predicates_of(def_id
)) {
206 // These types don't have their own def-ids (but may have subcomponents
207 // with def-ids that should be visited recursively).
208 ty
::Bool
| ty
::Char
| ty
::Int(..) | ty
::Uint(..) |
209 ty
::Float(..) | ty
::Str
| ty
::Never
|
210 ty
::Array(..) | ty
::Slice(..) | ty
::Tuple(..) |
211 ty
::RawPtr(..) | ty
::Ref(..) | ty
::FnPtr(..) |
212 ty
::Param(..) | ty
::Error
| ty
::GeneratorWitness(..) => {}
213 ty
::Bound(..) | ty
::Placeholder(..) | ty
::Infer(..) =>
214 bug
!("unexpected type: {:?}", ty
),
217 !self.def_id_visitor
.shallow() && ty
.super_visit_with(self)
221 fn def_id_visibility
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>, def_id
: DefId
)
222 -> (ty
::Visibility
, Span
, &'
static str) {
223 match tcx
.hir().as_local_node_id(def_id
) {
225 let vis
= match tcx
.hir().get(node_id
) {
226 Node
::Item(item
) => &item
.vis
,
227 Node
::ForeignItem(foreign_item
) => &foreign_item
.vis
,
228 Node
::TraitItem(..) | Node
::Variant(..) => {
229 return def_id_visibility(tcx
, tcx
.hir().get_parent_did(node_id
));
231 Node
::ImplItem(impl_item
) => {
232 match tcx
.hir().get(tcx
.hir().get_parent(node_id
)) {
233 Node
::Item(item
) => match &item
.node
{
234 hir
::ItemKind
::Impl(.., None
, _
, _
) => &impl_item
.vis
,
235 hir
::ItemKind
::Impl(.., Some(trait_ref
), _
, _
)
236 => return def_id_visibility(tcx
, trait_ref
.path
.def
.def_id()),
237 kind
=> bug
!("unexpected item kind: {:?}", kind
),
239 node
=> bug
!("unexpected node kind: {:?}", node
),
242 Node
::StructCtor(vdata
) => {
243 let struct_node_id
= tcx
.hir().get_parent(node_id
);
244 let item
= match tcx
.hir().get(struct_node_id
) {
245 Node
::Item(item
) => item
,
246 node
=> bug
!("unexpected node kind: {:?}", node
),
248 let (mut ctor_vis
, mut span
, mut descr
) =
249 (ty
::Visibility
::from_hir(&item
.vis
, struct_node_id
, tcx
),
250 item
.vis
.span
, item
.vis
.node
.descr());
251 for field
in vdata
.fields() {
252 let field_vis
= ty
::Visibility
::from_hir(&field
.vis
, node_id
, tcx
);
253 if ctor_vis
.is_at_least(field_vis
, tcx
) {
254 ctor_vis
= field_vis
;
255 span
= field
.vis
.span
;
256 descr
= field
.vis
.node
.descr();
260 // If the structure is marked as non_exhaustive then lower the
261 // visibility to within the crate.
262 if ctor_vis
== ty
::Visibility
::Public
{
263 let adt_def
= tcx
.adt_def(tcx
.hir().get_parent_did(node_id
));
264 if adt_def
.non_enum_variant().is_field_list_non_exhaustive() {
265 ctor_vis
= ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
));
266 span
= attr
::find_by_name(&item
.attrs
, "non_exhaustive").unwrap().span
;
267 descr
= "crate-visible";
271 return (ctor_vis
, span
, descr
);
273 Node
::Expr(expr
) => {
274 return (ty
::Visibility
::Restricted(tcx
.hir().get_module_parent(expr
.id
)),
275 expr
.span
, "private")
277 node
=> bug
!("unexpected node kind: {:?}", node
)
279 (ty
::Visibility
::from_hir(vis
, node_id
, tcx
), vis
.span
, vis
.node
.descr())
282 let vis
= tcx
.visibility(def_id
);
283 let descr
= if vis
== ty
::Visibility
::Public { "public" }
else { "private" }
;
284 (vis
, tcx
.def_span(def_id
), descr
)
289 // Set the correct `TypeckTables` for the given `item_id` (or an empty table if
290 // there is no `TypeckTables` for the item).
291 fn item_tables
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
292 node_id
: ast
::NodeId
,
293 empty_tables
: &'a ty
::TypeckTables
<'tcx
>)
294 -> &'a ty
::TypeckTables
<'tcx
> {
295 let def_id
= tcx
.hir().local_def_id(node_id
);
296 if tcx
.has_typeck_tables(def_id
) { tcx.typeck_tables_of(def_id) }
else { empty_tables }
299 fn min
<'a
, 'tcx
>(vis1
: ty
::Visibility
, vis2
: ty
::Visibility
, tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>)
301 if vis1
.is_at_least(vis2
, tcx
) { vis2 }
else { vis1 }
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Visitor used to determine if pub(restricted) is used anywhere in the crate.
307 /// This is done so that `private_in_public` warnings can be turned into hard errors
308 /// in crates that have been updated to use pub(restricted).
309 ////////////////////////////////////////////////////////////////////////////////
310 struct PubRestrictedVisitor
<'a
, 'tcx
: 'a
> {
311 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
312 has_pub_restricted
: bool
,
315 impl<'a
, 'tcx
> Visitor
<'tcx
> for PubRestrictedVisitor
<'a
, 'tcx
> {
316 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
317 NestedVisitorMap
::All(&self.tcx
.hir())
319 fn visit_vis(&mut self, vis
: &'tcx hir
::Visibility
) {
320 self.has_pub_restricted
= self.has_pub_restricted
|| vis
.node
.is_pub_restricted();
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Visitor used to determine impl visibility and reachability.
326 ////////////////////////////////////////////////////////////////////////////////
328 struct FindMin
<'a
, 'tcx
, VL
: VisibilityLike
> {
329 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
330 access_levels
: &'a AccessLevels
,
334 impl<'a
, 'tcx
, VL
: VisibilityLike
> DefIdVisitor
<'a
, 'tcx
> for FindMin
<'a
, 'tcx
, VL
> {
335 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> { self.tcx }
336 fn shallow(&self) -> bool { VL::SHALLOW }
337 fn skip_assoc_tys(&self) -> bool { true }
338 fn visit_def_id(&mut self, def_id
: DefId
, _kind
: &str, _descr
: &dyn fmt
::Display
) -> bool
{
339 self.min
= VL
::new_min(self, def_id
);
344 trait VisibilityLike
: Sized
{
346 const SHALLOW
: bool
= false;
347 fn new_min
<'a
, 'tcx
>(find
: &FindMin
<'a
, 'tcx
, Self>, def_id
: DefId
) -> Self;
349 // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
350 // associated types for which we can't determine visibility precisely.
351 fn of_impl
<'a
, 'tcx
>(node_id
: ast
::NodeId
, tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
352 access_levels
: &'a AccessLevels
) -> Self {
353 let mut find
= FindMin { tcx, access_levels, min: Self::MAX }
;
354 let def_id
= tcx
.hir().local_def_id(node_id
);
355 find
.visit(tcx
.type_of(def_id
));
356 if let Some(trait_ref
) = tcx
.impl_trait_ref(def_id
) {
357 find
.visit_trait(trait_ref
);
362 impl VisibilityLike
for ty
::Visibility
{
363 const MAX
: Self = ty
::Visibility
::Public
;
364 fn new_min
<'a
, 'tcx
>(find
: &FindMin
<'a
, 'tcx
, Self>, def_id
: DefId
) -> Self {
365 min(def_id_visibility(find
.tcx
, def_id
).0, find
.min
, find
.tcx
)
368 impl VisibilityLike
for Option
<AccessLevel
> {
369 const MAX
: Self = Some(AccessLevel
::Public
);
370 // Type inference is very smart sometimes.
371 // It can make an impl reachable even some components of its type or trait are unreachable.
372 // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
373 // can be usable from other crates (#57264). So we skip substs when calculating reachability
374 // and consider an impl reachable if its "shallow" type and trait are reachable.
376 // The assumption we make here is that type-inference won't let you use an impl without knowing
377 // both "shallow" version of its self type and "shallow" version of its trait if it exists
378 // (which require reaching the `DefId`s in them).
379 const SHALLOW
: bool
= true;
380 fn new_min
<'a
, 'tcx
>(find
: &FindMin
<'a
, 'tcx
, Self>, def_id
: DefId
) -> Self {
381 cmp
::min(if let Some(node_id
) = find
.tcx
.hir().as_local_node_id(def_id
) {
382 find
.access_levels
.map
.get(&node_id
).cloned()
389 ////////////////////////////////////////////////////////////////////////////////
390 /// The embargo visitor, used to determine the exports of the AST.
391 ////////////////////////////////////////////////////////////////////////////////
393 struct EmbargoVisitor
<'a
, 'tcx
: 'a
> {
394 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
396 // Accessibility levels for reachable nodes.
397 access_levels
: AccessLevels
,
398 // Previous accessibility level; `None` means unreachable.
399 prev_level
: Option
<AccessLevel
>,
400 // Has something changed in the level map?
404 struct ReachEverythingInTheInterfaceVisitor
<'b
, 'a
: 'b
, 'tcx
: 'a
> {
405 access_level
: Option
<AccessLevel
>,
407 ev
: &'b
mut EmbargoVisitor
<'a
, 'tcx
>,
410 impl<'a
, 'tcx
> EmbargoVisitor
<'a
, 'tcx
> {
411 fn get(&self, id
: ast
::NodeId
) -> Option
<AccessLevel
> {
412 self.access_levels
.map
.get(&id
).cloned()
415 // Updates node level and returns the updated level.
416 fn update(&mut self, id
: ast
::NodeId
, level
: Option
<AccessLevel
>) -> Option
<AccessLevel
> {
417 let old_level
= self.get(id
);
418 // Accessibility levels can only grow.
419 if level
> old_level
{
420 self.access_levels
.map
.insert(id
, level
.unwrap());
428 fn reach(&mut self, item_id
: ast
::NodeId
, access_level
: Option
<AccessLevel
>)
429 -> ReachEverythingInTheInterfaceVisitor
<'_
, 'a
, 'tcx
> {
430 ReachEverythingInTheInterfaceVisitor
{
431 access_level
: cmp
::min(access_level
, Some(AccessLevel
::Reachable
)),
432 item_def_id
: self.tcx
.hir().local_def_id(item_id
),
438 /// Given the path segments of a `ItemKind::Use`, then we need
439 /// to update the visibility of the intermediate use so that it isn't linted
440 /// by `unreachable_pub`.
442 /// This isn't trivial as `path.def` has the `DefId` of the eventual target
443 /// of the use statement not of the next intermediate use statement.
445 /// To do this, consider the last two segments of the path to our intermediate
446 /// use statement. We expect the penultimate segment to be a module and the
447 /// last segment to be the name of the item we are exporting. We can then
448 /// look at the items contained in the module for the use statement with that
449 /// name and update that item's visibility.
451 /// FIXME: This solution won't work with glob imports and doesn't respect
452 /// namespaces. See <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
453 fn update_visibility_of_intermediate_use_statements(&mut self, segments
: &[hir
::PathSegment
]) {
454 if let Some([module
, segment
]) = segments
.rchunks_exact(2).next() {
455 if let Some(item
) = module
.def
456 .and_then(|def
| def
.mod_def_id())
457 .and_then(|def_id
| self.tcx
.hir().as_local_hir_id(def_id
))
458 .map(|module_hir_id
| self.tcx
.hir().expect_item_by_hir_id(module_hir_id
))
460 if let hir
::ItemKind
::Mod(m
) = &item
.node
{
461 for item_id
in m
.item_ids
.as_ref() {
462 let item
= self.tcx
.hir().expect_item(item_id
.id
);
463 let def_id
= self.tcx
.hir().local_def_id(item_id
.id
);
464 if !self.tcx
.hygienic_eq(segment
.ident
, item
.ident
, def_id
) { continue; }
465 if let hir
::ItemKind
::Use(..) = item
.node
{
466 self.update(item
.id
, Some(AccessLevel
::Exported
));
475 impl<'a
, 'tcx
> Visitor
<'tcx
> for EmbargoVisitor
<'a
, 'tcx
> {
476 /// We want to visit items in the context of their containing
477 /// module and so forth, so supply a crate for doing a deep walk.
478 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
479 NestedVisitorMap
::All(&self.tcx
.hir())
482 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
483 let inherited_item_level
= match item
.node
{
484 hir
::ItemKind
::Impl(..) =>
485 Option
::<AccessLevel
>::of_impl(item
.id
, self.tcx
, &self.access_levels
),
486 // Foreign modules inherit level from parents.
487 hir
::ItemKind
::ForeignMod(..) => self.prev_level
,
488 // Other `pub` items inherit levels from parents.
489 hir
::ItemKind
::Const(..) | hir
::ItemKind
::Enum(..) | hir
::ItemKind
::ExternCrate(..) |
490 hir
::ItemKind
::GlobalAsm(..) | hir
::ItemKind
::Fn(..) | hir
::ItemKind
::Mod(..) |
491 hir
::ItemKind
::Static(..) | hir
::ItemKind
::Struct(..) |
492 hir
::ItemKind
::Trait(..) | hir
::ItemKind
::TraitAlias(..) |
493 hir
::ItemKind
::Existential(..) |
494 hir
::ItemKind
::Ty(..) | hir
::ItemKind
::Union(..) | hir
::ItemKind
::Use(..) => {
495 if item
.vis
.node
.is_pub() { self.prev_level }
else { None }
499 // Update level of the item itself.
500 let item_level
= self.update(item
.id
, inherited_item_level
);
502 // Update levels of nested things.
504 hir
::ItemKind
::Enum(ref def
, _
) => {
505 for variant
in &def
.variants
{
506 let variant_level
= self.update(variant
.node
.data
.id(), item_level
);
507 for field
in variant
.node
.data
.fields() {
508 self.update(field
.id
, variant_level
);
512 hir
::ItemKind
::Impl(.., ref trait_ref
, _
, ref impl_item_refs
) => {
513 for impl_item_ref
in impl_item_refs
{
514 if trait_ref
.is_some() || impl_item_ref
.vis
.node
.is_pub() {
515 self.update(impl_item_ref
.id
.node_id
, item_level
);
519 hir
::ItemKind
::Trait(.., ref trait_item_refs
) => {
520 for trait_item_ref
in trait_item_refs
{
521 self.update(trait_item_ref
.id
.node_id
, item_level
);
524 hir
::ItemKind
::Struct(ref def
, _
) | hir
::ItemKind
::Union(ref def
, _
) => {
525 if !def
.is_struct() {
526 self.update(def
.id(), item_level
);
528 for field
in def
.fields() {
529 if field
.vis
.node
.is_pub() {
530 self.update(field
.id
, item_level
);
534 hir
::ItemKind
::ForeignMod(ref foreign_mod
) => {
535 for foreign_item
in &foreign_mod
.items
{
536 if foreign_item
.vis
.node
.is_pub() {
537 self.update(foreign_item
.id
, item_level
);
541 hir
::ItemKind
::Existential(..) |
542 hir
::ItemKind
::Use(..) |
543 hir
::ItemKind
::Static(..) |
544 hir
::ItemKind
::Const(..) |
545 hir
::ItemKind
::GlobalAsm(..) |
546 hir
::ItemKind
::Ty(..) |
547 hir
::ItemKind
::Mod(..) |
548 hir
::ItemKind
::TraitAlias(..) |
549 hir
::ItemKind
::Fn(..) |
550 hir
::ItemKind
::ExternCrate(..) => {}
553 // Mark all items in interfaces of reachable items as reachable.
555 // The interface is empty.
556 hir
::ItemKind
::ExternCrate(..) => {}
557 // All nested items are checked by `visit_item`.
558 hir
::ItemKind
::Mod(..) => {}
559 // Re-exports are handled in `visit_mod`. However, in order to avoid looping over
560 // all of the items of a mod in `visit_mod` looking for use statements, we handle
561 // making sure that intermediate use statements have their visibilities updated here.
562 hir
::ItemKind
::Use(ref path
, _
) => {
563 if item_level
.is_some() {
564 self.update_visibility_of_intermediate_use_statements(path
.segments
.as_ref());
567 // The interface is empty.
568 hir
::ItemKind
::GlobalAsm(..) => {}
569 hir
::ItemKind
::Existential(..) => {
570 // FIXME: This is some serious pessimization intended to workaround deficiencies
571 // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
572 // reachable if they are returned via `impl Trait`, even from private functions.
573 let exist_level
= cmp
::max(item_level
, Some(AccessLevel
::ReachableFromImplTrait
));
574 self.reach(item
.id
, exist_level
).generics().predicates().ty();
577 hir
::ItemKind
::Const(..) | hir
::ItemKind
::Static(..) |
578 hir
::ItemKind
::Fn(..) | hir
::ItemKind
::Ty(..) => {
579 if item_level
.is_some() {
580 self.reach(item
.id
, item_level
).generics().predicates().ty();
583 hir
::ItemKind
::Trait(.., ref trait_item_refs
) => {
584 if item_level
.is_some() {
585 self.reach(item
.id
, item_level
).generics().predicates();
587 for trait_item_ref
in trait_item_refs
{
588 let mut reach
= self.reach(trait_item_ref
.id
.node_id
, item_level
);
589 reach
.generics().predicates();
591 if trait_item_ref
.kind
== AssociatedItemKind
::Type
&&
592 !trait_item_ref
.defaultness
.has_value() {
600 hir
::ItemKind
::TraitAlias(..) => {
601 if item_level
.is_some() {
602 self.reach(item
.id
, item_level
).generics().predicates();
605 // Visit everything except for private impl items.
606 hir
::ItemKind
::Impl(.., ref impl_item_refs
) => {
607 if item_level
.is_some() {
608 self.reach(item
.id
, item_level
).generics().predicates().ty().trait_ref();
610 for impl_item_ref
in impl_item_refs
{
611 let impl_item_level
= self.get(impl_item_ref
.id
.node_id
);
612 if impl_item_level
.is_some() {
613 self.reach(impl_item_ref
.id
.node_id
, impl_item_level
)
614 .generics().predicates().ty();
620 // Visit everything, but enum variants have their own levels.
621 hir
::ItemKind
::Enum(ref def
, _
) => {
622 if item_level
.is_some() {
623 self.reach(item
.id
, item_level
).generics().predicates();
625 for variant
in &def
.variants
{
626 let variant_level
= self.get(variant
.node
.data
.id());
627 if variant_level
.is_some() {
628 for field
in variant
.node
.data
.fields() {
629 self.reach(field
.id
, variant_level
).ty();
631 // Corner case: if the variant is reachable, but its
632 // enum is not, make the enum reachable as well.
633 self.update(item
.id
, variant_level
);
637 // Visit everything, but foreign items have their own levels.
638 hir
::ItemKind
::ForeignMod(ref foreign_mod
) => {
639 for foreign_item
in &foreign_mod
.items
{
640 let foreign_item_level
= self.get(foreign_item
.id
);
641 if foreign_item_level
.is_some() {
642 self.reach(foreign_item
.id
, foreign_item_level
)
643 .generics().predicates().ty();
647 // Visit everything except for private fields.
648 hir
::ItemKind
::Struct(ref struct_def
, _
) |
649 hir
::ItemKind
::Union(ref struct_def
, _
) => {
650 if item_level
.is_some() {
651 self.reach(item
.id
, item_level
).generics().predicates();
652 for field
in struct_def
.fields() {
653 let field_level
= self.get(field
.id
);
654 if field_level
.is_some() {
655 self.reach(field
.id
, field_level
).ty();
662 let orig_level
= mem
::replace(&mut self.prev_level
, item_level
);
663 intravisit
::walk_item(self, item
);
664 self.prev_level
= orig_level
;
667 fn visit_block(&mut self, b
: &'tcx hir
::Block
) {
668 // Blocks can have public items, for example impls, but they always
669 // start as completely private regardless of publicity of a function,
670 // constant, type, field, etc., in which this block resides.
671 let orig_level
= mem
::replace(&mut self.prev_level
, None
);
672 intravisit
::walk_block(self, b
);
673 self.prev_level
= orig_level
;
676 fn visit_mod(&mut self, m
: &'tcx hir
::Mod
, _sp
: Span
, id
: hir
::HirId
) {
677 // This code is here instead of in visit_item so that the
678 // crate module gets processed as well.
679 if self.prev_level
.is_some() {
680 let def_id
= self.tcx
.hir().local_def_id_from_hir_id(id
);
681 if let Some(exports
) = self.tcx
.module_exports(def_id
) {
682 for export
in exports
.iter() {
683 if export
.vis
== ty
::Visibility
::Public
{
684 if let Some(def_id
) = export
.def
.opt_def_id() {
685 if let Some(node_id
) = self.tcx
.hir().as_local_node_id(def_id
) {
686 self.update(node_id
, Some(AccessLevel
::Exported
));
694 intravisit
::walk_mod(self, m
, id
);
697 fn visit_macro_def(&mut self, md
: &'tcx hir
::MacroDef
) {
699 self.update(md
.id
, Some(AccessLevel
::Public
));
703 let module_did
= ty
::DefIdTree
::parent(
705 self.tcx
.hir().local_def_id(md
.id
)
707 let mut module_id
= self.tcx
.hir().as_local_node_id(module_did
).unwrap();
708 let level
= if md
.vis
.node
.is_pub() { self.get(module_id) }
else { None }
;
709 let level
= self.update(md
.id
, level
);
715 let module
= if module_id
== ast
::CRATE_NODE_ID
{
716 &self.tcx
.hir().krate().module
717 } else if let hir
::ItemKind
::Mod(ref module
) =
718 self.tcx
.hir().expect_item(module_id
).node
{
723 for id
in &module
.item_ids
{
724 self.update(id
.id
, level
);
726 let def_id
= self.tcx
.hir().local_def_id(module_id
);
727 if let Some(exports
) = self.tcx
.module_exports(def_id
) {
728 for export
in exports
.iter() {
729 if let Some(node_id
) = self.tcx
.hir().as_local_node_id(export
.def
.def_id()) {
730 self.update(node_id
, level
);
735 if module_id
== ast
::CRATE_NODE_ID
{
738 module_id
= self.tcx
.hir().get_parent_node(module_id
);
743 impl<'a
, 'tcx
> ReachEverythingInTheInterfaceVisitor
<'_
, 'a
, 'tcx
> {
744 fn generics(&mut self) -> &mut Self {
745 for param
in &self.ev
.tcx
.generics_of(self.item_def_id
).params
{
747 GenericParamDefKind
::Type { has_default, .. }
=> {
749 self.visit(self.ev
.tcx
.type_of(param
.def_id
));
752 GenericParamDefKind
::Lifetime
=> {}
758 fn predicates(&mut self) -> &mut Self {
759 self.visit_predicates(self.ev
.tcx
.predicates_of(self.item_def_id
));
763 fn ty(&mut self) -> &mut Self {
764 self.visit(self.ev
.tcx
.type_of(self.item_def_id
));
768 fn trait_ref(&mut self) -> &mut Self {
769 if let Some(trait_ref
) = self.ev
.tcx
.impl_trait_ref(self.item_def_id
) {
770 self.visit_trait(trait_ref
);
776 impl<'a
, 'tcx
> DefIdVisitor
<'a
, 'tcx
> for ReachEverythingInTheInterfaceVisitor
<'_
, 'a
, 'tcx
> {
777 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> { self.ev.tcx }
778 fn visit_def_id(&mut self, def_id
: DefId
, _kind
: &str, _descr
: &dyn fmt
::Display
) -> bool
{
779 if let Some(node_id
) = self.ev
.tcx
.hir().as_local_node_id(def_id
) {
780 self.ev
.update(node_id
, self.access_level
);
786 //////////////////////////////////////////////////////////////////////////////////////
787 /// Name privacy visitor, checks privacy and reports violations.
788 /// Most of name privacy checks are performed during the main resolution phase,
789 /// or later in type checking when field accesses and associated items are resolved.
790 /// This pass performs remaining checks for fields in struct expressions and patterns.
791 //////////////////////////////////////////////////////////////////////////////////////
793 struct NamePrivacyVisitor
<'a
, 'tcx
: 'a
> {
794 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
795 tables
: &'a ty
::TypeckTables
<'tcx
>,
796 current_item
: ast
::NodeId
,
797 empty_tables
: &'a ty
::TypeckTables
<'tcx
>,
800 impl<'a
, 'tcx
> NamePrivacyVisitor
<'a
, 'tcx
> {
801 // Checks that a field in a struct constructor (expression or pattern) is accessible.
802 fn check_field(&mut self,
803 use_ctxt
: Span
, // syntax context of the field name at the use site
804 span
: Span
, // span of the field pattern, e.g., `x: 0`
805 def
: &'tcx ty
::AdtDef
, // definition of the struct or enum
806 field
: &'tcx ty
::FieldDef
) { // definition of the field
807 let ident
= Ident
::new(keywords
::Invalid
.name(), use_ctxt
);
808 let current_hir
= self.tcx
.hir().node_to_hir_id(self.current_item
);
809 let def_id
= self.tcx
.adjust_ident(ident
, def
.did
, current_hir
).1;
810 if !def
.is_enum() && !field
.vis
.is_accessible_from(def_id
, self.tcx
) {
811 struct_span_err
!(self.tcx
.sess
, span
, E0451
, "field `{}` of {} `{}` is private",
812 field
.ident
, def
.variant_descr(), self.tcx
.item_path_str(def
.did
))
813 .span_label(span
, format
!("field `{}` is private", field
.ident
))
819 impl<'a
, 'tcx
> Visitor
<'tcx
> for NamePrivacyVisitor
<'a
, 'tcx
> {
820 /// We want to visit items in the context of their containing
821 /// module and so forth, so supply a crate for doing a deep walk.
822 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
823 NestedVisitorMap
::All(&self.tcx
.hir())
826 fn visit_mod(&mut self, _m
: &'tcx hir
::Mod
, _s
: Span
, _n
: hir
::HirId
) {
827 // Don't visit nested modules, since we run a separate visitor walk
828 // for each module in `privacy_access_levels`
831 fn visit_nested_body(&mut self, body
: hir
::BodyId
) {
832 let orig_tables
= mem
::replace(&mut self.tables
, self.tcx
.body_tables(body
));
833 let body
= self.tcx
.hir().body(body
);
834 self.visit_body(body
);
835 self.tables
= orig_tables
;
838 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
839 let orig_current_item
= mem
::replace(&mut self.current_item
, item
.id
);
841 mem
::replace(&mut self.tables
, item_tables(self.tcx
, item
.id
, self.empty_tables
));
842 intravisit
::walk_item(self, item
);
843 self.current_item
= orig_current_item
;
844 self.tables
= orig_tables
;
847 fn visit_trait_item(&mut self, ti
: &'tcx hir
::TraitItem
) {
849 mem
::replace(&mut self.tables
, item_tables(self.tcx
, ti
.id
, self.empty_tables
));
850 intravisit
::walk_trait_item(self, ti
);
851 self.tables
= orig_tables
;
854 fn visit_impl_item(&mut self, ii
: &'tcx hir
::ImplItem
) {
856 mem
::replace(&mut self.tables
, item_tables(self.tcx
, ii
.id
, self.empty_tables
));
857 intravisit
::walk_impl_item(self, ii
);
858 self.tables
= orig_tables
;
861 fn visit_expr(&mut self, expr
: &'tcx hir
::Expr
) {
863 hir
::ExprKind
::Struct(ref qpath
, ref fields
, ref base
) => {
864 let def
= self.tables
.qpath_def(qpath
, expr
.hir_id
);
865 let adt
= self.tables
.expr_ty(expr
).ty_adt_def().unwrap();
866 let variant
= adt
.variant_of_def(def
);
867 if let Some(ref base
) = *base
{
868 // If the expression uses FRU we need to make sure all the unmentioned fields
869 // are checked for privacy (RFC 736). Rather than computing the set of
870 // unmentioned fields, just check them all.
871 for (vf_index
, variant_field
) in variant
.fields
.iter().enumerate() {
872 let field
= fields
.iter().find(|f
| {
873 self.tcx
.field_index(f
.id
, self.tables
) == vf_index
875 let (use_ctxt
, span
) = match field
{
876 Some(field
) => (field
.ident
.span
, field
.span
),
877 None
=> (base
.span
, base
.span
),
879 self.check_field(use_ctxt
, span
, adt
, variant_field
);
882 for field
in fields
{
883 let use_ctxt
= field
.ident
.span
;
884 let index
= self.tcx
.field_index(field
.id
, self.tables
);
885 self.check_field(use_ctxt
, field
.span
, adt
, &variant
.fields
[index
]);
892 intravisit
::walk_expr(self, expr
);
895 fn visit_pat(&mut self, pat
: &'tcx hir
::Pat
) {
897 PatKind
::Struct(ref qpath
, ref fields
, _
) => {
898 let def
= self.tables
.qpath_def(qpath
, pat
.hir_id
);
899 let adt
= self.tables
.pat_ty(pat
).ty_adt_def().unwrap();
900 let variant
= adt
.variant_of_def(def
);
901 for field
in fields
{
902 let use_ctxt
= field
.node
.ident
.span
;
903 let index
= self.tcx
.field_index(field
.node
.id
, self.tables
);
904 self.check_field(use_ctxt
, field
.span
, adt
, &variant
.fields
[index
]);
910 intravisit
::walk_pat(self, pat
);
914 ////////////////////////////////////////////////////////////////////////////////////////////
915 /// Type privacy visitor, checks types for privacy and reports violations.
916 /// Both explicitly written types and inferred types of expressions and patters are checked.
917 /// Checks are performed on "semantic" types regardless of names and their hygiene.
918 ////////////////////////////////////////////////////////////////////////////////////////////
920 struct TypePrivacyVisitor
<'a
, 'tcx
: 'a
> {
921 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
922 tables
: &'a ty
::TypeckTables
<'tcx
>,
926 empty_tables
: &'a ty
::TypeckTables
<'tcx
>,
929 impl<'a
, 'tcx
> TypePrivacyVisitor
<'a
, 'tcx
> {
930 fn item_is_accessible(&self, did
: DefId
) -> bool
{
931 def_id_visibility(self.tcx
, did
).0.is_accessible_from
(self.current_item
, self.tcx
)
934 // Take node-id of an expression or pattern and check its type for privacy.
935 fn check_expr_pat_type(&mut self, id
: hir
::HirId
, span
: Span
) -> bool
{
937 if self.visit(self.tables
.node_type(id
)) || self.visit(self.tables
.node_substs(id
)) {
940 if let Some(adjustments
) = self.tables
.adjustments().get(id
) {
941 for adjustment
in adjustments
{
942 if self.visit(adjustment
.target
) {
950 fn check_def_id(&mut self, def_id
: DefId
, kind
: &str, descr
: &dyn fmt
::Display
) -> bool
{
951 let is_error
= !self.item_is_accessible(def_id
);
953 self.tcx
.sess
.span_err(self.span
, &format
!("{} `{}` is private", kind
, descr
));
959 impl<'a
, 'tcx
> Visitor
<'tcx
> for TypePrivacyVisitor
<'a
, 'tcx
> {
960 /// We want to visit items in the context of their containing
961 /// module and so forth, so supply a crate for doing a deep walk.
962 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
963 NestedVisitorMap
::All(&self.tcx
.hir())
966 fn visit_mod(&mut self, _m
: &'tcx hir
::Mod
, _s
: Span
, _n
: hir
::HirId
) {
967 // Don't visit nested modules, since we run a separate visitor walk
968 // for each module in `privacy_access_levels`
971 fn visit_nested_body(&mut self, body
: hir
::BodyId
) {
972 let orig_tables
= mem
::replace(&mut self.tables
, self.tcx
.body_tables(body
));
973 let orig_in_body
= mem
::replace(&mut self.in_body
, true);
974 let body
= self.tcx
.hir().body(body
);
975 self.visit_body(body
);
976 self.tables
= orig_tables
;
977 self.in_body
= orig_in_body
;
980 fn visit_ty(&mut self, hir_ty
: &'tcx hir
::Ty
) {
981 self.span
= hir_ty
.span
;
984 if self.visit(self.tables
.node_type(hir_ty
.hir_id
)) {
988 // Types in signatures.
989 // FIXME: This is very ineffective. Ideally each HIR type should be converted
990 // into a semantic type only once and the result should be cached somehow.
991 if self.visit(rustc_typeck
::hir_ty_to_ty(self.tcx
, hir_ty
)) {
996 intravisit
::walk_ty(self, hir_ty
);
999 fn visit_trait_ref(&mut self, trait_ref
: &'tcx hir
::TraitRef
) {
1000 self.span
= trait_ref
.path
.span
;
1002 // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
1003 // The traits' privacy in bodies is already checked as a part of trait object types.
1004 let (principal
, projections
) =
1005 rustc_typeck
::hir_trait_to_predicates(self.tcx
, trait_ref
);
1006 if self.visit_trait(*principal
.skip_binder()) {
1009 for (poly_predicate
, _
) in projections
{
1011 if self.visit(poly_predicate
.skip_binder().ty
) ||
1012 self.visit_trait(poly_predicate
.skip_binder().projection_ty
.trait_ref(tcx
)) {
1018 intravisit
::walk_trait_ref(self, trait_ref
);
1021 // Check types of expressions
1022 fn visit_expr(&mut self, expr
: &'tcx hir
::Expr
) {
1023 if self.check_expr_pat_type(expr
.hir_id
, expr
.span
) {
1024 // Do not check nested expressions if the error already happened.
1028 hir
::ExprKind
::Assign(.., ref rhs
) | hir
::ExprKind
::Match(ref rhs
, ..) => {
1029 // Do not report duplicate errors for `x = y` and `match x { ... }`.
1030 if self.check_expr_pat_type(rhs
.hir_id
, rhs
.span
) {
1034 hir
::ExprKind
::MethodCall(_
, span
, _
) => {
1035 // Method calls have to be checked specially.
1037 if let Some(def
) = self.tables
.type_dependent_defs().get(expr
.hir_id
) {
1038 if self.visit(self.tcx
.type_of(def
.def_id())) {
1042 self.tcx
.sess
.delay_span_bug(expr
.span
,
1043 "no type-dependent def for method call");
1049 intravisit
::walk_expr(self, expr
);
1052 // Prohibit access to associated items with insufficient nominal visibility.
1054 // Additionally, until better reachability analysis for macros 2.0 is available,
1055 // we prohibit access to private statics from other crates, this allows to give
1056 // more code internal visibility at link time. (Access to private functions
1057 // is already prohibited by type privacy for function types.)
1058 fn visit_qpath(&mut self, qpath
: &'tcx hir
::QPath
, id
: hir
::HirId
, span
: Span
) {
1059 let def
= match *qpath
{
1060 hir
::QPath
::Resolved(_
, ref path
) => match path
.def
{
1061 Def
::Method(..) | Def
::AssociatedConst(..) |
1062 Def
::AssociatedTy(..) | Def
::AssociatedExistential(..) |
1063 Def
::Static(..) => Some(path
.def
),
1066 hir
::QPath
::TypeRelative(..) => {
1067 self.tables
.type_dependent_defs().get(id
).cloned()
1070 if let Some(def
) = def
{
1071 let def_id
= def
.def_id();
1072 let is_local_static
= if let Def
::Static(..) = def { def_id.is_local() }
else { false }
;
1073 if !self.item_is_accessible(def_id
) && !is_local_static
{
1074 let name
= match *qpath
{
1075 hir
::QPath
::Resolved(_
, ref path
) => path
.to_string(),
1076 hir
::QPath
::TypeRelative(_
, ref segment
) => segment
.ident
.to_string(),
1078 let msg
= format
!("{} `{}` is private", def
.kind_name(), name
);
1079 self.tcx
.sess
.span_err(span
, &msg
);
1084 intravisit
::walk_qpath(self, qpath
, id
, span
);
1087 // Check types of patterns.
1088 fn visit_pat(&mut self, pattern
: &'tcx hir
::Pat
) {
1089 if self.check_expr_pat_type(pattern
.hir_id
, pattern
.span
) {
1090 // Do not check nested patterns if the error already happened.
1094 intravisit
::walk_pat(self, pattern
);
1097 fn visit_local(&mut self, local
: &'tcx hir
::Local
) {
1098 if let Some(ref init
) = local
.init
{
1099 if self.check_expr_pat_type(init
.hir_id
, init
.span
) {
1100 // Do not report duplicate errors for `let x = y`.
1105 intravisit
::walk_local(self, local
);
1108 // Check types in item interfaces.
1109 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
1110 let orig_current_item
=
1111 mem
::replace(&mut self.current_item
, self.tcx
.hir().local_def_id(item
.id
));
1112 let orig_in_body
= mem
::replace(&mut self.in_body
, false);
1114 mem
::replace(&mut self.tables
, item_tables(self.tcx
, item
.id
, self.empty_tables
));
1115 intravisit
::walk_item(self, item
);
1116 self.tables
= orig_tables
;
1117 self.in_body
= orig_in_body
;
1118 self.current_item
= orig_current_item
;
1121 fn visit_trait_item(&mut self, ti
: &'tcx hir
::TraitItem
) {
1123 mem
::replace(&mut self.tables
, item_tables(self.tcx
, ti
.id
, self.empty_tables
));
1124 intravisit
::walk_trait_item(self, ti
);
1125 self.tables
= orig_tables
;
1128 fn visit_impl_item(&mut self, ii
: &'tcx hir
::ImplItem
) {
1130 mem
::replace(&mut self.tables
, item_tables(self.tcx
, ii
.id
, self.empty_tables
));
1131 intravisit
::walk_impl_item(self, ii
);
1132 self.tables
= orig_tables
;
1136 impl<'a
, 'tcx
> DefIdVisitor
<'a
, 'tcx
> for TypePrivacyVisitor
<'a
, 'tcx
> {
1137 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> { self.tcx }
1138 fn visit_def_id(&mut self, def_id
: DefId
, kind
: &str, descr
: &dyn fmt
::Display
) -> bool
{
1139 self.check_def_id(def_id
, kind
, descr
)
1143 ///////////////////////////////////////////////////////////////////////////////
1144 /// Obsolete visitors for checking for private items in public interfaces.
1145 /// These visitors are supposed to be kept in frozen state and produce an
1146 /// "old error node set". For backward compatibility the new visitor reports
1147 /// warnings instead of hard errors when the erroneous node is not in this old set.
1148 ///////////////////////////////////////////////////////////////////////////////
1150 struct ObsoleteVisiblePrivateTypesVisitor
<'a
, 'tcx
: 'a
> {
1151 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1152 access_levels
: &'a AccessLevels
,
1154 // Set of errors produced by this obsolete visitor.
1155 old_error_set
: NodeSet
,
1158 struct ObsoleteCheckTypeForPrivatenessVisitor
<'a
, 'b
: 'a
, 'tcx
: 'b
> {
1159 inner
: &'a ObsoleteVisiblePrivateTypesVisitor
<'b
, 'tcx
>,
1160 /// Whether the type refers to private types.
1161 contains_private
: bool
,
1162 /// Whether we've recurred at all (i.e., if we're pointing at the
1163 /// first type on which `visit_ty` was called).
1164 at_outer_type
: bool
,
1165 /// Whether that first type is a public path.
1166 outer_type_is_public_path
: bool
,
1169 impl<'a
, 'tcx
> ObsoleteVisiblePrivateTypesVisitor
<'a
, 'tcx
> {
1170 fn path_is_private_type(&self, path
: &hir
::Path
) -> bool
{
1171 let did
= match path
.def
{
1172 Def
::PrimTy(..) | Def
::SelfTy(..) | Def
::Err
=> return false,
1173 def
=> def
.def_id(),
1176 // A path can only be private if:
1177 // it's in this crate...
1178 if let Some(node_id
) = self.tcx
.hir().as_local_node_id(did
) {
1179 // .. and it corresponds to a private type in the AST (this returns
1180 // `None` for type parameters).
1181 match self.tcx
.hir().find(node_id
) {
1182 Some(Node
::Item(ref item
)) => !item
.vis
.node
.is_pub(),
1183 Some(_
) | None
=> false,
1190 fn trait_is_public(&self, trait_id
: ast
::NodeId
) -> bool
{
1191 // FIXME: this would preferably be using `exported_items`, but all
1192 // traits are exported currently (see `EmbargoVisitor.exported_trait`).
1193 self.access_levels
.is_public(trait_id
)
1196 fn check_generic_bound(&mut self, bound
: &hir
::GenericBound
) {
1197 if let hir
::GenericBound
::Trait(ref trait_ref
, _
) = *bound
{
1198 if self.path_is_private_type(&trait_ref
.trait_ref
.path
) {
1199 self.old_error_set
.insert(trait_ref
.trait_ref
.ref_id
);
1204 fn item_is_public(&self, id
: &ast
::NodeId
, vis
: &hir
::Visibility
) -> bool
{
1205 self.access_levels
.is_reachable(*id
) || vis
.node
.is_pub()
1209 impl<'a
, 'b
, 'tcx
, 'v
> Visitor
<'v
> for ObsoleteCheckTypeForPrivatenessVisitor
<'a
, 'b
, 'tcx
> {
1210 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'v
> {
1211 NestedVisitorMap
::None
1214 fn visit_ty(&mut self, ty
: &hir
::Ty
) {
1215 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(_
, ref path
)) = ty
.node
{
1216 if self.inner
.path_is_private_type(path
) {
1217 self.contains_private
= true;
1218 // Found what we're looking for, so let's stop working.
1222 if let hir
::TyKind
::Path(_
) = ty
.node
{
1223 if self.at_outer_type
{
1224 self.outer_type_is_public_path
= true;
1227 self.at_outer_type
= false;
1228 intravisit
::walk_ty(self, ty
)
1231 // Don't want to recurse into `[, .. expr]`.
1232 fn visit_expr(&mut self, _
: &hir
::Expr
) {}
1235 impl<'a
, 'tcx
> Visitor
<'tcx
> for ObsoleteVisiblePrivateTypesVisitor
<'a
, 'tcx
> {
1236 /// We want to visit items in the context of their containing
1237 /// module and so forth, so supply a crate for doing a deep walk.
1238 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
1239 NestedVisitorMap
::All(&self.tcx
.hir())
1242 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
1244 // Contents of a private mod can be re-exported, so we need
1245 // to check internals.
1246 hir
::ItemKind
::Mod(_
) => {}
1248 // An `extern {}` doesn't introduce a new privacy
1249 // namespace (the contents have their own privacies).
1250 hir
::ItemKind
::ForeignMod(_
) => {}
1252 hir
::ItemKind
::Trait(.., ref bounds
, _
) => {
1253 if !self.trait_is_public(item
.id
) {
1257 for bound
in bounds
.iter() {
1258 self.check_generic_bound(bound
)
1262 // Impls need some special handling to try to offer useful
1263 // error messages without (too many) false positives
1264 // (i.e., we could just return here to not check them at
1265 // all, or some worse estimation of whether an impl is
1266 // publicly visible).
1267 hir
::ItemKind
::Impl(.., ref g
, ref trait_ref
, ref self_
, ref impl_item_refs
) => {
1268 // `impl [... for] Private` is never visible.
1269 let self_contains_private
;
1270 // `impl [... for] Public<...>`, but not `impl [... for]
1271 // Vec<Public>` or `(Public,)`, etc.
1272 let self_is_public_path
;
1274 // Check the properties of the `Self` type:
1276 let mut visitor
= ObsoleteCheckTypeForPrivatenessVisitor
{
1278 contains_private
: false,
1279 at_outer_type
: true,
1280 outer_type_is_public_path
: false,
1282 visitor
.visit_ty(&self_
);
1283 self_contains_private
= visitor
.contains_private
;
1284 self_is_public_path
= visitor
.outer_type_is_public_path
;
1287 // Miscellaneous info about the impl:
1289 // `true` iff this is `impl Private for ...`.
1290 let not_private_trait
=
1291 trait_ref
.as_ref().map_or(true, // no trait counts as public trait
1293 let did
= tr
.path
.def
.def_id();
1295 if let Some(node_id
) = self.tcx
.hir().as_local_node_id(did
) {
1296 self.trait_is_public(node_id
)
1298 true // external traits must be public
1302 // `true` iff this is a trait impl or at least one method is public.
1304 // `impl Public { $( fn ...() {} )* }` is not visible.
1306 // This is required over just using the methods' privacy
1307 // directly because we might have `impl<T: Foo<Private>> ...`,
1308 // and we shouldn't warn about the generics if all the methods
1309 // are private (because `T` won't be visible externally).
1310 let trait_or_some_public_method
=
1311 trait_ref
.is_some() ||
1312 impl_item_refs
.iter()
1313 .any(|impl_item_ref
| {
1314 let impl_item
= self.tcx
.hir().impl_item(impl_item_ref
.id
);
1315 match impl_item
.node
{
1316 hir
::ImplItemKind
::Const(..) |
1317 hir
::ImplItemKind
::Method(..) => {
1318 self.access_levels
.is_reachable(impl_item
.id
)
1320 hir
::ImplItemKind
::Existential(..) |
1321 hir
::ImplItemKind
::Type(_
) => false,
1325 if !self_contains_private
&&
1326 not_private_trait
&&
1327 trait_or_some_public_method
{
1329 intravisit
::walk_generics(self, g
);
1333 for impl_item_ref
in impl_item_refs
{
1334 // This is where we choose whether to walk down
1335 // further into the impl to check its items. We
1336 // should only walk into public items so that we
1337 // don't erroneously report errors for private
1338 // types in private items.
1339 let impl_item
= self.tcx
.hir().impl_item(impl_item_ref
.id
);
1340 match impl_item
.node
{
1341 hir
::ImplItemKind
::Const(..) |
1342 hir
::ImplItemKind
::Method(..)
1343 if self.item_is_public(&impl_item
.id
, &impl_item
.vis
) =>
1345 intravisit
::walk_impl_item(self, impl_item
)
1347 hir
::ImplItemKind
::Type(..) => {
1348 intravisit
::walk_impl_item(self, impl_item
)
1355 // Any private types in a trait impl fall into three
1357 // 1. mentioned in the trait definition
1358 // 2. mentioned in the type params/generics
1359 // 3. mentioned in the associated types of the impl
1361 // Those in 1. can only occur if the trait is in
1362 // this crate and will've been warned about on the
1363 // trait definition (there's no need to warn twice
1364 // so we don't check the methods).
1366 // Those in 2. are warned via walk_generics and this
1368 intravisit
::walk_path(self, &tr
.path
);
1370 // Those in 3. are warned with this call.
1371 for impl_item_ref
in impl_item_refs
{
1372 let impl_item
= self.tcx
.hir().impl_item(impl_item_ref
.id
);
1373 if let hir
::ImplItemKind
::Type(ref ty
) = impl_item
.node
{
1379 } else if trait_ref
.is_none() && self_is_public_path
{
1380 // `impl Public<Private> { ... }`. Any public static
1381 // methods will be visible as `Public::foo`.
1382 let mut found_pub_static
= false;
1383 for impl_item_ref
in impl_item_refs
{
1384 if self.item_is_public(&impl_item_ref
.id
.node_id
, &impl_item_ref
.vis
) {
1385 let impl_item
= self.tcx
.hir().impl_item(impl_item_ref
.id
);
1386 match impl_item_ref
.kind
{
1387 AssociatedItemKind
::Const
=> {
1388 found_pub_static
= true;
1389 intravisit
::walk_impl_item(self, impl_item
);
1391 AssociatedItemKind
::Method { has_self: false }
=> {
1392 found_pub_static
= true;
1393 intravisit
::walk_impl_item(self, impl_item
);
1399 if found_pub_static
{
1400 intravisit
::walk_generics(self, g
)
1406 // `type ... = ...;` can contain private types, because
1407 // we're introducing a new name.
1408 hir
::ItemKind
::Ty(..) => return,
1410 // Not at all public, so we don't care.
1411 _
if !self.item_is_public(&item
.id
, &item
.vis
) => {
1418 // We've carefully constructed it so that if we're here, then
1419 // any `visit_ty`'s will be called on things that are in
1420 // public signatures, i.e., things that we're interested in for
1422 intravisit
::walk_item(self, item
);
1425 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
) {
1426 for param
in &generics
.params
{
1427 for bound
in ¶m
.bounds
{
1428 self.check_generic_bound(bound
);
1431 for predicate
in &generics
.where_clause
.predicates
{
1433 hir
::WherePredicate
::BoundPredicate(bound_pred
) => {
1434 for bound
in bound_pred
.bounds
.iter() {
1435 self.check_generic_bound(bound
)
1438 hir
::WherePredicate
::RegionPredicate(_
) => {}
1439 hir
::WherePredicate
::EqPredicate(eq_pred
) => {
1440 self.visit_ty(&eq_pred
.rhs_ty
);
1446 fn visit_foreign_item(&mut self, item
: &'tcx hir
::ForeignItem
) {
1447 if self.access_levels
.is_reachable(item
.id
) {
1448 intravisit
::walk_foreign_item(self, item
)
1452 fn visit_ty(&mut self, t
: &'tcx hir
::Ty
) {
1453 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(_
, ref path
)) = t
.node
{
1454 if self.path_is_private_type(path
) {
1455 self.old_error_set
.insert(t
.id
);
1458 intravisit
::walk_ty(self, t
)
1461 fn visit_variant(&mut self,
1462 v
: &'tcx hir
::Variant
,
1463 g
: &'tcx hir
::Generics
,
1464 item_id
: hir
::HirId
) {
1465 if self.access_levels
.is_reachable(v
.node
.data
.id()) {
1466 self.in_variant
= true;
1467 intravisit
::walk_variant(self, v
, g
, item_id
);
1468 self.in_variant
= false;
1472 fn visit_struct_field(&mut self, s
: &'tcx hir
::StructField
) {
1473 if s
.vis
.node
.is_pub() || self.in_variant
{
1474 intravisit
::walk_struct_field(self, s
);
1478 // We don't need to introspect into these at all: an
1479 // expression/block context can't possibly contain exported things.
1480 // (Making them no-ops stops us from traversing the whole AST without
1481 // having to be super careful about our `walk_...` calls above.)
1482 fn visit_block(&mut self, _
: &'tcx hir
::Block
) {}
1483 fn visit_expr(&mut self, _
: &'tcx hir
::Expr
) {}
1486 ///////////////////////////////////////////////////////////////////////////////
1487 /// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
1488 /// finds any private components in it.
1489 /// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
1490 /// and traits in public interfaces.
1491 ///////////////////////////////////////////////////////////////////////////////
1493 struct SearchInterfaceForPrivateItemsVisitor
<'a
, 'tcx
: 'a
> {
1494 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1495 item_id
: ast
::NodeId
,
1498 /// The visitor checks that each component type is at least this visible.
1499 required_visibility
: ty
::Visibility
,
1500 has_pub_restricted
: bool
,
1501 has_old_errors
: bool
,
1503 private_crates
: FxHashSet
<CrateNum
>
1506 impl<'a
, 'tcx
: 'a
> SearchInterfaceForPrivateItemsVisitor
<'a
, 'tcx
> {
1507 fn generics(&mut self) -> &mut Self {
1508 for param
in &self.tcx
.generics_of(self.item_def_id
).params
{
1510 GenericParamDefKind
::Type { has_default, .. }
=> {
1512 self.visit(self.tcx
.type_of(param
.def_id
));
1515 GenericParamDefKind
::Lifetime
=> {}
1521 fn predicates(&mut self) -> &mut Self {
1522 // N.B., we use `explicit_predicates_of` and not `predicates_of`
1523 // because we don't want to report privacy errors due to where
1524 // clauses that the compiler inferred. We only want to
1525 // consider the ones that the user wrote. This is important
1526 // for the inferred outlives rules; see
1527 // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`.
1528 self.visit_predicates(self.tcx
.explicit_predicates_of(self.item_def_id
));
1532 fn ty(&mut self) -> &mut Self {
1533 self.visit(self.tcx
.type_of(self.item_def_id
));
1537 fn check_def_id(&mut self, def_id
: DefId
, kind
: &str, descr
: &dyn fmt
::Display
) -> bool
{
1538 if self.leaks_private_dep(def_id
) {
1539 self.tcx
.lint_node(lint
::builtin
::EXPORTED_PRIVATE_DEPENDENCIES
,
1542 &format
!("{} `{}` from private dependency '{}' in public \
1543 interface", kind
, descr
,
1544 self.tcx
.crate_name(def_id
.krate
)));
1548 let node_id
= match self.tcx
.hir().as_local_node_id(def_id
) {
1549 Some(node_id
) => node_id
,
1550 None
=> return false,
1553 let (vis
, vis_span
, vis_descr
) = def_id_visibility(self.tcx
, def_id
);
1554 if !vis
.is_at_least(self.required_visibility
, self.tcx
) {
1555 let msg
= format
!("{} {} `{}` in public interface", vis_descr
, kind
, descr
);
1556 if self.has_pub_restricted
|| self.has_old_errors
|| self.in_assoc_ty
{
1557 let mut err
= if kind
== "trait" {
1558 struct_span_err
!(self.tcx
.sess
, self.span
, E0445
, "{}", msg
)
1560 struct_span_err
!(self.tcx
.sess
, self.span
, E0446
, "{}", msg
)
1562 err
.span_label(self.span
, format
!("can't leak {} {}", vis_descr
, kind
));
1563 err
.span_label(vis_span
, format
!("`{}` declared as {}", descr
, vis_descr
));
1566 let err_code
= if kind
== "trait" { "E0445" }
else { "E0446" }
;
1567 self.tcx
.lint_node(lint
::builtin
::PRIVATE_IN_PUBLIC
, node_id
, self.span
,
1568 &format
!("{} (error {})", msg
, err_code
));
1576 /// An item is 'leaked' from a private dependency if all
1577 /// of the following are true:
1578 /// 1. It's contained within a public type
1579 /// 2. It comes from a private crate
1580 fn leaks_private_dep(&self, item_id
: DefId
) -> bool
{
1581 let ret
= self.required_visibility
== ty
::Visibility
::Public
&&
1582 self.private_crates
.contains(&item_id
.krate
);
1584 log
::debug
!("leaks_private_dep(item_id={:?})={}", item_id
, ret
);
1589 impl<'a
, 'tcx
> DefIdVisitor
<'a
, 'tcx
> for SearchInterfaceForPrivateItemsVisitor
<'a
, 'tcx
> {
1590 fn tcx(&self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> { self.tcx }
1591 fn visit_def_id(&mut self, def_id
: DefId
, kind
: &str, descr
: &dyn fmt
::Display
) -> bool
{
1592 self.check_def_id(def_id
, kind
, descr
)
1596 struct PrivateItemsInPublicInterfacesVisitor
<'a
, 'tcx
: 'a
> {
1597 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1598 has_pub_restricted
: bool
,
1599 old_error_set
: &'a NodeSet
,
1600 private_crates
: FxHashSet
<CrateNum
>
1603 impl<'a
, 'tcx
> PrivateItemsInPublicInterfacesVisitor
<'a
, 'tcx
> {
1604 fn check(&self, item_id
: ast
::NodeId
, required_visibility
: ty
::Visibility
)
1605 -> SearchInterfaceForPrivateItemsVisitor
<'a
, 'tcx
> {
1606 let mut has_old_errors
= false;
1608 // Slow path taken only if there any errors in the crate.
1609 for &id
in self.old_error_set
{
1610 // Walk up the nodes until we find `item_id` (or we hit a root).
1614 has_old_errors
= true;
1617 let parent
= self.tcx
.hir().get_parent_node(id
);
1629 SearchInterfaceForPrivateItemsVisitor
{
1632 item_def_id
: self.tcx
.hir().local_def_id(item_id
),
1633 span
: self.tcx
.hir().span(item_id
),
1634 required_visibility
,
1635 has_pub_restricted
: self.has_pub_restricted
,
1638 private_crates
: self.private_crates
.clone()
1642 fn check_trait_or_impl_item(&self, node_id
: ast
::NodeId
, assoc_item_kind
: AssociatedItemKind
,
1643 defaultness
: hir
::Defaultness
, vis
: ty
::Visibility
) {
1644 let mut check
= self.check(node_id
, vis
);
1646 let (check_ty
, is_assoc_ty
) = match assoc_item_kind
{
1647 AssociatedItemKind
::Const
| AssociatedItemKind
::Method { .. }
=> (true, false),
1648 AssociatedItemKind
::Type
=> (defaultness
.has_value(), true),
1649 // `ty()` for existential types is the underlying type,
1650 // it's not a part of interface, so we skip it.
1651 AssociatedItemKind
::Existential
=> (false, true),
1653 check
.in_assoc_ty
= is_assoc_ty
;
1654 check
.generics().predicates();
1661 impl<'a
, 'tcx
> Visitor
<'tcx
> for PrivateItemsInPublicInterfacesVisitor
<'a
, 'tcx
> {
1662 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
1663 NestedVisitorMap
::OnlyBodies(&self.tcx
.hir())
1666 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
1668 let item_visibility
= ty
::Visibility
::from_hir(&item
.vis
, item
.id
, tcx
);
1671 // Crates are always public.
1672 hir
::ItemKind
::ExternCrate(..) => {}
1673 // All nested items are checked by `visit_item`.
1674 hir
::ItemKind
::Mod(..) => {}
1675 // Checked in resolve.
1676 hir
::ItemKind
::Use(..) => {}
1678 hir
::ItemKind
::GlobalAsm(..) => {}
1679 // Subitems of these items have inherited publicity.
1680 hir
::ItemKind
::Const(..) | hir
::ItemKind
::Static(..) |
1681 hir
::ItemKind
::Fn(..) | hir
::ItemKind
::Ty(..) => {
1682 self.check(item
.id
, item_visibility
).generics().predicates().ty();
1684 hir
::ItemKind
::Existential(..) => {
1685 // `ty()` for existential types is the underlying type,
1686 // it's not a part of interface, so we skip it.
1687 self.check(item
.id
, item_visibility
).generics().predicates();
1689 hir
::ItemKind
::Trait(.., ref trait_item_refs
) => {
1690 self.check(item
.id
, item_visibility
).generics().predicates();
1692 for trait_item_ref
in trait_item_refs
{
1693 self.check_trait_or_impl_item(trait_item_ref
.id
.node_id
, trait_item_ref
.kind
,
1694 trait_item_ref
.defaultness
, item_visibility
);
1697 hir
::ItemKind
::TraitAlias(..) => {
1698 self.check(item
.id
, item_visibility
).generics().predicates();
1700 hir
::ItemKind
::Enum(ref def
, _
) => {
1701 self.check(item
.id
, item_visibility
).generics().predicates();
1703 for variant
in &def
.variants
{
1704 for field
in variant
.node
.data
.fields() {
1705 self.check(field
.id
, item_visibility
).ty();
1709 // Subitems of foreign modules have their own publicity.
1710 hir
::ItemKind
::ForeignMod(ref foreign_mod
) => {
1711 for foreign_item
in &foreign_mod
.items
{
1712 let vis
= ty
::Visibility
::from_hir(&foreign_item
.vis
, item
.id
, tcx
);
1713 self.check(foreign_item
.id
, vis
).generics().predicates().ty();
1716 // Subitems of structs and unions have their own publicity.
1717 hir
::ItemKind
::Struct(ref struct_def
, _
) |
1718 hir
::ItemKind
::Union(ref struct_def
, _
) => {
1719 self.check(item
.id
, item_visibility
).generics().predicates();
1721 for field
in struct_def
.fields() {
1722 let field_visibility
= ty
::Visibility
::from_hir(&field
.vis
, item
.id
, tcx
);
1723 self.check(field
.id
, min(item_visibility
, field_visibility
, tcx
)).ty();
1726 // An inherent impl is public when its type is public
1727 // Subitems of inherent impls have their own publicity.
1728 // A trait impl is public when both its type and its trait are public
1729 // Subitems of trait impls have inherited publicity.
1730 hir
::ItemKind
::Impl(.., ref trait_ref
, _
, ref impl_item_refs
) => {
1731 let impl_vis
= ty
::Visibility
::of_impl(item
.id
, tcx
, &Default
::default());
1732 self.check(item
.id
, impl_vis
).generics().predicates();
1733 for impl_item_ref
in impl_item_refs
{
1734 let impl_item
= tcx
.hir().impl_item(impl_item_ref
.id
);
1735 let impl_item_vis
= if trait_ref
.is_none() {
1736 min(ty
::Visibility
::from_hir(&impl_item
.vis
, item
.id
, tcx
), impl_vis
, tcx
)
1740 self.check_trait_or_impl_item(impl_item_ref
.id
.node_id
, impl_item_ref
.kind
,
1741 impl_item_ref
.defaultness
, impl_item_vis
);
1748 pub fn provide(providers
: &mut Providers
<'_
>) {
1749 *providers
= Providers
{
1750 privacy_access_levels
,
1756 pub fn check_crate
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>) -> Lrc
<AccessLevels
> {
1757 tcx
.privacy_access_levels(LOCAL_CRATE
)
1760 fn check_mod_privacy
<'tcx
>(tcx
: TyCtxt
<'_
, 'tcx
, 'tcx
>, module_def_id
: DefId
) {
1761 let empty_tables
= ty
::TypeckTables
::empty(None
);
1764 // Check privacy of names not checked in previous compilation stages.
1765 let mut visitor
= NamePrivacyVisitor
{
1767 tables
: &empty_tables
,
1768 current_item
: DUMMY_NODE_ID
,
1769 empty_tables
: &empty_tables
,
1771 let (module
, span
, node_id
) = tcx
.hir().get_module(module_def_id
);
1772 let hir_id
= tcx
.hir().node_to_hir_id(node_id
);
1773 intravisit
::walk_mod(&mut visitor
, module
, hir_id
);
1775 // Check privacy of explicitly written types and traits as well as
1776 // inferred types of expressions and patterns.
1777 let mut visitor
= TypePrivacyVisitor
{
1779 tables
: &empty_tables
,
1780 current_item
: module_def_id
,
1783 empty_tables
: &empty_tables
,
1785 intravisit
::walk_mod(&mut visitor
, module
, hir_id
);
1788 fn privacy_access_levels
<'tcx
>(
1789 tcx
: TyCtxt
<'_
, 'tcx
, 'tcx
>,
1791 ) -> Lrc
<AccessLevels
> {
1792 assert_eq
!(krate
, LOCAL_CRATE
);
1794 let krate
= tcx
.hir().krate();
1796 for &module
in krate
.modules
.keys() {
1797 tcx
.ensure().check_mod_privacy(tcx
.hir().local_def_id(module
));
1800 let private_crates
: FxHashSet
<CrateNum
> = tcx
.sess
.opts
.extern_private
.iter()
1802 tcx
.crates().iter().find(|&&krate
| &tcx
.crate_name(krate
) == c
).cloned()
1806 // Build up a set of all exported items in the AST. This is a set of all
1807 // items which are reachable from external crates based on visibility.
1808 let mut visitor
= EmbargoVisitor
{
1810 access_levels
: Default
::default(),
1811 prev_level
: Some(AccessLevel
::Public
),
1815 intravisit
::walk_crate(&mut visitor
, krate
);
1816 if visitor
.changed
{
1817 visitor
.changed
= false;
1822 visitor
.update(ast
::CRATE_NODE_ID
, Some(AccessLevel
::Public
));
1825 let mut visitor
= ObsoleteVisiblePrivateTypesVisitor
{
1827 access_levels
: &visitor
.access_levels
,
1829 old_error_set
: Default
::default(),
1831 intravisit
::walk_crate(&mut visitor
, krate
);
1834 let has_pub_restricted
= {
1835 let mut pub_restricted_visitor
= PubRestrictedVisitor
{
1837 has_pub_restricted
: false
1839 intravisit
::walk_crate(&mut pub_restricted_visitor
, krate
);
1840 pub_restricted_visitor
.has_pub_restricted
1843 // Check for private types and traits in public interfaces.
1844 let mut visitor
= PrivateItemsInPublicInterfacesVisitor
{
1847 old_error_set
: &visitor
.old_error_set
,
1850 krate
.visit_all_item_likes(&mut DeepVisitor
::new(&mut visitor
));
1853 Lrc
::new(visitor
.access_levels
)
1856 __build_diagnostic_array
! { librustc_privacy, DIAGNOSTICS }