@@ -75,14 +75,16 @@ pub trait DefIdVisitor<'tcx> {
75
75
}
76
76
77
77
fn tcx ( & self ) -> TyCtxt < ' tcx > ;
78
+ /// NOTE: Def-id visiting should be idempotent, because `DefIdVisitorSkeleton` will avoid
79
+ /// visiting duplicate def-ids. All the current visitors follow this rule.
78
80
fn visit_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display )
79
81
-> Self :: Result ;
80
82
81
83
/// Not overridden, but used to actually visit types and traits.
82
84
fn skeleton ( & mut self ) -> DefIdVisitorSkeleton < ' _ , ' tcx , Self > {
83
85
DefIdVisitorSkeleton {
84
86
def_id_visitor : self ,
85
- visited_opaque_tys : Default :: default ( ) ,
87
+ visited_def_ids : Default :: default ( ) ,
86
88
dummy : Default :: default ( ) ,
87
89
}
88
90
}
@@ -102,7 +104,7 @@ pub trait DefIdVisitor<'tcx> {
102
104
103
105
pub struct DefIdVisitorSkeleton < ' v , ' tcx , V : ?Sized > {
104
106
def_id_visitor : & ' v mut V ,
105
- visited_opaque_tys : FxHashSet < DefId > ,
107
+ visited_def_ids : FxHashSet < DefId > ,
106
108
dummy : PhantomData < TyCtxt < ' tcx > > ,
107
109
}
108
110
@@ -112,11 +114,13 @@ where
112
114
{
113
115
fn visit_trait ( & mut self , trait_ref : TraitRef < ' tcx > ) -> V :: Result {
114
116
let TraitRef { def_id, args, .. } = trait_ref;
115
- try_visit ! ( self . def_id_visitor. visit_def_id(
116
- def_id,
117
- "trait" ,
118
- & trait_ref. print_only_trait_path( )
119
- ) ) ;
117
+ if self . visited_def_ids . insert ( def_id) {
118
+ try_visit ! ( self . def_id_visitor. visit_def_id(
119
+ def_id,
120
+ "trait" ,
121
+ & trait_ref. print_only_trait_path( )
122
+ ) ) ;
123
+ }
120
124
if V :: SHALLOW { V :: Result :: output ( ) } else { args. visit_with ( self ) }
121
125
}
122
126
@@ -190,7 +194,9 @@ where
190
194
| ty:: Closure ( def_id, ..)
191
195
| ty:: CoroutineClosure ( def_id, ..)
192
196
| ty:: Coroutine ( def_id, ..) => {
193
- try_visit ! ( self . def_id_visitor. visit_def_id( def_id, "type" , & ty) ) ;
197
+ if self . visited_def_ids . insert ( def_id) {
198
+ try_visit ! ( self . def_id_visitor. visit_def_id( def_id, "type" , & ty) ) ;
199
+ }
194
200
if V :: SHALLOW {
195
201
return V :: Result :: output ( ) ;
196
202
}
@@ -221,15 +227,17 @@ where
221
227
return V :: Result :: output ( ) ;
222
228
}
223
229
224
- try_visit ! ( self . def_id_visitor. visit_def_id(
225
- data. def_id,
226
- match kind {
227
- ty:: Inherent | ty:: Projection => "associated type" ,
228
- ty:: Free => "type alias" ,
229
- ty:: Opaque => unreachable!( ) ,
230
- } ,
231
- & LazyDefPathStr { def_id: data. def_id, tcx } ,
232
- ) ) ;
230
+ if self . visited_def_ids . insert ( data. def_id ) {
231
+ try_visit ! ( self . def_id_visitor. visit_def_id(
232
+ data. def_id,
233
+ match kind {
234
+ ty:: Inherent | ty:: Projection => "associated type" ,
235
+ ty:: Free => "type alias" ,
236
+ ty:: Opaque => unreachable!( ) ,
237
+ } ,
238
+ & LazyDefPathStr { def_id: data. def_id, tcx } ,
239
+ ) ) ;
240
+ }
233
241
234
242
// This will also visit args if necessary, so we don't need to recurse.
235
243
return if V :: SHALLOW {
@@ -254,12 +262,14 @@ where
254
262
}
255
263
} ;
256
264
let ty:: ExistentialTraitRef { def_id, .. } = trait_ref;
257
- try_visit ! ( self . def_id_visitor. visit_def_id( def_id, "trait" , & trait_ref) ) ;
265
+ if self . visited_def_ids . insert ( def_id) {
266
+ try_visit ! ( self . def_id_visitor. visit_def_id( def_id, "trait" , & trait_ref) ) ;
267
+ }
258
268
}
259
269
}
260
270
ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) => {
261
271
// Skip repeated `Opaque`s to avoid infinite recursion.
262
- if self . visited_opaque_tys . insert ( def_id) {
272
+ if self . visited_def_ids . insert ( def_id) {
263
273
// The intent is to treat `impl Trait1 + Trait2` identically to
264
274
// `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
265
275
// (it either has no visibility, or its visibility is insignificant, like
@@ -923,7 +933,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
923
933
924
934
// Checks that a field in a struct constructor (expression or pattern) is accessible.
925
935
fn check_field (
926
- & mut self ,
936
+ & self ,
927
937
hir_id : hir:: HirId , // ID of the field use
928
938
use_ctxt : Span , // syntax context of the field name at the use site
929
939
def : ty:: AdtDef < ' tcx > , // definition of the struct or enum
@@ -941,7 +951,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
941
951
942
952
// Checks that a field in a struct constructor (expression or pattern) is accessible.
943
953
fn emit_unreachable_field_error (
944
- & mut self ,
954
+ & self ,
945
955
fields : Vec < ( Symbol , Span , bool /* field is present */ ) > ,
946
956
def : ty:: AdtDef < ' tcx > , // definition of the struct or enum
947
957
update_syntax : Option < Span > ,
@@ -1004,7 +1014,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
1004
1014
}
1005
1015
1006
1016
fn check_expanded_fields (
1007
- & mut self ,
1017
+ & self ,
1008
1018
adt : ty:: AdtDef < ' tcx > ,
1009
1019
variant : & ' tcx ty:: VariantDef ,
1010
1020
fields : & [ hir:: ExprField < ' tcx > ] ,
@@ -1142,7 +1152,7 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
1142
1152
result. is_break ( )
1143
1153
}
1144
1154
1145
- fn check_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1155
+ fn check_def_id ( & self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1146
1156
let is_error = !self . item_is_accessible ( def_id) ;
1147
1157
if is_error {
1148
1158
self . tcx . dcx ( ) . emit_err ( ItemIsPrivate { span : self . span , kind, descr : descr. into ( ) } ) ;
@@ -1401,7 +1411,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
1401
1411
self
1402
1412
}
1403
1413
1404
- fn check_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1414
+ fn check_def_id ( & self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool {
1405
1415
if self . leaks_private_dep ( def_id) {
1406
1416
self . tcx . emit_node_span_lint (
1407
1417
lint:: builtin:: EXPORTED_PRIVATE_DEPENDENCIES ,
0 commit comments