@@ -51,7 +51,8 @@ mod diagnostics;
51
51
/// in `impl Trait`, see individual commits in `DefIdVisitorSkeleton::visit_ty`.
52
52
trait DefIdVisitor < ' a , ' tcx : ' a > {
53
53
fn tcx ( & self ) -> TyCtxt < ' a , ' tcx , ' tcx > ;
54
- fn recurse_into_assoc_tys ( & self ) -> bool { true }
54
+ fn shallow ( & self ) -> bool { false }
55
+ fn skip_assoc_tys ( & self ) -> bool { false }
55
56
fn visit_def_id ( & mut self , def_id : DefId , kind : & str , descr : & dyn fmt:: Display ) -> bool ;
56
57
57
58
/// Not overridden, but used to actually visit types and traits.
@@ -86,7 +87,8 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V>
86
87
{
87
88
fn visit_trait ( & mut self , trait_ref : TraitRef < ' tcx > ) -> bool {
88
89
let TraitRef { def_id, substs } = trait_ref;
89
- self . def_id_visitor . visit_def_id ( def_id, "trait" , & trait_ref) || substs. visit_with ( self )
90
+ self . def_id_visitor . visit_def_id ( def_id, "trait" , & trait_ref) ||
91
+ ( !self . def_id_visitor . shallow ( ) && substs. visit_with ( self ) )
90
92
}
91
93
92
94
fn visit_predicates ( & mut self , predicates : Lrc < ty:: GenericPredicates < ' tcx > > ) -> bool {
@@ -138,6 +140,9 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V>
138
140
if self . def_id_visitor . visit_def_id ( def_id, "type" , ty) {
139
141
return true ;
140
142
}
143
+ if self . def_id_visitor . shallow ( ) {
144
+ return false ;
145
+ }
141
146
// Default type visitor doesn't visit signatures of fn types.
142
147
// Something like `fn() -> Priv {my_func}` is considered a private type even if
143
148
// `my_func` is public, so we need to visit signatures.
@@ -159,18 +164,20 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V>
159
164
}
160
165
}
161
166
ty:: Projection ( proj) | ty:: UnnormalizedProjection ( proj) => {
162
- if ! self . def_id_visitor . recurse_into_assoc_tys ( ) {
167
+ if self . def_id_visitor . skip_assoc_tys ( ) {
163
168
// Visitors searching for minimal visibility/reachability want to
164
169
// conservatively approximate associated types like `<Type as Trait>::Alias`
165
170
// as visible/reachable even if both `Type` and `Trait` are private.
166
171
// Ideally, associated types should be substituted in the same way as
167
172
// free type aliases, but this isn't done yet.
168
173
return false ;
169
174
}
170
- // This will also visit substs, so we don't need to recurse.
175
+ // This will also visit substs if necessary , so we don't need to recurse.
171
176
return self . visit_trait ( proj. trait_ref ( tcx) ) ;
172
177
}
173
178
ty:: Dynamic ( predicates, ..) => {
179
+ // All traits in the list are considered the "primary" part of the type
180
+ // and are visited by shallow visitors.
174
181
for predicate in * predicates. skip_binder ( ) {
175
182
let trait_ref = match * predicate {
176
183
ty:: ExistentialPredicate :: Trait ( trait_ref) => trait_ref,
@@ -187,9 +194,13 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V>
187
194
ty:: Opaque ( def_id, ..) => {
188
195
// Skip repeated `Opaque`s to avoid infinite recursion.
189
196
if self . visited_opaque_tys . insert ( def_id) {
190
- // Default type visitor doesn't visit traits in `impl Trait`.
191
- // Something like `impl PrivTr` is considered a private type,
192
- // so we need to visit the traits additionally.
197
+ // The intent is to treat `impl Trait1 + Trait2` identically to
198
+ // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
199
+ // (it either has no visibility, or its visibility is insignificant, like
200
+ // visibilities of type aliases) and recurse into predicates instead to go
201
+ // through the trait list (default type visitor doesn't visit those traits).
202
+ // All traits in the list are considered the "primary" part of the type
203
+ // and are visited by shallow visitors.
193
204
if self . visit_predicates ( tcx. predicates_of ( def_id) ) {
194
205
return true ;
195
206
}
@@ -206,7 +217,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V>
206
217
bug ! ( "unexpected type: {:?}" , ty) ,
207
218
}
208
219
209
- ty. super_visit_with ( self )
220
+ ! self . def_id_visitor . shallow ( ) && ty. super_visit_with ( self )
210
221
}
211
222
}
212
223
@@ -325,7 +336,8 @@ struct FindMin<'a, 'tcx, VL: VisibilityLike> {
325
336
326
337
impl < ' a , ' tcx , VL : VisibilityLike > DefIdVisitor < ' a , ' tcx > for FindMin < ' a , ' tcx , VL > {
327
338
fn tcx ( & self ) -> TyCtxt < ' a , ' tcx , ' tcx > { self . tcx }
328
- fn recurse_into_assoc_tys ( & self ) -> bool { false }
339
+ fn shallow ( & self ) -> bool { VL :: SHALLOW }
340
+ fn skip_assoc_tys ( & self ) -> bool { true }
329
341
fn visit_def_id ( & mut self , def_id : DefId , _kind : & str , _descr : & dyn fmt:: Display ) -> bool {
330
342
self . min = VL :: new_min ( self , def_id) ;
331
343
false
@@ -334,9 +346,10 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx,
334
346
335
347
trait VisibilityLike : Sized {
336
348
const MAX : Self ;
349
+ const SHALLOW : bool = false ;
337
350
fn new_min < ' a , ' tcx > ( find : & FindMin < ' a , ' tcx , Self > , def_id : DefId ) -> Self ;
338
351
339
- // Returns an over-approximation (`recurse_into_assoc_tys ` = false ) of visibility due to
352
+ // Returns an over-approximation (`skip_assoc_tys ` = true ) of visibility due to
340
353
// associated types for which we can't determine visibility precisely.
341
354
fn of_impl < ' a , ' tcx > ( node_id : ast:: NodeId , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
342
355
access_levels : & ' a AccessLevels ) -> Self {
@@ -357,6 +370,16 @@ impl VisibilityLike for ty::Visibility {
357
370
}
358
371
impl VisibilityLike for Option < AccessLevel > {
359
372
const MAX : Self = Some ( AccessLevel :: Public ) ;
373
+ // Type inference is very smart sometimes.
374
+ // It can make an impl reachable even some components of its type or trait are unreachable.
375
+ // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
376
+ // can be usable from other crates (#57264). So we skip substs when calculating reachability
377
+ // and consider an impl reachable if its "shallow" type and trait are reachable.
378
+ //
379
+ // The assumption we make here is that type-inference won't let you use an impl without knowing
380
+ // both "shallow" version of its self type and "shallow" version of its trait if it exists
381
+ // (which require reaching the `DefId`s in them).
382
+ const SHALLOW : bool = true ;
360
383
fn new_min < ' a , ' tcx > ( find : & FindMin < ' a , ' tcx , Self > , def_id : DefId ) -> Self {
361
384
cmp:: min ( if let Some ( node_id) = find. tcx . hir ( ) . as_local_node_id ( def_id) {
362
385
find. access_levels . map . get ( & node_id) . cloned ( )
@@ -542,7 +565,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
542
565
// Visit everything except for private impl items.
543
566
hir:: ItemKind :: Impl ( .., ref impl_item_refs) => {
544
567
if item_level. is_some ( ) {
545
- self . reach ( item. id , item_level) . generics ( ) . predicates ( ) ;
568
+ self . reach ( item. id , item_level) . generics ( ) . predicates ( ) . ty ( ) . trait_ref ( ) ;
546
569
547
570
for impl_item_ref in impl_item_refs {
548
571
let impl_item_level = self . get ( impl_item_ref. id . node_id ) ;
@@ -701,6 +724,13 @@ impl<'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> {
701
724
self . visit ( self . ev . tcx . type_of ( self . item_def_id ) ) ;
702
725
self
703
726
}
727
+
728
+ fn trait_ref ( & mut self ) -> & mut Self {
729
+ if let Some ( trait_ref) = self . ev . tcx . impl_trait_ref ( self . item_def_id ) {
730
+ self . visit_trait ( trait_ref) ;
731
+ }
732
+ self
733
+ }
704
734
}
705
735
706
736
impl < ' a , ' tcx > DefIdVisitor < ' a , ' tcx > for ReachEverythingInTheInterfaceVisitor < ' _ , ' a , ' tcx > {
0 commit comments