about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-02-27 11:20:50 -0800
committerPatrick Walton <pcwalton@mimiga.net>2013-02-28 11:32:26 -0800
commit09a2b4e5992a0508c6ea91c030ccee11151f67ac (patch)
tree1f2ef67e3def0f64226cc3220a0534bda13d425b
parent107bf96ff0dcc427c1842ffb232d29afaea53ca5 (diff)
downloadrust-09a2b4e5992a0508c6ea91c030ccee11151f67ac.tar.gz
rust-09a2b4e5992a0508c6ea91c030ccee11151f67ac.zip
librustc: Make methods private if the impl is private
-rw-r--r--src/libcore/dvec.rs23
-rw-r--r--src/librustc/middle/privacy.rs38
-rw-r--r--src/test/compile-fail/private-method-inherited.rs15
3 files changed, 63 insertions, 13 deletions
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs
index 6c7c195b9d3..1fef4ad42f1 100644
--- a/src/libcore/dvec.rs
+++ b/src/libcore/dvec.rs
@@ -93,17 +93,6 @@ priv impl<A> DVec<A> {
     }
 
     #[inline(always)]
-    fn check_out<B>(f: &fn(v: ~[A]) -> B) -> B {
-        unsafe {
-            let mut data = cast::reinterpret_cast(&null::<()>());
-            data <-> self.data;
-            let data_ptr: *() = cast::reinterpret_cast(&data);
-            if data_ptr.is_null() { fail!(~"Recursive use of dvec"); }
-            return f(data);
-        }
-    }
-
-    #[inline(always)]
     fn give_back(data: ~[A]) {
         unsafe {
             self.data = data;
@@ -118,6 +107,18 @@ priv impl<A> DVec<A> {
 // almost nothing works without the copy bound due to limitations
 // around closures.
 pub impl<A> DVec<A> {
+    // FIXME (#3758): This should not need to be public.
+    #[inline(always)]
+    fn check_out<B>(f: &fn(v: ~[A]) -> B) -> B {
+        unsafe {
+            let mut data = cast::reinterpret_cast(&null::<()>());
+            data <-> self.data;
+            let data_ptr: *() = cast::reinterpret_cast(&data);
+            if data_ptr.is_null() { fail!(~"Recursive use of dvec"); }
+            return f(data);
+        }
+    }
+
     /// Reserves space for N elements
     fn reserve(count: uint) {
         vec::reserve(&mut self.data, count)
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 3ec1cf3a705..712037720d5 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -25,7 +25,7 @@ use core::util::ignore;
 use syntax::ast::{def_variant, expr_field, expr_method_call, expr_struct};
 use syntax::ast::{expr_unary, ident, item_struct, item_enum, item_impl};
 use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private};
-use syntax::ast::{provided, required};
+use syntax::ast::{provided, public, required};
 use syntax::ast;
 use syntax::ast_map::{node_item, node_method};
 use syntax::ast_map;
@@ -107,7 +107,41 @@ pub fn check_crate(tcx: ty::ctxt,
                 if method_id.crate == local_crate {
                     match tcx.items.find(&method_id.node) {
                         Some(node_method(method, impl_id, _)) => {
-                            if method.vis == private &&
+                            let mut is_private = false;
+                            if method.vis == private {
+                                is_private = true;
+                            } else {
+                                // Look up the enclosing impl.
+                                if impl_id.crate != local_crate {
+                                    tcx.sess.span_bug(span,
+                                                      ~"local method isn't \
+                                                        in local impl?!");
+                                }
+
+                                match tcx.items.find(&impl_id.node) {
+                                    Some(node_item(item, _)) => {
+                                        match item.node {
+                                            item_impl(_, None, _, _) 
+                                                    if item.vis != public => {
+                                                is_private = true;
+                                            }
+                                            _ => {}
+                                        }
+                                    }
+                                    Some(_) => {
+                                        tcx.sess.span_bug(span,
+                                                          ~"impl wasn't an \
+                                                            item?!");
+                                    }
+                                    None => {
+                                        tcx.sess.span_bug(span,
+                                                          ~"impl wasn't in \
+                                                            AST map?!");
+                                    }
+                                }
+                            }
+
+                            if is_private &&
                                     (impl_id.crate != local_crate ||
                                      !privileged_items
                                      .contains(&(impl_id.node))) {
diff --git a/src/test/compile-fail/private-method-inherited.rs b/src/test/compile-fail/private-method-inherited.rs
new file mode 100644
index 00000000000..7b64623e16c
--- /dev/null
+++ b/src/test/compile-fail/private-method-inherited.rs
@@ -0,0 +1,15 @@
+// Tests that inherited visibility applies to methods.
+
+mod a {
+    pub struct Foo;
+
+    impl Foo {
+        fn f(self) {}
+    }
+}
+
+fn main() {
+    let x = a::Foo;
+    x.f();  //~ ERROR method `f` is private
+}
+