Skip to content

Commit fc8f4b1

Browse files
committed
Privacy: try use queue instead of fixed-point iteration
1 parent a51f3a8 commit fc8f4b1

1 file changed

Lines changed: 89 additions & 42 deletions

File tree

  • compiler/rustc_privacy/src

compiler/rustc_privacy/src/lib.rs

Lines changed: 89 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ use rustc_ast::visit::{VisitorResult, try_visit};
2020
use rustc_data_structures::fx::FxHashSet;
2121
use rustc_data_structures::intern::Interned;
2222
use rustc_errors::{MultiSpan, listify};
23-
use rustc_hir as hir;
2423
use rustc_hir::def::{DefKind, Res};
2524
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
2625
use 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+
};
2829
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
2930
use rustc_middle::query::Providers;
3031
use 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

442443
struct 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

Comments
 (0)