Skip to content

Commit 75b44e7

Browse files
committed
Use less HIR to compute effective visibility.
1 parent 498ae9f commit 75b44e7

File tree

1 file changed

+117
-99
lines changed
  • compiler/rustc_privacy/src

1 file changed

+117
-99
lines changed

compiler/rustc_privacy/src/lib.rs

Lines changed: 117 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ use rustc_data_structures::fx::FxHashSet;
2424
use rustc_data_structures::intern::Interned;
2525
use rustc_errors::{MultiSpan, listify};
2626
use rustc_hir::def::{DefKind, Res};
27-
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
27+
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
2828
use rustc_hir::intravisit::{self, InferKind, Visitor};
29-
use rustc_hir::{AmbigArg, ForeignItemId, ItemId, PatKind};
29+
use rustc_hir::{AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind};
3030
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
3131
use rustc_middle::query::Providers;
3232
use rustc_middle::ty::print::PrintTraitRefExt as _;
@@ -636,58 +636,62 @@ impl<'tcx> EmbargoVisitor<'tcx> {
636636
}
637637
}
638638

639-
impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
640-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
639+
impl<'tcx> EmbargoVisitor<'tcx> {
640+
fn check_def_id(&mut self, owner_id: OwnerId) {
641641
// Update levels of nested things and mark all items
642642
// in interfaces of reachable items as reachable.
643-
let item_ev = self.get(item.owner_id.def_id);
644-
match item.kind {
643+
let item_ev = self.get(owner_id.def_id);
644+
match self.tcx.def_kind(owner_id) {
645645
// The interface is empty, and no nested items.
646-
hir::ItemKind::Use(..)
647-
| hir::ItemKind::ExternCrate(..)
648-
| hir::ItemKind::GlobalAsm { .. } => {}
646+
DefKind::Use | DefKind::ExternCrate | DefKind::GlobalAsm => {}
649647
// The interface is empty, and all nested items are processed by `visit_item`.
650-
hir::ItemKind::Mod(..) => {}
651-
hir::ItemKind::Macro(_, macro_def, _) => {
648+
DefKind::Mod => {}
649+
DefKind::Macro { .. } => {
652650
if let Some(item_ev) = item_ev {
653-
self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev);
651+
let (_, macro_def, _) =
652+
self.tcx.hir_expect_item(owner_id.def_id).expect_macro();
653+
self.update_reachability_from_macro(owner_id.def_id, macro_def, item_ev);
654654
}
655655
}
656-
hir::ItemKind::Const(..)
657-
| hir::ItemKind::Static(..)
658-
| hir::ItemKind::Fn { .. }
659-
| hir::ItemKind::TyAlias(..) => {
656+
DefKind::ForeignTy
657+
| DefKind::Const
658+
| DefKind::Static { .. }
659+
| DefKind::Fn
660+
| DefKind::TyAlias => {
660661
if let Some(item_ev) = item_ev {
661-
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
662+
self.reach(owner_id.def_id, item_ev).generics().predicates().ty();
662663
}
663664
}
664-
hir::ItemKind::Trait(.., trait_item_refs) => {
665+
DefKind::Trait => {
665666
if let Some(item_ev) = item_ev {
666-
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
667+
self.reach(owner_id.def_id, item_ev).generics().predicates();
668+
669+
for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
670+
if assoc_item.is_impl_trait_in_trait() {
671+
continue;
672+
}
667673

668-
for trait_item_ref in trait_item_refs {
669-
self.update(trait_item_ref.owner_id.def_id, item_ev, Level::Reachable);
674+
let def_id = assoc_item.def_id.expect_local();
675+
self.update(def_id, item_ev, Level::Reachable);
670676

671677
let tcx = self.tcx;
672-
let mut reach = self.reach(trait_item_ref.owner_id.def_id, item_ev);
678+
let mut reach = self.reach(def_id, item_ev);
673679
reach.generics().predicates();
674680

675-
if let DefKind::AssocTy = tcx.def_kind(trait_item_ref.owner_id)
676-
&& !tcx.defaultness(trait_item_ref.owner_id).has_value()
677-
{
681+
if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() {
678682
// No type to visit.
679683
} else {
680684
reach.ty();
681685
}
682686
}
683687
}
684688
}
685-
hir::ItemKind::TraitAlias(..) => {
689+
DefKind::TraitAlias => {
686690
if let Some(item_ev) = item_ev {
687-
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
691+
self.reach(owner_id.def_id, item_ev).generics().predicates();
688692
}
689693
}
690-
hir::ItemKind::Impl(impl_) => {
694+
DefKind::Impl { of_trait } => {
691695
// Type inference is very smart sometimes. It can make an impl reachable even some
692696
// components of its type or trait are unreachable. E.g. methods of
693697
// `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
@@ -699,85 +703,100 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
699703
// without knowing both "shallow" version of its self type and "shallow" version of
700704
// its trait if it exists (which require reaching the `DefId`s in them).
701705
let item_ev = EffectiveVisibility::of_impl::<true>(
702-
item.owner_id.def_id,
706+
owner_id.def_id,
703707
self.tcx,
704708
&self.effective_visibilities,
705709
);
706710

707-
self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
711+
self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct);
712+
713+
self.reach(owner_id.def_id, item_ev).generics().predicates().ty().trait_ref();
708714

709-
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref();
715+
for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
716+
if assoc_item.is_impl_trait_in_trait() {
717+
continue;
718+
}
710719

711-
for impl_item_ref in impl_.items {
712-
let def_id = impl_item_ref.owner_id.def_id;
720+
let def_id = assoc_item.def_id.expect_local();
713721
let max_vis =
714-
impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
722+
if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
715723
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
716724

717725
if let Some(impl_item_ev) = self.get(def_id) {
718726
self.reach(def_id, impl_item_ev).generics().predicates().ty();
719727
}
720728
}
721729
}
722-
hir::ItemKind::Enum(_, _, ref def) => {
730+
DefKind::Enum => {
723731
if let Some(item_ev) = item_ev {
724-
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
732+
self.reach(owner_id.def_id, item_ev).generics().predicates();
725733
}
726-
for variant in def.variants {
734+
let def = self.tcx.adt_def(owner_id);
735+
for variant in def.variants() {
727736
if let Some(item_ev) = item_ev {
728-
self.update(variant.def_id, item_ev, Level::Reachable);
737+
self.update(variant.def_id.expect_local(), item_ev, Level::Reachable);
729738
}
730739

731-
if let Some(variant_ev) = self.get(variant.def_id) {
732-
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
733-
self.update(ctor_def_id, variant_ev, Level::Reachable);
740+
if let Some(variant_ev) = self.get(variant.def_id.expect_local()) {
741+
if let Some(ctor_def_id) = variant.ctor_def_id() {
742+
self.update(ctor_def_id.expect_local(), variant_ev, Level::Reachable);
734743
}
735744

736-
for field in variant.data.fields() {
737-
self.update(field.def_id, variant_ev, Level::Reachable);
738-
self.reach(field.def_id, variant_ev).ty();
745+
for field in variant.fields.iter() {
746+
let field = field.did.expect_local();
747+
self.update(field, variant_ev, Level::Reachable);
748+
self.reach(field, variant_ev).ty();
739749
}
740750
// Corner case: if the variant is reachable, but its
741751
// enum is not, make the enum reachable as well.
742-
self.reach(item.owner_id.def_id, variant_ev).ty();
752+
self.reach(owner_id.def_id, variant_ev).ty();
743753
}
744-
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
745-
if let Some(ctor_ev) = self.get(ctor_def_id) {
746-
self.reach(item.owner_id.def_id, ctor_ev).ty();
754+
if let Some(ctor_def_id) = variant.ctor_def_id() {
755+
if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
756+
self.reach(owner_id.def_id, ctor_ev).ty();
747757
}
748758
}
749759
}
750760
}
751-
hir::ItemKind::ForeignMod { items, .. } => {
752-
for foreign_item in items {
753-
if let Some(foreign_item_ev) = self.get(foreign_item.owner_id.def_id) {
754-
self.reach(foreign_item.owner_id.def_id, foreign_item_ev)
755-
.generics()
756-
.predicates()
757-
.ty();
758-
}
759-
}
760-
}
761-
hir::ItemKind::Struct(_, _, ref struct_def)
762-
| hir::ItemKind::Union(_, _, ref struct_def) => {
761+
DefKind::Struct | DefKind::Union => {
762+
let def = self.tcx.adt_def(owner_id).non_enum_variant();
763763
if let Some(item_ev) = item_ev {
764-
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
765-
for field in struct_def.fields() {
766-
self.update(field.def_id, item_ev, Level::Reachable);
767-
if let Some(field_ev) = self.get(field.def_id) {
768-
self.reach(field.def_id, field_ev).ty();
764+
self.reach(owner_id.def_id, item_ev).generics().predicates();
765+
for field in def.fields.iter() {
766+
let field = field.did.expect_local();
767+
self.update(field, item_ev, Level::Reachable);
768+
if let Some(field_ev) = self.get(field) {
769+
self.reach(field, field_ev).ty();
769770
}
770771
}
771772
}
772-
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
773+
if let Some(ctor_def_id) = def.ctor_def_id() {
773774
if let Some(item_ev) = item_ev {
774-
self.update(ctor_def_id, item_ev, Level::Reachable);
775+
self.update(ctor_def_id.expect_local(), item_ev, Level::Reachable);
775776
}
776-
if let Some(ctor_ev) = self.get(ctor_def_id) {
777-
self.reach(item.owner_id.def_id, ctor_ev).ty();
777+
if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
778+
self.reach(owner_id.def_id, ctor_ev).ty();
778779
}
779780
}
780781
}
782+
// Contents are checked directly.
783+
DefKind::ForeignMod => {}
784+
DefKind::Field
785+
| DefKind::Variant
786+
| DefKind::AssocFn
787+
| DefKind::AssocTy
788+
| DefKind::AssocConst
789+
| DefKind::TyParam
790+
| DefKind::AnonConst
791+
| DefKind::InlineConst
792+
| DefKind::OpaqueTy
793+
| DefKind::Closure
794+
| DefKind::SyntheticCoroutineBody
795+
| DefKind::ConstParam
796+
| DefKind::LifetimeParam
797+
| DefKind::Ctor(..) => {
798+
bug!("should be checked while checking parent")
799+
}
781800
}
782801
}
783802
}
@@ -838,7 +857,7 @@ pub struct TestReachabilityVisitor<'a, 'tcx> {
838857
}
839858

840859
impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
841-
fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
860+
fn effective_visibility_diagnostic(&self, def_id: LocalDefId) {
842861
if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
843862
let mut error_msg = String::new();
844863
let span = self.tcx.def_span(def_id.to_def_id());
@@ -858,43 +877,35 @@ impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
858877
}
859878
}
860879

861-
impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> {
862-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
863-
self.effective_visibility_diagnostic(item.owner_id.def_id);
880+
impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
881+
fn check_def_id(&self, owner_id: OwnerId) {
882+
self.effective_visibility_diagnostic(owner_id.def_id);
864883

865-
match item.kind {
866-
hir::ItemKind::Enum(_, _, ref def) => {
867-
for variant in def.variants.iter() {
868-
self.effective_visibility_diagnostic(variant.def_id);
869-
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
870-
self.effective_visibility_diagnostic(ctor_def_id);
884+
match self.tcx.def_kind(owner_id) {
885+
DefKind::Enum => {
886+
let def = self.tcx.adt_def(owner_id.def_id);
887+
for variant in def.variants() {
888+
self.effective_visibility_diagnostic(variant.def_id.expect_local());
889+
if let Some(ctor_def_id) = variant.ctor_def_id() {
890+
self.effective_visibility_diagnostic(ctor_def_id.expect_local());
871891
}
872-
for field in variant.data.fields() {
873-
self.effective_visibility_diagnostic(field.def_id);
892+
for field in variant.fields.iter() {
893+
self.effective_visibility_diagnostic(field.did.expect_local());
874894
}
875895
}
876896
}
877-
hir::ItemKind::Struct(_, _, ref def) | hir::ItemKind::Union(_, _, ref def) => {
897+
DefKind::Struct | DefKind::Union => {
898+
let def = self.tcx.adt_def(owner_id.def_id).non_enum_variant();
878899
if let Some(ctor_def_id) = def.ctor_def_id() {
879-
self.effective_visibility_diagnostic(ctor_def_id);
900+
self.effective_visibility_diagnostic(ctor_def_id.expect_local());
880901
}
881-
for field in def.fields() {
882-
self.effective_visibility_diagnostic(field.def_id);
902+
for field in def.fields.iter() {
903+
self.effective_visibility_diagnostic(field.did.expect_local());
883904
}
884905
}
885906
_ => {}
886907
}
887908
}
888-
889-
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
890-
self.effective_visibility_diagnostic(item.owner_id.def_id);
891-
}
892-
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
893-
self.effective_visibility_diagnostic(item.owner_id.def_id);
894-
}
895-
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
896-
self.effective_visibility_diagnostic(item.owner_id.def_id);
897-
}
898909
}
899910

900911
//////////////////////////////////////////////////////////////////////////////////////
@@ -1835,8 +1846,14 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18351846
visitor.changed = false;
18361847
}
18371848

1849+
let crate_items = tcx.hir_crate_items(());
18381850
loop {
1839-
tcx.hir_visit_all_item_likes_in_crate(&mut visitor);
1851+
for id in crate_items.free_items() {
1852+
visitor.check_def_id(id.owner_id);
1853+
}
1854+
for id in crate_items.foreign_items() {
1855+
visitor.check_def_id(id.owner_id);
1856+
}
18401857
if visitor.changed {
18411858
visitor.changed = false;
18421859
} else {
@@ -1845,10 +1862,11 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18451862
}
18461863
visitor.effective_visibilities.check_invariants(tcx);
18471864

1848-
let mut check_visitor =
1865+
let check_visitor =
18491866
TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
1850-
check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID);
1851-
tcx.hir_visit_all_item_likes_in_crate(&mut check_visitor);
1867+
for id in crate_items.owners() {
1868+
check_visitor.check_def_id(id);
1869+
}
18521870

18531871
tcx.arena.alloc(visitor.effective_visibilities)
18541872
}

0 commit comments

Comments
 (0)