@@ -20,11 +20,12 @@ use rustc_ast::visit::{VisitorResult, try_visit};
2020use rustc_data_structures:: fx:: FxHashSet ;
2121use rustc_data_structures:: intern:: Interned ;
2222use rustc_errors:: { MultiSpan , listify} ;
23- use rustc_hir as hir;
2423use rustc_hir:: def:: { DefKind , Res } ;
2524use rustc_hir:: def_id:: { DefId , LocalDefId , LocalModDefId } ;
2625use rustc_hir:: intravisit:: { self , InferKind , Visitor } ;
27- use rustc_hir:: { AmbigArg , ForeignItemId , ItemId , OwnerId , PatKind , find_attr} ;
26+ use rustc_hir:: {
27+ self as hir, AmbigArg , ForeignItemId , ItemId , ItemKind , OwnerId , PatKind , find_attr,
28+ } ;
2829use rustc_middle:: middle:: privacy:: { EffectiveVisibilities , EffectiveVisibility , Level } ;
2930use rustc_middle:: query:: Providers ;
3031use rustc_middle:: ty:: print:: PrintTraitRefExt as _;
@@ -436,7 +437,7 @@ struct EmbargoVisitor<'tcx> {
436437 /// }
437438 macro_reachable : FxHashSet < ( LocalModDefId , LocalModDefId ) > ,
438439 /// Has something changed in the level map?
439- changed : bool ,
440+ queue : Vec < LocalDefId > ,
440441}
441442
442443struct ReachEverythingInTheInterfaceVisitor < ' a , ' tcx > {
@@ -472,15 +473,68 @@ impl<'tcx> EmbargoVisitor<'tcx> {
472473 // FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default.
473474 let private_vis =
474475 ty:: Visibility :: Restricted ( self . tcx . parent_module_from_def_id ( def_id) . into ( ) ) ;
475- if max_vis != Some ( private_vis) {
476- self . changed |= self . effective_visibilities . update (
476+ if max_vis != Some ( private_vis)
477+ && self . effective_visibilities . update (
477478 def_id,
478479 max_vis,
479480 || private_vis,
480481 inherited_effective_vis,
481482 level,
482483 self . tcx ,
483- ) ;
484+ )
485+ {
486+ self . try_append_item_in_queue ( def_id)
487+ }
488+ }
489+
490+ fn try_append_item_in_queue ( & mut self , def_id : LocalDefId ) {
491+ match self . tcx . def_kind ( def_id) {
492+ DefKind :: Enum
493+ | DefKind :: Union
494+ | DefKind :: Struct
495+ | DefKind :: ForeignTy
496+ | DefKind :: TyAlias => {
497+ self . queue . push ( def_id) ;
498+ let items = self . tcx . hir_crate_items ( ( ) ) ;
499+ for item in items. free_items ( ) {
500+ if matches ! ( self . tcx. hir_item( item) . kind, ItemKind :: Impl ( ..) ) {
501+ self . queue . push ( item. owner_id . def_id ) ;
502+ }
503+ }
504+ }
505+ DefKind :: TraitAlias | DefKind :: Trait => {
506+ self . queue . push ( def_id) ;
507+ let impls = self . tcx . all_impls ( def_id. to_def_id ( ) ) ;
508+ for impl_ in impls {
509+ if let Some ( impl_local) = impl_. as_local ( ) {
510+ self . queue . push ( impl_local) ;
511+ }
512+ }
513+ }
514+ DefKind :: ForeignMod
515+ | DefKind :: Const { .. }
516+ | DefKind :: Static { .. }
517+ | DefKind :: Macro ( _)
518+ | DefKind :: Impl { .. }
519+ | DefKind :: AssocTy
520+ | DefKind :: Fn
521+ | DefKind :: Field
522+ | DefKind :: Variant
523+ | DefKind :: AssocFn
524+ | DefKind :: AssocConst { .. }
525+ | DefKind :: TyParam
526+ | DefKind :: AnonConst
527+ | DefKind :: InlineConst
528+ | DefKind :: OpaqueTy
529+ | DefKind :: Closure
530+ | DefKind :: SyntheticCoroutineBody
531+ | DefKind :: ConstParam
532+ | DefKind :: LifetimeParam
533+ | DefKind :: Mod
534+ | DefKind :: Use
535+ | DefKind :: ExternCrate
536+ | DefKind :: GlobalAsm
537+ | DefKind :: Ctor ( ..) => { }
484538 }
485539 }
486540
@@ -680,20 +734,19 @@ impl<'tcx> EmbargoVisitor<'tcx> {
680734 }
681735 }
682736
683- fn check_def_id ( & mut self , owner_id : OwnerId ) {
737+ fn check_def_id ( & mut self , def_id : LocalDefId ) {
684738 // Update levels of nested things and mark all items
685739 // in interfaces of reachable items as reachable.
686- let item_ev = self . get ( owner_id . def_id ) ;
687- match self . tcx . def_kind ( owner_id ) {
740+ let item_ev = self . get ( def_id) ;
741+ match self . tcx . def_kind ( def_id ) {
688742 // The interface is empty, and no nested items.
689743 DefKind :: Use | DefKind :: ExternCrate | DefKind :: GlobalAsm => { }
690744 // The interface is empty, and all nested items are processed by `check_def_id`.
691745 DefKind :: Mod => { }
692746 DefKind :: Macro { .. } => {
693747 if let Some ( item_ev) = item_ev {
694- let ( _, macro_def, _) =
695- self . tcx . hir_expect_item ( owner_id. def_id ) . expect_macro ( ) ;
696- self . update_reachability_from_macro ( owner_id. def_id , macro_def, item_ev) ;
748+ let ( _, macro_def, _) = self . tcx . hir_expect_item ( def_id) . expect_macro ( ) ;
749+ self . update_reachability_from_macro ( def_id, macro_def, item_ev) ;
697750 }
698751 }
699752 DefKind :: ForeignTy
@@ -702,14 +755,14 @@ impl<'tcx> EmbargoVisitor<'tcx> {
702755 | DefKind :: Fn
703756 | DefKind :: TyAlias => {
704757 if let Some ( item_ev) = item_ev {
705- self . reach ( owner_id . def_id , item_ev) . generics ( ) . predicates ( ) . ty ( ) ;
758+ self . reach ( def_id, item_ev) . generics ( ) . predicates ( ) . ty ( ) ;
706759 }
707760 }
708761 DefKind :: Trait => {
709762 if let Some ( item_ev) = item_ev {
710- self . reach ( owner_id . def_id , item_ev) . generics ( ) . predicates ( ) ;
763+ self . reach ( def_id, item_ev) . generics ( ) . predicates ( ) ;
711764
712- for assoc_item in self . tcx . associated_items ( owner_id ) . in_definition_order ( ) {
765+ for assoc_item in self . tcx . associated_items ( def_id ) . in_definition_order ( ) {
713766 let def_id = assoc_item. def_id . expect_local ( ) ;
714767 self . update ( def_id, item_ev, Level :: Reachable ) ;
715768
@@ -719,7 +772,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
719772 }
720773 DefKind :: TraitAlias => {
721774 if let Some ( item_ev) = item_ev {
722- self . reach ( owner_id . def_id , item_ev) . generics ( ) . predicates ( ) ;
775+ self . reach ( def_id, item_ev) . generics ( ) . predicates ( ) ;
723776 }
724777 }
725778 DefKind :: Impl { of_trait } => {
@@ -734,23 +787,23 @@ impl<'tcx> EmbargoVisitor<'tcx> {
734787 // without knowing both "shallow" version of its self type and "shallow" version of
735788 // its trait if it exists (which require reaching the `DefId`s in them).
736789 let item_ev = EffectiveVisibility :: of_impl :: < true > (
737- owner_id . def_id ,
790+ def_id,
738791 of_trait,
739792 self . tcx ,
740793 & self . effective_visibilities ,
741794 ) ;
742795
743- self . update_eff_vis ( owner_id . def_id , item_ev, None , Level :: Direct ) ;
796+ self . update_eff_vis ( def_id, item_ev, None , Level :: Direct ) ;
744797
745798 {
746- let mut reach = self . reach ( owner_id . def_id , item_ev) ;
799+ let mut reach = self . reach ( def_id, item_ev) ;
747800 reach. generics ( ) . predicates ( ) . ty ( ) ;
748801 if of_trait {
749802 reach. trait_ref ( ) ;
750803 }
751804 }
752805
753- for assoc_item in self . tcx . associated_items ( owner_id ) . in_definition_order ( ) {
806+ for assoc_item in self . tcx . associated_items ( def_id ) . in_definition_order ( ) {
754807 let def_id = assoc_item. def_id . expect_local ( ) ;
755808 let max_vis =
756809 if of_trait { None } else { Some ( self . tcx . local_visibility ( def_id) ) } ;
@@ -763,9 +816,9 @@ impl<'tcx> EmbargoVisitor<'tcx> {
763816 }
764817 DefKind :: Enum => {
765818 if let Some ( item_ev) = item_ev {
766- self . reach ( owner_id . def_id , item_ev) . generics ( ) . predicates ( ) ;
819+ self . reach ( def_id, item_ev) . generics ( ) . predicates ( ) ;
767820 }
768- let def = self . tcx . adt_def ( owner_id ) ;
821+ let def = self . tcx . adt_def ( def_id ) ;
769822 for variant in def. variants ( ) {
770823 if let Some ( item_ev) = item_ev {
771824 self . update ( variant. def_id . expect_local ( ) , item_ev, Level :: Reachable ) ;
@@ -783,19 +836,19 @@ impl<'tcx> EmbargoVisitor<'tcx> {
783836 }
784837 // Corner case: if the variant is reachable, but its
785838 // enum is not, make the enum reachable as well.
786- self . reach ( owner_id . def_id , variant_ev) . ty ( ) ;
839+ self . reach ( def_id, variant_ev) . ty ( ) ;
787840 }
788841 if let Some ( ctor_def_id) = variant. ctor_def_id ( ) {
789842 if let Some ( ctor_ev) = self . get ( ctor_def_id. expect_local ( ) ) {
790- self . reach ( owner_id . def_id , ctor_ev) . ty ( ) ;
843+ self . reach ( def_id, ctor_ev) . ty ( ) ;
791844 }
792845 }
793846 }
794847 }
795848 DefKind :: Struct | DefKind :: Union => {
796- let def = self . tcx . adt_def ( owner_id ) . non_enum_variant ( ) ;
849+ let def = self . tcx . adt_def ( def_id ) . non_enum_variant ( ) ;
797850 if let Some ( item_ev) = item_ev {
798- self . reach ( owner_id . def_id , item_ev) . generics ( ) . predicates ( ) ;
851+ self . reach ( def_id, item_ev) . generics ( ) . predicates ( ) ;
799852 for field in & def. fields {
800853 let field = field. did . expect_local ( ) ;
801854 self . update ( field, item_ev, Level :: Reachable ) ;
@@ -809,7 +862,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
809862 self . update ( ctor_def_id. expect_local ( ) , item_ev, Level :: Reachable ) ;
810863 }
811864 if let Some ( ctor_ev) = self . get ( ctor_def_id. expect_local ( ) ) {
812- self . reach ( owner_id . def_id , ctor_ev) . ty ( ) ;
865+ self . reach ( def_id, ctor_ev) . ty ( ) ;
813866 }
814867 }
815868 }
@@ -1816,7 +1869,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18161869 tcx,
18171870 effective_visibilities : tcx. resolutions ( ( ) ) . effective_visibilities . clone ( ) ,
18181871 macro_reachable : Default :: default ( ) ,
1819- changed : false ,
1872+ queue : vec ! [ ] ,
18201873 } ;
18211874
18221875 visitor. effective_visibilities . check_invariants ( tcx) ;
@@ -1868,23 +1921,17 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18681921 . ty ( ) ;
18691922 }
18701923 }
1871-
1872- visitor. changed = false ;
18731924 }
18741925
18751926 let crate_items = tcx. hir_crate_items ( ( ) ) ;
1876- loop {
1877- for id in crate_items. free_items ( ) {
1878- visitor. check_def_id ( id. owner_id ) ;
1879- }
1880- for id in crate_items. foreign_items ( ) {
1881- visitor. check_def_id ( id. owner_id ) ;
1882- }
1883- if visitor. changed {
1884- visitor. changed = false ;
1885- } else {
1886- break ;
1887- }
1927+ for id in crate_items. free_items ( ) {
1928+ visitor. check_def_id ( id. owner_id . def_id ) ;
1929+ }
1930+ for id in crate_items. foreign_items ( ) {
1931+ visitor. check_def_id ( id. owner_id . def_id ) ;
1932+ }
1933+ while let Some ( def_id) = visitor. queue . pop ( ) {
1934+ visitor. check_def_id ( def_id) ;
18881935 }
18891936 visitor. effective_visibilities . check_invariants ( tcx) ;
18901937
0 commit comments