1
Fork 0

Convert TypeVisitor and DefIdVisitor to use VisitorResult

This commit is contained in:
Jason Newcomb 2024-02-24 17:22:28 -05:00
parent 5abfb3775d
commit be9b125d41
53 changed files with 345 additions and 448 deletions

View file

@ -11,6 +11,7 @@ extern crate tracing;
mod errors;
use rustc_ast::visit::{try_visit, VisitorResult};
use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
@ -67,17 +68,13 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
/// 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`.
trait DefIdVisitor<'tcx> {
type BreakTy = ();
type Result: VisitorResult = ();
const SHALLOW: bool = false;
const SKIP_ASSOC_TYS: bool = false;
fn tcx(&self) -> TyCtxt<'tcx>;
fn visit_def_id(
&mut self,
def_id: DefId,
kind: &str,
descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy>;
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> {
@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> {
dummy: Default::default(),
}
}
fn visit(
&mut self,
ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>,
) -> ControlFlow<Self::BreakTy> {
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>) -> ControlFlow<Self::BreakTy> {
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>,
) -> ControlFlow<Self::BreakTy> {
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)],
) -> ControlFlow<Self::BreakTy> {
fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
self.skeleton().visit_clauses(clauses)
}
}
@ -120,36 +108,42 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
where
V: DefIdVisitor<'tcx> + ?Sized,
{
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
let TraitRef { def_id, args, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) }
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_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result {
let tcx = self.def_id_visitor.tcx();
let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
self.visit_trait(trait_ref)?;
try_visit!(self.visit_trait(trait_ref));
if V::SHALLOW {
ControlFlow::Continue(())
V::Result::output()
} else {
assoc_args.iter().try_for_each(|arg| arg.visit_with(self))
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>) -> ControlFlow<V::BreakTy> {
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::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
term.visit_with(self)?;
try_visit!(term.visit_with(self));
self.visit_projection_ty(projection_ty)
}
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()),
ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
ty::ClauseKind::ConstArgHasType(ct, ty) => {
ct.visit_with(self)?;
try_visit!(ct.visit_with(self));
ty.visit_with(self)
}
ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
@ -157,8 +151,11 @@ where
}
}
fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> {
clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
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()
}
}
@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
where
V: DefIdVisitor<'tcx> + ?Sized,
{
type BreakTy = V::BreakTy;
type Result = V::Result;
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
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>) -> ControlFlow<V::BreakTy> {
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`.
@ -183,16 +180,16 @@ where
| ty::Closure(def_id, ..)
| ty::CoroutineClosure(def_id, ..)
| ty::Coroutine(def_id, ..) => {
self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
if V::SHALLOW {
return ControlFlow::Continue(());
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`
tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?;
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
@ -200,7 +197,9 @@ where
// so we need to visit the self type additionally.
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?;
try_visit!(
tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
);
}
}
}
@ -211,10 +210,10 @@ where
// 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 ControlFlow::Continue(());
return V::Result::output();
}
self.def_id_visitor.visit_def_id(
try_visit!(self.def_id_visitor.visit_def_id(
data.def_id,
match kind {
ty::Inherent | ty::Projection => "associated type",
@ -222,15 +221,17 @@ where
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 {
ControlFlow::Continue(())
V::Result::output()
} else if kind == ty::Projection {
self.visit_projection_ty(data)
} else {
data.args.iter().try_for_each(|arg| arg.visit_with(self))
V::Result::from_branch(
data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
)
};
}
ty::Dynamic(predicates, ..) => {
@ -245,7 +246,7 @@ where
}
};
let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
}
}
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
@ -258,7 +259,7 @@ where
// 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.
self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?;
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
@ -285,10 +286,10 @@ where
}
}
if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) }
if V::SHALLOW { V::Result::output() } 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>) -> Self::Result {
let tcx = self.def_id_visitor.tcx();
tcx.expand_abstract_consts(c).super_visit_with(self)
}
@ -316,16 +317,10 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_def_id(
&mut self,
def_id: DefId,
_kind: &str,
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
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);
}
ControlFlow::Continue(())
}
}
@ -836,12 +831,7 @@ 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,
) -> ControlFlow<Self::BreakTy> {
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
@ -850,7 +840,6 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
.then(|| self.ev.tcx.local_visibility(def_id));
self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
}
ControlFlow::Continue(())
}
}
@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
}
impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
type Result = ControlFlow<()>;
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
def_id: DefId,
kind: &str,
descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
) -> Self::Result {
if self.check_def_id(def_id, kind, descr) {
ControlFlow::Break(())
} else {
@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
}
impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
type Result = ControlFlow<()>;
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
def_id: DefId,
kind: &str,
descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
) -> Self::Result {
if self.check_def_id(def_id, kind, descr) {
ControlFlow::Break(())
} else {