privacy: Remove (Non)ShallowEffectiveVis

Use a boolean constant parameter instead.

Also turn some methods on `DefIdVisitor` into associated constants.
This commit is contained in:
Vadim Petrochenkov 2023-06-15 17:15:24 +03:00
parent d326aed46f
commit 17edd1a779

View File

@ -73,14 +73,10 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`. /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
trait DefIdVisitor<'tcx> { trait DefIdVisitor<'tcx> {
type BreakTy = (); type BreakTy = ();
const SHALLOW: bool = false;
const SKIP_ASSOC_TYS: bool = false;
fn tcx(&self) -> TyCtxt<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>;
fn shallow(&self) -> bool {
false
}
fn skip_assoc_tys(&self) -> bool {
false
}
fn visit_def_id( fn visit_def_id(
&mut self, &mut self,
def_id: DefId, def_id: DefId,
@ -129,11 +125,7 @@ where
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
let TraitRef { def_id, substs, .. } = trait_ref; let TraitRef { def_id, substs, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
if self.def_id_visitor.shallow() { if V::SHALLOW { ControlFlow::Continue(()) } else { substs.visit_with(self) }
ControlFlow::Continue(())
} else {
substs.visit_with(self)
}
} }
fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> { fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
@ -152,7 +144,7 @@ where
) )
}; };
self.visit_trait(trait_ref)?; self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() { if V::SHALLOW {
ControlFlow::Continue(()) ControlFlow::Continue(())
} else { } else {
assoc_substs.iter().try_for_each(|subst| subst.visit_with(self)) assoc_substs.iter().try_for_each(|subst| subst.visit_with(self))
@ -222,7 +214,7 @@ where
| ty::Closure(def_id, ..) | ty::Closure(def_id, ..)
| ty::Generator(def_id, ..) => { | ty::Generator(def_id, ..) => {
self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
if self.def_id_visitor.shallow() { if V::SHALLOW {
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
// Default type visitor doesn't visit signatures of fn types. // Default type visitor doesn't visit signatures of fn types.
@ -243,7 +235,7 @@ where
} }
} }
ty::Alias(ty::Projection, proj) => { ty::Alias(ty::Projection, proj) => {
if self.def_id_visitor.skip_assoc_tys() { if V::SKIP_ASSOC_TYS {
// Visitors searching for minimal visibility/reachability want to // Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `<Type as Trait>::Alias` // conservatively approximate associated types like `<Type as Trait>::Alias`
// as visible/reachable even if both `Type` and `Trait` are private. // as visible/reachable even if both `Type` and `Trait` are private.
@ -255,7 +247,7 @@ where
return self.visit_projection_ty(proj); return self.visit_projection_ty(proj);
} }
ty::Alias(ty::Inherent, data) => { ty::Alias(ty::Inherent, data) => {
if self.def_id_visitor.skip_assoc_tys() { if V::SKIP_ASSOC_TYS {
// Visitors searching for minimal visibility/reachability want to // Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `Type::Alias` // conservatively approximate associated types like `Type::Alias`
// as visible/reachable even if `Type` is private. // as visible/reachable even if `Type` is private.
@ -271,7 +263,7 @@ where
)?; )?;
// This will also visit substs if necessary, so we don't need to recurse. // This will also visit substs if necessary, so we don't need to recurse.
return if self.def_id_visitor.shallow() { return if V::SHALLOW {
ControlFlow::Continue(()) ControlFlow::Continue(())
} else { } else {
data.substs.iter().try_for_each(|subst| subst.visit_with(self)) data.substs.iter().try_for_each(|subst| subst.visit_with(self))
@ -333,11 +325,7 @@ where
} }
} }
if self.def_id_visitor.shallow() { if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) }
ControlFlow::Continue(())
} else {
ty.super_visit_with(self)
}
} }
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -354,22 +342,20 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
/// Visitor used to determine impl visibility and reachability. /// Visitor used to determine impl visibility and reachability.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct FindMin<'a, 'tcx, VL: VisibilityLike> { struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
effective_visibilities: &'a EffectiveVisibilities, effective_visibilities: &'a EffectiveVisibilities,
min: VL, min: VL,
} }
impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL> { impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
for FindMin<'a, 'tcx, VL, SHALLOW>
{
const SHALLOW: bool = SHALLOW;
const SKIP_ASSOC_TYS: bool = true;
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
fn shallow(&self) -> bool {
VL::SHALLOW
}
fn skip_assoc_tys(&self) -> bool {
true
}
fn visit_def_id( fn visit_def_id(
&mut self, &mut self,
def_id: DefId, def_id: DefId,
@ -385,17 +371,19 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
trait VisibilityLike: Sized { trait VisibilityLike: Sized {
const MAX: Self; const MAX: Self;
const SHALLOW: bool = false; fn new_min<const SHALLOW: bool>(
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self; find: &FindMin<'_, '_, Self, SHALLOW>,
def_id: LocalDefId,
) -> Self;
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to // Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to
// associated types for which we can't determine visibility precisely. // associated types for which we can't determine visibility precisely.
fn of_impl( fn of_impl<const SHALLOW: bool>(
def_id: LocalDefId, def_id: LocalDefId,
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
effective_visibilities: &EffectiveVisibilities, effective_visibilities: &EffectiveVisibilities,
) -> Self { ) -> Self {
let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX }; let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
find.visit(tcx.type_of(def_id).subst_identity()); find.visit(tcx.type_of(def_id).subst_identity());
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref.subst_identity()); find.visit_trait(trait_ref.subst_identity());
@ -405,49 +393,28 @@ trait VisibilityLike: Sized {
} }
impl VisibilityLike for ty::Visibility { impl VisibilityLike for ty::Visibility {
const MAX: Self = ty::Visibility::Public; const MAX: Self = ty::Visibility::Public;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self { 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) min(find.tcx.local_visibility(def_id), find.min, find.tcx)
} }
} }
struct NonShallowEffectiveVis(EffectiveVisibility); impl VisibilityLike for EffectiveVisibility {
const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
impl VisibilityLike for NonShallowEffectiveVis { fn new_min<const SHALLOW: bool>(
const MAX: Self = NonShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public)); find: &FindMin<'_, '_, Self, SHALLOW>,
const SHALLOW: bool = false; def_id: LocalDefId,
) -> Self {
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
let find = FindMin {
tcx: find.tcx,
effective_visibilities: find.effective_visibilities,
min: ShallowEffectiveVis(find.min.0),
};
NonShallowEffectiveVis(VisibilityLike::new_min(&find, def_id).0)
}
}
struct ShallowEffectiveVis(EffectiveVisibility);
impl VisibilityLike for ShallowEffectiveVis {
const MAX: Self = ShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public));
// 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 substs 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).
const SHALLOW: bool = true;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
let effective_vis = let effective_vis =
find.effective_visibilities.effective_vis(def_id).cloned().unwrap_or_else(|| { find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
let private_vis = let private_vis =
ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id)); ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id));
EffectiveVisibility::from_vis(private_vis) EffectiveVisibility::from_vis(private_vis)
}); });
ShallowEffectiveVis(effective_vis.min(find.min.0, find.tcx)) effective_vis.min(find.min, find.tcx)
} }
} }
@ -785,12 +752,21 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
} }
} }
hir::ItemKind::Impl(ref impl_) => { hir::ItemKind::Impl(ref impl_) => {
let item_ev = ShallowEffectiveVis::of_impl( // 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 substs 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>(
item.owner_id.def_id, item.owner_id.def_id,
self.tcx, self.tcx,
&self.effective_visibilities, &self.effective_visibilities,
) );
.0;
self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct); self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
@ -2154,27 +2130,28 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
DefKind::Impl { .. } => { DefKind::Impl { .. } => {
let item = tcx.hir().item(id); let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind { if let hir::ItemKind::Impl(ref impl_) = item.kind {
let impl_vis = let impl_vis = ty::Visibility::of_impl::<false>(
ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default()); item.owner_id.def_id,
tcx,
&Default::default(),
);
// we are using the non-shallow version here, unlike when building the // We are using the non-shallow version here, unlike when building the
// effective visisibilities table to avoid large number of false positives. // effective visisibilities table to avoid large number of false positives.
// For example: // For example in
// //
// impl From<Priv> for Pub { // impl From<Priv> for Pub {
// fn from(_: Priv) -> Pub {...} // fn from(_: Priv) -> Pub {...}
// } // }
// //
// lints shouldn't be emmited even `from` effective visibility // lints shouldn't be emmited even if `from` effective visibility
// is larger then `Priv` nominal visibility. // is larger than `Priv` nominal visibility and if `Priv` can leak
let impl_ev = Some( // in some scenarios due to type inference.
NonShallowEffectiveVis::of_impl( let impl_ev = Some(EffectiveVisibility::of_impl::<false>(
item.owner_id.def_id, item.owner_id.def_id,
tcx, tcx,
self.effective_visibilities, self.effective_visibilities,
) ));
.0,
);
// check that private components do not appear in the generics or predicates of inherent impls // check that private components do not appear in the generics or predicates of inherent impls
// this check is intentionally NOT performed for impls of traits, per #90586 // this check is intentionally NOT performed for impls of traits, per #90586