privacy: Introduce some caching to type visiting in DefIdVisitorSkeleton
This commit is contained in:
parent
156499e561
commit
f9464f827b
1 changed files with 15 additions and 5 deletions
|
|
@ -75,6 +75,9 @@ pub trait DefIdVisitor<'tcx> {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -82,7 +85,7 @@ pub trait DefIdVisitor<'tcx> {
|
|||
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
|
||||
DefIdVisitorSkeleton {
|
||||
def_id_visitor: self,
|
||||
visited_opaque_tys: Default::default(),
|
||||
visited_tys: Default::default(),
|
||||
dummy: Default::default(),
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +105,7 @@ pub trait DefIdVisitor<'tcx> {
|
|||
|
||||
pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
|
||||
def_id_visitor: &'v mut V,
|
||||
visited_opaque_tys: FxHashSet<DefId>,
|
||||
visited_tys: FxHashSet<Ty<'tcx>>,
|
||||
dummy: PhantomData<TyCtxt<'tcx>>,
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +186,8 @@ where
|
|||
let tcx = self.def_id_visitor.tcx();
|
||||
// GenericArgs are not visited here because they are visited below
|
||||
// in `super_visit_with`.
|
||||
match *ty.kind() {
|
||||
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, ..)
|
||||
|
|
@ -197,7 +201,7 @@ where
|
|||
// 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() {
|
||||
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));
|
||||
}
|
||||
|
|
@ -220,6 +224,12 @@ where
|
|||
// 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,
|
||||
|
|
@ -259,7 +269,7 @@ where
|
|||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
|
||||
// Skip repeated `Opaque`s to avoid infinite recursion.
|
||||
if self.visited_opaque_tys.insert(def_id) {
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue