Skip to content

Commit 63e1327

Browse files
committed
Use less HIR to compute effective visibility.
1 parent adcb3d3 commit 63e1327

File tree

1 file changed

+119
-101
lines changed
  • compiler/rustc_privacy/src

1 file changed

+119
-101
lines changed

compiler/rustc_privacy/src/lib.rs

Lines changed: 119 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ use rustc_errors::{MultiSpan, listify};
2626
use rustc_hir as hir;
2727
use rustc_hir::attrs::AttributeKind;
2828
use rustc_hir::def::{DefKind, Res};
29-
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
29+
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
3030
use rustc_hir::intravisit::{self, InferKind, Visitor};
31-
use rustc_hir::{AmbigArg, ForeignItemId, ItemId, PatKind, find_attr};
31+
use rustc_hir::{AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr};
3232
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
3333
use rustc_middle::query::Providers;
3434
use rustc_middle::ty::print::PrintTraitRefExt as _;
@@ -599,7 +599,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
599599
DefKind::Struct | DefKind::Union => {
600600
// While structs and unions have type privacy, their fields do not.
601601
let struct_def = self.tcx.adt_def(def_id);
602-
for field in struct_def.non_enum_variant().fields.iter() {
602+
for field in &struct_def.non_enum_variant().fields {
603603
let def_id = field.did.expect_local();
604604
let field_vis = self.tcx.local_visibility(def_id);
605605
if field_vis.is_accessible_from(module, self.tcx) {
@@ -637,58 +637,62 @@ impl<'tcx> EmbargoVisitor<'tcx> {
637637
}
638638
}
639639

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

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

672678
let tcx = self.tcx;
673-
let mut reach = self.reach(trait_item_ref.owner_id.def_id, item_ev);
679+
let mut reach = self.reach(def_id, item_ev);
674680
reach.generics().predicates();
675681

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

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

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

712-
for impl_item_ref in impl_.items {
713-
let def_id = impl_item_ref.owner_id.def_id;
721+
let def_id = assoc_item.def_id.expect_local();
714722
let max_vis =
715-
impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
723+
if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
716724
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
717725

718726
if let Some(impl_item_ev) = self.get(def_id) {
719727
self.reach(def_id, impl_item_ev).generics().predicates().ty();
720728
}
721729
}
722730
}
723-
hir::ItemKind::Enum(_, _, ref def) => {
731+
DefKind::Enum => {
724732
if let Some(item_ev) = item_ev {
725-
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
733+
self.reach(owner_id.def_id, item_ev).generics().predicates();
726734
}
727-
for variant in def.variants {
735+
let def = self.tcx.adt_def(owner_id);
736+
for variant in def.variants() {
728737
if let Some(item_ev) = item_ev {
729-
self.update(variant.def_id, item_ev, Level::Reachable);
738+
self.update(variant.def_id.expect_local(), item_ev, Level::Reachable);
730739
}
731740

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

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

841860
impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
842-
fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
861+
fn effective_visibility_diagnostic(&self, def_id: LocalDefId) {
843862
if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
844863
let mut error_msg = String::new();
845864
let span = self.tcx.def_span(def_id.to_def_id());
@@ -859,43 +878,35 @@ impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
859878
}
860879
}
861880

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

866-
match item.kind {
867-
hir::ItemKind::Enum(_, _, ref def) => {
868-
for variant in def.variants.iter() {
869-
self.effective_visibility_diagnostic(variant.def_id);
870-
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
871-
self.effective_visibility_diagnostic(ctor_def_id);
885+
match self.tcx.def_kind(owner_id) {
886+
DefKind::Enum => {
887+
let def = self.tcx.adt_def(owner_id.def_id);
888+
for variant in def.variants() {
889+
self.effective_visibility_diagnostic(variant.def_id.expect_local());
890+
if let Some(ctor_def_id) = variant.ctor_def_id() {
891+
self.effective_visibility_diagnostic(ctor_def_id.expect_local());
872892
}
873-
for field in variant.data.fields() {
874-
self.effective_visibility_diagnostic(field.def_id);
893+
for field in &variant.fields {
894+
self.effective_visibility_diagnostic(field.did.expect_local());
875895
}
876896
}
877897
}
878-
hir::ItemKind::Struct(_, _, ref def) | hir::ItemKind::Union(_, _, ref def) => {
898+
DefKind::Struct | DefKind::Union => {
899+
let def = self.tcx.adt_def(owner_id.def_id).non_enum_variant();
879900
if let Some(ctor_def_id) = def.ctor_def_id() {
880-
self.effective_visibility_diagnostic(ctor_def_id);
901+
self.effective_visibility_diagnostic(ctor_def_id.expect_local());
881902
}
882-
for field in def.fields() {
883-
self.effective_visibility_diagnostic(field.def_id);
903+
for field in &def.fields {
904+
self.effective_visibility_diagnostic(field.did.expect_local());
884905
}
885906
}
886907
_ => {}
887908
}
888909
}
889-
890-
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
891-
self.effective_visibility_diagnostic(item.owner_id.def_id);
892-
}
893-
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
894-
self.effective_visibility_diagnostic(item.owner_id.def_id);
895-
}
896-
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
897-
self.effective_visibility_diagnostic(item.owner_id.def_id);
898-
}
899910
}
900911

901912
//////////////////////////////////////////////////////////////////////////////////////
@@ -1836,8 +1847,14 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18361847
visitor.changed = false;
18371848
}
18381849

1850+
let crate_items = tcx.hir_crate_items(());
18391851
loop {
1840-
tcx.hir_visit_all_item_likes_in_crate(&mut visitor);
1852+
for id in crate_items.free_items() {
1853+
visitor.check_def_id(id.owner_id);
1854+
}
1855+
for id in crate_items.foreign_items() {
1856+
visitor.check_def_id(id.owner_id);
1857+
}
18411858
if visitor.changed {
18421859
visitor.changed = false;
18431860
} else {
@@ -1846,10 +1863,11 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
18461863
}
18471864
visitor.effective_visibilities.check_invariants(tcx);
18481865

1849-
let mut check_visitor =
1866+
let check_visitor =
18501867
TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
1851-
check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID);
1852-
tcx.hir_visit_all_item_likes_in_crate(&mut check_visitor);
1868+
for id in crate_items.owners() {
1869+
check_visitor.check_def_id(id);
1870+
}
18531871

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

0 commit comments

Comments
 (0)