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