Convert TypeVisitor
and DefIdVisitor
to use VisitorResult
This commit is contained in:
parent
5abfb3775d
commit
be9b125d41
53 changed files with 345 additions and 448 deletions
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue