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