13
13
//! which are available for use externally when compiled as a library.
14
14
15
15
use std:: hashmap:: { HashSet , HashMap } ;
16
+ use std:: util;
16
17
17
18
use middle:: resolve;
18
19
use middle:: ty;
@@ -275,6 +276,7 @@ impl<'self> Visitor<()> for EmbargoVisitor<'self> {
275
276
struct PrivacyVisitor < ' self > {
276
277
tcx : ty:: ctxt ,
277
278
curitem : ast:: NodeId ,
279
+ in_fn : bool ,
278
280
279
281
// See comments on the same field in `EmbargoVisitor`.
280
282
path_all_public_items : & ' self ExportedItems ,
@@ -688,6 +690,63 @@ impl<'self> PrivacyVisitor<'self> {
688
690
}
689
691
}
690
692
}
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
+ }
691
750
}
692
751
693
752
impl < ' self > Visitor < ( ) > for PrivacyVisitor < ' self > {
@@ -699,12 +758,28 @@ impl<'self> Visitor<()> for PrivacyVisitor<'self> {
699
758
}
700
759
701
760
// 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
+ }
703
766
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
+ } ) ;
706
772
visit:: walk_item ( self , item, ( ) ) ;
707
773
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;
708
783
}
709
784
710
785
fn visit_expr ( & mut self , expr : @ast:: Expr , _: ( ) ) {
@@ -907,6 +982,7 @@ pub fn check_crate(tcx: ty::ctxt,
907
982
{
908
983
let mut visitor = PrivacyVisitor {
909
984
curitem : ast:: DUMMY_NODE_ID ,
985
+ in_fn : false ,
910
986
tcx : tcx,
911
987
path_all_public_items : & path_all_public_items,
912
988
parents : & parents,
0 commit comments