about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-03-02 02:40:07 +0000
committerbors <bors@rust-lang.org>2016-03-02 02:40:07 +0000
commit0400d929e8626192ba97b4ec12e52aabc8b476d5 (patch)
tree1d76a2732d288f0076f65b618e3ce17c9411e340 /src
parent339a409bfdb6c1e9b280388b5d8d9e898217840f (diff)
parentb515bb3b6b6c50539f81bd6e3a1c3c9d92f43e40 (diff)
downloadrust-0400d929e8626192ba97b4ec12e52aabc8b476d5.tar.gz
rust-0400d929e8626192ba97b4ec12e52aabc8b476d5.zip
Auto merge of #32001 - Manishearth:rollup, r=Manishearth
- Successful merges: #31919, #31982, #31985, #31989, #31999
- Failed merges:
Diffstat (limited to 'src')
-rw-r--r--src/libcollectionstest/str.rs13
-rw-r--r--src/libcore/cell.rs6
-rw-r--r--src/libcore/slice.rs8
-rw-r--r--src/libcore/str/mod.rs2
-rw-r--r--src/libcore/str/pattern.rs2
-rw-r--r--src/librustc_privacy/lib.rs85
-rw-r--r--src/libstd/build.rs2
-rw-r--r--src/libstd/sync/mpsc/mod.rs6
-rw-r--r--src/test/compile-fail/comm-not-freeze-receiver.rs17
-rw-r--r--src/test/compile-fail/comm-not-freeze.rs17
-rw-r--r--src/test/compile-fail/no_share-rc.rs20
-rw-r--r--src/test/compile-fail/not-sync.rs34
-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
15 files changed, 163 insertions, 190 deletions
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 25457043a9d..b84b37dbf75 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -1508,6 +1508,19 @@ generate_iterator_test! {
     with str::rsplitn;
 }
 
+#[test]
+fn different_str_pattern_forwarding_lifetimes() {
+    use std::str::pattern::Pattern;
+
+    fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
+        for _ in 0..3 {
+            "asdf".find(&p);
+        }
+    }
+
+    foo::<&str>("x");
+}
+
 mod bench {
     use test::{Bencher, black_box};
 
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 255c846244b..144adde12e4 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -242,6 +242,9 @@ impl<T:Copy> Cell<T> {
 unsafe impl<T> Send for Cell<T> where T: Send {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl<T> !Sync for Cell<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T:Copy> Clone for Cell<T> {
     #[inline]
     fn clone(&self) -> Cell<T> {
@@ -462,6 +465,9 @@ impl<T: ?Sized> RefCell<T> {
 unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> !Sync for RefCell<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for RefCell<T> {
     #[inline]
     fn clone(&self) -> RefCell<T> {
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index afda70f4fcc..fb15533f33c 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -285,12 +285,12 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked(&self, index: usize) -> &T {
-        &*(self.repr().data.offset(index as isize))
+        &*(self.as_ptr().offset(index as isize))
     }
 
     #[inline]
     fn as_ptr(&self) -> *const T {
-        self.repr().data
+        self as *const [T] as *const T
     }
 
     fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize> where
@@ -448,12 +448,12 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
-        &mut *(self.repr().data as *mut T).offset(index as isize)
+        &mut *self.as_mut_ptr().offset(index as isize)
     }
 
     #[inline]
     fn as_mut_ptr(&mut self) -> *mut T {
-        self.repr().data as *mut T
+        self as *mut [T] as *mut T
     }
 
     #[inline]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 4d367cfd432..a555b859291 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1894,7 +1894,7 @@ impl StrExt for str {
 
     #[inline]
     fn as_ptr(&self) -> *const u8 {
-        self.repr().data
+        self as *const str as *const u8
     }
 
     #[inline]
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 29130100e99..abad29cb775 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -492,7 +492,7 @@ impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
 /////////////////////////////////////////////////////////////////////////////
 
 /// Delegates to the `&str` impl.
-impl<'a, 'b> Pattern<'a> for &'b &'b str {
+impl<'a, 'b, 'c> Pattern<'a> for &'c &'b str {
     pattern_methods!(StrSearcher<'a, 'b>, |&s| s, |s| s);
 }
 
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/libstd/build.rs b/src/libstd/build.rs
index 8fb49a1be4e..a1144a964fd 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -23,7 +23,7 @@ fn main() {
 
     let target = env::var("TARGET").unwrap();
     let host = env::var("HOST").unwrap();
-    if !target.contains("apple") && !target.contains("msvc") {
+    if !target.contains("apple") && !target.contains("msvc") && !target.contains("emscripten"){
         build_libbacktrace(&host, &target);
     }
 
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index fadca390986..dbcc2bc95bc 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -299,6 +299,9 @@ pub struct Receiver<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Send> Send for Receiver<T> { }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> !Sync for Receiver<T> { }
+
 /// An iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
@@ -327,6 +330,9 @@ pub struct Sender<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Send> Send for Sender<T> { }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> !Sync for Sender<T> { }
+
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one thread, but it can be cloned to send to other threads.
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/compile-fail/comm-not-freeze-receiver.rs b/src/test/compile-fail/comm-not-freeze-receiver.rs
deleted file mode 100644
index 305acfec401..00000000000
--- a/src/test/compile-fail/comm-not-freeze-receiver.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 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.
-
-use std::sync::mpsc::Receiver;
-
-fn test<T: Sync>() {}
-
-fn main() {
-    test::<Receiver<isize>>();   //~ ERROR: `core::marker::Sync` is not implemented
-}
diff --git a/src/test/compile-fail/comm-not-freeze.rs b/src/test/compile-fail/comm-not-freeze.rs
deleted file mode 100644
index de2c96920c3..00000000000
--- a/src/test/compile-fail/comm-not-freeze.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 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.
-
-use std::sync::mpsc::Sender;
-
-fn test<T: Sync>() {}
-
-fn main() {
-    test::<Sender<isize>>();     //~ ERROR: `core::marker::Sync` is not implemented
-}
diff --git a/src/test/compile-fail/no_share-rc.rs b/src/test/compile-fail/no_share-rc.rs
deleted file mode 100644
index 4bc3442871f..00000000000
--- a/src/test/compile-fail/no_share-rc.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 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.
-
-use std::rc::Rc;
-use std::cell::RefCell;
-
-fn bar<T: Sync>(_: T) {}
-
-fn main() {
-    let x = Rc::new(RefCell::new(5));
-    bar(x);
-    //~^ ERROR the trait `core::marker::Sync` is not implemented
-}
diff --git a/src/test/compile-fail/not-sync.rs b/src/test/compile-fail/not-sync.rs
new file mode 100644
index 00000000000..a60138c6e1f
--- /dev/null
+++ b/src/test/compile-fail/not-sync.rs
@@ -0,0 +1,34 @@
+// 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.
+
+use std::cell::{Cell, RefCell};
+use std::rc::{Rc, Weak};
+use std::sync::mpsc::{Receiver, Sender, SyncSender};
+
+fn test<T: Sync>() {}
+
+fn main() {
+    test::<Cell<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `core::cell::Cell<i32>`
+    test::<RefCell<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `core::cell::RefCell<i32>`
+
+    test::<Rc<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `alloc::rc::Rc<i32>`
+    test::<Weak<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `alloc::rc::Weak<i32>`
+
+    test::<Receiver<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `std::sync::mpsc::Receiver<i32>`
+    test::<Sender<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `std::sync::mpsc::Sender<i32>`
+    test::<SyncSender<i32>>();
+    //~^ ERROR marker::Sync` is not implemented for the type `std::sync::mpsc::SyncSender<i32>`
+}
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
+}