rustc_privacy/
lib.rs

1// tidy-alphabetical-start
2#![allow(internal_features)]
3#![cfg_attr(bootstrap, feature(let_chains))]
4#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
5#![doc(rust_logo)]
6#![feature(associated_type_defaults)]
7#![feature(rustdoc_internals)]
8#![feature(try_blocks)]
9// tidy-alphabetical-end
10
11mod errors;
12
13use std::fmt;
14use std::marker::PhantomData;
15use std::ops::ControlFlow;
16
17use errors::{
18    FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
19    ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
20    UnnamedItemIsPrivate,
21};
22use rustc_ast::MacroDef;
23use rustc_ast::visit::{VisitorResult, try_visit};
24use rustc_attr_parsing::AttributeKind;
25use rustc_data_structures::fx::FxHashSet;
26use rustc_data_structures::intern::Interned;
27use rustc_errors::{MultiSpan, listify};
28use rustc_hir::def::{DefKind, Res};
29use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
30use rustc_hir::intravisit::{self, InferKind, Visitor};
31use rustc_hir::{AmbigArg, AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
32use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
33use rustc_middle::query::Providers;
34use rustc_middle::ty::print::PrintTraitRefExt as _;
35use rustc_middle::ty::{
36    self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
37    TypeVisitor,
38};
39use rustc_middle::{bug, span_bug};
40use rustc_session::lint;
41use rustc_span::hygiene::Transparency;
42use rustc_span::{Ident, Span, Symbol, sym};
43use tracing::debug;
44use {rustc_attr_parsing as attr, rustc_hir as hir};
45
46rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
47
48////////////////////////////////////////////////////////////////////////////////
49/// Generic infrastructure used to implement specific visitors below.
50////////////////////////////////////////////////////////////////////////////////
51
52struct LazyDefPathStr<'tcx> {
53    def_id: DefId,
54    tcx: TyCtxt<'tcx>,
55}
56
57impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "{}", self.tcx.def_path_str(self.def_id))
60    }
61}
62
63/// Implemented to visit all `DefId`s in a type.
64/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them.
65/// The idea is to visit "all components of a type", as documented in
66/// <https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type>.
67/// The default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings.
68/// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
69/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
70/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
71pub trait DefIdVisitor<'tcx> {
72    type Result: VisitorResult = ();
73    const SHALLOW: bool = false;
74    fn skip_assoc_tys(&self) -> bool {
75        false
76    }
77
78    fn tcx(&self) -> TyCtxt<'tcx>;
79    fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
80    -> Self::Result;
81
82    /// Not overridden, but used to actually visit types and traits.
83    fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
84        DefIdVisitorSkeleton {
85            def_id_visitor: self,
86            visited_opaque_tys: Default::default(),
87            dummy: Default::default(),
88        }
89    }
90    fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
91        ty_fragment.visit_with(&mut self.skeleton())
92    }
93    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
94        self.skeleton().visit_trait(trait_ref)
95    }
96    fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
97        self.skeleton().visit_clauses(predicates.predicates)
98    }
99    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
100        self.skeleton().visit_clauses(clauses)
101    }
102}
103
104pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
105    def_id_visitor: &'v mut V,
106    visited_opaque_tys: FxHashSet<DefId>,
107    dummy: PhantomData<TyCtxt<'tcx>>,
108}
109
110impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
111where
112    V: DefIdVisitor<'tcx> + ?Sized,
113{
114    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
115        let TraitRef { def_id, args, .. } = trait_ref;
116        try_visit!(self.def_id_visitor.visit_def_id(
117            def_id,
118            "trait",
119            &trait_ref.print_only_trait_path()
120        ));
121        if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
122    }
123
124    fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
125        let tcx = self.def_id_visitor.tcx();
126        let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
127        try_visit!(self.visit_trait(trait_ref));
128        if V::SHALLOW {
129            V::Result::output()
130        } else {
131            V::Result::from_branch(
132                assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
133            )
134        }
135    }
136
137    fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
138        match clause.kind().skip_binder() {
139            ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
140                self.visit_trait(trait_ref)
141            }
142            ty::ClauseKind::HostEffect(pred) => {
143                try_visit!(self.visit_trait(pred.trait_ref));
144                pred.constness.visit_with(self)
145            }
146            ty::ClauseKind::Projection(ty::ProjectionPredicate {
147                projection_term: projection_ty,
148                term,
149            }) => {
150                try_visit!(term.visit_with(self));
151                self.visit_projection_term(projection_ty)
152            }
153            ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
154            ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
155            ty::ClauseKind::ConstArgHasType(ct, ty) => {
156                try_visit!(ct.visit_with(self));
157                ty.visit_with(self)
158            }
159            ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
160            ty::ClauseKind::WellFormed(term) => term.visit_with(self),
161        }
162    }
163
164    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
165        for &(clause, _) in clauses {
166            try_visit!(self.visit_clause(clause));
167        }
168        V::Result::output()
169    }
170}
171
172impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
173where
174    V: DefIdVisitor<'tcx> + ?Sized,
175{
176    type Result = V::Result;
177
178    fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
179        self.visit_clause(p.as_clause().unwrap())
180    }
181
182    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
183        let tcx = self.def_id_visitor.tcx();
184        // GenericArgs are not visited here because they are visited below
185        // in `super_visit_with`.
186        match *ty.kind() {
187            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
188            | ty::Foreign(def_id)
189            | ty::FnDef(def_id, ..)
190            | ty::Closure(def_id, ..)
191            | ty::CoroutineClosure(def_id, ..)
192            | ty::Coroutine(def_id, ..) => {
193                try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
194                if V::SHALLOW {
195                    return V::Result::output();
196                }
197                // Default type visitor doesn't visit signatures of fn types.
198                // Something like `fn() -> Priv {my_func}` is considered a private type even if
199                // `my_func` is public, so we need to visit signatures.
200                if let ty::FnDef(..) = ty.kind() {
201                    // FIXME: this should probably use `args` from `FnDef`
202                    try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self));
203                }
204                // Inherent static methods don't have self type in args.
205                // Something like `fn() {my_method}` type of the method
206                // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
207                // so we need to visit the self type additionally.
208                if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
209                    if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
210                        try_visit!(
211                            tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
212                        );
213                    }
214                }
215            }
216            ty::Alias(kind @ (ty::Inherent | ty::Free | ty::Projection), data) => {
217                if self.def_id_visitor.skip_assoc_tys() {
218                    // Visitors searching for minimal visibility/reachability want to
219                    // conservatively approximate associated types like `Type::Alias`
220                    // as visible/reachable even if `Type` is private.
221                    // Ideally, associated types should be instantiated in the same way as
222                    // free type aliases, but this isn't done yet.
223                    return V::Result::output();
224                }
225
226                try_visit!(self.def_id_visitor.visit_def_id(
227                    data.def_id,
228                    match kind {
229                        ty::Inherent | ty::Projection => "associated type",
230                        ty::Free => "type alias",
231                        ty::Opaque => unreachable!(),
232                    },
233                    &LazyDefPathStr { def_id: data.def_id, tcx },
234                ));
235
236                // This will also visit args if necessary, so we don't need to recurse.
237                return if V::SHALLOW {
238                    V::Result::output()
239                } else if kind == ty::Projection {
240                    self.visit_projection_term(data.into())
241                } else {
242                    V::Result::from_branch(
243                        data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
244                    )
245                };
246            }
247            ty::Dynamic(predicates, ..) => {
248                // All traits in the list are considered the "primary" part of the type
249                // and are visited by shallow visitors.
250                for predicate in predicates {
251                    let trait_ref = match predicate.skip_binder() {
252                        ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
253                        ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
254                        ty::ExistentialPredicate::AutoTrait(def_id) => {
255                            ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
256                        }
257                    };
258                    let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
259                    try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
260                }
261            }
262            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
263                // Skip repeated `Opaque`s to avoid infinite recursion.
264                if self.visited_opaque_tys.insert(def_id) {
265                    // The intent is to treat `impl Trait1 + Trait2` identically to
266                    // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
267                    // (it either has no visibility, or its visibility is insignificant, like
268                    // visibilities of type aliases) and recurse into bounds instead to go
269                    // through the trait list (default type visitor doesn't visit those traits).
270                    // All traits in the list are considered the "primary" part of the type
271                    // and are visited by shallow visitors.
272                    try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()));
273                }
274            }
275            // These types don't have their own def-ids (but may have subcomponents
276            // with def-ids that should be visited recursively).
277            ty::Bool
278            | ty::Char
279            | ty::Int(..)
280            | ty::Uint(..)
281            | ty::Float(..)
282            | ty::Str
283            | ty::Never
284            | ty::Array(..)
285            | ty::Slice(..)
286            | ty::Tuple(..)
287            | ty::RawPtr(..)
288            | ty::Ref(..)
289            | ty::Pat(..)
290            | ty::FnPtr(..)
291            | ty::UnsafeBinder(_)
292            | ty::Param(..)
293            | ty::Bound(..)
294            | ty::Error(_)
295            | ty::CoroutineWitness(..) => {}
296            ty::Placeholder(..) | ty::Infer(..) => {
297                bug!("unexpected type: {:?}", ty)
298            }
299        }
300
301        if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
302    }
303
304    fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
305        let tcx = self.def_id_visitor.tcx();
306        tcx.expand_abstract_consts(c).super_visit_with(self)
307    }
308}
309
310fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
311    if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Visitor used to determine impl visibility and reachability.
316////////////////////////////////////////////////////////////////////////////////
317
318struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
319    tcx: TyCtxt<'tcx>,
320    effective_visibilities: &'a EffectiveVisibilities,
321    min: VL,
322}
323
324impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
325    for FindMin<'a, 'tcx, VL, SHALLOW>
326{
327    const SHALLOW: bool = SHALLOW;
328    fn skip_assoc_tys(&self) -> bool {
329        true
330    }
331    fn tcx(&self) -> TyCtxt<'tcx> {
332        self.tcx
333    }
334    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
335        if let Some(def_id) = def_id.as_local() {
336            self.min = VL::new_min(self, def_id);
337        }
338    }
339}
340
341trait VisibilityLike: Sized {
342    const MAX: Self;
343    fn new_min<const SHALLOW: bool>(
344        find: &FindMin<'_, '_, Self, SHALLOW>,
345        def_id: LocalDefId,
346    ) -> Self;
347
348    // Returns an over-approximation (`skip_assoc_tys()` = true) of visibility due to
349    // associated types for which we can't determine visibility precisely.
350    fn of_impl<const SHALLOW: bool>(
351        def_id: LocalDefId,
352        tcx: TyCtxt<'_>,
353        effective_visibilities: &EffectiveVisibilities,
354    ) -> Self {
355        let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
356        find.visit(tcx.type_of(def_id).instantiate_identity());
357        if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
358            find.visit_trait(trait_ref.instantiate_identity());
359        }
360        find.min
361    }
362}
363
364impl VisibilityLike for ty::Visibility {
365    const MAX: Self = ty::Visibility::Public;
366    fn new_min<const SHALLOW: bool>(
367        find: &FindMin<'_, '_, Self, SHALLOW>,
368        def_id: LocalDefId,
369    ) -> Self {
370        min(find.tcx.local_visibility(def_id), find.min, find.tcx)
371    }
372}
373
374impl VisibilityLike for EffectiveVisibility {
375    const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
376    fn new_min<const SHALLOW: bool>(
377        find: &FindMin<'_, '_, Self, SHALLOW>,
378        def_id: LocalDefId,
379    ) -> Self {
380        let effective_vis =
381            find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
382                let private_vis = ty::Visibility::Restricted(
383                    find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
384                );
385                EffectiveVisibility::from_vis(private_vis)
386            });
387
388        effective_vis.min(find.min, find.tcx)
389    }
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// The embargo visitor, used to determine the exports of the AST.
394////////////////////////////////////////////////////////////////////////////////
395
396struct EmbargoVisitor<'tcx> {
397    tcx: TyCtxt<'tcx>,
398
399    /// Effective visibilities for reachable nodes.
400    effective_visibilities: EffectiveVisibilities,
401    /// A set of pairs corresponding to modules, where the first module is
402    /// reachable via a macro that's defined in the second module. This cannot
403    /// be represented as reachable because it can't handle the following case:
404    ///
405    /// pub mod n {                         // Should be `Public`
406    ///     pub(crate) mod p {              // Should *not* be accessible
407    ///         pub fn f() -> i32 { 12 }    // Must be `Reachable`
408    ///     }
409    /// }
410    /// pub macro m() {
411    ///     n::p::f()
412    /// }
413    macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>,
414    /// Has something changed in the level map?
415    changed: bool,
416}
417
418struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
419    effective_vis: EffectiveVisibility,
420    item_def_id: LocalDefId,
421    ev: &'a mut EmbargoVisitor<'tcx>,
422    level: Level,
423}
424
425impl<'tcx> EmbargoVisitor<'tcx> {
426    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
427        self.effective_visibilities.effective_vis(def_id).copied()
428    }
429
430    // Updates node effective visibility.
431    fn update(
432        &mut self,
433        def_id: LocalDefId,
434        inherited_effective_vis: EffectiveVisibility,
435        level: Level,
436    ) {
437        let nominal_vis = self.tcx.local_visibility(def_id);
438        self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
439    }
440
441    fn update_eff_vis(
442        &mut self,
443        def_id: LocalDefId,
444        inherited_effective_vis: EffectiveVisibility,
445        max_vis: Option<ty::Visibility>,
446        level: Level,
447    ) {
448        // FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default.
449        let private_vis =
450            ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
451        if max_vis != Some(private_vis) {
452            self.changed |= self.effective_visibilities.update(
453                def_id,
454                max_vis,
455                || private_vis,
456                inherited_effective_vis,
457                level,
458                self.tcx,
459            );
460        }
461    }
462
463    fn reach(
464        &mut self,
465        def_id: LocalDefId,
466        effective_vis: EffectiveVisibility,
467    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
468        ReachEverythingInTheInterfaceVisitor {
469            effective_vis,
470            item_def_id: def_id,
471            ev: self,
472            level: Level::Reachable,
473        }
474    }
475
476    fn reach_through_impl_trait(
477        &mut self,
478        def_id: LocalDefId,
479        effective_vis: EffectiveVisibility,
480    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
481        ReachEverythingInTheInterfaceVisitor {
482            effective_vis,
483            item_def_id: def_id,
484            ev: self,
485            level: Level::ReachableThroughImplTrait,
486        }
487    }
488
489    // We have to make sure that the items that macros might reference
490    // are reachable, since they might be exported transitively.
491    fn update_reachability_from_macro(
492        &mut self,
493        local_def_id: LocalDefId,
494        md: &MacroDef,
495        macro_ev: EffectiveVisibility,
496    ) {
497        // Non-opaque macros cannot make other items more accessible than they already are.
498        let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
499        let attrs = self.tcx.hir_attrs(hir_id);
500
501        if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
502            .unwrap_or(Transparency::fallback(md.macro_rules))
503            != Transparency::Opaque
504        {
505            return;
506        }
507
508        let macro_module_def_id = self.tcx.local_parent(local_def_id);
509        if self.tcx.def_kind(macro_module_def_id) != DefKind::Mod {
510            // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
511            return;
512        }
513        // FIXME(typed_def_id): Introduce checked constructors that check def_kind.
514        let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id);
515
516        if self.effective_visibilities.public_at_level(local_def_id).is_none() {
517            return;
518        }
519
520        // Since we are starting from an externally visible module,
521        // all the parents in the loop below are also guaranteed to be modules.
522        let mut module_def_id = macro_module_def_id;
523        loop {
524            let changed_reachability =
525                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
526            if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID {
527                break;
528            }
529            module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id));
530        }
531    }
532
533    /// Updates the item as being reachable through a macro defined in the given
534    /// module. Returns `true` if the level has changed.
535    fn update_macro_reachable(
536        &mut self,
537        module_def_id: LocalModDefId,
538        defining_mod: LocalModDefId,
539        macro_ev: EffectiveVisibility,
540    ) -> bool {
541        if self.macro_reachable.insert((module_def_id, defining_mod)) {
542            for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) {
543                if let Res::Def(def_kind, def_id) = child.res
544                    && let Some(def_id) = def_id.as_local()
545                    && child.vis.is_accessible_from(defining_mod, self.tcx)
546                {
547                    let vis = self.tcx.local_visibility(def_id);
548                    self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
549                }
550            }
551            true
552        } else {
553            false
554        }
555    }
556
557    fn update_macro_reachable_def(
558        &mut self,
559        def_id: LocalDefId,
560        def_kind: DefKind,
561        vis: ty::Visibility,
562        module: LocalModDefId,
563        macro_ev: EffectiveVisibility,
564    ) {
565        self.update(def_id, macro_ev, Level::Reachable);
566        match def_kind {
567            // No type privacy, so can be directly marked as reachable.
568            DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => {
569                if vis.is_accessible_from(module, self.tcx) {
570                    self.update(def_id, macro_ev, Level::Reachable);
571                }
572            }
573
574            // Hygiene isn't really implemented for `macro_rules!` macros at the
575            // moment. Accordingly, marking them as reachable is unwise. `macro` macros
576            // have normal hygiene, so we can treat them like other items without type
577            // privacy and mark them reachable.
578            DefKind::Macro(_) => {
579                let item = self.tcx.hir_expect_item(def_id);
580                if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind {
581                    if vis.is_accessible_from(module, self.tcx) {
582                        self.update(def_id, macro_ev, Level::Reachable);
583                    }
584                }
585            }
586
587            // We can't use a module name as the final segment of a path, except
588            // in use statements. Since re-export checking doesn't consider
589            // hygiene these don't need to be marked reachable. The contents of
590            // the module, however may be reachable.
591            DefKind::Mod => {
592                if vis.is_accessible_from(module, self.tcx) {
593                    self.update_macro_reachable(
594                        LocalModDefId::new_unchecked(def_id),
595                        module,
596                        macro_ev,
597                    );
598                }
599            }
600
601            DefKind::Struct | DefKind::Union => {
602                // While structs and unions have type privacy, their fields do not.
603                let item = self.tcx.hir_expect_item(def_id);
604                if let hir::ItemKind::Struct(_, ref struct_def, _)
605                | hir::ItemKind::Union(_, ref struct_def, _) = item.kind
606                {
607                    for field in struct_def.fields() {
608                        let field_vis = self.tcx.local_visibility(field.def_id);
609                        if field_vis.is_accessible_from(module, self.tcx) {
610                            self.reach(field.def_id, macro_ev).ty();
611                        }
612                    }
613                } else {
614                    bug!("item {:?} with DefKind {:?}", item, def_kind);
615                }
616            }
617
618            // These have type privacy, so are not reachable unless they're
619            // public, or are not namespaced at all.
620            DefKind::AssocConst
621            | DefKind::AssocTy
622            | DefKind::ConstParam
623            | DefKind::Ctor(_, _)
624            | DefKind::Enum
625            | DefKind::ForeignTy
626            | DefKind::Fn
627            | DefKind::OpaqueTy
628            | DefKind::AssocFn
629            | DefKind::Trait
630            | DefKind::TyParam
631            | DefKind::Variant
632            | DefKind::LifetimeParam
633            | DefKind::ExternCrate
634            | DefKind::Use
635            | DefKind::ForeignMod
636            | DefKind::AnonConst
637            | DefKind::InlineConst
638            | DefKind::Field
639            | DefKind::GlobalAsm
640            | DefKind::Impl { .. }
641            | DefKind::Closure
642            | DefKind::SyntheticCoroutineBody => (),
643        }
644    }
645}
646
647impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
648    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
649        // Update levels of nested things and mark all items
650        // in interfaces of reachable items as reachable.
651        let item_ev = self.get(item.owner_id.def_id);
652        match item.kind {
653            // The interface is empty, and no nested items.
654            hir::ItemKind::Use(..)
655            | hir::ItemKind::ExternCrate(..)
656            | hir::ItemKind::GlobalAsm { .. } => {}
657            // The interface is empty, and all nested items are processed by `visit_item`.
658            hir::ItemKind::Mod(..) => {}
659            hir::ItemKind::Macro(_, macro_def, _) => {
660                if let Some(item_ev) = item_ev {
661                    self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev);
662                }
663            }
664            hir::ItemKind::Const(..)
665            | hir::ItemKind::Static(..)
666            | hir::ItemKind::Fn { .. }
667            | hir::ItemKind::TyAlias(..) => {
668                if let Some(item_ev) = item_ev {
669                    self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
670                }
671            }
672            hir::ItemKind::Trait(.., trait_item_refs) => {
673                if let Some(item_ev) = item_ev {
674                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
675
676                    for trait_item_ref in trait_item_refs {
677                        self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
678
679                        let tcx = self.tcx;
680                        let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
681                        reach.generics().predicates();
682
683                        if trait_item_ref.kind == AssocItemKind::Type
684                            && !tcx.defaultness(trait_item_ref.id.owner_id).has_value()
685                        {
686                            // No type to visit.
687                        } else {
688                            reach.ty();
689                        }
690                    }
691                }
692            }
693            hir::ItemKind::TraitAlias(..) => {
694                if let Some(item_ev) = item_ev {
695                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
696                }
697            }
698            hir::ItemKind::Impl(impl_) => {
699                // Type inference is very smart sometimes. It can make an impl reachable even some
700                // components of its type or trait are unreachable. E.g. methods of
701                // `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
702                // can be usable from other crates (#57264). So we skip args when calculating
703                // reachability and consider an impl reachable if its "shallow" type and trait are
704                // reachable.
705                //
706                // The assumption we make here is that type-inference won't let you use an impl
707                // without knowing both "shallow" version of its self type and "shallow" version of
708                // its trait if it exists (which require reaching the `DefId`s in them).
709                let item_ev = EffectiveVisibility::of_impl::<true>(
710                    item.owner_id.def_id,
711                    self.tcx,
712                    &self.effective_visibilities,
713                );
714
715                self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
716
717                self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref();
718
719                for impl_item_ref in impl_.items {
720                    let def_id = impl_item_ref.id.owner_id.def_id;
721                    let max_vis =
722                        impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
723                    self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
724
725                    if let Some(impl_item_ev) = self.get(def_id) {
726                        self.reach(def_id, impl_item_ev).generics().predicates().ty();
727                    }
728                }
729            }
730            hir::ItemKind::Enum(_, ref def, _) => {
731                if let Some(item_ev) = item_ev {
732                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
733                }
734                for variant in def.variants {
735                    if let Some(item_ev) = item_ev {
736                        self.update(variant.def_id, item_ev, Level::Reachable);
737                    }
738
739                    if let Some(variant_ev) = self.get(variant.def_id) {
740                        if let Some(ctor_def_id) = variant.data.ctor_def_id() {
741                            self.update(ctor_def_id, variant_ev, Level::Reachable);
742                        }
743                        for field in variant.data.fields() {
744                            self.update(field.def_id, variant_ev, Level::Reachable);
745                            self.reach(field.def_id, variant_ev).ty();
746                        }
747                        // Corner case: if the variant is reachable, but its
748                        // enum is not, make the enum reachable as well.
749                        self.reach(item.owner_id.def_id, variant_ev).ty();
750                    }
751                    if let Some(ctor_def_id) = variant.data.ctor_def_id() {
752                        if let Some(ctor_ev) = self.get(ctor_def_id) {
753                            self.reach(item.owner_id.def_id, ctor_ev).ty();
754                        }
755                    }
756                }
757            }
758            hir::ItemKind::ForeignMod { items, .. } => {
759                for foreign_item in items {
760                    if let Some(foreign_item_ev) = self.get(foreign_item.id.owner_id.def_id) {
761                        self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
762                            .generics()
763                            .predicates()
764                            .ty();
765                    }
766                }
767            }
768            hir::ItemKind::Struct(_, ref struct_def, _)
769            | hir::ItemKind::Union(_, ref struct_def, _) => {
770                if let Some(item_ev) = item_ev {
771                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
772                    for field in struct_def.fields() {
773                        self.update(field.def_id, item_ev, Level::Reachable);
774                        if let Some(field_ev) = self.get(field.def_id) {
775                            self.reach(field.def_id, field_ev).ty();
776                        }
777                    }
778                }
779                if let Some(ctor_def_id) = struct_def.ctor_def_id() {
780                    if let Some(item_ev) = item_ev {
781                        self.update(ctor_def_id, item_ev, Level::Reachable);
782                    }
783                    if let Some(ctor_ev) = self.get(ctor_def_id) {
784                        self.reach(item.owner_id.def_id, ctor_ev).ty();
785                    }
786                }
787            }
788        }
789    }
790}
791
792impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
793    fn generics(&mut self) -> &mut Self {
794        for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
795            if let GenericParamDefKind::Const { .. } = param.kind {
796                self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
797            }
798            if let Some(default) = param.default_value(self.ev.tcx) {
799                self.visit(default.instantiate_identity());
800            }
801        }
802        self
803    }
804
805    fn predicates(&mut self) -> &mut Self {
806        self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
807        self
808    }
809
810    fn ty(&mut self) -> &mut Self {
811        self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity());
812        self
813    }
814
815    fn trait_ref(&mut self) -> &mut Self {
816        if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
817            self.visit_trait(trait_ref.instantiate_identity());
818        }
819        self
820    }
821}
822
823impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
824    fn tcx(&self) -> TyCtxt<'tcx> {
825        self.ev.tcx
826    }
827    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
828        if let Some(def_id) = def_id.as_local() {
829            // All effective visibilities except `reachable_through_impl_trait` are limited to
830            // nominal visibility. If any type or trait is leaked farther than that, it will
831            // produce type privacy errors on any use, so we don't consider it leaked.
832            let max_vis = (self.level != Level::ReachableThroughImplTrait)
833                .then(|| self.ev.tcx.local_visibility(def_id));
834            self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
835        }
836    }
837}
838
839////////////////////////////////////////////////////////////////////////////////
840/// Visitor, used for EffectiveVisibilities table checking
841////////////////////////////////////////////////////////////////////////////////
842pub struct TestReachabilityVisitor<'a, 'tcx> {
843    tcx: TyCtxt<'tcx>,
844    effective_visibilities: &'a EffectiveVisibilities,
845}
846
847impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
848    fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
849        if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
850            let mut error_msg = String::new();
851            let span = self.tcx.def_span(def_id.to_def_id());
852            if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
853                for level in Level::all_levels() {
854                    let vis_str = effective_vis.at_level(level).to_string(def_id, self.tcx);
855                    if level != Level::Direct {
856                        error_msg.push_str(", ");
857                    }
858                    error_msg.push_str(&format!("{level:?}: {vis_str}"));
859                }
860            } else {
861                error_msg.push_str("not in the table");
862            }
863            self.tcx.dcx().emit_err(ReportEffectiveVisibility { span, descr: error_msg });
864        }
865    }
866}
867
868impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> {
869    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
870        self.effective_visibility_diagnostic(item.owner_id.def_id);
871
872        match item.kind {
873            hir::ItemKind::Enum(_, ref def, _) => {
874                for variant in def.variants.iter() {
875                    self.effective_visibility_diagnostic(variant.def_id);
876                    if let Some(ctor_def_id) = variant.data.ctor_def_id() {
877                        self.effective_visibility_diagnostic(ctor_def_id);
878                    }
879                    for field in variant.data.fields() {
880                        self.effective_visibility_diagnostic(field.def_id);
881                    }
882                }
883            }
884            hir::ItemKind::Struct(_, ref def, _) | hir::ItemKind::Union(_, ref def, _) => {
885                if let Some(ctor_def_id) = def.ctor_def_id() {
886                    self.effective_visibility_diagnostic(ctor_def_id);
887                }
888                for field in def.fields() {
889                    self.effective_visibility_diagnostic(field.def_id);
890                }
891            }
892            _ => {}
893        }
894    }
895
896    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
897        self.effective_visibility_diagnostic(item.owner_id.def_id);
898    }
899    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
900        self.effective_visibility_diagnostic(item.owner_id.def_id);
901    }
902    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
903        self.effective_visibility_diagnostic(item.owner_id.def_id);
904    }
905}
906
907//////////////////////////////////////////////////////////////////////////////////////
908/// Name privacy visitor, checks privacy and reports violations.
909/// Most of name privacy checks are performed during the main resolution phase,
910/// or later in type checking when field accesses and associated items are resolved.
911/// This pass performs remaining checks for fields in struct expressions and patterns.
912//////////////////////////////////////////////////////////////////////////////////////
913
914struct NamePrivacyVisitor<'tcx> {
915    tcx: TyCtxt<'tcx>,
916    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
917}
918
919impl<'tcx> NamePrivacyVisitor<'tcx> {
920    /// Gets the type-checking results for the current body.
921    /// As this will ICE if called outside bodies, only call when working with
922    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
923    #[track_caller]
924    fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
925        self.maybe_typeck_results
926            .expect("`NamePrivacyVisitor::typeck_results` called outside of body")
927    }
928
929    // Checks that a field in a struct constructor (expression or pattern) is accessible.
930    fn check_field(
931        &mut self,
932        hir_id: hir::HirId,    // ID of the field use
933        use_ctxt: Span,        // syntax context of the field name at the use site
934        def: ty::AdtDef<'tcx>, // definition of the struct or enum
935        field: &'tcx ty::FieldDef,
936    ) -> bool {
937        if def.is_enum() {
938            return true;
939        }
940
941        // definition of the field
942        let ident = Ident::new(sym::dummy, use_ctxt);
943        let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id);
944        !field.vis.is_accessible_from(def_id, self.tcx)
945    }
946
947    // Checks that a field in a struct constructor (expression or pattern) is accessible.
948    fn emit_unreachable_field_error(
949        &mut self,
950        fields: Vec<(Symbol, Span, bool /* field is present */)>,
951        def: ty::AdtDef<'tcx>, // definition of the struct or enum
952        update_syntax: Option<Span>,
953        struct_span: Span,
954    ) {
955        if def.is_enum() || fields.is_empty() {
956            return;
957        }
958
959        //   error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private
960        //   --> $DIR/visibility.rs:18:13
961        //    |
962        // LL |     let _x = Alpha {
963        //    |              ----- in this type      # from `def`
964        // LL |         beta: 0,
965        //    |         ^^^^^^^ private field        # `fields.2` is `true`
966        // LL |         ..
967        //    |         ^^ field `gamma` is private  # `fields.2` is `false`
968
969        // Get the list of all private fields for the main message.
970        let Some(field_names) = listify(&fields[..], |(n, _, _)| format!("`{n}`")) else { return };
971        let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();
972
973        // Get the list of all private fields when pointing at the `..rest`.
974        let rest_field_names: Vec<_> =
975            fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
976        let rest_len = rest_field_names.len();
977        let rest_field_names =
978            listify(&rest_field_names[..], |n| format!("`{n}`")).unwrap_or_default();
979        // Get all the labels for each field or `..rest` in the primary MultiSpan.
980        let labels = fields
981            .iter()
982            .filter(|(_, _, is_present)| *is_present)
983            .map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span })
984            .chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax {
985                span: *span,
986                rest_field_names: rest_field_names.clone(),
987                rest_len,
988            }))
989            .collect();
990
991        self.tcx.dcx().emit_err(FieldIsPrivate {
992            span,
993            struct_span: if self
994                .tcx
995                .sess
996                .source_map()
997                .is_multiline(fields[0].1.between(struct_span))
998            {
999                Some(struct_span)
1000            } else {
1001                None
1002            },
1003            field_names,
1004            variant_descr: def.variant_descr(),
1005            def_path_str: self.tcx.def_path_str(def.did()),
1006            labels,
1007            len: fields.len(),
1008        });
1009    }
1010
1011    fn check_expanded_fields(
1012        &mut self,
1013        adt: ty::AdtDef<'tcx>,
1014        variant: &'tcx ty::VariantDef,
1015        fields: &[hir::ExprField<'tcx>],
1016        hir_id: hir::HirId,
1017        span: Span,
1018        struct_span: Span,
1019    ) {
1020        let mut failed_fields = vec![];
1021        for (vf_index, variant_field) in variant.fields.iter_enumerated() {
1022            let field =
1023                fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
1024            let (hir_id, use_ctxt, span) = match field {
1025                Some(field) => (field.hir_id, field.ident.span, field.span),
1026                None => (hir_id, span, span),
1027            };
1028            if self.check_field(hir_id, use_ctxt, adt, variant_field) {
1029                let name = match field {
1030                    Some(field) => field.ident.name,
1031                    None => variant_field.name,
1032                };
1033                failed_fields.push((name, span, field.is_some()));
1034            }
1035        }
1036        self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span);
1037    }
1038}
1039
1040impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
1041    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1042        let new_typeck_results = self.tcx.typeck_body(body_id);
1043        // Do not try reporting privacy violations if we failed to infer types.
1044        if new_typeck_results.tainted_by_errors.is_some() {
1045            return;
1046        }
1047        let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
1048        self.visit_body(self.tcx.hir_body(body_id));
1049        self.maybe_typeck_results = old_maybe_typeck_results;
1050    }
1051
1052    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1053        if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
1054            let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
1055            let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
1056            let variant = adt.variant_of_res(res);
1057            match *base {
1058                hir::StructTailExpr::Base(base) => {
1059                    // If the expression uses FRU we need to make sure all the unmentioned fields
1060                    // are checked for privacy (RFC 736). Rather than computing the set of
1061                    // unmentioned fields, just check them all.
1062                    self.check_expanded_fields(
1063                        adt,
1064                        variant,
1065                        fields,
1066                        base.hir_id,
1067                        base.span,
1068                        qpath.span(),
1069                    );
1070                }
1071                hir::StructTailExpr::DefaultFields(span) => {
1072                    self.check_expanded_fields(
1073                        adt,
1074                        variant,
1075                        fields,
1076                        expr.hir_id,
1077                        span,
1078                        qpath.span(),
1079                    );
1080                }
1081                hir::StructTailExpr::None => {
1082                    let mut failed_fields = vec![];
1083                    for field in fields {
1084                        let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1085                        let index = self.typeck_results().field_index(field.hir_id);
1086                        if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1087                            failed_fields.push((field.ident.name, field.ident.span, true));
1088                        }
1089                    }
1090                    self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1091                }
1092            }
1093        }
1094
1095        intravisit::walk_expr(self, expr);
1096    }
1097
1098    fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
1099        if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
1100            let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
1101            let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
1102            let variant = adt.variant_of_res(res);
1103            let mut failed_fields = vec![];
1104            for field in fields {
1105                let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1106                let index = self.typeck_results().field_index(field.hir_id);
1107                if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1108                    failed_fields.push((field.ident.name, field.ident.span, true));
1109                }
1110            }
1111            self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1112        }
1113
1114        intravisit::walk_pat(self, pat);
1115    }
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////////////////
1119/// Type privacy visitor, checks types for privacy and reports violations.
1120/// Both explicitly written types and inferred types of expressions and patterns are checked.
1121/// Checks are performed on "semantic" types regardless of names and their hygiene.
1122////////////////////////////////////////////////////////////////////////////////////////////
1123
1124struct TypePrivacyVisitor<'tcx> {
1125    tcx: TyCtxt<'tcx>,
1126    module_def_id: LocalModDefId,
1127    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
1128    span: Span,
1129}
1130
1131impl<'tcx> TypePrivacyVisitor<'tcx> {
1132    fn item_is_accessible(&self, did: DefId) -> bool {
1133        self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
1134    }
1135
1136    // Take node-id of an expression or pattern and check its type for privacy.
1137    fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
1138        self.span = span;
1139        let typeck_results = self
1140            .maybe_typeck_results
1141            .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
1142        let result: ControlFlow<()> = try {
1143            self.visit(typeck_results.node_type(id))?;
1144            self.visit(typeck_results.node_args(id))?;
1145            if let Some(adjustments) = typeck_results.adjustments().get(id) {
1146                adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
1147            }
1148        };
1149        result.is_break()
1150    }
1151
1152    fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1153        let is_error = !self.item_is_accessible(def_id);
1154        if is_error {
1155            self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() });
1156        }
1157        is_error
1158    }
1159}
1160
1161impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1162    type Result = ControlFlow<()>;
1163    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
1164        self.span = span;
1165        value.visit_with(&mut self.skeleton())
1166    }
1167}
1168
1169impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
1170    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1171        let old_maybe_typeck_results =
1172            self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
1173        self.visit_body(self.tcx.hir_body(body_id));
1174        self.maybe_typeck_results = old_maybe_typeck_results;
1175    }
1176
1177    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
1178        self.span = hir_ty.span;
1179        if self
1180            .visit(
1181                self.maybe_typeck_results
1182                    .unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body"))
1183                    .node_type(hir_ty.hir_id),
1184            )
1185            .is_break()
1186        {
1187            return;
1188        }
1189
1190        intravisit::walk_ty(self, hir_ty);
1191    }
1192
1193    fn visit_infer(
1194        &mut self,
1195        inf_id: rustc_hir::HirId,
1196        inf_span: Span,
1197        _kind: InferKind<'tcx>,
1198    ) -> Self::Result {
1199        self.span = inf_span;
1200        if let Some(ty) = self
1201            .maybe_typeck_results
1202            .unwrap_or_else(|| span_bug!(inf_span, "Inference variable outside of a body"))
1203            .node_type_opt(inf_id)
1204        {
1205            if self.visit(ty).is_break() {
1206                return;
1207            }
1208        } else {
1209            // FIXME: check types of const infers here.
1210        }
1211
1212        self.visit_id(inf_id)
1213    }
1214
1215    // Check types of expressions
1216    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1217        if self.check_expr_pat_type(expr.hir_id, expr.span) {
1218            // Do not check nested expressions if the error already happened.
1219            return;
1220        }
1221        match expr.kind {
1222            hir::ExprKind::Assign(_, rhs, _) | hir::ExprKind::Match(rhs, ..) => {
1223                // Do not report duplicate errors for `x = y` and `match x { ... }`.
1224                if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
1225                    return;
1226                }
1227            }
1228            hir::ExprKind::MethodCall(segment, ..) => {
1229                // Method calls have to be checked specially.
1230                self.span = segment.ident.span;
1231                let typeck_results = self
1232                    .maybe_typeck_results
1233                    .unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body"));
1234                if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
1235                    if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
1236                        return;
1237                    }
1238                } else {
1239                    self.tcx
1240                        .dcx()
1241                        .span_delayed_bug(expr.span, "no type-dependent def for method call");
1242                }
1243            }
1244            _ => {}
1245        }
1246
1247        intravisit::walk_expr(self, expr);
1248    }
1249
1250    // Prohibit access to associated items with insufficient nominal visibility.
1251    //
1252    // Additionally, until better reachability analysis for macros 2.0 is available,
1253    // we prohibit access to private statics from other crates, this allows to give
1254    // more code internal visibility at link time. (Access to private functions
1255    // is already prohibited by type privacy for function types.)
1256    fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
1257        let def = match qpath {
1258            hir::QPath::Resolved(_, path) => match path.res {
1259                Res::Def(kind, def_id) => Some((kind, def_id)),
1260                _ => None,
1261            },
1262            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
1263                match self.maybe_typeck_results {
1264                    Some(typeck_results) => typeck_results.type_dependent_def(id),
1265                    // FIXME: Check type-relative associated types in signatures.
1266                    None => None,
1267                }
1268            }
1269        };
1270        let def = def.filter(|(kind, _)| {
1271            matches!(
1272                kind,
1273                DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. }
1274            )
1275        });
1276        if let Some((kind, def_id)) = def {
1277            let is_local_static =
1278                if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
1279            if !self.item_is_accessible(def_id) && !is_local_static {
1280                let name = match *qpath {
1281                    hir::QPath::LangItem(it, ..) => {
1282                        self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
1283                    }
1284                    hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
1285                    hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
1286                };
1287                let kind = self.tcx.def_descr(def_id);
1288                let sess = self.tcx.sess;
1289                let _ = match name {
1290                    Some(name) => {
1291                        sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
1292                    }
1293                    None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }),
1294                };
1295                return;
1296            }
1297        }
1298
1299        intravisit::walk_qpath(self, qpath, id);
1300    }
1301
1302    // Check types of patterns.
1303    fn visit_pat(&mut self, pattern: &'tcx hir::Pat<'tcx>) {
1304        if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
1305            // Do not check nested patterns if the error already happened.
1306            return;
1307        }
1308
1309        intravisit::walk_pat(self, pattern);
1310    }
1311
1312    fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) {
1313        if let Some(init) = local.init {
1314            if self.check_expr_pat_type(init.hir_id, init.span) {
1315                // Do not report duplicate errors for `let x = y`.
1316                return;
1317            }
1318        }
1319
1320        intravisit::walk_local(self, local);
1321    }
1322}
1323
1324impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1325    type Result = ControlFlow<()>;
1326    fn tcx(&self) -> TyCtxt<'tcx> {
1327        self.tcx
1328    }
1329    fn visit_def_id(
1330        &mut self,
1331        def_id: DefId,
1332        kind: &str,
1333        descr: &dyn fmt::Display,
1334    ) -> Self::Result {
1335        if self.check_def_id(def_id, kind, descr) {
1336            ControlFlow::Break(())
1337        } else {
1338            ControlFlow::Continue(())
1339        }
1340    }
1341}
1342
1343///////////////////////////////////////////////////////////////////////////////
1344/// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
1345/// finds any private components in it.
1346/// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
1347/// and traits in public interfaces.
1348///////////////////////////////////////////////////////////////////////////////
1349
1350struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
1351    tcx: TyCtxt<'tcx>,
1352    item_def_id: LocalDefId,
1353    /// The visitor checks that each component type is at least this visible.
1354    required_visibility: ty::Visibility,
1355    required_effective_vis: Option<EffectiveVisibility>,
1356    in_assoc_ty: bool,
1357    in_primary_interface: bool,
1358    skip_assoc_tys: bool,
1359}
1360
1361impl SearchInterfaceForPrivateItemsVisitor<'_> {
1362    fn generics(&mut self) -> &mut Self {
1363        self.in_primary_interface = true;
1364        for param in &self.tcx.generics_of(self.item_def_id).own_params {
1365            match param.kind {
1366                GenericParamDefKind::Lifetime => {}
1367                GenericParamDefKind::Type { has_default, .. } => {
1368                    if has_default {
1369                        let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
1370                    }
1371                }
1372                // FIXME(generic_const_exprs): May want to look inside const here
1373                GenericParamDefKind::Const { .. } => {
1374                    let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
1375                }
1376            }
1377        }
1378        self
1379    }
1380
1381    fn predicates(&mut self) -> &mut Self {
1382        self.in_primary_interface = false;
1383        // N.B., we use `explicit_predicates_of` and not `predicates_of`
1384        // because we don't want to report privacy errors due to where
1385        // clauses that the compiler inferred. We only want to
1386        // consider the ones that the user wrote. This is important
1387        // for the inferred outlives rules; see
1388        // `tests/ui/rfc-2093-infer-outlives/privacy.rs`.
1389        let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
1390        self
1391    }
1392
1393    fn bounds(&mut self) -> &mut Self {
1394        self.in_primary_interface = false;
1395        let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
1396        self
1397    }
1398
1399    fn ty(&mut self) -> &mut Self {
1400        self.in_primary_interface = true;
1401        let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
1402        self
1403    }
1404
1405    fn trait_ref(&mut self) -> &mut Self {
1406        self.in_primary_interface = true;
1407        if let Some(trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) {
1408            let _ = self.visit_trait(trait_ref.instantiate_identity());
1409        }
1410        self
1411    }
1412
1413    fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1414        if self.leaks_private_dep(def_id) {
1415            self.tcx.emit_node_span_lint(
1416                lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
1417                self.tcx.local_def_id_to_hir_id(self.item_def_id),
1418                self.tcx.def_span(self.item_def_id.to_def_id()),
1419                FromPrivateDependencyInPublicInterface {
1420                    kind,
1421                    descr: descr.into(),
1422                    krate: self.tcx.crate_name(def_id.krate),
1423                },
1424            );
1425        }
1426
1427        let Some(local_def_id) = def_id.as_local() else {
1428            return false;
1429        };
1430
1431        let vis = self.tcx.local_visibility(local_def_id);
1432        let span = self.tcx.def_span(self.item_def_id.to_def_id());
1433        let vis_span = self.tcx.def_span(def_id);
1434        if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
1435            let vis_descr = match vis {
1436                ty::Visibility::Public => "public",
1437                ty::Visibility::Restricted(vis_def_id) => {
1438                    if vis_def_id
1439                        == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
1440                    {
1441                        "private"
1442                    } else if vis_def_id.is_top_level_module() {
1443                        "crate-private"
1444                    } else {
1445                        "restricted"
1446                    }
1447                }
1448            };
1449
1450            self.tcx.dcx().emit_err(InPublicInterface {
1451                span,
1452                vis_descr,
1453                kind,
1454                descr: descr.into(),
1455                vis_span,
1456            });
1457            return false;
1458        }
1459
1460        let Some(effective_vis) = self.required_effective_vis else {
1461            return false;
1462        };
1463
1464        let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
1465
1466        if !vis.is_at_least(reachable_at_vis, self.tcx) {
1467            let lint = if self.in_primary_interface {
1468                lint::builtin::PRIVATE_INTERFACES
1469            } else {
1470                lint::builtin::PRIVATE_BOUNDS
1471            };
1472            self.tcx.emit_node_span_lint(
1473                lint,
1474                self.tcx.local_def_id_to_hir_id(self.item_def_id),
1475                span,
1476                PrivateInterfacesOrBoundsLint {
1477                    item_span: span,
1478                    item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()),
1479                    item_descr: (&LazyDefPathStr {
1480                        def_id: self.item_def_id.to_def_id(),
1481                        tcx: self.tcx,
1482                    })
1483                        .into(),
1484                    item_vis_descr: &reachable_at_vis.to_string(self.item_def_id, self.tcx),
1485                    ty_span: vis_span,
1486                    ty_kind: kind,
1487                    ty_descr: descr.into(),
1488                    ty_vis_descr: &vis.to_string(local_def_id, self.tcx),
1489                },
1490            );
1491        }
1492
1493        false
1494    }
1495
1496    /// An item is 'leaked' from a private dependency if all
1497    /// of the following are true:
1498    /// 1. It's contained within a public type
1499    /// 2. It comes from a private crate
1500    fn leaks_private_dep(&self, item_id: DefId) -> bool {
1501        let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);
1502
1503        debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
1504        ret
1505    }
1506}
1507
1508impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
1509    type Result = ControlFlow<()>;
1510    fn skip_assoc_tys(&self) -> bool {
1511        self.skip_assoc_tys
1512    }
1513    fn tcx(&self) -> TyCtxt<'tcx> {
1514        self.tcx
1515    }
1516    fn visit_def_id(
1517        &mut self,
1518        def_id: DefId,
1519        kind: &str,
1520        descr: &dyn fmt::Display,
1521    ) -> Self::Result {
1522        if self.check_def_id(def_id, kind, descr) {
1523            ControlFlow::Break(())
1524        } else {
1525            ControlFlow::Continue(())
1526        }
1527    }
1528}
1529
1530struct PrivateItemsInPublicInterfacesChecker<'a, 'tcx> {
1531    tcx: TyCtxt<'tcx>,
1532    effective_visibilities: &'a EffectiveVisibilities,
1533}
1534
1535impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
1536    fn check(
1537        &self,
1538        def_id: LocalDefId,
1539        required_visibility: ty::Visibility,
1540        required_effective_vis: Option<EffectiveVisibility>,
1541    ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
1542        SearchInterfaceForPrivateItemsVisitor {
1543            tcx: self.tcx,
1544            item_def_id: def_id,
1545            required_visibility,
1546            required_effective_vis,
1547            in_assoc_ty: false,
1548            in_primary_interface: true,
1549            skip_assoc_tys: false,
1550        }
1551    }
1552
1553    fn check_unnameable(&self, def_id: LocalDefId, effective_vis: Option<EffectiveVisibility>) {
1554        let Some(effective_vis) = effective_vis else {
1555            return;
1556        };
1557
1558        let reexported_at_vis = effective_vis.at_level(Level::Reexported);
1559        let reachable_at_vis = effective_vis.at_level(Level::Reachable);
1560
1561        if reachable_at_vis.is_public() && reexported_at_vis != reachable_at_vis {
1562            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
1563            let span = self.tcx.def_span(def_id.to_def_id());
1564            self.tcx.emit_node_span_lint(
1565                lint::builtin::UNNAMEABLE_TYPES,
1566                hir_id,
1567                span,
1568                UnnameableTypesLint {
1569                    span,
1570                    kind: self.tcx.def_descr(def_id.to_def_id()),
1571                    descr: (&LazyDefPathStr { def_id: def_id.to_def_id(), tcx: self.tcx }).into(),
1572                    reachable_vis: &reachable_at_vis.to_string(def_id, self.tcx),
1573                    reexported_vis: &reexported_at_vis.to_string(def_id, self.tcx),
1574                },
1575            );
1576        }
1577    }
1578
1579    fn check_assoc_item(
1580        &self,
1581        def_id: LocalDefId,
1582        assoc_item_kind: AssocItemKind,
1583        vis: ty::Visibility,
1584        effective_vis: Option<EffectiveVisibility>,
1585    ) {
1586        let mut check = self.check(def_id, vis, effective_vis);
1587
1588        let (check_ty, is_assoc_ty) = match assoc_item_kind {
1589            AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
1590            AssocItemKind::Type => (self.tcx.defaultness(def_id).has_value(), true),
1591        };
1592
1593        check.in_assoc_ty = is_assoc_ty;
1594        check.generics().predicates();
1595        if check_ty {
1596            check.ty();
1597        }
1598    }
1599
1600    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
1601        self.effective_visibilities.effective_vis(def_id).copied()
1602    }
1603
1604    fn check_item(&mut self, id: ItemId) {
1605        let tcx = self.tcx;
1606        let def_id = id.owner_id.def_id;
1607        let item_visibility = tcx.local_visibility(def_id);
1608        let effective_vis = self.get(def_id);
1609        let def_kind = tcx.def_kind(def_id);
1610
1611        match def_kind {
1612            DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
1613                if let DefKind::TyAlias = def_kind {
1614                    self.check_unnameable(def_id, effective_vis);
1615                }
1616                self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
1617            }
1618            DefKind::OpaqueTy => {
1619                // `ty()` for opaque types is the underlying type,
1620                // it's not a part of interface, so we skip it.
1621                self.check(def_id, item_visibility, effective_vis).generics().bounds();
1622            }
1623            DefKind::Trait => {
1624                let item = tcx.hir_item(id);
1625                if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind {
1626                    self.check_unnameable(item.owner_id.def_id, effective_vis);
1627
1628                    self.check(item.owner_id.def_id, item_visibility, effective_vis)
1629                        .generics()
1630                        .predicates();
1631
1632                    for trait_item_ref in trait_item_refs {
1633                        self.check_assoc_item(
1634                            trait_item_ref.id.owner_id.def_id,
1635                            trait_item_ref.kind,
1636                            item_visibility,
1637                            effective_vis,
1638                        );
1639
1640                        if let AssocItemKind::Type = trait_item_ref.kind {
1641                            self.check(
1642                                trait_item_ref.id.owner_id.def_id,
1643                                item_visibility,
1644                                effective_vis,
1645                            )
1646                            .bounds();
1647                        }
1648                    }
1649                }
1650            }
1651            DefKind::TraitAlias => {
1652                self.check(def_id, item_visibility, effective_vis).generics().predicates();
1653            }
1654            DefKind::Enum => {
1655                let item = tcx.hir_item(id);
1656                if let hir::ItemKind::Enum(_, ref def, _) = item.kind {
1657                    self.check_unnameable(item.owner_id.def_id, effective_vis);
1658
1659                    self.check(item.owner_id.def_id, item_visibility, effective_vis)
1660                        .generics()
1661                        .predicates();
1662
1663                    for variant in def.variants {
1664                        for field in variant.data.fields() {
1665                            self.check(field.def_id, item_visibility, effective_vis).ty();
1666                        }
1667                    }
1668                }
1669            }
1670            // Subitems of foreign modules have their own publicity.
1671            DefKind::ForeignMod => {
1672                let item = tcx.hir_item(id);
1673                if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
1674                    for foreign_item in items {
1675                        let foreign_item = tcx.hir_foreign_item(foreign_item.id);
1676
1677                        let ev = self.get(foreign_item.owner_id.def_id);
1678                        let vis = tcx.local_visibility(foreign_item.owner_id.def_id);
1679
1680                        if let ForeignItemKind::Type = foreign_item.kind {
1681                            self.check_unnameable(foreign_item.owner_id.def_id, ev);
1682                        }
1683
1684                        self.check(foreign_item.owner_id.def_id, vis, ev)
1685                            .generics()
1686                            .predicates()
1687                            .ty();
1688                    }
1689                }
1690            }
1691            // Subitems of structs and unions have their own publicity.
1692            DefKind::Struct | DefKind::Union => {
1693                let item = tcx.hir_item(id);
1694                if let hir::ItemKind::Struct(_, ref struct_def, _)
1695                | hir::ItemKind::Union(_, ref struct_def, _) = item.kind
1696                {
1697                    self.check_unnameable(item.owner_id.def_id, effective_vis);
1698                    self.check(item.owner_id.def_id, item_visibility, effective_vis)
1699                        .generics()
1700                        .predicates();
1701
1702                    for field in struct_def.fields() {
1703                        let field_visibility = tcx.local_visibility(field.def_id);
1704                        let field_ev = self.get(field.def_id);
1705
1706                        self.check(
1707                            field.def_id,
1708                            min(item_visibility, field_visibility, tcx),
1709                            field_ev,
1710                        )
1711                        .ty();
1712                    }
1713                }
1714            }
1715            // An inherent impl is public when its type is public
1716            // Subitems of inherent impls have their own publicity.
1717            // A trait impl is public when both its type and its trait are public
1718            // Subitems of trait impls have inherited publicity.
1719            DefKind::Impl { .. } => {
1720                let item = tcx.hir_item(id);
1721                if let hir::ItemKind::Impl(impl_) = item.kind {
1722                    let impl_vis = ty::Visibility::of_impl::<false>(
1723                        item.owner_id.def_id,
1724                        tcx,
1725                        &Default::default(),
1726                    );
1727
1728                    // We are using the non-shallow version here, unlike when building the
1729                    // effective visisibilities table to avoid large number of false positives.
1730                    // For example in
1731                    //
1732                    // impl From<Priv> for Pub {
1733                    //     fn from(_: Priv) -> Pub {...}
1734                    // }
1735                    //
1736                    // lints shouldn't be emitted even if `from` effective visibility
1737                    // is larger than `Priv` nominal visibility and if `Priv` can leak
1738                    // in some scenarios due to type inference.
1739                    let impl_ev = EffectiveVisibility::of_impl::<false>(
1740                        item.owner_id.def_id,
1741                        tcx,
1742                        self.effective_visibilities,
1743                    );
1744
1745                    let mut check = self.check(item.owner_id.def_id, impl_vis, Some(impl_ev));
1746                    // Generics and predicates of trait impls are intentionally not checked
1747                    // for private components (#90586).
1748                    if impl_.of_trait.is_none() {
1749                        check.generics().predicates();
1750                    }
1751                    // Skip checking private components in associated types, due to lack of full
1752                    // normalization they produce very ridiculous false positives.
1753                    // FIXME: Remove this when full normalization is implemented.
1754                    check.skip_assoc_tys = true;
1755                    check.ty().trait_ref();
1756
1757                    for impl_item_ref in impl_.items {
1758                        let impl_item_vis = if impl_.of_trait.is_none() {
1759                            min(
1760                                tcx.local_visibility(impl_item_ref.id.owner_id.def_id),
1761                                impl_vis,
1762                                tcx,
1763                            )
1764                        } else {
1765                            impl_vis
1766                        };
1767
1768                        let impl_item_ev = if impl_.of_trait.is_none() {
1769                            self.get(impl_item_ref.id.owner_id.def_id)
1770                                .map(|ev| ev.min(impl_ev, self.tcx))
1771                        } else {
1772                            Some(impl_ev)
1773                        };
1774
1775                        self.check_assoc_item(
1776                            impl_item_ref.id.owner_id.def_id,
1777                            impl_item_ref.kind,
1778                            impl_item_vis,
1779                            impl_item_ev,
1780                        );
1781                    }
1782                }
1783            }
1784            _ => {}
1785        }
1786    }
1787}
1788
1789pub fn provide(providers: &mut Providers) {
1790    *providers = Providers {
1791        effective_visibilities,
1792        check_private_in_public,
1793        check_mod_privacy,
1794        ..*providers
1795    };
1796}
1797
1798fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
1799    // Check privacy of names not checked in previous compilation stages.
1800    let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
1801    tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor);
1802
1803    // Check privacy of explicitly written types and traits as well as
1804    // inferred types of expressions and patterns.
1805    let span = tcx.def_span(module_def_id);
1806    let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
1807
1808    let module = tcx.hir_module_items(module_def_id);
1809    for def_id in module.definitions() {
1810        let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
1811
1812        if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
1813            visitor.visit_nested_body(body_id.id());
1814        }
1815    }
1816
1817    for id in module.free_items() {
1818        if let ItemKind::Impl(i) = tcx.hir_item(id).kind {
1819            if let Some(item) = i.of_trait {
1820                let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap();
1821                let trait_ref = trait_ref.instantiate_identity();
1822                visitor.span = item.path.span;
1823                let _ = visitor.visit_def_id(
1824                    trait_ref.def_id,
1825                    "trait",
1826                    &trait_ref.print_only_trait_path(),
1827                );
1828            }
1829        }
1830    }
1831}
1832
1833fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
1834    // Build up a set of all exported items in the AST. This is a set of all
1835    // items which are reachable from external crates based on visibility.
1836    let mut visitor = EmbargoVisitor {
1837        tcx,
1838        effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
1839        macro_reachable: Default::default(),
1840        changed: false,
1841    };
1842
1843    visitor.effective_visibilities.check_invariants(tcx);
1844
1845    // HACK(jynelson): trying to infer the type of `impl Trait` breaks `async-std` (and
1846    // `pub async fn` in general). Since rustdoc never needs to do codegen and doesn't
1847    // care about link-time reachability, keep them unreachable (issue #75100).
1848    let impl_trait_pass = !tcx.sess.opts.actually_rustdoc;
1849    if impl_trait_pass {
1850        // Underlying types of `impl Trait`s are marked as reachable unconditionally,
1851        // so this pass doesn't need to be a part of the fixed point iteration below.
1852        let krate = tcx.hir_crate_items(());
1853        for id in krate.opaques() {
1854            let opaque = tcx.hir_node_by_def_id(id).expect_opaque_ty();
1855            let should_visit = match opaque.origin {
1856                hir::OpaqueTyOrigin::FnReturn {
1857                    parent,
1858                    in_trait_or_impl: Some(hir::RpitContext::Trait),
1859                }
1860                | hir::OpaqueTyOrigin::AsyncFn {
1861                    parent,
1862                    in_trait_or_impl: Some(hir::RpitContext::Trait),
1863                } => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 {
1864                    hir::TraitFn::Required(_) => false,
1865                    hir::TraitFn::Provided(..) => true,
1866                },
1867
1868                // Always visit RPITs in functions that have definitions,
1869                // and all TAITs.
1870                hir::OpaqueTyOrigin::FnReturn {
1871                    in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1872                    ..
1873                }
1874                | hir::OpaqueTyOrigin::AsyncFn {
1875                    in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1876                    ..
1877                }
1878                | hir::OpaqueTyOrigin::TyAlias { .. } => true,
1879            };
1880            if should_visit {
1881                // FIXME: This is some serious pessimization intended to workaround deficiencies
1882                // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
1883                // reachable if they are returned via `impl Trait`, even from private functions.
1884                let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
1885                visitor
1886                    .reach_through_impl_trait(opaque.def_id, pub_ev)
1887                    .generics()
1888                    .predicates()
1889                    .ty();
1890            }
1891        }
1892
1893        visitor.changed = false;
1894    }
1895
1896    loop {
1897        tcx.hir_visit_all_item_likes_in_crate(&mut visitor);
1898        if visitor.changed {
1899            visitor.changed = false;
1900        } else {
1901            break;
1902        }
1903    }
1904    visitor.effective_visibilities.check_invariants(tcx);
1905
1906    let mut check_visitor =
1907        TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
1908    check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID);
1909    tcx.hir_visit_all_item_likes_in_crate(&mut check_visitor);
1910
1911    tcx.arena.alloc(visitor.effective_visibilities)
1912}
1913
1914fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
1915    let effective_visibilities = tcx.effective_visibilities(());
1916    // Check for private types in public interfaces.
1917    let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };
1918
1919    for id in tcx.hir_free_items() {
1920        checker.check_item(id);
1921    }
1922}