@@ -75,14 +75,17 @@ pub trait DefIdVisitor<'tcx> {
7575 }
7676
7777 fn tcx ( & self ) -> TyCtxt < ' tcx > ;
78+ /// NOTE: Def-id visiting should be idempotent (or at least produce duplicated errors),
79+ /// because `DefIdVisitorSkeleton` will use caching and sometimes avoid visiting duplicate
80+ /// def-ids. All the current visitors follow this rule.
7881 fn visit_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display )
7982 -> Self :: Result ;
8083
8184 /// Not overridden, but used to actually visit types and traits.
8285 fn skeleton ( & mut self ) -> DefIdVisitorSkeleton < ' _ , ' tcx , Self > {
8386 DefIdVisitorSkeleton {
8487 def_id_visitor : self ,
85- visited_opaque_tys : Default :: default ( ) ,
88+ visited_tys : Default :: default ( ) ,
8689 dummy : Default :: default ( ) ,
8790 }
8891 }
@@ -102,7 +105,7 @@ pub trait DefIdVisitor<'tcx> {
102105
103106pub struct DefIdVisitorSkeleton < ' v , ' tcx , V : ?Sized > {
104107 def_id_visitor : & ' v mut V ,
105- visited_opaque_tys : FxHashSet < DefId > ,
108+ visited_tys : FxHashSet < Ty < ' tcx > > ,
106109 dummy : PhantomData < TyCtxt < ' tcx > > ,
107110}
108111
@@ -183,7 +186,8 @@ where
183186 let tcx = self . def_id_visitor . tcx ( ) ;
184187 // GenericArgs are not visited here because they are visited below
185188 // in `super_visit_with`.
186- match * ty. kind ( ) {
189+ let ty_kind = * ty. kind ( ) ;
190+ match ty_kind {
187191 ty:: Adt ( ty:: AdtDef ( Interned ( & ty:: AdtDefData { did : def_id, .. } , _) ) , ..)
188192 | ty:: Foreign ( def_id)
189193 | ty:: FnDef ( def_id, ..)
@@ -197,7 +201,7 @@ where
197201 // Default type visitor doesn't visit signatures of fn types.
198202 // Something like `fn() -> Priv {my_func}` is considered a private type even if
199203 // `my_func` is public, so we need to visit signatures.
200- if let ty:: FnDef ( ..) = ty . kind ( ) {
204+ if let ty:: FnDef ( ..) = ty_kind {
201205 // FIXME: this should probably use `args` from `FnDef`
202206 try_visit ! ( tcx. fn_sig( def_id) . instantiate_identity( ) . visit_with( self ) ) ;
203207 }
@@ -220,6 +224,12 @@ where
220224 // free type aliases, but this isn't done yet.
221225 return V :: Result :: output ( ) ;
222226 }
227+ if !self . visited_tys . insert ( ty) {
228+ // Avoid repeatedly visiting alias types (including projections).
229+ // This helps with special cases like #145741, but doesn't introduce
230+ // too much overhead in general case, unlike caching for other types.
231+ return V :: Result :: output ( ) ;
232+ }
223233
224234 try_visit ! ( self . def_id_visitor. visit_def_id(
225235 data. def_id,
@@ -259,7 +269,7 @@ where
259269 }
260270 ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) => {
261271 // Skip repeated `Opaque`s to avoid infinite recursion.
262- if self . visited_opaque_tys . insert ( def_id ) {
272+ if self . visited_tys . insert ( ty ) {
263273 // The intent is to treat `impl Trait1 + Trait2` identically to
264274 // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
265275 // (it either has no visibility, or its visibility is insignificant, like
0 commit comments