1313//! which are available for use externally when compiled as a library.
1414
1515use std:: hashmap:: { HashSet , HashMap } ;
16+ use std:: util;
1617
1718use middle:: resolve;
1819use middle:: ty;
@@ -275,6 +276,7 @@ impl<'self> Visitor<()> for EmbargoVisitor<'self> {
275276struct PrivacyVisitor < ' self > {
276277 tcx : ty:: ctxt ,
277278 curitem : ast:: NodeId ,
279+ in_fn : bool ,
278280
279281 // See comments on the same field in `EmbargoVisitor`.
280282 path_all_public_items : & ' self ExportedItems ,
@@ -688,6 +690,63 @@ impl<'self> PrivacyVisitor<'self> {
688690 }
689691 }
690692 }
693+
694+ /// When inside of something like a function or a method, visibility has no
695+ /// control over anything so this forbids any mention of any visibility
696+ fn check_all_inherited ( & self , item : @ast:: item ) {
697+ let tcx = self . tcx ;
698+ let check_inherited = |sp : Span , vis : ast:: visibility | {
699+ if vis != ast:: inherited {
700+ tcx. sess . span_err ( sp, "visibility has no effect inside functions" ) ;
701+ }
702+ } ;
703+ let check_struct = |def : & @ast:: struct_def | {
704+ for f in def. fields . iter ( ) {
705+ match f. node . kind {
706+ ast:: named_field( _, p) => check_inherited ( f. span , p) ,
707+ ast:: unnamed_field => { }
708+ }
709+ }
710+ } ;
711+ check_inherited ( item. span , item. vis ) ;
712+ match item. node {
713+ ast:: item_impl( _, _, _, ref methods) => {
714+ for m in methods. iter ( ) {
715+ check_inherited ( m. span , m. vis ) ;
716+ }
717+ }
718+ ast:: item_foreign_mod( ref fm) => {
719+ for i in fm. items . iter ( ) {
720+ check_inherited ( i. span , i. vis ) ;
721+ }
722+ }
723+ ast:: item_enum( ref def, _) => {
724+ for v in def. variants . iter ( ) {
725+ check_inherited ( v. span , v. node . vis ) ;
726+
727+ match v. node . kind {
728+ ast:: struct_variant_kind( ref s) => check_struct ( s) ,
729+ ast:: tuple_variant_kind( * ) => { }
730+ }
731+ }
732+ }
733+
734+ ast:: item_struct( ref def, _) => check_struct ( def) ,
735+
736+ ast:: item_trait( _, _, ref methods) => {
737+ for m in methods. iter ( ) {
738+ match * m {
739+ ast:: required( * ) => { }
740+ ast:: provided( ref m) => check_inherited ( m. span , m. vis ) ,
741+ }
742+ }
743+ }
744+
745+ ast:: item_static( * ) |
746+ ast:: item_fn( * ) | ast:: item_mod( * ) | ast:: item_ty( * ) |
747+ ast:: item_mac( * ) => { }
748+ }
749+ }
691750}
692751
693752impl < ' self > Visitor < ( ) > for PrivacyVisitor < ' self > {
@@ -699,12 +758,28 @@ impl<'self> Visitor<()> for PrivacyVisitor<'self> {
699758 }
700759
701760 // Disallow unnecessary visibility qualifiers
702- self . check_sane_privacy ( item) ;
761+ if self . in_fn {
762+ self . check_all_inherited ( item) ;
763+ } else {
764+ self . check_sane_privacy ( item) ;
765+ }
703766
704- let orig_curitem = self . curitem ;
705- self . curitem = item. id ;
767+ let orig_curitem = util:: replace ( & mut self . curitem , item. id ) ;
768+ let orig_in_fn = util:: replace ( & mut self . in_fn , match item. node {
769+ ast:: item_mod( * ) => false , // modules turn privacy back on
770+ _ => self . in_fn , // otherwise we inherit
771+ } ) ;
706772 visit:: walk_item ( self , item, ( ) ) ;
707773 self . curitem = orig_curitem;
774+ self . in_fn = orig_in_fn;
775+ }
776+
777+ fn visit_fn ( & mut self , fk : & visit:: fn_kind , fd : & ast:: fn_decl ,
778+ b : & ast:: Block , s : Span , n : ast:: NodeId , _: ( ) ) {
779+ // This catches both functions and methods
780+ let orig_in_fn = util:: replace ( & mut self . in_fn , true ) ;
781+ visit:: walk_fn ( self , fk, fd, b, s, n, ( ) ) ;
782+ self . in_fn = orig_in_fn;
708783 }
709784
710785 fn visit_expr ( & mut self , expr : @ast:: Expr , _: ( ) ) {
@@ -907,6 +982,7 @@ pub fn check_crate(tcx: ty::ctxt,
907982 {
908983 let mut visitor = PrivacyVisitor {
909984 curitem : ast:: DUMMY_NODE_ID ,
985+ in_fn : false ,
910986 tcx : tcx,
911987 path_all_public_items : & path_all_public_items,
912988 parents : & parents,
0 commit comments