@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
3030use rustc_middle:: ty:: { TraitRef , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
3131use rustc_session:: lint;
3232use rustc_span:: hygiene:: Transparency ;
33- use rustc_span:: symbol:: { kw, Ident } ;
33+ use rustc_span:: symbol:: { kw, sym , Ident } ;
3434use rustc_span:: Span ;
3535
3636use std:: marker:: PhantomData ;
@@ -39,7 +39,8 @@ use std::{cmp, fmt, mem};
3939
4040use errors:: {
4141 FieldIsPrivate , FieldIsPrivateLabel , FromPrivateDependencyInPublicInterface , InPublicInterface ,
42- InPublicInterfaceTraits , ItemIsPrivate , PrivateInPublicLint , UnnamedItemIsPrivate ,
42+ InPublicInterfaceTraits , ItemIsPrivate , PrivateInPublicLint , ReportAccessLevel ,
43+ UnnamedItemIsPrivate ,
4344} ;
4445
4546////////////////////////////////////////////////////////////////////////////////
@@ -904,6 +905,60 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
904905 }
905906}
906907
908+ ////////////////////////////////////////////////////////////////////////////////
909+ /// Visitor, used for AccessLevels table checking
910+ ////////////////////////////////////////////////////////////////////////////////
911+ pub struct TestReachabilityVisitor < ' tcx > {
912+ tcx : TyCtxt < ' tcx > ,
913+ access_levels : & ' tcx AccessLevels ,
914+ }
915+
916+ impl < ' tcx > TestReachabilityVisitor < ' tcx > {
917+ fn access_level_diagnostic ( & mut self , def_id : LocalDefId ) {
918+ if self . tcx . has_attr ( def_id. to_def_id ( ) , sym:: rustc_access_level) {
919+ let access_level = format ! ( "{:?}" , self . access_levels. map. get( & def_id) ) ;
920+ let span = self . tcx . def_span ( def_id. to_def_id ( ) ) ;
921+ self . tcx . sess . emit_err ( ReportAccessLevel { span, descr : access_level } ) ;
922+ }
923+ }
924+ }
925+
926+ impl < ' tcx > Visitor < ' tcx > for TestReachabilityVisitor < ' tcx > {
927+ fn visit_item ( & mut self , item : & ' tcx hir:: Item < ' tcx > ) {
928+ self . access_level_diagnostic ( item. def_id ) ;
929+
930+ match item. kind {
931+ hir:: ItemKind :: Enum ( ref def, _) => {
932+ for variant in def. variants . iter ( ) {
933+ let variant_id = self . tcx . hir ( ) . local_def_id ( variant. id ) ;
934+ self . access_level_diagnostic ( variant_id) ;
935+ for field in variant. data . fields ( ) {
936+ let def_id = self . tcx . hir ( ) . local_def_id ( field. hir_id ) ;
937+ self . access_level_diagnostic ( def_id) ;
938+ }
939+ }
940+ }
941+ hir:: ItemKind :: Struct ( ref def, _) | hir:: ItemKind :: Union ( ref def, _) => {
942+ for field in def. fields ( ) {
943+ let def_id = self . tcx . hir ( ) . local_def_id ( field. hir_id ) ;
944+ self . access_level_diagnostic ( def_id) ;
945+ }
946+ }
947+ _ => { }
948+ }
949+ }
950+
951+ fn visit_trait_item ( & mut self , item : & ' tcx hir:: TraitItem < ' tcx > ) {
952+ self . access_level_diagnostic ( item. def_id ) ;
953+ }
954+ fn visit_impl_item ( & mut self , item : & ' tcx hir:: ImplItem < ' tcx > ) {
955+ self . access_level_diagnostic ( item. def_id ) ;
956+ }
957+ fn visit_foreign_item ( & mut self , item : & ' tcx hir:: ForeignItem < ' tcx > ) {
958+ self . access_level_diagnostic ( item. def_id ) ;
959+ }
960+ }
961+
907962//////////////////////////////////////////////////////////////////////////////////////
908963/// Name privacy visitor, checks privacy and reports violations.
909964/// Most of name privacy checks are performed during the main resolution phase,
@@ -2043,6 +2098,10 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
20432098 }
20442099 }
20452100
2101+ let mut check_visitor =
2102+ TestReachabilityVisitor { tcx, access_levels : & tcx. resolutions ( ( ) ) . access_levels } ;
2103+ tcx. hir ( ) . visit_all_item_likes_in_crate ( & mut check_visitor) ;
2104+
20462105 tcx. arena . alloc ( visitor. access_levels )
20472106}
20482107
0 commit comments