]> git.lizzy.rs Git - rust.git/blob - src/librustc_privacy/lib.rs
673762ee4c6f78d2cdbe00504b559f5ce11b2b32
[rust.git] / src / librustc_privacy / lib.rs
1 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
2
3 #![feature(in_band_lifetimes)]
4 #![feature(nll)]
5 #![feature(rustc_diagnostic_macros)]
6
7 #![recursion_limit="256"]
8
9 #[macro_use] extern crate syntax;
10
11 use rustc::bug;
12 use rustc::hir::{self, Node, PatKind, AssocItemKind};
13 use rustc::hir::def::{Res, DefKind};
14 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
15 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
16 use rustc::hir::itemlikevisit::DeepVisitor;
17 use rustc::lint;
18 use rustc::middle::privacy::{AccessLevel, AccessLevels};
19 use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind};
20 use rustc::ty::fold::TypeVisitor;
21 use rustc::ty::query::Providers;
22 use rustc::ty::subst::InternalSubsts;
23 use rustc::util::nodemap::HirIdSet;
24 use rustc_data_structures::fx::FxHashSet;
25 use syntax::ast::Ident;
26 use syntax::attr;
27 use syntax::symbol::{kw, sym};
28 use syntax_pos::hygiene::Transparency;
29 use syntax_pos::Span;
30
31 use std::{cmp, fmt, mem};
32 use std::marker::PhantomData;
33
34 mod error_codes;
35
36 ////////////////////////////////////////////////////////////////////////////////
37 /// Generic infrastructure used to implement specific visitors below.
38 ////////////////////////////////////////////////////////////////////////////////
39
40 /// Implemented to visit all `DefId`s in a type.
41 /// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them.
42 /// The idea is to visit "all components of a type", as documented in
43 /// https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type.
44 /// The default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings.
45 /// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
46 /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
47 /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
48 trait DefIdVisitor<'tcx> {
49     fn tcx(&self) -> TyCtxt<'tcx>;
50     fn shallow(&self) -> bool { false }
51     fn skip_assoc_tys(&self) -> bool { false }
52     fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool;
53
54     /// Not overridden, but used to actually visit types and traits.
55     fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
56         DefIdVisitorSkeleton {
57             def_id_visitor: self,
58             visited_opaque_tys: Default::default(),
59             dummy: Default::default(),
60         }
61     }
62     fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool {
63         ty_fragment.visit_with(&mut self.skeleton())
64     }
65     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
66         self.skeleton().visit_trait(trait_ref)
67     }
68     fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool {
69         self.skeleton().visit_predicates(predicates)
70     }
71 }
72
73 struct DefIdVisitorSkeleton<'v, 'tcx, V>
74 where
75     V: DefIdVisitor<'tcx> + ?Sized,
76 {
77     def_id_visitor: &'v mut V,
78     visited_opaque_tys: FxHashSet<DefId>,
79     dummy: PhantomData<TyCtxt<'tcx>>,
80 }
81
82 impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
83 where
84     V: DefIdVisitor<'tcx> + ?Sized,
85 {
86     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
87         let TraitRef { def_id, substs } = trait_ref;
88         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) ||
89         (!self.def_id_visitor.shallow() && substs.visit_with(self))
90     }
91
92     fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool {
93         let ty::GenericPredicates { parent: _, predicates } = predicates;
94         for (predicate, _span) in predicates {
95             match predicate {
96                 ty::Predicate::Trait(poly_predicate) => {
97                     let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder();
98                     if self.visit_trait(trait_ref) {
99                         return true;
100                     }
101                 }
102                 ty::Predicate::Projection(poly_predicate) => {
103                     let ty::ProjectionPredicate { projection_ty, ty } =
104                         *poly_predicate.skip_binder();
105                     if ty.visit_with(self) {
106                         return true;
107                     }
108                     if self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx())) {
109                         return true;
110                     }
111                 }
112                 ty::Predicate::TypeOutlives(poly_predicate) => {
113                     let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder();
114                     if ty.visit_with(self) {
115                         return true;
116                     }
117                 }
118                 ty::Predicate::RegionOutlives(..) => {},
119                 _ => bug!("unexpected predicate: {:?}", predicate),
120             }
121         }
122         false
123     }
124 }
125
126 impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V>
127 where
128     V: DefIdVisitor<'tcx> + ?Sized,
129 {
130     fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
131         let tcx = self.def_id_visitor.tcx();
132         // InternalSubsts are not visited here because they are visited below in `super_visit_with`.
133         match ty.sty {
134             ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) |
135             ty::Foreign(def_id) |
136             ty::FnDef(def_id, ..) |
137             ty::Closure(def_id, ..) |
138             ty::Generator(def_id, ..) => {
139                 if self.def_id_visitor.visit_def_id(def_id, "type", &ty) {
140                     return true;
141                 }
142                 if self.def_id_visitor.shallow() {
143                     return false;
144                 }
145                 // Default type visitor doesn't visit signatures of fn types.
146                 // Something like `fn() -> Priv {my_func}` is considered a private type even if
147                 // `my_func` is public, so we need to visit signatures.
148                 if let ty::FnDef(..) = ty.sty {
149                     if tcx.fn_sig(def_id).visit_with(self) {
150                         return true;
151                     }
152                 }
153                 // Inherent static methods don't have self type in substs.
154                 // Something like `fn() {my_method}` type of the method
155                 // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
156                 // so we need to visit the self type additionally.
157                 if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
158                     if let ty::ImplContainer(impl_def_id) = assoc_item.container {
159                         if tcx.type_of(impl_def_id).visit_with(self) {
160                             return true;
161                         }
162                     }
163                 }
164             }
165             ty::Projection(proj) | ty::UnnormalizedProjection(proj) => {
166                 if self.def_id_visitor.skip_assoc_tys() {
167                     // Visitors searching for minimal visibility/reachability want to
168                     // conservatively approximate associated types like `<Type as Trait>::Alias`
169                     // as visible/reachable even if both `Type` and `Trait` are private.
170                     // Ideally, associated types should be substituted in the same way as
171                     // free type aliases, but this isn't done yet.
172                     return false;
173                 }
174                 // This will also visit substs if necessary, so we don't need to recurse.
175                 return self.visit_trait(proj.trait_ref(tcx));
176             }
177             ty::Dynamic(predicates, ..) => {
178                 // All traits in the list are considered the "primary" part of the type
179                 // and are visited by shallow visitors.
180                 for predicate in *predicates.skip_binder() {
181                     let trait_ref = match *predicate {
182                         ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
183                         ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
184                         ty::ExistentialPredicate::AutoTrait(def_id) =>
185                             ty::ExistentialTraitRef { def_id, substs: InternalSubsts::empty() },
186                     };
187                     let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref;
188                     if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) {
189                         return true;
190                     }
191                 }
192             }
193             ty::Opaque(def_id, ..) => {
194                 // Skip repeated `Opaque`s to avoid infinite recursion.
195                 if self.visited_opaque_tys.insert(def_id) {
196                     // The intent is to treat `impl Trait1 + Trait2` identically to
197                     // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
198                     // (it either has no visibility, or its visibility is insignificant, like
199                     // visibilities of type aliases) and recurse into predicates instead to go
200                     // through the trait list (default type visitor doesn't visit those traits).
201                     // All traits in the list are considered the "primary" part of the type
202                     // and are visited by shallow visitors.
203                     if self.visit_predicates(tcx.predicates_of(def_id)) {
204                         return true;
205                     }
206                 }
207             }
208             // These types don't have their own def-ids (but may have subcomponents
209             // with def-ids that should be visited recursively).
210             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
211             ty::Float(..) | ty::Str | ty::Never |
212             ty::Array(..) | ty::Slice(..) | ty::Tuple(..) |
213             ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) |
214             ty::Param(..) | ty::Error | ty::GeneratorWitness(..) => {}
215             ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) =>
216                 bug!("unexpected type: {:?}", ty),
217         }
218
219         !self.def_id_visitor.shallow() && ty.super_visit_with(self)
220     }
221 }
222
223 fn def_id_visibility<'tcx>(
224     tcx: TyCtxt<'tcx>,
225     def_id: DefId,
226 ) -> (ty::Visibility, Span, &'static str) {
227     match tcx.hir().as_local_hir_id(def_id) {
228         Some(hir_id) => {
229             let vis = match tcx.hir().get(hir_id) {
230                 Node::Item(item) => &item.vis,
231                 Node::ForeignItem(foreign_item) => &foreign_item.vis,
232                 Node::MacroDef(macro_def) => {
233                     if attr::contains_name(&macro_def.attrs, sym::macro_export) {
234                         return (ty::Visibility::Public, macro_def.span, "public");
235                     } else {
236                         &macro_def.vis
237                     }
238                 },
239                 Node::TraitItem(..) | Node::Variant(..) => {
240                     return def_id_visibility(tcx, tcx.hir().get_parent_did(hir_id));
241                 }
242                 Node::ImplItem(impl_item) => {
243                     match tcx.hir().get(tcx.hir().get_parent_item(hir_id)) {
244                         Node::Item(item) => match &item.node {
245                             hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis,
246                             hir::ItemKind::Impl(.., Some(trait_ref), _, _)
247                                 => return def_id_visibility(tcx, trait_ref.path.res.def_id()),
248                             kind => bug!("unexpected item kind: {:?}", kind),
249                         }
250                         node => bug!("unexpected node kind: {:?}", node),
251                     }
252                 }
253                 Node::Ctor(vdata) => {
254                     let parent_hir_id = tcx.hir().get_parent_node(hir_id);
255                     match tcx.hir().get(parent_hir_id) {
256                         Node::Variant(..) => {
257                             let parent_did = tcx.hir().local_def_id(parent_hir_id);
258                             let (mut ctor_vis, mut span, mut descr) = def_id_visibility(
259                                 tcx, parent_did,
260                             );
261
262                             let adt_def = tcx.adt_def(tcx.hir().get_parent_did(hir_id));
263                             let ctor_did = tcx.hir().local_def_id(
264                                 vdata.ctor_hir_id().unwrap());
265                             let variant = adt_def.variant_with_ctor_id(ctor_did);
266
267                             if variant.is_field_list_non_exhaustive() &&
268                                 ctor_vis == ty::Visibility::Public
269                             {
270                                 ctor_vis = ty::Visibility::Restricted(
271                                     DefId::local(CRATE_DEF_INDEX));
272                                 let attrs = tcx.get_attrs(variant.def_id);
273                                 span = attr::find_by_name(&attrs, sym::non_exhaustive)
274                                     .unwrap().span;
275                                 descr = "crate-visible";
276                             }
277
278                             return (ctor_vis, span, descr);
279                         }
280                         Node::Item(..) => {
281                             let item = match tcx.hir().get(parent_hir_id) {
282                                 Node::Item(item) => item,
283                                 node => bug!("unexpected node kind: {:?}", node),
284                             };
285                             let (mut ctor_vis, mut span, mut descr) =
286                                 (ty::Visibility::from_hir(&item.vis, parent_hir_id, tcx),
287                                 item.vis.span, item.vis.node.descr());
288                             for field in vdata.fields() {
289                                 let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
290                                 if ctor_vis.is_at_least(field_vis, tcx) {
291                                     ctor_vis = field_vis;
292                                     span = field.vis.span;
293                                     descr = field.vis.node.descr();
294                                 }
295                             }
296
297                             // If the structure is marked as non_exhaustive then lower the
298                             // visibility to within the crate.
299                             if ctor_vis == ty::Visibility::Public {
300                                 let adt_def =
301                                     tcx.adt_def(tcx.hir().get_parent_did(hir_id));
302                                 if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
303                                     ctor_vis =
304                                         ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
305                                     span = attr::find_by_name(&item.attrs, sym::non_exhaustive)
306                                                 .unwrap().span;
307                                     descr = "crate-visible";
308                                 }
309                             }
310
311                             return (ctor_vis, span, descr);
312                         }
313                         node => bug!("unexpected node kind: {:?}", node),
314                     }
315                 }
316                 Node::Expr(expr) => {
317                     return (ty::Visibility::Restricted(
318                         tcx.hir().get_module_parent(expr.hir_id)),
319                             expr.span, "private")
320                 }
321                 node => bug!("unexpected node kind: {:?}", node)
322             };
323             (ty::Visibility::from_hir(vis, hir_id, tcx), vis.span, vis.node.descr())
324         }
325         None => {
326             let vis = tcx.visibility(def_id);
327             let descr = if vis == ty::Visibility::Public { "public" } else { "private" };
328             (vis, tcx.def_span(def_id), descr)
329         }
330     }
331 }
332
333 // Set the correct `TypeckTables` for the given `item_id` (or an empty table if
334 // there is no `TypeckTables` for the item).
335 fn item_tables<'a, 'tcx>(
336     tcx: TyCtxt<'tcx>,
337     hir_id: hir::HirId,
338     empty_tables: &'a ty::TypeckTables<'tcx>,
339 ) -> &'a ty::TypeckTables<'tcx> {
340     let def_id = tcx.hir().local_def_id(hir_id);
341     if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
342 }
343
344 fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
345     if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
346 }
347
348 ////////////////////////////////////////////////////////////////////////////////
349 /// Visitor used to determine if pub(restricted) is used anywhere in the crate.
350 ///
351 /// This is done so that `private_in_public` warnings can be turned into hard errors
352 /// in crates that have been updated to use pub(restricted).
353 ////////////////////////////////////////////////////////////////////////////////
354 struct PubRestrictedVisitor<'tcx> {
355     tcx: TyCtxt<'tcx>,
356     has_pub_restricted: bool,
357 }
358
359 impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
360     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
361         NestedVisitorMap::All(&self.tcx.hir())
362     }
363     fn visit_vis(&mut self, vis: &'tcx hir::Visibility) {
364         self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
365     }
366 }
367
368 ////////////////////////////////////////////////////////////////////////////////
369 /// Visitor used to determine impl visibility and reachability.
370 ////////////////////////////////////////////////////////////////////////////////
371
372 struct FindMin<'a, 'tcx, VL: VisibilityLike> {
373     tcx: TyCtxt<'tcx>,
374     access_levels: &'a AccessLevels,
375     min: VL,
376 }
377
378 impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL> {
379     fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
380     fn shallow(&self) -> bool { VL::SHALLOW }
381     fn skip_assoc_tys(&self) -> bool { true }
382     fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
383         self.min = VL::new_min(self, def_id);
384         false
385     }
386 }
387
388 trait VisibilityLike: Sized {
389     const MAX: Self;
390     const SHALLOW: bool = false;
391     fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self;
392
393     // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
394     // associated types for which we can't determine visibility precisely.
395     fn of_impl(
396         hir_id: hir::HirId,
397         tcx: TyCtxt<'_>,
398         access_levels: &AccessLevels,
399     ) -> Self {
400         let mut find = FindMin { tcx, access_levels, min: Self::MAX };
401         let def_id = tcx.hir().local_def_id(hir_id);
402         find.visit(tcx.type_of(def_id));
403         if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
404             find.visit_trait(trait_ref);
405         }
406         find.min
407     }
408 }
409 impl VisibilityLike for ty::Visibility {
410     const MAX: Self = ty::Visibility::Public;
411     fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
412         min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx)
413     }
414 }
415 impl VisibilityLike for Option<AccessLevel> {
416     const MAX: Self = Some(AccessLevel::Public);
417     // Type inference is very smart sometimes.
418     // It can make an impl reachable even some components of its type or trait are unreachable.
419     // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
420     // can be usable from other crates (#57264). So we skip substs when calculating reachability
421     // and consider an impl reachable if its "shallow" type and trait are reachable.
422     //
423     // The assumption we make here is that type-inference won't let you use an impl without knowing
424     // both "shallow" version of its self type and "shallow" version of its trait if it exists
425     // (which require reaching the `DefId`s in them).
426     const SHALLOW: bool = true;
427     fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
428         cmp::min(if let Some(hir_id) = find.tcx.hir().as_local_hir_id(def_id) {
429             find.access_levels.map.get(&hir_id).cloned()
430         } else {
431             Self::MAX
432         }, find.min)
433     }
434 }
435
436 ////////////////////////////////////////////////////////////////////////////////
437 /// The embargo visitor, used to determine the exports of the AST.
438 ////////////////////////////////////////////////////////////////////////////////
439
440 struct EmbargoVisitor<'tcx> {
441     tcx: TyCtxt<'tcx>,
442
443     /// Accessibility levels for reachable nodes.
444     access_levels: AccessLevels,
445     /// A set of pairs corresponding to modules, where the first module is
446     /// reachable via a macro that's defined in the second module. This cannot
447     /// be represented as reachable because it can't handle the following case:
448     ///
449     /// pub mod n {                         // Should be `Public`
450     ///     pub(crate) mod p {              // Should *not* be accessible
451     ///         pub fn f() -> i32 { 12 }    // Must be `Reachable`
452     ///     }
453     /// }
454     /// pub macro m() {
455     ///     n::p::f()
456     /// }
457     macro_reachable: FxHashSet<(hir::HirId, DefId)>,
458     /// Previous accessibility level; `None` means unreachable.
459     prev_level: Option<AccessLevel>,
460     /// Has something changed in the level map?
461     changed: bool,
462 }
463
464 struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
465     access_level: Option<AccessLevel>,
466     item_def_id: DefId,
467     ev: &'a mut EmbargoVisitor<'tcx>,
468 }
469
470 impl EmbargoVisitor<'tcx> {
471     fn get(&self, id: hir::HirId) -> Option<AccessLevel> {
472         self.access_levels.map.get(&id).cloned()
473     }
474
475     /// Updates node level and returns the updated level.
476     fn update(&mut self, id: hir::HirId, level: Option<AccessLevel>) -> Option<AccessLevel> {
477         let old_level = self.get(id);
478         // Accessibility levels can only grow.
479         if level > old_level {
480             self.access_levels.map.insert(id, level.unwrap());
481             self.changed = true;
482             level
483         } else {
484             old_level
485         }
486     }
487
488     fn reach(
489         &mut self,
490         item_id: hir::HirId,
491         access_level: Option<AccessLevel>,
492     ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
493         ReachEverythingInTheInterfaceVisitor {
494             access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
495             item_def_id: self.tcx.hir().local_def_id(item_id),
496             ev: self,
497         }
498     }
499
500     /// Updates the item as being reachable through a macro defined in the given
501     /// module. Returns `true` if the level has changed.
502     fn update_macro_reachable(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) -> bool {
503         if self.macro_reachable.insert((reachable_mod, defining_mod)) {
504             self.update_macro_reachable_mod(reachable_mod, defining_mod);
505             true
506         } else {
507             false
508         }
509     }
510
511     fn update_macro_reachable_mod(
512         &mut self,
513         reachable_mod: hir::HirId,
514         defining_mod: DefId,
515     ) {
516         let module_def_id = self.tcx.hir().local_def_id(reachable_mod);
517         let module = self.tcx.hir().get_module(module_def_id).0;
518         for item_id in &module.item_ids {
519             let hir_id = item_id.id;
520             let item_def_id = self.tcx.hir().local_def_id(hir_id);
521             if let Some(def_kind) = self.tcx.def_kind(item_def_id) {
522                 let item = self.tcx.hir().expect_item(hir_id);
523                 let vis = ty::Visibility::from_hir(&item.vis, hir_id, self.tcx);
524                 self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
525             }
526         }
527
528         if let Some(exports) = self.tcx.module_exports(module_def_id) {
529             for export in exports {
530                 if export.vis.is_accessible_from(defining_mod, self.tcx) {
531                     if let Res::Def(def_kind, def_id) = export.res {
532                         let vis = def_id_visibility(self.tcx, def_id).0;
533                         if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
534                             self.update_macro_reachable_def(
535                                 hir_id,
536                                 def_kind,
537                                 vis,
538                                 defining_mod,
539                             );
540                         }
541                     }
542                 }
543             }
544         }
545     }
546
547     fn update_macro_reachable_def(
548         &mut self,
549         hir_id: hir::HirId,
550         def_kind: DefKind,
551         vis: ty::Visibility,
552         module: DefId,
553     ) {
554         let level = Some(AccessLevel::Reachable);
555         if let ty::Visibility::Public = vis {
556             self.update(hir_id, level);
557         }
558         match def_kind {
559             // No type privacy, so can be directly marked as reachable.
560             DefKind::Const
561             | DefKind::Macro(_)
562             | DefKind::Static
563             | DefKind::TraitAlias
564             | DefKind::TyAlias => {
565                 if vis.is_accessible_from(module, self.tcx) {
566                     self.update(hir_id, level);
567                 }
568             },
569
570             // We can't use a module name as the final segment of a path, except
571             // in use statements. Since re-export checking doesn't consider
572             // hygiene these don't need to be marked reachable. The contents of
573             // the module, however may be reachable.
574             DefKind::Mod => {
575                 if vis.is_accessible_from(module, self.tcx) {
576                     self.update_macro_reachable(hir_id, module);
577                 }
578             }
579
580             DefKind::Struct | DefKind::Union => {
581                 // While structs and unions have type privacy, their fields do
582                 // not.
583                 if let ty::Visibility::Public = vis {
584                     let item = self.tcx.hir().expect_item(hir_id);
585                     if let hir::ItemKind::Struct(ref struct_def, _)
586                         | hir::ItemKind::Union(ref struct_def, _) = item.node
587                     {
588                         for field in struct_def.fields() {
589                             let field_vis = ty::Visibility::from_hir(
590                                 &field.vis,
591                                 field.hir_id,
592                                 self.tcx,
593                             );
594                             if field_vis.is_accessible_from(module, self.tcx) {
595                                 self.reach(field.hir_id, level).ty();
596                             }
597                         }
598                     } else {
599                         bug!("item {:?} with DefKind {:?}", item, def_kind);
600                     }
601                 }
602             }
603
604             // These have type privacy, so are not reachable unless they're
605             // public
606             DefKind::AssocConst
607             | DefKind::AssocTy
608             | DefKind::AssocOpaqueTy
609             | DefKind::ConstParam
610             | DefKind::Ctor(_, _)
611             | DefKind::Enum
612             | DefKind::ForeignTy
613             | DefKind::Fn
614             | DefKind::OpaqueTy
615             | DefKind::Method
616             | DefKind::Trait
617             | DefKind::TyParam
618             | DefKind::Variant => (),
619         }
620     }
621
622     /// Given the path segments of a `ItemKind::Use`, then we need
623     /// to update the visibility of the intermediate use so that it isn't linted
624     /// by `unreachable_pub`.
625     ///
626     /// This isn't trivial as `path.res` has the `DefId` of the eventual target
627     /// of the use statement not of the next intermediate use statement.
628     ///
629     /// To do this, consider the last two segments of the path to our intermediate
630     /// use statement. We expect the penultimate segment to be a module and the
631     /// last segment to be the name of the item we are exporting. We can then
632     /// look at the items contained in the module for the use statement with that
633     /// name and update that item's visibility.
634     ///
635     /// FIXME: This solution won't work with glob imports and doesn't respect
636     /// namespaces. See <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
637     fn update_visibility_of_intermediate_use_statements(&mut self, segments: &[hir::PathSegment]) {
638         if let Some([module, segment]) = segments.rchunks_exact(2).next() {
639             if let Some(item) = module.res
640                 .and_then(|res| res.mod_def_id())
641                 .and_then(|def_id| self.tcx.hir().as_local_hir_id(def_id))
642                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
643              {
644                 if let hir::ItemKind::Mod(m) = &item.node {
645                     for item_id in m.item_ids.as_ref() {
646                         let item = self.tcx.hir().expect_item(item_id.id);
647                         let def_id = self.tcx.hir().local_def_id(item_id.id);
648                         if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { continue; }
649                         if let hir::ItemKind::Use(..) = item.node {
650                             self.update(item.hir_id, Some(AccessLevel::Exported));
651                         }
652                     }
653                 }
654             }
655         }
656     }
657 }
658
659 impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
660     /// We want to visit items in the context of their containing
661     /// module and so forth, so supply a crate for doing a deep walk.
662     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
663         NestedVisitorMap::All(&self.tcx.hir())
664     }
665
666     fn visit_item(&mut self, item: &'tcx hir::Item) {
667         let inherited_item_level = match item.node {
668             hir::ItemKind::Impl(..) =>
669                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels),
670             // Foreign modules inherit level from parents.
671             hir::ItemKind::ForeignMod(..) => self.prev_level,
672             // Other `pub` items inherit levels from parents.
673             hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) |
674             hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) |
675             hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) |
676             hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) |
677             hir::ItemKind::OpaqueTy(..) |
678             hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::Use(..) => {
679                 if item.vis.node.is_pub() { self.prev_level } else { None }
680             }
681         };
682
683         // Update level of the item itself.
684         let item_level = self.update(item.hir_id, inherited_item_level);
685
686         // Update levels of nested things.
687         match item.node {
688             hir::ItemKind::Enum(ref def, _) => {
689                 for variant in &def.variants {
690                     let variant_level = self.update(variant.node.id, item_level);
691                     if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
692                         self.update(ctor_hir_id, item_level);
693                     }
694                     for field in variant.node.data.fields() {
695                         self.update(field.hir_id, variant_level);
696                     }
697                 }
698             }
699             hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
700                 for impl_item_ref in impl_item_refs {
701                     if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() {
702                         self.update(impl_item_ref.id.hir_id, item_level);
703                     }
704                 }
705             }
706             hir::ItemKind::Trait(.., ref trait_item_refs) => {
707                 for trait_item_ref in trait_item_refs {
708                     self.update(trait_item_ref.id.hir_id, item_level);
709                 }
710             }
711             hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
712                 if let Some(ctor_hir_id) = def.ctor_hir_id() {
713                     self.update(ctor_hir_id, item_level);
714                 }
715                 for field in def.fields() {
716                     if field.vis.node.is_pub() {
717                         self.update(field.hir_id, item_level);
718                     }
719                 }
720             }
721             hir::ItemKind::ForeignMod(ref foreign_mod) => {
722                 for foreign_item in &foreign_mod.items {
723                     if foreign_item.vis.node.is_pub() {
724                         self.update(foreign_item.hir_id, item_level);
725                     }
726                 }
727             }
728             hir::ItemKind::OpaqueTy(..) |
729             hir::ItemKind::Use(..) |
730             hir::ItemKind::Static(..) |
731             hir::ItemKind::Const(..) |
732             hir::ItemKind::GlobalAsm(..) |
733             hir::ItemKind::TyAlias(..) |
734             hir::ItemKind::Mod(..) |
735             hir::ItemKind::TraitAlias(..) |
736             hir::ItemKind::Fn(..) |
737             hir::ItemKind::ExternCrate(..) => {}
738         }
739
740         // Mark all items in interfaces of reachable items as reachable.
741         match item.node {
742             // The interface is empty.
743             hir::ItemKind::ExternCrate(..) => {}
744             // All nested items are checked by `visit_item`.
745             hir::ItemKind::Mod(..) => {}
746             // Re-exports are handled in `visit_mod`. However, in order to avoid looping over
747             // all of the items of a mod in `visit_mod` looking for use statements, we handle
748             // making sure that intermediate use statements have their visibilities updated here.
749             hir::ItemKind::Use(ref path, _) => {
750                 if item_level.is_some() {
751                     self.update_visibility_of_intermediate_use_statements(path.segments.as_ref());
752                 }
753             }
754             // The interface is empty.
755             hir::ItemKind::GlobalAsm(..) => {}
756             hir::ItemKind::OpaqueTy(..) => {
757                 // FIXME: This is some serious pessimization intended to workaround deficiencies
758                 // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
759                 // reachable if they are returned via `impl Trait`, even from private functions.
760                 let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
761                 self.reach(item.hir_id, exist_level).generics().predicates().ty();
762             }
763             // Visit everything.
764             hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
765             hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => {
766                 if item_level.is_some() {
767                     self.reach(item.hir_id, item_level).generics().predicates().ty();
768                 }
769             }
770             hir::ItemKind::Trait(.., ref trait_item_refs) => {
771                 if item_level.is_some() {
772                     self.reach(item.hir_id, item_level).generics().predicates();
773
774                     for trait_item_ref in trait_item_refs {
775                         let mut reach = self.reach(trait_item_ref.id.hir_id, item_level);
776                         reach.generics().predicates();
777
778                         if trait_item_ref.kind == AssocItemKind::Type &&
779                            !trait_item_ref.defaultness.has_value() {
780                             // No type to visit.
781                         } else {
782                             reach.ty();
783                         }
784                     }
785                 }
786             }
787             hir::ItemKind::TraitAlias(..) => {
788                 if item_level.is_some() {
789                     self.reach(item.hir_id, item_level).generics().predicates();
790                 }
791             }
792             // Visit everything except for private impl items.
793             hir::ItemKind::Impl(.., ref impl_item_refs) => {
794                 if item_level.is_some() {
795                     self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
796
797                     for impl_item_ref in impl_item_refs {
798                         let impl_item_level = self.get(impl_item_ref.id.hir_id);
799                         if impl_item_level.is_some() {
800                             self.reach(impl_item_ref.id.hir_id, impl_item_level)
801                                 .generics().predicates().ty();
802                         }
803                     }
804                 }
805             }
806
807             // Visit everything, but enum variants have their own levels.
808             hir::ItemKind::Enum(ref def, _) => {
809                 if item_level.is_some() {
810                     self.reach(item.hir_id, item_level).generics().predicates();
811                 }
812                 for variant in &def.variants {
813                     let variant_level = self.get(variant.node.id);
814                     if variant_level.is_some() {
815                         for field in variant.node.data.fields() {
816                             self.reach(field.hir_id, variant_level).ty();
817                         }
818                         // Corner case: if the variant is reachable, but its
819                         // enum is not, make the enum reachable as well.
820                         self.update(item.hir_id, variant_level);
821                     }
822                 }
823             }
824             // Visit everything, but foreign items have their own levels.
825             hir::ItemKind::ForeignMod(ref foreign_mod) => {
826                 for foreign_item in &foreign_mod.items {
827                     let foreign_item_level = self.get(foreign_item.hir_id);
828                     if foreign_item_level.is_some() {
829                         self.reach(foreign_item.hir_id, foreign_item_level)
830                             .generics().predicates().ty();
831                     }
832                 }
833             }
834             // Visit everything except for private fields.
835             hir::ItemKind::Struct(ref struct_def, _) |
836             hir::ItemKind::Union(ref struct_def, _) => {
837                 if item_level.is_some() {
838                     self.reach(item.hir_id, item_level).generics().predicates();
839                     for field in struct_def.fields() {
840                         let field_level = self.get(field.hir_id);
841                         if field_level.is_some() {
842                             self.reach(field.hir_id, field_level).ty();
843                         }
844                     }
845                 }
846             }
847         }
848
849         let orig_level = mem::replace(&mut self.prev_level, item_level);
850         intravisit::walk_item(self, item);
851         self.prev_level = orig_level;
852     }
853
854     fn visit_block(&mut self, b: &'tcx hir::Block) {
855         // Blocks can have public items, for example impls, but they always
856         // start as completely private regardless of publicity of a function,
857         // constant, type, field, etc., in which this block resides.
858         let orig_level = mem::replace(&mut self.prev_level, None);
859         intravisit::walk_block(self, b);
860         self.prev_level = orig_level;
861     }
862
863     fn visit_mod(&mut self, m: &'tcx hir::Mod, _sp: Span, id: hir::HirId) {
864         // This code is here instead of in visit_item so that the
865         // crate module gets processed as well.
866         if self.prev_level.is_some() {
867             let def_id = self.tcx.hir().local_def_id(id);
868             if let Some(exports) = self.tcx.module_exports(def_id) {
869                 for export in exports.iter() {
870                     if export.vis == ty::Visibility::Public {
871                         if let Some(def_id) = export.res.opt_def_id() {
872                             if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
873                                 self.update(hir_id, Some(AccessLevel::Exported));
874                             }
875                         }
876                     }
877                 }
878             }
879         }
880
881         intravisit::walk_mod(self, m, id);
882     }
883
884     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
885         if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
886             self.update(md.hir_id, Some(AccessLevel::Public));
887             return
888         }
889
890         let macro_module_def_id = ty::DefIdTree::parent(
891             self.tcx,
892             self.tcx.hir().local_def_id(md.hir_id)
893         ).unwrap();
894         let mut module_id = self.tcx.hir().as_local_hir_id(macro_module_def_id).unwrap();
895         let level = if md.vis.node.is_pub() { self.get(module_id) } else { None };
896         let new_level = self.update(md.hir_id, level);
897         if new_level.is_none() {
898             return
899         }
900
901         loop {
902             let changed_reachability = self.update_macro_reachable(module_id, macro_module_def_id);
903             if changed_reachability || module_id == hir::CRATE_HIR_ID {
904                 break;
905             }
906             module_id = self.tcx.hir().get_parent_node(module_id);
907         }
908     }
909 }
910
911 impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
912     fn generics(&mut self) -> &mut Self {
913         for param in &self.ev.tcx.generics_of(self.item_def_id).params {
914             match param.kind {
915                 GenericParamDefKind::Lifetime => {}
916                 GenericParamDefKind::Type { has_default, .. } => {
917                     if has_default {
918                         self.visit(self.ev.tcx.type_of(param.def_id));
919                     }
920                 }
921                 GenericParamDefKind::Const => {
922                     self.visit(self.ev.tcx.type_of(param.def_id));
923                 }
924             }
925         }
926         self
927     }
928
929     fn predicates(&mut self) -> &mut Self {
930         self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
931         self
932     }
933
934     fn ty(&mut self) -> &mut Self {
935         self.visit(self.ev.tcx.type_of(self.item_def_id));
936         self
937     }
938
939     fn trait_ref(&mut self) -> &mut Self {
940         if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
941             self.visit_trait(trait_ref);
942         }
943         self
944     }
945 }
946
947 impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
948     fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx }
949     fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
950         if let Some(hir_id) = self.ev.tcx.hir().as_local_hir_id(def_id) {
951             if let ((ty::Visibility::Public, ..), _)
952                 | (_, Some(AccessLevel::ReachableFromImplTrait))
953                 = (def_id_visibility(self.tcx(), def_id), self.access_level)
954             {
955                 self.ev.update(hir_id, self.access_level);
956             }
957         }
958         false
959     }
960 }
961
962 //////////////////////////////////////////////////////////////////////////////////////
963 /// Name privacy visitor, checks privacy and reports violations.
964 /// Most of name privacy checks are performed during the main resolution phase,
965 /// or later in type checking when field accesses and associated items are resolved.
966 /// This pass performs remaining checks for fields in struct expressions and patterns.
967 //////////////////////////////////////////////////////////////////////////////////////
968
969 struct NamePrivacyVisitor<'a, 'tcx> {
970     tcx: TyCtxt<'tcx>,
971     tables: &'a ty::TypeckTables<'tcx>,
972     current_item: hir::HirId,
973     empty_tables: &'a ty::TypeckTables<'tcx>,
974 }
975
976 impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
977     // Checks that a field in a struct constructor (expression or pattern) is accessible.
978     fn check_field(&mut self,
979                    use_ctxt: Span, // syntax context of the field name at the use site
980                    span: Span, // span of the field pattern, e.g., `x: 0`
981                    def: &'tcx ty::AdtDef, // definition of the struct or enum
982                    field: &'tcx ty::FieldDef) { // definition of the field
983         let ident = Ident::new(kw::Invalid, use_ctxt);
984         let current_hir = self.current_item;
985         let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, current_hir).1;
986         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
987             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
988                              field.ident, def.variant_descr(), self.tcx.def_path_str(def.did))
989                 .span_label(span, format!("field `{}` is private", field.ident))
990                 .emit();
991         }
992     }
993 }
994
995 impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
996     /// We want to visit items in the context of their containing
997     /// module and so forth, so supply a crate for doing a deep walk.
998     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
999         NestedVisitorMap::All(&self.tcx.hir())
1000     }
1001
1002     fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: hir::HirId) {
1003         // Don't visit nested modules, since we run a separate visitor walk
1004         // for each module in `privacy_access_levels`
1005     }
1006
1007     fn visit_nested_body(&mut self, body: hir::BodyId) {
1008         let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
1009         let body = self.tcx.hir().body(body);
1010         self.visit_body(body);
1011         self.tables = orig_tables;
1012     }
1013
1014     fn visit_item(&mut self, item: &'tcx hir::Item) {
1015         let orig_current_item = mem::replace(&mut self.current_item, item.hir_id);
1016         let orig_tables =
1017             mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
1018         intravisit::walk_item(self, item);
1019         self.current_item = orig_current_item;
1020         self.tables = orig_tables;
1021     }
1022
1023     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
1024         let orig_tables =
1025             mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
1026         intravisit::walk_trait_item(self, ti);
1027         self.tables = orig_tables;
1028     }
1029
1030     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
1031         let orig_tables =
1032             mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
1033         intravisit::walk_impl_item(self, ii);
1034         self.tables = orig_tables;
1035     }
1036
1037     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
1038         match expr.node {
1039             hir::ExprKind::Struct(ref qpath, ref fields, ref base) => {
1040                 let res = self.tables.qpath_res(qpath, expr.hir_id);
1041                 let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap();
1042                 let variant = adt.variant_of_res(res);
1043                 if let Some(ref base) = *base {
1044                     // If the expression uses FRU we need to make sure all the unmentioned fields
1045                     // are checked for privacy (RFC 736). Rather than computing the set of
1046                     // unmentioned fields, just check them all.
1047                     for (vf_index, variant_field) in variant.fields.iter().enumerate() {
1048                         let field = fields.iter().find(|f| {
1049                             self.tcx.field_index(f.hir_id, self.tables) == vf_index
1050                         });
1051                         let (use_ctxt, span) = match field {
1052                             Some(field) => (field.ident.span, field.span),
1053                             None => (base.span, base.span),
1054                         };
1055                         self.check_field(use_ctxt, span, adt, variant_field);
1056                     }
1057                 } else {
1058                     for field in fields {
1059                         let use_ctxt = field.ident.span;
1060                         let index = self.tcx.field_index(field.hir_id, self.tables);
1061                         self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
1062                     }
1063                 }
1064             }
1065             _ => {}
1066         }
1067
1068         intravisit::walk_expr(self, expr);
1069     }
1070
1071     fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
1072         match pat.node {
1073             PatKind::Struct(ref qpath, ref fields, _) => {
1074                 let res = self.tables.qpath_res(qpath, pat.hir_id);
1075                 let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
1076                 let variant = adt.variant_of_res(res);
1077                 for field in fields {
1078                     let use_ctxt = field.node.ident.span;
1079                     let index = self.tcx.field_index(field.node.hir_id, self.tables);
1080                     self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
1081                 }
1082             }
1083             _ => {}
1084         }
1085
1086         intravisit::walk_pat(self, pat);
1087     }
1088 }
1089
1090 ////////////////////////////////////////////////////////////////////////////////////////////
1091 /// Type privacy visitor, checks types for privacy and reports violations.
1092 /// Both explicitly written types and inferred types of expressions and patters are checked.
1093 /// Checks are performed on "semantic" types regardless of names and their hygiene.
1094 ////////////////////////////////////////////////////////////////////////////////////////////
1095
1096 struct TypePrivacyVisitor<'a, 'tcx> {
1097     tcx: TyCtxt<'tcx>,
1098     tables: &'a ty::TypeckTables<'tcx>,
1099     current_item: DefId,
1100     in_body: bool,
1101     span: Span,
1102     empty_tables: &'a ty::TypeckTables<'tcx>,
1103 }
1104
1105 impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
1106     fn item_is_accessible(&self, did: DefId) -> bool {
1107         def_id_visibility(self.tcx, did).0.is_accessible_from(self.current_item, self.tcx)
1108     }
1109
1110     // Take node-id of an expression or pattern and check its type for privacy.
1111     fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
1112         self.span = span;
1113         if self.visit(self.tables.node_type(id)) || self.visit(self.tables.node_substs(id)) {
1114             return true;
1115         }
1116         if let Some(adjustments) = self.tables.adjustments().get(id) {
1117             for adjustment in adjustments {
1118                 if self.visit(adjustment.target) {
1119                     return true;
1120                 }
1121             }
1122         }
1123         false
1124     }
1125
1126     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1127         let is_error = !self.item_is_accessible(def_id);
1128         if is_error {
1129             self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr));
1130         }
1131         is_error
1132     }
1133 }
1134
1135 impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1136     /// We want to visit items in the context of their containing
1137     /// module and so forth, so supply a crate for doing a deep walk.
1138     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1139         NestedVisitorMap::All(&self.tcx.hir())
1140     }
1141
1142     fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: hir::HirId) {
1143         // Don't visit nested modules, since we run a separate visitor walk
1144         // for each module in `privacy_access_levels`
1145     }
1146
1147     fn visit_nested_body(&mut self, body: hir::BodyId) {
1148         let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
1149         let orig_in_body = mem::replace(&mut self.in_body, true);
1150         let body = self.tcx.hir().body(body);
1151         self.visit_body(body);
1152         self.tables = orig_tables;
1153         self.in_body = orig_in_body;
1154     }
1155
1156     fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) {
1157         self.span = hir_ty.span;
1158         if self.in_body {
1159             // Types in bodies.
1160             if self.visit(self.tables.node_type(hir_ty.hir_id)) {
1161                 return;
1162             }
1163         } else {
1164             // Types in signatures.
1165             // FIXME: This is very ineffective. Ideally each HIR type should be converted
1166             // into a semantic type only once and the result should be cached somehow.
1167             if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) {
1168                 return;
1169             }
1170         }
1171
1172         intravisit::walk_ty(self, hir_ty);
1173     }
1174
1175     fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef) {
1176         self.span = trait_ref.path.span;
1177         if !self.in_body {
1178             // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
1179             // The traits' privacy in bodies is already checked as a part of trait object types.
1180             let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
1181
1182             for (trait_predicate, _) in bounds.trait_bounds {
1183                 if self.visit_trait(*trait_predicate.skip_binder()) {
1184                     return;
1185                 }
1186             }
1187
1188             for (poly_predicate, _) in bounds.projection_bounds {
1189                 let tcx = self.tcx;
1190                 if self.visit(poly_predicate.skip_binder().ty)
1191                     || self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx))
1192                 {
1193                     return;
1194                 }
1195             }
1196         }
1197
1198         intravisit::walk_trait_ref(self, trait_ref);
1199     }
1200
1201     // Check types of expressions
1202     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
1203         if self.check_expr_pat_type(expr.hir_id, expr.span) {
1204             // Do not check nested expressions if the error already happened.
1205             return;
1206         }
1207         match expr.node {
1208             hir::ExprKind::Assign(.., ref rhs) | hir::ExprKind::Match(ref rhs, ..) => {
1209                 // Do not report duplicate errors for `x = y` and `match x { ... }`.
1210                 if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
1211                     return;
1212                 }
1213             }
1214             hir::ExprKind::MethodCall(_, span, _) => {
1215                 // Method calls have to be checked specially.
1216                 self.span = span;
1217                 if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {
1218                     if self.visit(self.tcx.type_of(def_id)) {
1219                         return;
1220                     }
1221                 } else {
1222                     self.tcx.sess.delay_span_bug(expr.span,
1223                                                  "no type-dependent def for method call");
1224                 }
1225             }
1226             _ => {}
1227         }
1228
1229         intravisit::walk_expr(self, expr);
1230     }
1231
1232     // Prohibit access to associated items with insufficient nominal visibility.
1233     //
1234     // Additionally, until better reachability analysis for macros 2.0 is available,
1235     // we prohibit access to private statics from other crates, this allows to give
1236     // more code internal visibility at link time. (Access to private functions
1237     // is already prohibited by type privacy for function types.)
1238     fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: hir::HirId, span: Span) {
1239         let def = match self.tables.qpath_res(qpath, id) {
1240             Res::Def(kind, def_id) => Some((kind, def_id)),
1241             _ => None,
1242         };
1243         let def = def.filter(|(kind, _)| {
1244             match kind {
1245                 DefKind::Method
1246                 | DefKind::AssocConst
1247                 | DefKind::AssocTy
1248                 | DefKind::AssocOpaqueTy
1249                 | DefKind::Static => true,
1250                 _ => false,
1251             }
1252         });
1253         if let Some((kind, def_id)) = def {
1254             let is_local_static = if let DefKind::Static = kind {
1255                 def_id.is_local()
1256             } else { false };
1257             if !self.item_is_accessible(def_id) && !is_local_static {
1258                 let name = match *qpath {
1259                     hir::QPath::Resolved(_, ref path) => path.to_string(),
1260                     hir::QPath::TypeRelative(_, ref segment) => segment.ident.to_string(),
1261                 };
1262                 let msg = format!("{} `{}` is private", kind.descr(def_id), name);
1263                 self.tcx.sess.span_err(span, &msg);
1264                 return;
1265             }
1266         }
1267
1268         intravisit::walk_qpath(self, qpath, id, span);
1269     }
1270
1271     // Check types of patterns.
1272     fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
1273         if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
1274             // Do not check nested patterns if the error already happened.
1275             return;
1276         }
1277
1278         intravisit::walk_pat(self, pattern);
1279     }
1280
1281     fn visit_local(&mut self, local: &'tcx hir::Local) {
1282         if let Some(ref init) = local.init {
1283             if self.check_expr_pat_type(init.hir_id, init.span) {
1284                 // Do not report duplicate errors for `let x = y`.
1285                 return;
1286             }
1287         }
1288
1289         intravisit::walk_local(self, local);
1290     }
1291
1292     // Check types in item interfaces.
1293     fn visit_item(&mut self, item: &'tcx hir::Item) {
1294         let orig_current_item = mem::replace(&mut self.current_item,
1295             self.tcx.hir().local_def_id(item.hir_id));
1296         let orig_in_body = mem::replace(&mut self.in_body, false);
1297         let orig_tables =
1298             mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
1299         intravisit::walk_item(self, item);
1300         self.tables = orig_tables;
1301         self.in_body = orig_in_body;
1302         self.current_item = orig_current_item;
1303     }
1304
1305     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
1306         let orig_tables =
1307             mem::replace(&mut self.tables, item_tables(self.tcx, ti.hir_id, self.empty_tables));
1308         intravisit::walk_trait_item(self, ti);
1309         self.tables = orig_tables;
1310     }
1311
1312     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
1313         let orig_tables =
1314             mem::replace(&mut self.tables, item_tables(self.tcx, ii.hir_id, self.empty_tables));
1315         intravisit::walk_impl_item(self, ii);
1316         self.tables = orig_tables;
1317     }
1318 }
1319
1320 impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
1321     fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
1322     fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1323         self.check_def_id(def_id, kind, descr)
1324     }
1325 }
1326
1327 ///////////////////////////////////////////////////////////////////////////////
1328 /// Obsolete visitors for checking for private items in public interfaces.
1329 /// These visitors are supposed to be kept in frozen state and produce an
1330 /// "old error node set". For backward compatibility the new visitor reports
1331 /// warnings instead of hard errors when the erroneous node is not in this old set.
1332 ///////////////////////////////////////////////////////////////////////////////
1333
1334 struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1335     tcx: TyCtxt<'tcx>,
1336     access_levels: &'a AccessLevels,
1337     in_variant: bool,
1338     // Set of errors produced by this obsolete visitor.
1339     old_error_set: HirIdSet,
1340 }
1341
1342 struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
1343     inner: &'a ObsoleteVisiblePrivateTypesVisitor<'b, 'tcx>,
1344     /// Whether the type refers to private types.
1345     contains_private: bool,
1346     /// Whether we've recurred at all (i.e., if we're pointing at the
1347     /// first type on which `visit_ty` was called).
1348     at_outer_type: bool,
1349     /// Whether that first type is a public path.
1350     outer_type_is_public_path: bool,
1351 }
1352
1353 impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1354     fn path_is_private_type(&self, path: &hir::Path) -> bool {
1355         let did = match path.res {
1356             Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => return false,
1357             res => res.def_id(),
1358         };
1359
1360         // A path can only be private if:
1361         // it's in this crate...
1362         if let Some(hir_id) = self.tcx.hir().as_local_hir_id(did) {
1363             // .. and it corresponds to a private type in the AST (this returns
1364             // `None` for type parameters).
1365             match self.tcx.hir().find(hir_id) {
1366                 Some(Node::Item(ref item)) => !item.vis.node.is_pub(),
1367                 Some(_) | None => false,
1368             }
1369         } else {
1370             return false
1371         }
1372     }
1373
1374     fn trait_is_public(&self, trait_id: hir::HirId) -> bool {
1375         // FIXME: this would preferably be using `exported_items`, but all
1376         // traits are exported currently (see `EmbargoVisitor.exported_trait`).
1377         self.access_levels.is_public(trait_id)
1378     }
1379
1380     fn check_generic_bound(&mut self, bound: &hir::GenericBound) {
1381         if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
1382             if self.path_is_private_type(&trait_ref.trait_ref.path) {
1383                 self.old_error_set.insert(trait_ref.trait_ref.hir_ref_id);
1384             }
1385         }
1386     }
1387
1388     fn item_is_public(&self, id: &hir::HirId, vis: &hir::Visibility) -> bool {
1389         self.access_levels.is_reachable(*id) || vis.node.is_pub()
1390     }
1391 }
1392
1393 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
1394     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
1395         NestedVisitorMap::None
1396     }
1397
1398     fn visit_ty(&mut self, ty: &hir::Ty) {
1399         if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.node {
1400             if self.inner.path_is_private_type(path) {
1401                 self.contains_private = true;
1402                 // Found what we're looking for, so let's stop working.
1403                 return
1404             }
1405         }
1406         if let hir::TyKind::Path(_) = ty.node {
1407             if self.at_outer_type {
1408                 self.outer_type_is_public_path = true;
1409             }
1410         }
1411         self.at_outer_type = false;
1412         intravisit::walk_ty(self, ty)
1413     }
1414
1415     // Don't want to recurse into `[, .. expr]`.
1416     fn visit_expr(&mut self, _: &hir::Expr) {}
1417 }
1418
1419 impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
1420     /// We want to visit items in the context of their containing
1421     /// module and so forth, so supply a crate for doing a deep walk.
1422     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1423         NestedVisitorMap::All(&self.tcx.hir())
1424     }
1425
1426     fn visit_item(&mut self, item: &'tcx hir::Item) {
1427         match item.node {
1428             // Contents of a private mod can be re-exported, so we need
1429             // to check internals.
1430             hir::ItemKind::Mod(_) => {}
1431
1432             // An `extern {}` doesn't introduce a new privacy
1433             // namespace (the contents have their own privacies).
1434             hir::ItemKind::ForeignMod(_) => {}
1435
1436             hir::ItemKind::Trait(.., ref bounds, _) => {
1437                 if !self.trait_is_public(item.hir_id) {
1438                     return
1439                 }
1440
1441                 for bound in bounds.iter() {
1442                     self.check_generic_bound(bound)
1443                 }
1444             }
1445
1446             // Impls need some special handling to try to offer useful
1447             // error messages without (too many) false positives
1448             // (i.e., we could just return here to not check them at
1449             // all, or some worse estimation of whether an impl is
1450             // publicly visible).
1451             hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, ref impl_item_refs) => {
1452                 // `impl [... for] Private` is never visible.
1453                 let self_contains_private;
1454                 // `impl [... for] Public<...>`, but not `impl [... for]
1455                 // Vec<Public>` or `(Public,)`, etc.
1456                 let self_is_public_path;
1457
1458                 // Check the properties of the `Self` type:
1459                 {
1460                     let mut visitor = ObsoleteCheckTypeForPrivatenessVisitor {
1461                         inner: self,
1462                         contains_private: false,
1463                         at_outer_type: true,
1464                         outer_type_is_public_path: false,
1465                     };
1466                     visitor.visit_ty(&self_);
1467                     self_contains_private = visitor.contains_private;
1468                     self_is_public_path = visitor.outer_type_is_public_path;
1469                 }
1470
1471                 // Miscellaneous info about the impl:
1472
1473                 // `true` iff this is `impl Private for ...`.
1474                 let not_private_trait =
1475                     trait_ref.as_ref().map_or(true, // no trait counts as public trait
1476                                               |tr| {
1477                         let did = tr.path.res.def_id();
1478
1479                         if let Some(hir_id) = self.tcx.hir().as_local_hir_id(did) {
1480                             self.trait_is_public(hir_id)
1481                         } else {
1482                             true // external traits must be public
1483                         }
1484                     });
1485
1486                 // `true` iff this is a trait impl or at least one method is public.
1487                 //
1488                 // `impl Public { $( fn ...() {} )* }` is not visible.
1489                 //
1490                 // This is required over just using the methods' privacy
1491                 // directly because we might have `impl<T: Foo<Private>> ...`,
1492                 // and we shouldn't warn about the generics if all the methods
1493                 // are private (because `T` won't be visible externally).
1494                 let trait_or_some_public_method =
1495                     trait_ref.is_some() ||
1496                     impl_item_refs.iter()
1497                                  .any(|impl_item_ref| {
1498                                      let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
1499                                      match impl_item.node {
1500                                          hir::ImplItemKind::Const(..) |
1501                                          hir::ImplItemKind::Method(..) => {
1502                                              self.access_levels.is_reachable(
1503                                                 impl_item_ref.id.hir_id)
1504                                          }
1505                                          hir::ImplItemKind::OpaqueTy(..) |
1506                                          hir::ImplItemKind::TyAlias(_) => false,
1507                                      }
1508                                  });
1509
1510                 if !self_contains_private &&
1511                         not_private_trait &&
1512                         trait_or_some_public_method {
1513
1514                     intravisit::walk_generics(self, g);
1515
1516                     match *trait_ref {
1517                         None => {
1518                             for impl_item_ref in impl_item_refs {
1519                                 // This is where we choose whether to walk down
1520                                 // further into the impl to check its items. We
1521                                 // should only walk into public items so that we
1522                                 // don't erroneously report errors for private
1523                                 // types in private items.
1524                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
1525                                 match impl_item.node {
1526                                     hir::ImplItemKind::Const(..) |
1527                                     hir::ImplItemKind::Method(..)
1528                                         if self.item_is_public(&impl_item.hir_id, &impl_item.vis) =>
1529                                     {
1530                                         intravisit::walk_impl_item(self, impl_item)
1531                                     }
1532                                     hir::ImplItemKind::TyAlias(..) => {
1533                                         intravisit::walk_impl_item(self, impl_item)
1534                                     }
1535                                     _ => {}
1536                                 }
1537                             }
1538                         }
1539                         Some(ref tr) => {
1540                             // Any private types in a trait impl fall into three
1541                             // categories.
1542                             // 1. mentioned in the trait definition
1543                             // 2. mentioned in the type params/generics
1544                             // 3. mentioned in the associated types of the impl
1545                             //
1546                             // Those in 1. can only occur if the trait is in
1547                             // this crate and will've been warned about on the
1548                             // trait definition (there's no need to warn twice
1549                             // so we don't check the methods).
1550                             //
1551                             // Those in 2. are warned via walk_generics and this
1552                             // call here.
1553                             intravisit::walk_path(self, &tr.path);
1554
1555                             // Those in 3. are warned with this call.
1556                             for impl_item_ref in impl_item_refs {
1557                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
1558                                 if let hir::ImplItemKind::TyAlias(ref ty) = impl_item.node {
1559                                     self.visit_ty(ty);
1560                                 }
1561                             }
1562                         }
1563                     }
1564                 } else if trait_ref.is_none() && self_is_public_path {
1565                     // `impl Public<Private> { ... }`. Any public static
1566                     // methods will be visible as `Public::foo`.
1567                     let mut found_pub_static = false;
1568                     for impl_item_ref in impl_item_refs {
1569                         if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) {
1570                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
1571                             match impl_item_ref.kind {
1572                                 AssocItemKind::Const => {
1573                                     found_pub_static = true;
1574                                     intravisit::walk_impl_item(self, impl_item);
1575                                 }
1576                                 AssocItemKind::Method { has_self: false } => {
1577                                     found_pub_static = true;
1578                                     intravisit::walk_impl_item(self, impl_item);
1579                                 }
1580                                 _ => {}
1581                             }
1582                         }
1583                     }
1584                     if found_pub_static {
1585                         intravisit::walk_generics(self, g)
1586                     }
1587                 }
1588                 return
1589             }
1590
1591             // `type ... = ...;` can contain private types, because
1592             // we're introducing a new name.
1593             hir::ItemKind::TyAlias(..) => return,
1594
1595             // Not at all public, so we don't care.
1596             _ if !self.item_is_public(&item.hir_id, &item.vis) => {
1597                 return;
1598             }
1599
1600             _ => {}
1601         }
1602
1603         // We've carefully constructed it so that if we're here, then
1604         // any `visit_ty`'s will be called on things that are in
1605         // public signatures, i.e., things that we're interested in for
1606         // this visitor.
1607         intravisit::walk_item(self, item);
1608     }
1609
1610     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
1611         for param in &generics.params {
1612             for bound in &param.bounds {
1613                 self.check_generic_bound(bound);
1614             }
1615         }
1616         for predicate in &generics.where_clause.predicates {
1617             match predicate {
1618                 hir::WherePredicate::BoundPredicate(bound_pred) => {
1619                     for bound in bound_pred.bounds.iter() {
1620                         self.check_generic_bound(bound)
1621                     }
1622                 }
1623                 hir::WherePredicate::RegionPredicate(_) => {}
1624                 hir::WherePredicate::EqPredicate(eq_pred) => {
1625                     self.visit_ty(&eq_pred.rhs_ty);
1626                 }
1627             }
1628         }
1629     }
1630
1631     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
1632         if self.access_levels.is_reachable(item.hir_id) {
1633             intravisit::walk_foreign_item(self, item)
1634         }
1635     }
1636
1637     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
1638         if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = t.node {
1639             if self.path_is_private_type(path) {
1640                 self.old_error_set.insert(t.hir_id);
1641             }
1642         }
1643         intravisit::walk_ty(self, t)
1644     }
1645
1646     fn visit_variant(&mut self,
1647                      v: &'tcx hir::Variant,
1648                      g: &'tcx hir::Generics,
1649                      item_id: hir::HirId) {
1650         if self.access_levels.is_reachable(v.node.id) {
1651             self.in_variant = true;
1652             intravisit::walk_variant(self, v, g, item_id);
1653             self.in_variant = false;
1654         }
1655     }
1656
1657     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
1658         if s.vis.node.is_pub() || self.in_variant {
1659             intravisit::walk_struct_field(self, s);
1660         }
1661     }
1662
1663     // We don't need to introspect into these at all: an
1664     // expression/block context can't possibly contain exported things.
1665     // (Making them no-ops stops us from traversing the whole AST without
1666     // having to be super careful about our `walk_...` calls above.)
1667     fn visit_block(&mut self, _: &'tcx hir::Block) {}
1668     fn visit_expr(&mut self, _: &'tcx hir::Expr) {}
1669 }
1670
1671 ///////////////////////////////////////////////////////////////////////////////
1672 /// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
1673 /// finds any private components in it.
1674 /// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
1675 /// and traits in public interfaces.
1676 ///////////////////////////////////////////////////////////////////////////////
1677
1678 struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
1679     tcx: TyCtxt<'tcx>,
1680     item_id: hir::HirId,
1681     item_def_id: DefId,
1682     span: Span,
1683     /// The visitor checks that each component type is at least this visible.
1684     required_visibility: ty::Visibility,
1685     has_pub_restricted: bool,
1686     has_old_errors: bool,
1687     in_assoc_ty: bool,
1688 }
1689
1690 impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
1691     fn generics(&mut self) -> &mut Self {
1692         for param in &self.tcx.generics_of(self.item_def_id).params {
1693             match param.kind {
1694                 GenericParamDefKind::Lifetime => {}
1695                 GenericParamDefKind::Type { has_default, .. } => {
1696                     if has_default {
1697                         self.visit(self.tcx.type_of(param.def_id));
1698                     }
1699                 }
1700                 GenericParamDefKind::Const => {
1701                     self.visit(self.tcx.type_of(param.def_id));
1702                 }
1703             }
1704         }
1705         self
1706     }
1707
1708     fn predicates(&mut self) -> &mut Self {
1709         // N.B., we use `explicit_predicates_of` and not `predicates_of`
1710         // because we don't want to report privacy errors due to where
1711         // clauses that the compiler inferred. We only want to
1712         // consider the ones that the user wrote. This is important
1713         // for the inferred outlives rules; see
1714         // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`.
1715         self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
1716         self
1717     }
1718
1719     fn ty(&mut self) -> &mut Self {
1720         self.visit(self.tcx.type_of(self.item_def_id));
1721         self
1722     }
1723
1724     fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1725         if self.leaks_private_dep(def_id) {
1726             self.tcx.lint_hir(lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
1727                               self.item_id,
1728                               self.span,
1729                               &format!("{} `{}` from private dependency '{}' in public \
1730                                         interface", kind, descr,
1731                                         self.tcx.crate_name(def_id.krate)));
1732
1733         }
1734
1735         let hir_id = match self.tcx.hir().as_local_hir_id(def_id) {
1736             Some(hir_id) => hir_id,
1737             None => return false,
1738         };
1739
1740         let (vis, vis_span, vis_descr) = def_id_visibility(self.tcx, def_id);
1741         if !vis.is_at_least(self.required_visibility, self.tcx) {
1742             let msg = format!("{} {} `{}` in public interface", vis_descr, kind, descr);
1743             if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
1744                 let mut err = if kind == "trait" {
1745                     struct_span_err!(self.tcx.sess, self.span, E0445, "{}", msg)
1746                 } else {
1747                     struct_span_err!(self.tcx.sess, self.span, E0446, "{}", msg)
1748                 };
1749                 err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind));
1750                 err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
1751                 err.emit();
1752             } else {
1753                 let err_code = if kind == "trait" { "E0445" } else { "E0446" };
1754                 self.tcx.lint_hir(lint::builtin::PRIVATE_IN_PUBLIC, hir_id, self.span,
1755                                   &format!("{} (error {})", msg, err_code));
1756             }
1757
1758         }
1759
1760         false
1761     }
1762
1763     /// An item is 'leaked' from a private dependency if all
1764     /// of the following are true:
1765     /// 1. It's contained within a public type
1766     /// 2. It comes from a private crate
1767     fn leaks_private_dep(&self, item_id: DefId) -> bool {
1768         let ret = self.required_visibility == ty::Visibility::Public &&
1769             self.tcx.is_private_dep(item_id.krate);
1770
1771         log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
1772         return ret;
1773     }
1774 }
1775
1776 impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
1777     fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
1778     fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1779         self.check_def_id(def_id, kind, descr)
1780     }
1781 }
1782
1783 struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1784     tcx: TyCtxt<'tcx>,
1785     has_pub_restricted: bool,
1786     old_error_set: &'a HirIdSet,
1787 }
1788
1789 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1790     fn check(
1791         &self,
1792         item_id: hir::HirId,
1793         required_visibility: ty::Visibility,
1794     ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
1795         let mut has_old_errors = false;
1796
1797         // Slow path taken only if there any errors in the crate.
1798         for &id in self.old_error_set {
1799             // Walk up the nodes until we find `item_id` (or we hit a root).
1800             let mut id = id;
1801             loop {
1802                 if id == item_id {
1803                     has_old_errors = true;
1804                     break;
1805                 }
1806                 let parent = self.tcx.hir().get_parent_node(id);
1807                 if parent == id {
1808                     break;
1809                 }
1810                 id = parent;
1811             }
1812
1813             if has_old_errors {
1814                 break;
1815             }
1816         }
1817
1818         SearchInterfaceForPrivateItemsVisitor {
1819             tcx: self.tcx,
1820             item_id,
1821             item_def_id: self.tcx.hir().local_def_id(item_id),
1822             span: self.tcx.hir().span(item_id),
1823             required_visibility,
1824             has_pub_restricted: self.has_pub_restricted,
1825             has_old_errors,
1826             in_assoc_ty: false,
1827         }
1828     }
1829
1830     fn check_assoc_item(
1831         &self,
1832         hir_id: hir::HirId,
1833         assoc_item_kind: AssocItemKind,
1834         defaultness: hir::Defaultness,
1835         vis: ty::Visibility,
1836     ) {
1837         let mut check = self.check(hir_id, vis);
1838
1839         let (check_ty, is_assoc_ty) = match assoc_item_kind {
1840             AssocItemKind::Const | AssocItemKind::Method { .. } => (true, false),
1841             AssocItemKind::Type => (defaultness.has_value(), true),
1842             // `ty()` for opaque types is the underlying type,
1843             // it's not a part of interface, so we skip it.
1844             AssocItemKind::OpaqueTy => (false, true),
1845         };
1846         check.in_assoc_ty = is_assoc_ty;
1847         check.generics().predicates();
1848         if check_ty {
1849             check.ty();
1850         }
1851     }
1852 }
1853
1854 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
1855     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1856         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
1857     }
1858
1859     fn visit_item(&mut self, item: &'tcx hir::Item) {
1860         let tcx = self.tcx;
1861         let item_visibility = ty::Visibility::from_hir(&item.vis, item.hir_id, tcx);
1862
1863         match item.node {
1864             // Crates are always public.
1865             hir::ItemKind::ExternCrate(..) => {}
1866             // All nested items are checked by `visit_item`.
1867             hir::ItemKind::Mod(..) => {}
1868             // Checked in resolve.
1869             hir::ItemKind::Use(..) => {}
1870             // No subitems.
1871             hir::ItemKind::GlobalAsm(..) => {}
1872             // Subitems of these items have inherited publicity.
1873             hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
1874             hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => {
1875                 self.check(item.hir_id, item_visibility).generics().predicates().ty();
1876             }
1877             hir::ItemKind::OpaqueTy(..) => {
1878                 // `ty()` for opaque types is the underlying type,
1879                 // it's not a part of interface, so we skip it.
1880                 self.check(item.hir_id, item_visibility).generics().predicates();
1881             }
1882             hir::ItemKind::Trait(.., ref trait_item_refs) => {
1883                 self.check(item.hir_id, item_visibility).generics().predicates();
1884
1885                 for trait_item_ref in trait_item_refs {
1886                     self.check_assoc_item(
1887                         trait_item_ref.id.hir_id,
1888                         trait_item_ref.kind,
1889                         trait_item_ref.defaultness,
1890                         item_visibility,
1891                     );
1892                 }
1893             }
1894             hir::ItemKind::TraitAlias(..) => {
1895                 self.check(item.hir_id, item_visibility).generics().predicates();
1896             }
1897             hir::ItemKind::Enum(ref def, _) => {
1898                 self.check(item.hir_id, item_visibility).generics().predicates();
1899
1900                 for variant in &def.variants {
1901                     for field in variant.node.data.fields() {
1902                         self.check(field.hir_id, item_visibility).ty();
1903                     }
1904                 }
1905             }
1906             // Subitems of foreign modules have their own publicity.
1907             hir::ItemKind::ForeignMod(ref foreign_mod) => {
1908                 for foreign_item in &foreign_mod.items {
1909                     let vis = ty::Visibility::from_hir(&foreign_item.vis, item.hir_id, tcx);
1910                     self.check(foreign_item.hir_id, vis).generics().predicates().ty();
1911                 }
1912             }
1913             // Subitems of structs and unions have their own publicity.
1914             hir::ItemKind::Struct(ref struct_def, _) |
1915             hir::ItemKind::Union(ref struct_def, _) => {
1916                 self.check(item.hir_id, item_visibility).generics().predicates();
1917
1918                 for field in struct_def.fields() {
1919                     let field_visibility = ty::Visibility::from_hir(&field.vis, item.hir_id, tcx);
1920                     self.check(field.hir_id, min(item_visibility, field_visibility, tcx)).ty();
1921                 }
1922             }
1923             // An inherent impl is public when its type is public
1924             // Subitems of inherent impls have their own publicity.
1925             // A trait impl is public when both its type and its trait are public
1926             // Subitems of trait impls have inherited publicity.
1927             hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
1928                 let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
1929                 self.check(item.hir_id, impl_vis).generics().predicates();
1930                 for impl_item_ref in impl_item_refs {
1931                     let impl_item = tcx.hir().impl_item(impl_item_ref.id);
1932                     let impl_item_vis = if trait_ref.is_none() {
1933                         min(ty::Visibility::from_hir(&impl_item.vis, item.hir_id, tcx),
1934                             impl_vis,
1935                             tcx)
1936                     } else {
1937                         impl_vis
1938                     };
1939                     self.check_assoc_item(
1940                         impl_item_ref.id.hir_id,
1941                         impl_item_ref.kind,
1942                         impl_item_ref.defaultness,
1943                         impl_item_vis,
1944                     );
1945                 }
1946             }
1947         }
1948     }
1949 }
1950
1951 pub fn provide(providers: &mut Providers<'_>) {
1952     *providers = Providers {
1953         privacy_access_levels,
1954         check_private_in_public,
1955         check_mod_privacy,
1956         ..*providers
1957     };
1958 }
1959
1960 fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: DefId) {
1961     let empty_tables = ty::TypeckTables::empty(None);
1962
1963     // Check privacy of names not checked in previous compilation stages.
1964     let mut visitor = NamePrivacyVisitor {
1965         tcx,
1966         tables: &empty_tables,
1967         current_item: hir::DUMMY_HIR_ID,
1968         empty_tables: &empty_tables,
1969     };
1970     let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
1971
1972     intravisit::walk_mod(&mut visitor, module, hir_id);
1973
1974     // Check privacy of explicitly written types and traits as well as
1975     // inferred types of expressions and patterns.
1976     let mut visitor = TypePrivacyVisitor {
1977         tcx,
1978         tables: &empty_tables,
1979         current_item: module_def_id,
1980         in_body: false,
1981         span,
1982         empty_tables: &empty_tables,
1983     };
1984     intravisit::walk_mod(&mut visitor, module, hir_id);
1985 }
1986
1987 fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels {
1988     assert_eq!(krate, LOCAL_CRATE);
1989
1990     // Build up a set of all exported items in the AST. This is a set of all
1991     // items which are reachable from external crates based on visibility.
1992     let mut visitor = EmbargoVisitor {
1993         tcx,
1994         access_levels: Default::default(),
1995         macro_reachable: Default::default(),
1996         prev_level: Some(AccessLevel::Public),
1997         changed: false,
1998     };
1999     loop {
2000         intravisit::walk_crate(&mut visitor, tcx.hir().krate());
2001         if visitor.changed {
2002             visitor.changed = false;
2003         } else {
2004             break
2005         }
2006     }
2007     visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
2008
2009     tcx.arena.alloc(visitor.access_levels)
2010 }
2011
2012 fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) {
2013     assert_eq!(krate, LOCAL_CRATE);
2014
2015     let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
2016
2017     let krate = tcx.hir().krate();
2018
2019     let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
2020         tcx,
2021         access_levels: &access_levels,
2022         in_variant: false,
2023         old_error_set: Default::default(),
2024     };
2025     intravisit::walk_crate(&mut visitor, krate);
2026
2027     let has_pub_restricted = {
2028         let mut pub_restricted_visitor = PubRestrictedVisitor {
2029             tcx,
2030             has_pub_restricted: false
2031         };
2032         intravisit::walk_crate(&mut pub_restricted_visitor, krate);
2033         pub_restricted_visitor.has_pub_restricted
2034     };
2035
2036     // Check for private types and traits in public interfaces.
2037     let mut visitor = PrivateItemsInPublicInterfacesVisitor {
2038         tcx,
2039         has_pub_restricted,
2040         old_error_set: &visitor.old_error_set,
2041     };
2042     krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
2043 }
2044
2045 __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }