@@ -11,8 +11,7 @@ use rustc_data_structures::fx::FxHashSet;
11
11
use rustc_errors:: struct_span_err;
12
12
use rustc_hir as hir;
13
13
use rustc_hir:: def:: { DefKind , Res } ;
14
- use rustc_hir:: def_id:: { DefId , LocalDefId , LocalDefIdSet } ;
15
- use rustc_hir:: def_id:: { CRATE_DEF_ID , CRATE_DEF_INDEX , LOCAL_CRATE } ;
14
+ use rustc_hir:: def_id:: { DefId , LocalDefId , LocalDefIdSet , CRATE_DEF_ID } ;
16
15
use rustc_hir:: intravisit:: { self , DeepVisitor , NestedVisitorMap , Visitor } ;
17
16
use rustc_hir:: { AssocItemKind , HirIdSet , Node , PatKind } ;
18
17
use rustc_middle:: bug;
@@ -26,7 +25,7 @@ use rustc_middle::ty::subst::InternalSubsts;
26
25
use rustc_middle:: ty:: { self , Const , GenericParamDefKind , TraitRef , Ty , TyCtxt , TypeFoldable } ;
27
26
use rustc_session:: lint;
28
27
use rustc_span:: hygiene:: Transparency ;
29
- use rustc_span:: symbol:: { kw, sym , Ident } ;
28
+ use rustc_span:: symbol:: { kw, Ident } ;
30
29
use rustc_span:: Span ;
31
30
use rustc_trait_selection:: traits:: const_evaluatable:: { self , AbstractConst } ;
32
31
@@ -436,6 +435,15 @@ impl<'tcx> EmbargoVisitor<'tcx> {
436
435
self . access_levels . map . get ( & def_id) . copied ( )
437
436
}
438
437
438
+ fn update_with_hir_id (
439
+ & mut self ,
440
+ hir_id : hir:: HirId ,
441
+ level : Option < AccessLevel > ,
442
+ ) -> Option < AccessLevel > {
443
+ let def_id = self . tcx . hir ( ) . local_def_id ( hir_id) ;
444
+ self . update ( def_id, level)
445
+ }
446
+
439
447
/// Updates node level and returns the updated level.
440
448
fn update ( & mut self , def_id : LocalDefId , level : Option < AccessLevel > ) -> Option < AccessLevel > {
441
449
let old_level = self . get ( def_id) ;
@@ -623,54 +631,6 @@ impl<'tcx> EmbargoVisitor<'tcx> {
623
631
| DefKind :: Generator => ( ) ,
624
632
}
625
633
}
626
-
627
- /// Given the path segments of an `ItemKind::Use`, then we need
628
- /// to update the visibility of the intermediate use so that it isn't linted
629
- /// by `unreachable_pub`.
630
- ///
631
- /// This isn't trivial as `path.res` has the `DefId` of the eventual target
632
- /// of the use statement not of the next intermediate use statement.
633
- ///
634
- /// To do this, consider the last two segments of the path to our intermediate
635
- /// use statement. We expect the penultimate segment to be a module and the
636
- /// last segment to be the name of the item we are exporting. We can then
637
- /// look at the items contained in the module for the use statement with that
638
- /// name and update that item's visibility.
639
- ///
640
- /// FIXME: This solution won't work with glob imports and doesn't respect
641
- /// namespaces. See <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
642
- fn update_visibility_of_intermediate_use_statements (
643
- & mut self ,
644
- segments : & [ hir:: PathSegment < ' _ > ] ,
645
- ) {
646
- if let [ .., module, segment] = segments {
647
- if let Some ( item) = module
648
- . res
649
- . and_then ( |res| res. mod_def_id ( ) )
650
- // If the module is `self`, i.e. the current crate,
651
- // there will be no corresponding item.
652
- . filter ( |def_id| def_id. index != CRATE_DEF_INDEX || def_id. krate != LOCAL_CRATE )
653
- . and_then ( |def_id| def_id. as_local ( ) )
654
- . map ( |module_hir_id| self . tcx . hir ( ) . expect_item ( module_hir_id) )
655
- {
656
- if let hir:: ItemKind :: Mod ( m) = & item. kind {
657
- for & item_id in m. item_ids {
658
- let item = self . tcx . hir ( ) . item ( item_id) ;
659
- if !self . tcx . hygienic_eq (
660
- segment. ident ,
661
- item. ident ,
662
- item_id. def_id . to_def_id ( ) ,
663
- ) {
664
- continue ;
665
- }
666
- if let hir:: ItemKind :: Use ( ..) = item. kind {
667
- self . update ( item. def_id , Some ( AccessLevel :: Exported ) ) ;
668
- }
669
- }
670
- }
671
- }
672
- }
673
- }
674
634
}
675
635
676
636
impl < ' tcx > Visitor < ' tcx > for EmbargoVisitor < ' tcx > {
@@ -683,120 +643,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
683
643
}
684
644
685
645
fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
686
- let inherited_item_level = match item. kind {
646
+ let item_level = match item. kind {
687
647
hir:: ItemKind :: Impl { .. } => {
688
- Option :: < AccessLevel > :: of_impl ( item. def_id , self . tcx , & self . access_levels )
689
- }
690
- // Only exported `macro_rules!` items are public, but they always are.
691
- hir:: ItemKind :: Macro ( MacroDef { macro_rules : true , .. } ) => {
692
- let def_id = item. def_id . to_def_id ( ) ;
693
- let is_macro_export = self . tcx . has_attr ( def_id, sym:: macro_export) ;
694
- if is_macro_export { Some ( AccessLevel :: Public ) } else { None }
695
- }
696
- // Foreign modules inherit level from parents.
697
- hir:: ItemKind :: ForeignMod { .. } => self . prev_level ,
698
- // Other `pub` items inherit levels from parents.
699
- hir:: ItemKind :: Const ( ..)
700
- | hir:: ItemKind :: Enum ( ..)
701
- | hir:: ItemKind :: ExternCrate ( ..)
702
- | hir:: ItemKind :: GlobalAsm ( ..)
703
- | hir:: ItemKind :: Fn ( ..)
704
- | hir:: ItemKind :: Macro ( ..)
705
- | hir:: ItemKind :: Mod ( ..)
706
- | hir:: ItemKind :: Static ( ..)
707
- | hir:: ItemKind :: Struct ( ..)
708
- | hir:: ItemKind :: Trait ( ..)
709
- | hir:: ItemKind :: TraitAlias ( ..)
710
- | hir:: ItemKind :: OpaqueTy ( ..)
711
- | hir:: ItemKind :: TyAlias ( ..)
712
- | hir:: ItemKind :: Union ( ..)
713
- | hir:: ItemKind :: Use ( ..) => {
714
- if item. vis . node . is_pub ( ) {
715
- self . prev_level
716
- } else {
717
- None
718
- }
648
+ let impl_level =
649
+ Option :: < AccessLevel > :: of_impl ( item. def_id , self . tcx , & self . access_levels ) ;
650
+ self . update ( item. def_id , impl_level)
719
651
}
652
+ _ => self . get ( item. def_id ) ,
720
653
} ;
721
654
722
- // Update level of the item itself.
723
- let item_level = self . update ( item. def_id , inherited_item_level) ;
724
-
725
- // Update levels of nested things.
726
- match item. kind {
727
- hir:: ItemKind :: Enum ( ref def, _) => {
728
- for variant in def. variants {
729
- let variant_level =
730
- self . update ( self . tcx . hir ( ) . local_def_id ( variant. id ) , item_level) ;
731
- if let Some ( ctor_hir_id) = variant. data . ctor_hir_id ( ) {
732
- self . update ( self . tcx . hir ( ) . local_def_id ( ctor_hir_id) , item_level) ;
733
- }
734
- for field in variant. data . fields ( ) {
735
- self . update ( self . tcx . hir ( ) . local_def_id ( field. hir_id ) , variant_level) ;
736
- }
737
- }
738
- }
739
- hir:: ItemKind :: Impl ( ref impl_) => {
740
- for impl_item_ref in impl_. items {
741
- if impl_. of_trait . is_some ( )
742
- || self . tcx . visibility ( impl_item_ref. id . def_id ) == ty:: Visibility :: Public
743
- {
744
- self . update ( impl_item_ref. id . def_id , item_level) ;
745
- }
746
- }
747
- }
748
- hir:: ItemKind :: Trait ( .., trait_item_refs) => {
749
- for trait_item_ref in trait_item_refs {
750
- self . update ( trait_item_ref. id . def_id , item_level) ;
751
- }
752
- }
753
- hir:: ItemKind :: Struct ( ref def, _) | hir:: ItemKind :: Union ( ref def, _) => {
754
- if let Some ( ctor_hir_id) = def. ctor_hir_id ( ) {
755
- self . update ( self . tcx . hir ( ) . local_def_id ( ctor_hir_id) , item_level) ;
756
- }
757
- for field in def. fields ( ) {
758
- if field. vis . node . is_pub ( ) {
759
- self . update ( self . tcx . hir ( ) . local_def_id ( field. hir_id ) , item_level) ;
760
- }
761
- }
762
- }
763
- hir:: ItemKind :: Macro ( ref macro_def) => {
764
- self . update_reachability_from_macro ( item. def_id , macro_def) ;
765
- }
766
- hir:: ItemKind :: ForeignMod { items, .. } => {
767
- for foreign_item in items {
768
- if self . tcx . visibility ( foreign_item. id . def_id ) == ty:: Visibility :: Public {
769
- self . update ( foreign_item. id . def_id , item_level) ;
770
- }
771
- }
772
- }
773
-
774
- hir:: ItemKind :: OpaqueTy ( ..)
775
- | hir:: ItemKind :: Use ( ..)
776
- | hir:: ItemKind :: Static ( ..)
777
- | hir:: ItemKind :: Const ( ..)
778
- | hir:: ItemKind :: GlobalAsm ( ..)
779
- | hir:: ItemKind :: TyAlias ( ..)
780
- | hir:: ItemKind :: Mod ( ..)
781
- | hir:: ItemKind :: TraitAlias ( ..)
782
- | hir:: ItemKind :: Fn ( ..)
783
- | hir:: ItemKind :: ExternCrate ( ..) => { }
784
- }
785
-
786
655
// Mark all items in interfaces of reachable items as reachable.
787
656
match item. kind {
788
657
// The interface is empty.
789
- hir:: ItemKind :: Macro ( .. ) | hir :: ItemKind :: ExternCrate ( ..) => { }
658
+ hir:: ItemKind :: ExternCrate ( ..) => { }
790
659
// All nested items are checked by `visit_item`.
791
660
hir:: ItemKind :: Mod ( ..) => { }
792
- // Re-exports are handled in `visit_mod`. However, in order to avoid looping over
793
- // all of the items of a mod in `visit_mod` looking for use statements, we handle
794
- // making sure that intermediate use statements have their visibilities updated here.
795
- hir:: ItemKind :: Use ( path, _) => {
796
- if item_level. is_some ( ) {
797
- self . update_visibility_of_intermediate_use_statements ( path. segments . as_ref ( ) ) ;
798
- }
799
- }
661
+ hir:: ItemKind :: Use ( ..) => { }
800
662
// The interface is empty.
801
663
hir:: ItemKind :: GlobalAsm ( ..) => { }
802
664
hir:: ItemKind :: OpaqueTy ( ..) => {
@@ -847,6 +709,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
847
709
}
848
710
// Visit everything except for private impl items.
849
711
hir:: ItemKind :: Impl ( ref impl_) => {
712
+ for impl_item_ref in impl_. items {
713
+ if impl_. of_trait . is_some ( )
714
+ || self . tcx . visibility ( impl_item_ref. id . def_id ) == ty:: Visibility :: Public
715
+ {
716
+ self . update ( impl_item_ref. id . def_id , item_level) ;
717
+ }
718
+ }
719
+
850
720
if item_level. is_some ( ) {
851
721
self . reach ( item. def_id , item_level) . generics ( ) . predicates ( ) . ty ( ) . trait_ref ( ) ;
852
722
@@ -861,15 +731,21 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
861
731
}
862
732
}
863
733
}
864
-
865
734
// Visit everything, but enum variants have their own levels.
866
735
hir:: ItemKind :: Enum ( ref def, _) => {
867
736
if item_level. is_some ( ) {
868
737
self . reach ( item. def_id , item_level) . generics ( ) . predicates ( ) ;
869
738
}
739
+
740
+ let enum_level = self . get ( item. def_id ) ;
870
741
for variant in def. variants {
871
- let variant_level = self . get ( self . tcx . hir ( ) . local_def_id ( variant. id ) ) ;
742
+ let variant_level = self . update_with_hir_id ( variant. id , enum_level) ;
743
+
872
744
if variant_level. is_some ( ) {
745
+ if let Some ( ctor_id) = variant. data . ctor_hir_id ( ) {
746
+ self . update_with_hir_id ( ctor_id, variant_level) ;
747
+ }
748
+
873
749
for field in variant. data . fields ( ) {
874
750
self . reach ( self . tcx . hir ( ) . local_def_id ( field. hir_id ) , variant_level)
875
751
. ty ( ) ;
@@ -880,6 +756,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
880
756
}
881
757
}
882
758
}
759
+ hir:: ItemKind :: Macro ( ref macro_def) => {
760
+ self . update_reachability_from_macro ( item. def_id , macro_def) ;
761
+ }
883
762
// Visit everything, but foreign items have their own levels.
884
763
hir:: ItemKind :: ForeignMod { items, .. } => {
885
764
for foreign_item in items {
@@ -920,27 +799,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
920
799
intravisit:: walk_block ( self , b) ;
921
800
self . prev_level = orig_level;
922
801
}
923
-
924
- fn visit_mod ( & mut self , m : & ' tcx hir:: Mod < ' tcx > , _sp : Span , id : hir:: HirId ) {
925
- // This code is here instead of in visit_item so that the
926
- // crate module gets processed as well.
927
- if self . prev_level . is_some ( ) {
928
- let def_id = self . tcx . hir ( ) . local_def_id ( id) ;
929
- if let Some ( exports) = self . tcx . module_reexports ( def_id) {
930
- for export in exports. iter ( ) {
931
- if export. vis . is_public ( ) {
932
- if let Some ( def_id) = export. res . opt_def_id ( ) {
933
- if let Some ( def_id) = def_id. as_local ( ) {
934
- self . update ( def_id, Some ( AccessLevel :: Exported ) ) ;
935
- }
936
- }
937
- }
938
- }
939
- }
940
- }
941
-
942
- intravisit:: walk_mod ( self , m, id) ;
943
- }
944
802
}
945
803
946
804
impl ReachEverythingInTheInterfaceVisitor < ' _ , ' _ > {
@@ -2166,11 +2024,12 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
2166
2024
// items which are reachable from external crates based on visibility.
2167
2025
let mut visitor = EmbargoVisitor {
2168
2026
tcx,
2169
- access_levels : Default :: default ( ) ,
2027
+ access_levels : tcx . resolutions ( ( ) ) . access_levels . clone ( ) ,
2170
2028
macro_reachable : Default :: default ( ) ,
2171
2029
prev_level : Some ( AccessLevel :: Public ) ,
2172
2030
changed : false ,
2173
2031
} ;
2032
+
2174
2033
loop {
2175
2034
tcx. hir ( ) . walk_toplevel_module ( & mut visitor) ;
2176
2035
if visitor. changed {
@@ -2179,7 +2038,6 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
2179
2038
break ;
2180
2039
}
2181
2040
}
2182
- visitor. update ( CRATE_DEF_ID , Some ( AccessLevel :: Public ) ) ;
2183
2041
2184
2042
tcx. arena . alloc ( visitor. access_levels )
2185
2043
}
0 commit comments