about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-03-02 07:01:15 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-03-02 07:01:15 +0530
commit9d4422e1fc2d579b1f7f28837c2cc78f453d818a (patch)
treea7025bb377ab4fb9b47d15662622cb294f71811d
parent84d8fec9b014975145eb0d9d6ec29216593e10f6 (diff)
parentb6f441d9861868eefd81460e0c3e4295fca12ffe (diff)
downloadrust-9d4422e1fc2d579b1f7f28837c2cc78f453d818a.tar.gz
rust-9d4422e1fc2d579b1f7f28837c2cc78f453d818a.zip
Rollup merge of #31919 - petrochenkov:blockpub, r=nikomatsakis
Closes https://github.com/rust-lang/rust/issues/31776

r? @nikomatsakis
-rw-r--r--src/librustc_privacy/lib.rs85
-rw-r--r--src/test/compile-fail/privacy-sanity.rs50
-rw-r--r--src/test/compile-fail/unnecessary-private.rs27
-rw-r--r--src/test/run-pass/issue-31776.rs64
4 files changed, 97 insertions, 129 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 8908dac7a36..e0ede288523 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1129,43 +1129,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 
 struct SanePrivacyVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    in_block: bool,
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
-    /// We want to visit items in the context of their containing
-    /// module and so forth, so supply a crate for doing a deep walk.
-    fn visit_nested_item(&mut self, item: hir::ItemId) {
-        self.visit_item(self.tcx.map.expect_item(item.id))
-    }
-
     fn visit_item(&mut self, item: &hir::Item) {
         self.check_sane_privacy(item);
-        if self.in_block {
-            self.check_all_inherited(item);
-        }
-
-        let orig_in_block = self.in_block;
-
-        // Modules turn privacy back on, otherwise we inherit
-        self.in_block = if let hir::ItemMod(..) = item.node { false } else { orig_in_block };
-
         intravisit::walk_item(self, item);
-        self.in_block = orig_in_block;
-    }
-
-    fn visit_block(&mut self, b: &'v hir::Block) {
-        let orig_in_block = replace(&mut self.in_block, true);
-        intravisit::walk_block(self, b);
-        self.in_block = orig_in_block;
     }
 }
 
 impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
-    /// Validates all of the visibility qualifiers placed on the item given. This
-    /// ensures that there are no extraneous qualifiers that don't actually do
-    /// anything. In theory these qualifiers wouldn't parse, but that may happen
-    /// later on down the road...
+    /// Validate that items that shouldn't have visibility qualifiers don't have them.
+    /// Such qualifiers can be set by syntax extensions even if the parser doesn't allow them,
+    /// so we check things like variant fields too.
     fn check_sane_privacy(&self, item: &hir::Item) {
         let check_inherited = |sp, vis, note: &str| {
             if vis != hir::Inherited {
@@ -1179,13 +1155,12 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
         };
 
         match item.node {
-            // implementations of traits don't need visibility qualifiers because
-            // that's controlled by having the trait in scope.
             hir::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
                 check_inherited(item.span, item.vis,
                                 "visibility qualifiers have no effect on trait impls");
                 for impl_item in impl_items {
-                    check_inherited(impl_item.span, impl_item.vis, "");
+                    check_inherited(impl_item.span, impl_item.vis,
+                                    "visibility qualifiers have no effect on trait impl items");
                 }
             }
             hir::ItemImpl(_, _, _, None, _, _) => {
@@ -1200,41 +1175,15 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                 check_inherited(item.span, item.vis,
                                 "place qualifiers on individual functions instead");
             }
-            hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemTrait(..) |
-            hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
-            hir::ItemMod(..) | hir::ItemExternCrate(..) |
-            hir::ItemUse(..) | hir::ItemTy(..) => {}
-        }
-    }
-
-    /// When inside of something like a function or a method, visibility has no
-    /// control over anything so this forbids any mention of any visibility
-    fn check_all_inherited(&self, item: &hir::Item) {
-        let check_inherited = |sp, vis| {
-            if vis != hir::Inherited {
-                span_err!(self.tcx.sess, sp, E0447,
-                          "visibility has no effect inside functions or block expressions");
-            }
-        };
-
-        check_inherited(item.span, item.vis);
-        match item.node {
-            hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
-                for impl_item in impl_items {
-                    check_inherited(impl_item.span, impl_item.vis);
-                }
-            }
-            hir::ItemForeignMod(ref fm) => {
-                for fi in &fm.items {
-                    check_inherited(fi.span, fi.vis);
-                }
-            }
-            hir::ItemStruct(ref vdata, _) => {
-                for f in vdata.fields() {
-                    check_inherited(f.span, f.node.kind.visibility());
+            hir::ItemEnum(ref def, _) => {
+                for variant in &def.variants {
+                    for field in variant.node.data.fields() {
+                        check_inherited(field.span, field.node.kind.visibility(),
+                                        "visibility qualifiers have no effect on variant fields");
+                    }
                 }
             }
-            hir::ItemDefaultImpl(..) | hir::ItemEnum(..) | hir::ItemTrait(..) |
+            hir::ItemStruct(..) | hir::ItemTrait(..) |
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemMod(..) | hir::ItemExternCrate(..) |
             hir::ItemUse(..) | hir::ItemTy(..) => {}
@@ -1821,13 +1770,9 @@ pub fn check_crate(tcx: &ty::ctxt,
 
     let krate = tcx.map.krate();
 
-    // Sanity check to make sure that all privacy usage and controls are
-    // reasonable.
-    let mut visitor = SanePrivacyVisitor {
-        tcx: tcx,
-        in_block: false,
-    };
-    intravisit::walk_crate(&mut visitor, krate);
+    // Sanity check to make sure that all privacy usage is reasonable.
+    let mut visitor = SanePrivacyVisitor { tcx: tcx };
+    krate.visit_all_items(&mut visitor);
 
     // Figure out who everyone's parent is
     let mut visitor = ParentVisitor {
diff --git a/src/test/compile-fail/privacy-sanity.rs b/src/test/compile-fail/privacy-sanity.rs
index 336913b8772..063848f62aa 100644
--- a/src/test/compile-fail/privacy-sanity.rs
+++ b/src/test/compile-fail/privacy-sanity.rs
@@ -40,37 +40,30 @@ pub extern "C" { //~ ERROR unnecessary visibility qualifier
 
 const MAIN: u8 = {
     trait MarkerTr {}
-    pub trait Tr { //~ ERROR visibility has no effect inside functions or block
+    pub trait Tr {
         fn f();
         const C: u8;
         type T;
     }
-    pub struct S { //~ ERROR visibility has no effect inside functions or block
-        pub a: u8 //~ ERROR visibility has no effect inside functions or block
+    pub struct S {
+        pub a: u8
     }
-    struct Ts(pub u8); //~ ERROR visibility has no effect inside functions or block
+    struct Ts(pub u8);
 
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
         pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
         pub type T = u8; //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
     }
     pub impl S { //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
-        pub fn f() {} //~ ERROR visibility has no effect inside functions or block
-        pub const C: u8 = 0; //~ ERROR visibility has no effect inside functions or block
-        // pub type T = u8; // ERROR visibility has no effect inside functions or block
+        pub fn f() {}
+        pub const C: u8 = 0;
+        // pub type T = u8;
     }
     pub extern "C" { //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
-        pub fn f(); //~ ERROR visibility has no effect inside functions or block
-        pub static St: u8; //~ ERROR visibility has no effect inside functions or block
+        pub fn f();
+        pub static St: u8;
     }
 
     0
@@ -78,36 +71,29 @@ const MAIN: u8 = {
 
 fn main() {
     trait MarkerTr {}
-    pub trait Tr { //~ ERROR visibility has no effect inside functions or block
+    pub trait Tr {
         fn f();
         const C: u8;
         type T;
     }
-    pub struct S { //~ ERROR visibility has no effect inside functions or block
-        pub a: u8 //~ ERROR visibility has no effect inside functions or block
+    pub struct S {
+        pub a: u8
     }
-    struct Ts(pub u8); //~ ERROR visibility has no effect inside functions or block
+    struct Ts(pub u8);
 
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
         pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
         pub type T = u8; //~ ERROR unnecessary visibility qualifier
-        //~^ ERROR visibility has no effect inside functions or block
     }
     pub impl S { //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
-        pub fn f() {} //~ ERROR visibility has no effect inside functions or block
-        pub const C: u8 = 0; //~ ERROR visibility has no effect inside functions or block
-        // pub type T = u8; // ERROR visibility has no effect inside functions or block
+        pub fn f() {}
+        pub const C: u8 = 0;
+        // pub type T = u8;
     }
     pub extern "C" { //~ ERROR unnecessary visibility qualifier
-    //~^ ERROR visibility has no effect inside functions or block
-        pub fn f(); //~ ERROR visibility has no effect inside functions or block
-        pub static St: u8; //~ ERROR visibility has no effect inside functions or block
+        pub fn f();
+        pub static St: u8;
     }
 }
diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs
deleted file mode 100644
index 113393490cb..00000000000
--- a/src/test/compile-fail/unnecessary-private.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    pub use std::usize; //~ ERROR: visibility has no effect
-    pub struct A; //~ ERROR: visibility has no effect
-    pub enum B {} //~ ERROR: visibility has no effect
-    pub trait C { //~ ERROR: visibility has no effect
-        fn foo(&self) {}
-    }
-    impl A {
-        pub fn foo(&self) {} //~ ERROR: visibility has no effect
-    }
-
-    struct D {
-        pub foo: isize, //~ ERROR: visibility has no effect
-    }
-    pub fn foo() {} //~ ERROR: visibility has no effect
-    pub mod bar {} //~ ERROR: visibility has no effect
-}
diff --git a/src/test/run-pass/issue-31776.rs b/src/test/run-pass/issue-31776.rs
new file mode 100644
index 00000000000..a12e569df2b
--- /dev/null
+++ b/src/test/run-pass/issue-31776.rs
@@ -0,0 +1,64 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Various scenarios in which `pub` is required in blocks
+
+struct S;
+
+mod m {
+    fn f() {
+        impl ::S {
+            pub fn s(&self) {}
+        }
+    }
+}
+
+// ------------------------------------------------------
+
+pub trait Tr {
+    type A;
+}
+pub struct S1;
+
+fn f() {
+    pub struct Z;
+
+    impl ::Tr for ::S1 {
+        type A = Z; // Private-in-public error unless `struct Z` is pub
+    }
+}
+
+// ------------------------------------------------------
+
+trait Tr1 {
+    type A;
+    fn pull(&self) -> Self::A;
+}
+struct S2;
+
+mod m1 {
+    fn f() {
+        struct Z {
+            pub field: u8
+        }
+
+        impl ::Tr1 for ::S2 {
+            type A = Z;
+            fn pull(&self) -> Self::A { Z{field: 10} }
+        }
+    }
+}
+
+// ------------------------------------------------------
+
+fn main() {
+    S.s(); // Privacy error, unless `fn s` is pub
+    let a = S2.pull().field; // Privacy error unless `field: u8` is pub
+}