about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_metadata/encoder.rs8
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs22
-rw-r--r--src/test/compile-fail/auxiliary/privacy-struct-ctor.rs21
-rw-r--r--src/test/compile-fail/privacy-struct-ctor.rs42
4 files changed, 83 insertions, 10 deletions
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 028555d1df8..b9c2f0622b6 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -396,10 +396,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
         let struct_vis = &tcx.hir.expect_item(struct_id).vis;
+        let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
+        for field in &variant.fields {
+            if ctor_vis.is_at_least(field.vis, tcx) {
+                ctor_vis = field.vis;
+            }
+        }
 
         Entry {
             kind: EntryKind::Struct(self.lazy(&data)),
-            visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)),
+            visibility: self.lazy(&ctor_vis),
             span: self.lazy(&tcx.def_span(def_id)),
             attributes: LazySeq::empty(),
             children: LazySeq::empty(),
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f74af416cde..f144be7996a 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -327,21 +327,25 @@ impl<'a> Resolver<'a> {
                 let def = Def::Struct(self.definitions.local_def_id(item.id));
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
 
-                // If this is a tuple or unit struct, define a name
-                // in the value namespace as well.
-                if !struct_def.is_struct() {
-                    let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
-                                                   CtorKind::from_ast(struct_def));
-                    self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion));
-                }
-
                 // Record field names for error reporting.
+                let mut ctor_vis = vis;
                 let field_names = struct_def.fields().iter().filter_map(|field| {
-                    self.resolve_visibility(&field.vis);
+                    let field_vis = self.resolve_visibility(&field.vis);
+                    if ctor_vis.is_at_least(field_vis, &*self) {
+                        ctor_vis = field_vis;
+                    }
                     field.ident.map(|ident| ident.name)
                 }).collect();
                 let item_def_id = self.definitions.local_def_id(item.id);
                 self.insert_field_names(item_def_id, field_names);
+
+                // If this is a tuple or unit struct, define a name
+                // in the value namespace as well.
+                if !struct_def.is_struct() {
+                    let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
+                                                   CtorKind::from_ast(struct_def));
+                    self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
+                }
             }
 
             ItemKind::Union(ref vdata, _) => {
diff --git a/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs
new file mode 100644
index 00000000000..f190f5dd053
--- /dev/null
+++ b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs
@@ -0,0 +1,21 @@
+// 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.
+
+#![feature(pub_restricted)]
+
+pub mod m {
+    pub struct S(u8);
+
+    pub mod n {
+        pub(m) struct Z(pub(m::n) u8);
+    }
+}
+
+pub use m::S;
diff --git a/src/test/compile-fail/privacy-struct-ctor.rs b/src/test/compile-fail/privacy-struct-ctor.rs
new file mode 100644
index 00000000000..13a04f49014
--- /dev/null
+++ b/src/test/compile-fail/privacy-struct-ctor.rs
@@ -0,0 +1,42 @@
+// 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.
+
+// aux-build:privacy-struct-ctor.rs
+
+#![feature(pub_restricted)]
+
+extern crate privacy_struct_ctor as xcrate;
+
+mod m {
+    pub struct S(u8);
+
+    pub mod n {
+        pub(m) struct Z(pub(m::n) u8);
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z; //~ ERROR tuple struct `Z` is private
+        Z; //~ ERROR expected value, found struct `Z`
+    }
+}
+
+use m::S; // OK, only the type is imported
+
+fn main() {
+    m::S; //~ ERROR tuple struct `S` is private
+    S; //~ ERROR expected value, found struct `S`
+    m::n::Z; //~ ERROR tuple struct `Z` is private
+
+    xcrate::m::S; //~ ERROR tuple struct `S` is private
+    xcrate::S; //~ ERROR expected value, found struct `xcrate::S`
+    xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+}