// tidy-alphabetical-start
#![feature(associated_type_defaults)]
#![feature(try_blocks)]
// tidy-alphabetical-end

mod errors;

use std::fmt;
use std::marker::PhantomData;
use std::ops::ControlFlow;

use errors::{
    FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
    ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
    UnnamedItemIsPrivate,
};
use rustc_ast::MacroDef;
use rustc_ast::visit::{VisitorResult, try_visit};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_errors::{MultiSpan, listify};
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::{AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr};
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
use rustc_middle::query::Providers;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
    self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
    TypeVisitor,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
use rustc_span::{Ident, Span, Symbol, sym};
use tracing::debug;

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

////////////////////////////////////////////////////////////////////////////////
// Generic infrastructure used to implement specific visitors below.
////////////////////////////////////////////////////////////////////////////////

struct LazyDefPathStr<'tcx> {
    def_id: DefId,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.tcx.def_path_str(self.def_id))
    }
}

/// Implemented to visit all `DefId`s in a type.
/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them.
/// The idea is to visit "all components of a type", as documented in
/// <https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type>.
/// The default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings.
/// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
pub trait DefIdVisitor<'tcx> {
    type Result: VisitorResult = ();
    const SHALLOW: bool = false;
    fn skip_assoc_tys(&self) -> bool {
        false
    }

    fn tcx(&self) -> TyCtxt<'tcx>;
    /// NOTE: Def-id visiting should be idempotent (or at least produce duplicated errors),
    /// because `DefIdVisitorSkeleton` will use caching and sometimes avoid visiting duplicate
    /// def-ids. All the current visitors follow this rule.
    fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
    -> Self::Result;

    /// Not overridden, but used to actually visit types and traits.
    fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
        DefIdVisitorSkeleton {
            def_id_visitor: self,
            visited_tys: Default::default(),
            dummy: Default::default(),
        }
    }
    fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
        ty_fragment.visit_with(&mut self.skeleton())
    }
    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
        self.skeleton().visit_trait(trait_ref)
    }
    fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
        self.skeleton().visit_clauses(predicates.predicates)
    }
    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
        self.skeleton().visit_clauses(clauses)
    }
}

pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
    def_id_visitor: &'v mut V,
    visited_tys: FxHashSet<Ty<'tcx>>,
    dummy: PhantomData<TyCtxt<'tcx>>,
}

impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
where
    V: DefIdVisitor<'tcx> + ?Sized,
{
    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
        let TraitRef { def_id, args, .. } = trait_ref;
        try_visit!(self.def_id_visitor.visit_def_id(
            def_id,
            "trait",
            &trait_ref.print_only_trait_path()
        ));
        if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
    }

    fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
        let tcx = self.def_id_visitor.tcx();
        let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
        try_visit!(self.visit_trait(trait_ref));
        if V::SHALLOW {
            V::Result::output()
        } else {
            V::Result::from_branch(
                assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
            )
        }
    }

    fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
        match clause.kind().skip_binder() {
            ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
                self.visit_trait(trait_ref)
            }
            ty::ClauseKind::HostEffect(pred) => {
                try_visit!(self.visit_trait(pred.trait_ref));
                pred.constness.visit_with(self)
            }
            ty::ClauseKind::Projection(ty::ProjectionPredicate {
                projection_term: projection_ty,
                term,
            }) => {
                try_visit!(term.visit_with(self));
                self.visit_projection_term(projection_ty)
            }
            ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
            ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
            ty::ClauseKind::ConstArgHasType(ct, ty) => {
                try_visit!(ct.visit_with(self));
                ty.visit_with(self)
            }
            ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
            ty::ClauseKind::WellFormed(term) => term.visit_with(self),
            ty::ClauseKind::UnstableFeature(_) => V::Result::output(),
        }
    }

    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
        for &(clause, _) in clauses {
            try_visit!(self.visit_clause(clause));
        }
        V::Result::output()
    }
}

impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
where
    V: DefIdVisitor<'tcx> + ?Sized,
{
    type Result = V::Result;

    fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
        self.visit_clause(p.as_clause().unwrap())
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
        let tcx = self.def_id_visitor.tcx();
        // GenericArgs are not visited here because they are visited below
        // in `super_visit_with`.
        let ty_kind = *ty.kind();
        match ty_kind {
            ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
            | ty::Foreign(def_id)
            | ty::FnDef(def_id, ..)
            | ty::Closure(def_id, ..)
            | ty::CoroutineClosure(def_id, ..)
            | ty::Coroutine(def_id, ..) => {
                try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
                if V::SHALLOW {
                    return V::Result::output();
                }
                // Default type visitor doesn't visit signatures of fn types.
                // Something like `fn() -> Priv {my_func}` is considered a private type even if
                // `my_func` is public, so we need to visit signatures.
                if let ty::FnDef(..) = ty_kind {
                    // FIXME: this should probably use `args` from `FnDef`
                    try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self));
                }
                // Inherent static methods don't have self type in args.
                // Something like `fn() {my_method}` type of the method
                // `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
                // so we need to visit the self type additionally.
                if let Some(assoc_item) = tcx.opt_associated_item(def_id)
                    && let Some(impl_def_id) = assoc_item.impl_container(tcx)
                {
                    try_visit!(tcx.type_of(impl_def_id).instantiate_identity().visit_with(self));
                }
            }
            ty::Alias(kind @ (ty::Inherent | ty::Free | ty::Projection), data) => {
                if self.def_id_visitor.skip_assoc_tys() {
                    // Visitors searching for minimal visibility/reachability want to
                    // conservatively approximate associated types like `Type::Alias`
                    // as visible/reachable even if `Type` is private.
                    // Ideally, associated types should be instantiated in the same way as
                    // free type aliases, but this isn't done yet.
                    return V::Result::output();
                }
                if !self.visited_tys.insert(ty) {
                    // Avoid repeatedly visiting alias types (including projections).
                    // This helps with special cases like #145741, but doesn't introduce
                    // too much overhead in general case, unlike caching for other types.
                    return V::Result::output();
                }

                try_visit!(self.def_id_visitor.visit_def_id(
                    data.def_id,
                    match kind {
                        ty::Inherent | ty::Projection => "associated type",
                        ty::Free => "type alias",
                        ty::Opaque => unreachable!(),
                    },
                    &LazyDefPathStr { def_id: data.def_id, tcx },
                ));

                // This will also visit args if necessary, so we don't need to recurse.
                return if V::SHALLOW {
                    V::Result::output()
                } else if kind == ty::Projection {
                    self.visit_projection_term(data.into())
                } else {
                    V::Result::from_branch(
                        data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
                    )
                };
            }
            ty::Dynamic(predicates, ..) => {
                // All traits in the list are considered the "primary" part of the type
                // and are visited by shallow visitors.
                for predicate in predicates {
                    let trait_ref = match predicate.skip_binder() {
                        ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
                        ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
                        ty::ExistentialPredicate::AutoTrait(def_id) => {
                            ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
                        }
                    };
                    let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
                    try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
                }
            }
            ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                // Skip repeated `Opaque`s to avoid infinite recursion.
                if self.visited_tys.insert(ty) {
                    // The intent is to treat `impl Trait1 + Trait2` identically to
                    // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
                    // (it either has no visibility, or its visibility is insignificant, like
                    // visibilities of type aliases) and recurse into bounds instead to go
                    // through the trait list (default type visitor doesn't visit those traits).
                    // All traits in the list are considered the "primary" part of the type
                    // and are visited by shallow visitors.
                    try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()));
                }
            }
            // These types don't have their own def-ids (but may have subcomponents
            // with def-ids that should be visited recursively).
            ty::Bool
            | ty::Char
            | ty::Int(..)
            | ty::Uint(..)
            | ty::Float(..)
            | ty::Str
            | ty::Never
            | ty::Array(..)
            | ty::Slice(..)
            | ty::Tuple(..)
            | ty::RawPtr(..)
            | ty::Ref(..)
            | ty::Pat(..)
            | ty::FnPtr(..)
            | ty::UnsafeBinder(_)
            | ty::Param(..)
            | ty::Bound(..)
            | ty::Error(_)
            | ty::CoroutineWitness(..) => {}
            ty::Placeholder(..) | ty::Infer(..) => {
                bug!("unexpected type: {:?}", ty)
            }
        }

        if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
    }

    fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
        let tcx = self.def_id_visitor.tcx();
        tcx.expand_abstract_consts(c).super_visit_with(self)
    }
}

fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
    if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
}

/// Visitor used to determine impl visibility and reachability.
struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
    tcx: TyCtxt<'tcx>,
    effective_visibilities: &'a EffectiveVisibilities,
    min: VL,
}

impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
    for FindMin<'a, 'tcx, VL, SHALLOW>
{
    const SHALLOW: bool = SHALLOW;
    fn skip_assoc_tys(&self) -> bool {
        true
    }
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }
    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
        if let Some(def_id) = def_id.as_local() {
            self.min = VL::new_min(self, def_id);
        }
    }
}

trait VisibilityLike: Sized {
    const MAX: Self;
    fn new_min<const SHALLOW: bool>(
        find: &FindMin<'_, '_, Self, SHALLOW>,
        def_id: LocalDefId,
    ) -> Self;

    // Returns an over-approximation (`skip_assoc_tys()` = true) of visibility due to
    // associated types for which we can't determine visibility precisely.
    fn of_impl<const SHALLOW: bool>(
        def_id: LocalDefId,
        of_trait: bool,
        tcx: TyCtxt<'_>,
        effective_visibilities: &EffectiveVisibilities,
    ) -> Self {
        let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
        find.visit(tcx.type_of(def_id).instantiate_identity());
        if of_trait {
            find.visit_trait(tcx.impl_trait_ref(def_id).instantiate_identity());
        }
        find.min
    }
}

impl VisibilityLike for ty::Visibility {
    const MAX: Self = ty::Visibility::Public;
    fn new_min<const SHALLOW: bool>(
        find: &FindMin<'_, '_, Self, SHALLOW>,
        def_id: LocalDefId,
    ) -> Self {
        min(find.tcx.local_visibility(def_id), find.min, find.tcx)
    }
}

impl VisibilityLike for EffectiveVisibility {
    const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
    fn new_min<const SHALLOW: bool>(
        find: &FindMin<'_, '_, Self, SHALLOW>,
        def_id: LocalDefId,
    ) -> Self {
        let effective_vis =
            find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
                let private_vis = ty::Visibility::Restricted(
                    find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
                );
                EffectiveVisibility::from_vis(private_vis)
            });

        effective_vis.min(find.min, find.tcx)
    }
}

/// The embargo visitor, used to determine the exports of the AST.
struct EmbargoVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,

    /// Effective visibilities for reachable nodes.
    effective_visibilities: EffectiveVisibilities,
    /// A set of pairs corresponding to modules, where the first module is
    /// reachable via a macro that's defined in the second module. This cannot
    /// be represented as reachable because it can't handle the following case:
    ///
    /// pub mod n {                         // Should be `Public`
    ///     pub(crate) mod p {              // Should *not* be accessible
    ///         pub fn f() -> i32 { 12 }    // Must be `Reachable`
    ///     }
    /// }
    /// pub macro m() {
    ///     n::p::f()
    /// }
    macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>,
    /// Has something changed in the level map?
    changed: bool,
}

struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
    effective_vis: EffectiveVisibility,
    item_def_id: LocalDefId,
    ev: &'a mut EmbargoVisitor<'tcx>,
    level: Level,
}

impl<'tcx> EmbargoVisitor<'tcx> {
    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
        self.effective_visibilities.effective_vis(def_id).copied()
    }

    // Updates node effective visibility.
    fn update(
        &mut self,
        def_id: LocalDefId,
        inherited_effective_vis: EffectiveVisibility,
        level: Level,
    ) {
        let nominal_vis = self.tcx.local_visibility(def_id);
        self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
    }

    fn update_eff_vis(
        &mut self,
        def_id: LocalDefId,
        inherited_effective_vis: EffectiveVisibility,
        max_vis: Option<ty::Visibility>,
        level: Level,
    ) {
        // FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default.
        let private_vis =
            ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
        if max_vis != Some(private_vis) {
            self.changed |= self.effective_visibilities.update(
                def_id,
                max_vis,
                || private_vis,
                inherited_effective_vis,
                level,
                self.tcx,
            );
        }
    }

    fn reach(
        &mut self,
        def_id: LocalDefId,
        effective_vis: EffectiveVisibility,
    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
        ReachEverythingInTheInterfaceVisitor {
            effective_vis,
            item_def_id: def_id,
            ev: self,
            level: Level::Reachable,
        }
    }

    fn reach_through_impl_trait(
        &mut self,
        def_id: LocalDefId,
        effective_vis: EffectiveVisibility,
    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
        ReachEverythingInTheInterfaceVisitor {
            effective_vis,
            item_def_id: def_id,
            ev: self,
            level: Level::ReachableThroughImplTrait,
        }
    }

    // We have to make sure that the items that macros might reference
    // are reachable, since they might be exported transitively.
    fn update_reachability_from_macro(
        &mut self,
        local_def_id: LocalDefId,
        md: &MacroDef,
        macro_ev: EffectiveVisibility,
    ) {
        // Non-opaque macros cannot make other items more accessible than they already are.
        let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
        let attrs = self.tcx.hir_attrs(hir_id);

        if find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
            .unwrap_or(Transparency::fallback(md.macro_rules))
            != Transparency::Opaque
        {
            return;
        }

        let macro_module_def_id = self.tcx.local_parent(local_def_id);
        if self.tcx.def_kind(macro_module_def_id) != DefKind::Mod {
            // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
            return;
        }
        // FIXME(typed_def_id): Introduce checked constructors that check def_kind.
        let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id);

        if self.effective_visibilities.public_at_level(local_def_id).is_none() {
            return;
        }

        // Since we are starting from an externally visible module,
        // all the parents in the loop below are also guaranteed to be modules.
        let mut module_def_id = macro_module_def_id;
        loop {
            let changed_reachability =
                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
            if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID {
                break;
            }
            module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id));
        }
    }

    /// Updates the item as being reachable through a macro defined in the given
    /// module. Returns `true` if the level has changed.
    fn update_macro_reachable(
        &mut self,
        module_def_id: LocalModDefId,
        defining_mod: LocalModDefId,
        macro_ev: EffectiveVisibility,
    ) -> bool {
        if self.macro_reachable.insert((module_def_id, defining_mod)) {
            for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) {
                if let Res::Def(def_kind, def_id) = child.res
                    && let Some(def_id) = def_id.as_local()
                    && child.vis.is_accessible_from(defining_mod, self.tcx)
                {
                    let vis = self.tcx.local_visibility(def_id);
                    self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
                }
            }
            true
        } else {
            false
        }
    }

    fn update_macro_reachable_def(
        &mut self,
        def_id: LocalDefId,
        def_kind: DefKind,
        vis: ty::Visibility,
        module: LocalModDefId,
        macro_ev: EffectiveVisibility,
    ) {
        self.update(def_id, macro_ev, Level::Reachable);
        match def_kind {
            // No type privacy, so can be directly marked as reachable.
            DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => {
                if vis.is_accessible_from(module, self.tcx) {
                    self.update(def_id, macro_ev, Level::Reachable);
                }
            }

            // Hygiene isn't really implemented for `macro_rules!` macros at the
            // moment. Accordingly, marking them as reachable is unwise. `macro` macros
            // have normal hygiene, so we can treat them like other items without type
            // privacy and mark them reachable.
            DefKind::Macro(_) => {
                let item = self.tcx.hir_expect_item(def_id);
                if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind {
                    if vis.is_accessible_from(module, self.tcx) {
                        self.update(def_id, macro_ev, Level::Reachable);
                    }
                }
            }

            // We can't use a module name as the final segment of a path, except
            // in use statements. Since re-export checking doesn't consider
            // hygiene these don't need to be marked reachable. The contents of
            // the module, however may be reachable.
            DefKind::Mod => {
                if vis.is_accessible_from(module, self.tcx) {
                    self.update_macro_reachable(
                        LocalModDefId::new_unchecked(def_id),
                        module,
                        macro_ev,
                    );
                }
            }

            DefKind::Struct | DefKind::Union => {
                // While structs and unions have type privacy, their fields do not.
                let struct_def = self.tcx.adt_def(def_id);
                for field in &struct_def.non_enum_variant().fields {
                    let def_id = field.did.expect_local();
                    let field_vis = self.tcx.local_visibility(def_id);
                    if field_vis.is_accessible_from(module, self.tcx) {
                        self.reach(def_id, macro_ev).ty();
                    }
                }
            }

            // These have type privacy, so are not reachable unless they're
            // public, or are not namespaced at all.
            DefKind::AssocConst
            | DefKind::AssocTy
            | DefKind::ConstParam
            | DefKind::Ctor(_, _)
            | DefKind::Enum
            | DefKind::ForeignTy
            | DefKind::Fn
            | DefKind::OpaqueTy
            | DefKind::AssocFn
            | DefKind::Trait
            | DefKind::TyParam
            | DefKind::Variant
            | DefKind::LifetimeParam
            | DefKind::ExternCrate
            | DefKind::Use
            | DefKind::ForeignMod
            | DefKind::AnonConst
            | DefKind::InlineConst
            | DefKind::Field
            | DefKind::GlobalAsm
            | DefKind::Impl { .. }
            | DefKind::Closure
            | DefKind::SyntheticCoroutineBody => (),
        }
    }
}

impl<'tcx> EmbargoVisitor<'tcx> {
    fn check_def_id(&mut self, owner_id: OwnerId) {
        // Update levels of nested things and mark all items
        // in interfaces of reachable items as reachable.
        let item_ev = self.get(owner_id.def_id);
        match self.tcx.def_kind(owner_id) {
            // The interface is empty, and no nested items.
            DefKind::Use | DefKind::ExternCrate | DefKind::GlobalAsm => {}
            // The interface is empty, and all nested items are processed by `check_def_id`.
            DefKind::Mod => {}
            DefKind::Macro { .. } => {
                if let Some(item_ev) = item_ev {
                    let (_, macro_def, _) =
                        self.tcx.hir_expect_item(owner_id.def_id).expect_macro();
                    self.update_reachability_from_macro(owner_id.def_id, macro_def, item_ev);
                }
            }
            DefKind::ForeignTy
            | DefKind::Const
            | DefKind::Static { .. }
            | DefKind::Fn
            | DefKind::TyAlias => {
                if let Some(item_ev) = item_ev {
                    self.reach(owner_id.def_id, item_ev).generics().predicates().ty();
                }
            }
            DefKind::Trait => {
                if let Some(item_ev) = item_ev {
                    self.reach(owner_id.def_id, item_ev).generics().predicates();

                    for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
                        if assoc_item.is_impl_trait_in_trait() {
                            continue;
                        }

                        let def_id = assoc_item.def_id.expect_local();
                        self.update(def_id, item_ev, Level::Reachable);

                        let tcx = self.tcx;
                        let mut reach = self.reach(def_id, item_ev);
                        reach.generics().predicates();

                        if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() {
                            // No type to visit.
                        } else {
                            reach.ty();
                        }
                    }
                }
            }
            DefKind::TraitAlias => {
                if let Some(item_ev) = item_ev {
                    self.reach(owner_id.def_id, item_ev).generics().predicates();
                }
            }
            DefKind::Impl { of_trait } => {
                // Type inference is very smart sometimes. It can make an impl reachable even some
                // components of its type or trait are unreachable. E.g. methods of
                // `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
                // can be usable from other crates (#57264). So we skip args when calculating
                // reachability and consider an impl reachable if its "shallow" type and trait are
                // reachable.
                //
                // The assumption we make here is that type-inference won't let you use an impl
                // without knowing both "shallow" version of its self type and "shallow" version of
                // its trait if it exists (which require reaching the `DefId`s in them).
                let item_ev = EffectiveVisibility::of_impl::<true>(
                    owner_id.def_id,
                    of_trait,
                    self.tcx,
                    &self.effective_visibilities,
                );

                self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct);

                {
                    let mut reach = self.reach(owner_id.def_id, item_ev);
                    reach.generics().predicates().ty();
                    if of_trait {
                        reach.trait_ref();
                    }
                }

                for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
                    if assoc_item.is_impl_trait_in_trait() {
                        continue;
                    }

                    let def_id = assoc_item.def_id.expect_local();
                    let max_vis =
                        if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
                    self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);

                    if let Some(impl_item_ev) = self.get(def_id) {
                        self.reach(def_id, impl_item_ev).generics().predicates().ty();
                    }
                }
            }
            DefKind::Enum => {
                if let Some(item_ev) = item_ev {
                    self.reach(owner_id.def_id, item_ev).generics().predicates();
                }
                let def = self.tcx.adt_def(owner_id);
                for variant in def.variants() {
                    if let Some(item_ev) = item_ev {
                        self.update(variant.def_id.expect_local(), item_ev, Level::Reachable);
                    }

                    if let Some(variant_ev) = self.get(variant.def_id.expect_local()) {
                        if let Some(ctor_def_id) = variant.ctor_def_id() {
                            self.update(ctor_def_id.expect_local(), variant_ev, Level::Reachable);
                        }

                        for field in &variant.fields {
                            let field = field.did.expect_local();
                            self.update(field, variant_ev, Level::Reachable);
                            self.reach(field, variant_ev).ty();
                        }
                        // Corner case: if the variant is reachable, but its
                        // enum is not, make the enum reachable as well.
                        self.reach(owner_id.def_id, variant_ev).ty();
                    }
                    if let Some(ctor_def_id) = variant.ctor_def_id() {
                        if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
                            self.reach(owner_id.def_id, ctor_ev).ty();
                        }
                    }
                }
            }
            DefKind::Struct | DefKind::Union => {
                let def = self.tcx.adt_def(owner_id).non_enum_variant();
                if let Some(item_ev) = item_ev {
                    self.reach(owner_id.def_id, item_ev).generics().predicates();
                    for field in &def.fields {
                        let field = field.did.expect_local();
                        self.update(field, item_ev, Level::Reachable);
                        if let Some(field_ev) = self.get(field) {
                            self.reach(field, field_ev).ty();
                        }
                    }
                }
                if let Some(ctor_def_id) = def.ctor_def_id() {
                    if let Some(item_ev) = item_ev {
                        self.update(ctor_def_id.expect_local(), item_ev, Level::Reachable);
                    }
                    if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
                        self.reach(owner_id.def_id, ctor_ev).ty();
                    }
                }
            }
            // Contents are checked directly.
            DefKind::ForeignMod => {}
            DefKind::Field
            | DefKind::Variant
            | DefKind::AssocFn
            | DefKind::AssocTy
            | DefKind::AssocConst
            | DefKind::TyParam
            | DefKind::AnonConst
            | DefKind::InlineConst
            | DefKind::OpaqueTy
            | DefKind::Closure
            | DefKind::SyntheticCoroutineBody
            | DefKind::ConstParam
            | DefKind::LifetimeParam
            | DefKind::Ctor(..) => {
                bug!("should be checked while checking parent")
            }
        }
    }
}

impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
    fn generics(&mut self) -> &mut Self {
        for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
            if let GenericParamDefKind::Const { .. } = param.kind {
                self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
            }
            if let Some(default) = param.default_value(self.ev.tcx) {
                self.visit(default.instantiate_identity());
            }
        }
        self
    }

    fn predicates(&mut self) -> &mut Self {
        self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
        self
    }

    fn ty(&mut self) -> &mut Self {
        self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity());
        self
    }

    fn trait_ref(&mut self) -> &mut Self {
        self.visit_trait(self.ev.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
        self
    }
}

impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.ev.tcx
    }
    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
        if let Some(def_id) = def_id.as_local() {
            // All effective visibilities except `reachable_through_impl_trait` are limited to
            // nominal visibility. If any type or trait is leaked farther than that, it will
            // produce type privacy errors on any use, so we don't consider it leaked.
            let max_vis = (self.level != Level::ReachableThroughImplTrait)
                .then(|| self.ev.tcx.local_visibility(def_id));
            self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
        }
    }
}

/// Visitor, used for EffectiveVisibilities table checking
pub struct TestReachabilityVisitor<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    effective_visibilities: &'a EffectiveVisibilities,
}

impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
    fn effective_visibility_diagnostic(&self, def_id: LocalDefId) {
        if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
            let mut error_msg = String::new();
            let span = self.tcx.def_span(def_id.to_def_id());
            if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
                for level in Level::all_levels() {
                    let vis_str = effective_vis.at_level(level).to_string(def_id, self.tcx);
                    if level != Level::Direct {
                        error_msg.push_str(", ");
                    }
                    error_msg.push_str(&format!("{level:?}: {vis_str}"));
                }
            } else {
                error_msg.push_str("not in the table");
            }
            self.tcx.dcx().emit_err(ReportEffectiveVisibility { span, descr: error_msg });
        }
    }
}

impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
    fn check_def_id(&self, owner_id: OwnerId) {
        self.effective_visibility_diagnostic(owner_id.def_id);

        match self.tcx.def_kind(owner_id) {
            DefKind::Enum => {
                let def = self.tcx.adt_def(owner_id.def_id);
                for variant in def.variants() {
                    self.effective_visibility_diagnostic(variant.def_id.expect_local());
                    if let Some(ctor_def_id) = variant.ctor_def_id() {
                        self.effective_visibility_diagnostic(ctor_def_id.expect_local());
                    }
                    for field in &variant.fields {
                        self.effective_visibility_diagnostic(field.did.expect_local());
                    }
                }
            }
            DefKind::Struct | DefKind::Union => {
                let def = self.tcx.adt_def(owner_id.def_id).non_enum_variant();
                if let Some(ctor_def_id) = def.ctor_def_id() {
                    self.effective_visibility_diagnostic(ctor_def_id.expect_local());
                }
                for field in &def.fields {
                    self.effective_visibility_diagnostic(field.did.expect_local());
                }
            }
            _ => {}
        }
    }
}

/// Name privacy visitor, checks privacy and reports violations.
///
/// Most of name privacy checks are performed during the main resolution phase,
/// or later in type checking when field accesses and associated items are resolved.
/// This pass performs remaining checks for fields in struct expressions and patterns.
struct NamePrivacyVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
}

impl<'tcx> NamePrivacyVisitor<'tcx> {
    /// Gets the type-checking results for the current body.
    /// As this will ICE if called outside bodies, only call when working with
    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
    #[track_caller]
    fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
        self.maybe_typeck_results
            .expect("`NamePrivacyVisitor::typeck_results` called outside of body")
    }

    // Checks that a field in a struct constructor (expression or pattern) is accessible.
    fn check_field(
        &self,
        hir_id: hir::HirId,    // ID of the field use
        use_ctxt: Span,        // syntax context of the field name at the use site
        def: ty::AdtDef<'tcx>, // definition of the struct or enum
        field: &'tcx ty::FieldDef,
    ) -> bool {
        if def.is_enum() {
            return true;
        }

        // definition of the field
        let ident = Ident::new(sym::dummy, use_ctxt);
        let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id);
        !field.vis.is_accessible_from(def_id, self.tcx)
    }

    // Checks that a field in a struct constructor (expression or pattern) is accessible.
    fn emit_unreachable_field_error(
        &self,
        fields: Vec<(Symbol, Span, bool /* field is present */)>,
        def: ty::AdtDef<'tcx>, // definition of the struct or enum
        update_syntax: Option<Span>,
        struct_span: Span,
    ) {
        if def.is_enum() || fields.is_empty() {
            return;
        }

        //   error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private
        //   --> $DIR/visibility.rs:18:13
        //    |
        // LL |     let _x = Alpha {
        //    |              ----- in this type      # from `def`
        // LL |         beta: 0,
        //    |         ^^^^^^^ private field        # `fields.2` is `true`
        // LL |         ..
        //    |         ^^ field `gamma` is private  # `fields.2` is `false`

        // Get the list of all private fields for the main message.
        let Some(field_names) = listify(&fields[..], |(n, _, _)| format!("`{n}`")) else { return };
        let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();

        // Get the list of all private fields when pointing at the `..rest`.
        let rest_field_names: Vec<_> =
            fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
        let rest_len = rest_field_names.len();
        let rest_field_names =
            listify(&rest_field_names[..], |n| format!("`{n}`")).unwrap_or_default();
        // Get all the labels for each field or `..rest` in the primary MultiSpan.
        let labels = fields
            .iter()
            .filter(|(_, _, is_present)| *is_present)
            .map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span })
            .chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax {
                span: *span,
                rest_field_names: rest_field_names.clone(),
                rest_len,
            }))
            .collect();

        self.tcx.dcx().emit_err(FieldIsPrivate {
            span,
            struct_span: if self
                .tcx
                .sess
                .source_map()
                .is_multiline(fields[0].1.between(struct_span))
            {
                Some(struct_span)
            } else {
                None
            },
            field_names,
            variant_descr: def.variant_descr(),
            def_path_str: self.tcx.def_path_str(def.did()),
            labels,
            len: fields.len(),
        });
    }

    fn check_expanded_fields(
        &self,
        adt: ty::AdtDef<'tcx>,
        variant: &'tcx ty::VariantDef,
        fields: &[hir::ExprField<'tcx>],
        hir_id: hir::HirId,
        span: Span,
        struct_span: Span,
    ) {
        let mut failed_fields = vec![];
        for (vf_index, variant_field) in variant.fields.iter_enumerated() {
            let field =
                fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
            let (hir_id, use_ctxt, span) = match field {
                Some(field) => (field.hir_id, field.ident.span, field.span),
                None => (hir_id, span, span),
            };
            if self.check_field(hir_id, use_ctxt, adt, variant_field) {
                let name = match field {
                    Some(field) => field.ident.name,
                    None => variant_field.name,
                };
                failed_fields.push((name, span, field.is_some()));
            }
        }
        self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span);
    }
}

impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
        let new_typeck_results = self.tcx.typeck_body(body_id);
        // Do not try reporting privacy violations if we failed to infer types.
        if new_typeck_results.tainted_by_errors.is_some() {
            return;
        }
        let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
        self.visit_body(self.tcx.hir_body(body_id));
        self.maybe_typeck_results = old_maybe_typeck_results;
    }

    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
        if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
            let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
            let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
            let variant = adt.variant_of_res(res);
            match *base {
                hir::StructTailExpr::Base(base) => {
                    // If the expression uses FRU we need to make sure all the unmentioned fields
                    // are checked for privacy (RFC 736). Rather than computing the set of
                    // unmentioned fields, just check them all.
                    self.check_expanded_fields(
                        adt,
                        variant,
                        fields,
                        base.hir_id,
                        base.span,
                        qpath.span(),
                    );
                }
                hir::StructTailExpr::DefaultFields(span) => {
                    self.check_expanded_fields(
                        adt,
                        variant,
                        fields,
                        expr.hir_id,
                        span,
                        qpath.span(),
                    );
                }
                hir::StructTailExpr::None => {
                    let mut failed_fields = vec![];
                    for field in fields {
                        let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
                        let index = self.typeck_results().field_index(field.hir_id);
                        if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
                            failed_fields.push((field.ident.name, field.ident.span, true));
                        }
                    }
                    self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
                }
            }
        }

        intravisit::walk_expr(self, expr);
    }

    fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
        if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
            let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
            let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
            let variant = adt.variant_of_res(res);
            let mut failed_fields = vec![];
            for field in fields {
                let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
                let index = self.typeck_results().field_index(field.hir_id);
                if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
                    failed_fields.push((field.ident.name, field.ident.span, true));
                }
            }
            self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
        }

        intravisit::walk_pat(self, pat);
    }
}

/// Type privacy visitor, checks types for privacy and reports violations.
///
/// Both explicitly written types and inferred types of expressions and patterns are checked.
/// Checks are performed on "semantic" types regardless of names and their hygiene.
struct TypePrivacyVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    module_def_id: LocalModDefId,
    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
    span: Span,
}

impl<'tcx> TypePrivacyVisitor<'tcx> {
    fn item_is_accessible(&self, did: DefId) -> bool {
        self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
    }

    // Take node-id of an expression or pattern and check its type for privacy.
    fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
        self.span = span;
        let typeck_results = self
            .maybe_typeck_results
            .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
        let result: ControlFlow<()> = try {
            self.visit(typeck_results.node_type(id))?;
            self.visit(typeck_results.node_args(id))?;
            if let Some(adjustments) = typeck_results.adjustments().get(id) {
                adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
            }
        };
        result.is_break()
    }

    fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
        let is_error = !self.item_is_accessible(def_id);
        if is_error {
            self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() });
        }
        is_error
    }
}

impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
    type Result = ControlFlow<()>;
    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
        self.span = span;
        value.visit_with(&mut self.skeleton())
    }
}

impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
        let old_maybe_typeck_results =
            self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
        self.visit_body(self.tcx.hir_body(body_id));
        self.maybe_typeck_results = old_maybe_typeck_results;
    }

    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
        self.span = hir_ty.span;
        if self
            .visit(
                self.maybe_typeck_results
                    .unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body"))
                    .node_type(hir_ty.hir_id),
            )
            .is_break()
        {
            return;
        }

        intravisit::walk_ty(self, hir_ty);
    }

    fn visit_infer(
        &mut self,
        inf_id: rustc_hir::HirId,
        inf_span: Span,
        _kind: InferKind<'tcx>,
    ) -> Self::Result {
        self.span = inf_span;
        if let Some(ty) = self
            .maybe_typeck_results
            .unwrap_or_else(|| span_bug!(inf_span, "Inference variable outside of a body"))
            .node_type_opt(inf_id)
        {
            if self.visit(ty).is_break() {
                return;
            }
        } else {
            // FIXME: check types of const infers here.
        }

        self.visit_id(inf_id)
    }

    // Check types of expressions
    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
        if self.check_expr_pat_type(expr.hir_id, expr.span) {
            // Do not check nested expressions if the error already happened.
            return;
        }
        match expr.kind {
            hir::ExprKind::Assign(_, rhs, _) | hir::ExprKind::Match(rhs, ..) => {
                // Do not report duplicate errors for `x = y` and `match x { ... }`.
                if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
                    return;
                }
            }
            hir::ExprKind::MethodCall(segment, ..) => {
                // Method calls have to be checked specially.
                self.span = segment.ident.span;
                let typeck_results = self
                    .maybe_typeck_results
                    .unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body"));
                if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
                    if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
                        return;
                    }
                } else {
                    self.tcx
                        .dcx()
                        .span_delayed_bug(expr.span, "no type-dependent def for method call");
                }
            }
            _ => {}
        }

        intravisit::walk_expr(self, expr);
    }

    // Prohibit access to associated items with insufficient nominal visibility.
    //
    // Additionally, until better reachability analysis for macros 2.0 is available,
    // we prohibit access to private statics from other crates, this allows to give
    // more code internal visibility at link time. (Access to private functions
    // is already prohibited by type privacy for function types.)
    fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
        let def = match qpath {
            hir::QPath::Resolved(_, path) => match path.res {
                Res::Def(kind, def_id) => Some((kind, def_id)),
                _ => None,
            },
            hir::QPath::TypeRelative(..) => {
                match self.maybe_typeck_results {
                    Some(typeck_results) => typeck_results.type_dependent_def(id),
                    // FIXME: Check type-relative associated types in signatures.
                    None => None,
                }
            }
        };
        let def = def.filter(|(kind, _)| {
            matches!(
                kind,
                DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. }
            )
        });
        if let Some((kind, def_id)) = def {
            let is_local_static =
                if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
            if !self.item_is_accessible(def_id) && !is_local_static {
                let name = match *qpath {
                    hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
                    hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
                };
                let kind = self.tcx.def_descr(def_id);
                let sess = self.tcx.sess;
                let _ = match name {
                    Some(name) => {
                        sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
                    }
                    None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }),
                };
                return;
            }
        }

        intravisit::walk_qpath(self, qpath, id);
    }

    // Check types of patterns.
    fn visit_pat(&mut self, pattern: &'tcx hir::Pat<'tcx>) {
        if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
            // Do not check nested patterns if the error already happened.
            return;
        }

        intravisit::walk_pat(self, pattern);
    }

    fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) {
        if let Some(init) = local.init {
            if self.check_expr_pat_type(init.hir_id, init.span) {
                // Do not report duplicate errors for `let x = y`.
                return;
            }
        }

        intravisit::walk_local(self, local);
    }
}

impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
    type Result = ControlFlow<()>;
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }
    fn visit_def_id(
        &mut self,
        def_id: DefId,
        kind: &str,
        descr: &dyn fmt::Display,
    ) -> Self::Result {
        if self.check_def_id(def_id, kind, descr) {
            ControlFlow::Break(())
        } else {
            ControlFlow::Continue(())
        }
    }
}

/// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
/// finds any private components in it.
///
/// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
/// and traits in public interfaces.
struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    item_def_id: LocalDefId,
    /// The visitor checks that each component type is at least this visible.
    required_visibility: ty::Visibility,
    required_effective_vis: Option<EffectiveVisibility>,
    in_assoc_ty: bool,
    in_primary_interface: bool,
    skip_assoc_tys: bool,
}

impl SearchInterfaceForPrivateItemsVisitor<'_> {
    fn generics(&mut self) -> &mut Self {
        self.in_primary_interface = true;
        for param in &self.tcx.generics_of(self.item_def_id).own_params {
            match param.kind {
                GenericParamDefKind::Lifetime => {}
                GenericParamDefKind::Type { has_default, .. } => {
                    if has_default {
                        let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                    }
                }
                // FIXME(generic_const_exprs): May want to look inside const here
                GenericParamDefKind::Const { .. } => {
                    let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                }
            }
        }
        self
    }

    fn predicates(&mut self) -> &mut Self {
        self.in_primary_interface = false;
        // N.B., we use `explicit_predicates_of` and not `predicates_of`
        // because we don't want to report privacy errors due to where
        // clauses that the compiler inferred. We only want to
        // consider the ones that the user wrote. This is important
        // for the inferred outlives rules; see
        // `tests/ui/rfc-2093-infer-outlives/privacy.rs`.
        let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
        self
    }

    fn bounds(&mut self) -> &mut Self {
        self.in_primary_interface = false;
        let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
        self
    }

    fn ty(&mut self) -> &mut Self {
        self.in_primary_interface = true;
        let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
        self
    }

    fn trait_ref(&mut self) -> &mut Self {
        self.in_primary_interface = true;
        let _ = self.visit_trait(self.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
        self
    }

    fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
        if self.leaks_private_dep(def_id) {
            self.tcx.emit_node_span_lint(
                lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
                self.tcx.local_def_id_to_hir_id(self.item_def_id),
                self.tcx.def_span(self.item_def_id.to_def_id()),
                FromPrivateDependencyInPublicInterface {
                    kind,
                    descr: descr.into(),
                    krate: self.tcx.crate_name(def_id.krate),
                },
            );
        }

        let Some(local_def_id) = def_id.as_local() else {
            return false;
        };

        let vis = self.tcx.local_visibility(local_def_id);
        if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
            let vis_descr = match vis {
                ty::Visibility::Public => "public",
                ty::Visibility::Restricted(vis_def_id) => {
                    if vis_def_id
                        == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
                    {
                        "private"
                    } else if vis_def_id.is_top_level_module() {
                        "crate-private"
                    } else {
                        "restricted"
                    }
                }
            };

            let span = self.tcx.def_span(self.item_def_id.to_def_id());
            let vis_span = self.tcx.def_span(def_id);
            self.tcx.dcx().emit_err(InPublicInterface {
                span,
                vis_descr,
                kind,
                descr: descr.into(),
                vis_span,
            });
            return false;
        }

        let Some(effective_vis) = self.required_effective_vis else {
            return false;
        };

        let reachable_at_vis = *effective_vis.at_level(Level::Reachable);

        if !vis.is_at_least(reachable_at_vis, self.tcx) {
            let lint = if self.in_primary_interface {
                lint::builtin::PRIVATE_INTERFACES
            } else {
                lint::builtin::PRIVATE_BOUNDS
            };
            let span = self.tcx.def_span(self.item_def_id.to_def_id());
            let vis_span = self.tcx.def_span(def_id);
            self.tcx.emit_node_span_lint(
                lint,
                self.tcx.local_def_id_to_hir_id(self.item_def_id),
                span,
                PrivateInterfacesOrBoundsLint {
                    item_span: span,
                    item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()),
                    item_descr: (&LazyDefPathStr {
                        def_id: self.item_def_id.to_def_id(),
                        tcx: self.tcx,
                    })
                        .into(),
                    item_vis_descr: &reachable_at_vis.to_string(self.item_def_id, self.tcx),
                    ty_span: vis_span,
                    ty_kind: kind,
                    ty_descr: descr.into(),
                    ty_vis_descr: &vis.to_string(local_def_id, self.tcx),
                },
            );
        }

        false
    }

    /// An item is 'leaked' from a private dependency if all
    /// of the following are true:
    /// 1. It's contained within a public type
    /// 2. It comes from a private crate
    fn leaks_private_dep(&self, item_id: DefId) -> bool {
        let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);

        debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
        ret
    }
}

impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
    type Result = ControlFlow<()>;
    fn skip_assoc_tys(&self) -> bool {
        self.skip_assoc_tys
    }
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }
    fn visit_def_id(
        &mut self,
        def_id: DefId,
        kind: &str,
        descr: &dyn fmt::Display,
    ) -> Self::Result {
        if self.check_def_id(def_id, kind, descr) {
            ControlFlow::Break(())
        } else {
            ControlFlow::Continue(())
        }
    }
}

struct PrivateItemsInPublicInterfacesChecker<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    effective_visibilities: &'a EffectiveVisibilities,
}

impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
    fn check(
        &self,
        def_id: LocalDefId,
        required_visibility: ty::Visibility,
        required_effective_vis: Option<EffectiveVisibility>,
    ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
        SearchInterfaceForPrivateItemsVisitor {
            tcx: self.tcx,
            item_def_id: def_id,
            required_visibility,
            required_effective_vis,
            in_assoc_ty: false,
            in_primary_interface: true,
            skip_assoc_tys: false,
        }
    }

    fn check_unnameable(&self, def_id: LocalDefId, effective_vis: Option<EffectiveVisibility>) {
        let Some(effective_vis) = effective_vis else {
            return;
        };

        let reexported_at_vis = effective_vis.at_level(Level::Reexported);
        let reachable_at_vis = effective_vis.at_level(Level::Reachable);

        if reachable_at_vis.is_public() && reexported_at_vis != reachable_at_vis {
            let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
            let span = self.tcx.def_span(def_id.to_def_id());
            self.tcx.emit_node_span_lint(
                lint::builtin::UNNAMEABLE_TYPES,
                hir_id,
                span,
                UnnameableTypesLint {
                    span,
                    kind: self.tcx.def_descr(def_id.to_def_id()),
                    descr: (&LazyDefPathStr { def_id: def_id.to_def_id(), tcx: self.tcx }).into(),
                    reachable_vis: &reachable_at_vis.to_string(def_id, self.tcx),
                    reexported_vis: &reexported_at_vis.to_string(def_id, self.tcx),
                },
            );
        }
    }

    fn check_assoc_item(
        &self,
        item: &ty::AssocItem,
        vis: ty::Visibility,
        effective_vis: Option<EffectiveVisibility>,
    ) {
        let mut check = self.check(item.def_id.expect_local(), vis, effective_vis);

        let (check_ty, is_assoc_ty) = match item.kind {
            ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false),
            ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true),
        };

        check.in_assoc_ty = is_assoc_ty;
        check.generics().predicates();
        if check_ty {
            check.ty();
        }
    }

    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
        self.effective_visibilities.effective_vis(def_id).copied()
    }

    fn check_item(&self, id: ItemId) {
        let tcx = self.tcx;
        let def_id = id.owner_id.def_id;
        let item_visibility = tcx.local_visibility(def_id);
        let effective_vis = self.get(def_id);
        let def_kind = tcx.def_kind(def_id);

        match def_kind {
            DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
                if let DefKind::TyAlias = def_kind {
                    self.check_unnameable(def_id, effective_vis);
                }
                self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
            }
            DefKind::OpaqueTy => {
                // `ty()` for opaque types is the underlying type,
                // it's not a part of interface, so we skip it.
                self.check(def_id, item_visibility, effective_vis).generics().bounds();
            }
            DefKind::Trait => {
                self.check_unnameable(def_id, effective_vis);

                self.check(def_id, item_visibility, effective_vis).generics().predicates();

                for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
                    if assoc_item.is_impl_trait_in_trait() {
                        continue;
                    }

                    self.check_assoc_item(assoc_item, item_visibility, effective_vis);

                    if assoc_item.is_type() {
                        self.check(
                            assoc_item.def_id.expect_local(),
                            item_visibility,
                            effective_vis,
                        )
                        .bounds();
                    }
                }
            }
            DefKind::TraitAlias => {
                self.check(def_id, item_visibility, effective_vis).generics().predicates();
            }
            DefKind::Enum => {
                self.check_unnameable(def_id, effective_vis);
                self.check(def_id, item_visibility, effective_vis).generics().predicates();

                let adt = tcx.adt_def(id.owner_id);
                for field in adt.all_fields() {
                    self.check(field.did.expect_local(), item_visibility, effective_vis).ty();
                }
            }
            // Subitems of structs and unions have their own publicity.
            DefKind::Struct | DefKind::Union => {
                self.check_unnameable(def_id, effective_vis);
                self.check(def_id, item_visibility, effective_vis).generics().predicates();

                let adt = tcx.adt_def(id.owner_id);
                for field in adt.all_fields() {
                    let visibility = min(item_visibility, field.vis.expect_local(), tcx);
                    let field_ev = self.get(field.did.expect_local());

                    self.check(field.did.expect_local(), visibility, field_ev).ty();
                }
            }
            // Subitems of foreign modules have their own publicity.
            DefKind::ForeignMod => {}
            // An inherent impl is public when its type is public
            // Subitems of inherent impls have their own publicity.
            // A trait impl is public when both its type and its trait are public
            // Subitems of trait impls have inherited publicity.
            DefKind::Impl { of_trait } => {
                let impl_vis =
                    ty::Visibility::of_impl::<false>(def_id, of_trait, tcx, &Default::default());

                // We are using the non-shallow version here, unlike when building the
                // effective visisibilities table to avoid large number of false positives.
                // For example in
                //
                // impl From<Priv> for Pub {
                //     fn from(_: Priv) -> Pub {...}
                // }
                //
                // lints shouldn't be emitted even if `from` effective visibility
                // is larger than `Priv` nominal visibility and if `Priv` can leak
                // in some scenarios due to type inference.
                let impl_ev = EffectiveVisibility::of_impl::<false>(
                    def_id,
                    of_trait,
                    tcx,
                    self.effective_visibilities,
                );

                let mut check = self.check(def_id, impl_vis, Some(impl_ev));

                // Generics and predicates of trait impls are intentionally not checked
                // for private components (#90586).
                if !of_trait {
                    check.generics().predicates();
                }

                // Skip checking private components in associated types, due to lack of full
                // normalization they produce very ridiculous false positives.
                // FIXME: Remove this when full normalization is implemented.
                check.skip_assoc_tys = true;
                check.ty();
                if of_trait {
                    check.trait_ref();
                }

                for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
                    if assoc_item.is_impl_trait_in_trait() {
                        continue;
                    }

                    let impl_item_vis = if !of_trait {
                        min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
                    } else {
                        impl_vis
                    };

                    let impl_item_ev = if !of_trait {
                        self.get(assoc_item.def_id.expect_local())
                            .map(|ev| ev.min(impl_ev, self.tcx))
                    } else {
                        Some(impl_ev)
                    };

                    self.check_assoc_item(assoc_item, impl_item_vis, impl_item_ev);
                }
            }
            _ => {}
        }
    }

    fn check_foreign_item(&self, id: ForeignItemId) {
        let tcx = self.tcx;
        let def_id = id.owner_id.def_id;
        let item_visibility = tcx.local_visibility(def_id);
        let effective_vis = self.get(def_id);

        if let DefKind::ForeignTy = self.tcx.def_kind(def_id) {
            self.check_unnameable(def_id, effective_vis);
        }

        self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
    }
}

pub fn provide(providers: &mut Providers) {
    *providers = Providers {
        effective_visibilities,
        check_private_in_public,
        check_mod_privacy,
        ..*providers
    };
}

fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
    // Check privacy of names not checked in previous compilation stages.
    let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
    tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor);

    // Check privacy of explicitly written types and traits as well as
    // inferred types of expressions and patterns.
    let span = tcx.def_span(module_def_id);
    let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };

    let module = tcx.hir_module_items(module_def_id);
    for def_id in module.definitions() {
        let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);

        if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
            visitor.visit_nested_body(body_id.id());
        }

        if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) {
            let trait_ref = tcx.impl_trait_ref(def_id);
            let trait_ref = trait_ref.instantiate_identity();
            visitor.span =
                tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;
            let _ =
                visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path());
        }
    }
}

fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
    // Build up a set of all exported items in the AST. This is a set of all
    // items which are reachable from external crates based on visibility.
    let mut visitor = EmbargoVisitor {
        tcx,
        effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
        macro_reachable: Default::default(),
        changed: false,
    };

    visitor.effective_visibilities.check_invariants(tcx);

    // HACK(jynelson): trying to infer the type of `impl Trait` breaks `async-std` (and
    // `pub async fn` in general). Since rustdoc never needs to do codegen and doesn't
    // care about link-time reachability, keep them unreachable (issue #75100).
    let impl_trait_pass = !tcx.sess.opts.actually_rustdoc;
    if impl_trait_pass {
        // Underlying types of `impl Trait`s are marked as reachable unconditionally,
        // so this pass doesn't need to be a part of the fixed point iteration below.
        let krate = tcx.hir_crate_items(());
        for id in krate.opaques() {
            let opaque = tcx.hir_node_by_def_id(id).expect_opaque_ty();
            let should_visit = match opaque.origin {
                hir::OpaqueTyOrigin::FnReturn {
                    parent,
                    in_trait_or_impl: Some(hir::RpitContext::Trait),
                }
                | hir::OpaqueTyOrigin::AsyncFn {
                    parent,
                    in_trait_or_impl: Some(hir::RpitContext::Trait),
                } => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 {
                    hir::TraitFn::Required(_) => false,
                    hir::TraitFn::Provided(..) => true,
                },

                // Always visit RPITs in functions that have definitions,
                // and all TAITs.
                hir::OpaqueTyOrigin::FnReturn {
                    in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                    ..
                }
                | hir::OpaqueTyOrigin::AsyncFn {
                    in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                    ..
                }
                | hir::OpaqueTyOrigin::TyAlias { .. } => true,
            };
            if should_visit {
                // FIXME: This is some serious pessimization intended to workaround deficiencies
                // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
                // reachable if they are returned via `impl Trait`, even from private functions.
                let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
                visitor
                    .reach_through_impl_trait(opaque.def_id, pub_ev)
                    .generics()
                    .predicates()
                    .ty();
            }
        }

        visitor.changed = false;
    }

    let crate_items = tcx.hir_crate_items(());
    loop {
        for id in crate_items.free_items() {
            visitor.check_def_id(id.owner_id);
        }
        for id in crate_items.foreign_items() {
            visitor.check_def_id(id.owner_id);
        }
        if visitor.changed {
            visitor.changed = false;
        } else {
            break;
        }
    }
    visitor.effective_visibilities.check_invariants(tcx);

    let check_visitor =
        TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
    for id in crate_items.owners() {
        check_visitor.check_def_id(id);
    }

    tcx.arena.alloc(visitor.effective_visibilities)
}

fn check_private_in_public(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
    let effective_visibilities = tcx.effective_visibilities(());
    // Check for private types in public interfaces.
    let checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };

    let crate_items = tcx.hir_module_items(module_def_id);
    let _ = crate_items.par_items(|id| Ok(checker.check_item(id)));
    let _ = crate_items.par_foreign_items(|id| Ok(checker.check_foreign_item(id)));
}
