@@ -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
@@ -929,7 +939,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
929939
930940 // Checks that a field in a struct constructor (expression or pattern) is accessible.
931941 fn check_field (
932- & mut self ,
942+ & self ,
933943 hir_id : hir:: HirId , // ID of the field use
934944 use_ctxt : Span , // syntax context of the field name at the use site
935945 def : ty:: AdtDef < ' tcx > , // definition of the struct or enum
@@ -947,7 +957,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
947957
948958 // Checks that a field in a struct constructor (expression or pattern) is accessible.
949959 fn emit_unreachable_field_error (
950- & mut self ,
960+ & self ,
951961 fields : Vec < ( Symbol , Span , bool /* field is present */ ) > ,
952962 def : ty:: AdtDef < ' tcx > , // definition of the struct or enum
953963 update_syntax : Option < Span > ,
@@ -1010,7 +1020,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
10101020 }
10111021
10121022 fn check_expanded_fields (
1013- & mut self ,
1023+ & self ,
10141024 adt : ty:: AdtDef < ' tcx > ,
10151025 variant : & ' tcx ty:: VariantDef ,
10161026 fields : & [ hir:: ExprField < ' tcx > ] ,
@@ -1148,7 +1158,7 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
11481158 result. is_break ( )
11491159 }
11501160
1151- fn check_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1161+ fn check_def_id ( & self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
11521162 let is_error = !self . item_is_accessible ( def_id) ;
11531163 if is_error {
11541164 self . tcx . dcx ( ) . emit_err ( ItemIsPrivate { span : self . span , kind, descr : descr. into ( ) } ) ;
@@ -1405,7 +1415,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
14051415 self
14061416 }
14071417
1408- fn check_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1418+ fn check_def_id ( & self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
14091419 if self . leaks_private_dep ( def_id) {
14101420 self . tcx . emit_node_span_lint (
14111421 lint:: builtin:: EXPORTED_PRIVATE_DEPENDENCIES ,
0 commit comments