about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/rustc/driver/driver.rs3
-rw-r--r--src/rustc/middle/privacy.rs75
-rw-r--r--src/rustc/middle/ty.rs4
-rw-r--r--src/rustc/middle/typeck.rs5
-rw-r--r--src/rustc/middle/typeck/check.rs16
-rw-r--r--src/rustc/rustc.rc1
-rw-r--r--src/test/compile-fail/private-class-field.rs15
-rw-r--r--src/test/compile-fail/private-struct-field-cross-crate.rs (renamed from src/test/compile-fail/private-class-field-cross-crate.rs)3
-rw-r--r--src/test/compile-fail/private-struct-field.rs14
9 files changed, 98 insertions, 38 deletions
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 345678bb661..9c6a168d10f 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -221,6 +221,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
 
     if upto == cu_typeck { return {crate: crate, tcx: Some(ty_cx)}; }
 
+    time(time_passes, ~"privacy checking", ||
+        middle::privacy::check_crate(ty_cx, crate));
+
     time(time_passes, ~"loop checking", ||
         middle::check_loop::check_crate(ty_cx, crate));
 
diff --git a/src/rustc/middle/privacy.rs b/src/rustc/middle/privacy.rs
new file mode 100644
index 00000000000..83c341c609a
--- /dev/null
+++ b/src/rustc/middle/privacy.rs
@@ -0,0 +1,75 @@
+// A pass that checks to make sure private fields and methods aren't used
+// outside their scopes.
+
+use /*mod*/ syntax::ast;
+use /*mod*/ syntax::visit;
+use syntax::ast::{expr_field, ident, item_class, local_crate, node_id};
+use syntax::ast::{private};
+use ty::ty_class;
+
+use core::util::ignore;
+use dvec::DVec;
+use send_map::linear::LinearMap;
+
+fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
+    let privileged_structs = @DVec();
+
+    let add_privileged_structs = |items: &[@ast::item]| {
+        let mut count = 0;
+        for items.each |item| {
+            match item.node {
+                item_class(*) => {
+                    privileged_structs.push(item.id);
+                    count += 1;
+                }
+                _ => {}
+            }
+        }
+        count
+    };
+
+    let visitor = visit::mk_vt(@{
+        visit_mod: |the_module, span, node_id, env, visitor| {
+            let n_added = add_privileged_structs(the_module.items);
+
+            visit::visit_mod(the_module, span, node_id, env, visitor);
+
+            for n_added.times {
+                ignore(privileged_structs.pop());
+            }
+        },
+        visit_expr: |expr, env, visitor| {
+            match expr.node {
+                expr_field(base, ident, _) => {
+                    match ty::get(ty::expr_ty(tcx, base)).struct {
+                        ty_class(id, _)
+                        if id.crate != local_crate ||
+                           !privileged_structs.contains(id.node) => {
+                            let fields = ty::lookup_class_fields(tcx, id);
+                            for fields.each |field| {
+                                if field.ident != ident { again; }
+                                if field.vis == private {
+                                    tcx.sess.span_err(expr.span,
+                                                      fmt!("field `%s` is \
+                                                            private",
+                                                           *tcx.sess
+                                                               .parse_sess
+                                                               .interner
+                                                               .get(ident)));
+                                }
+                                break;
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+                _ => {}
+            }
+
+            visit::visit_expr(expr, env, visitor);
+        }
+        with *visit::default_visitor()
+    });
+    visit::visit_crate(*crate, (), visitor);
+}
+
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index f473244eda8..a3b9f1d05ac 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -3160,10 +3160,6 @@ fn lookup_class_field(cx: ctxt, parent: ast::def_id, field_id: ast::def_id)
     }
 }
 
-fn lookup_public_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
-    vec::filter(lookup_class_fields(cx, did), is_public)
-}
-
 pure fn is_public(f: field_ty) -> bool {
     // XXX: This is wrong.
     match f.vis {
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index dc484f581e7..87012054779 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -51,9 +51,8 @@ use util::common::may_break;
 use syntax::codemap::span;
 use pat_util::{pat_is_variant, pat_id_map};
 use middle::ty;
-use middle::ty::{arg, field, node_type_table, mk_nil,
-                    ty_param_bounds_and_ty, lookup_public_fields,
-                    vstore_uniq};
+use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
+use middle::ty::{vstore_uniq};
 use std::smallintmap;
 use std::map;
 use std::map::{hashmap, int_hash};
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index dd8ac61dd46..ad0eb81c826 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -1317,18 +1317,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
               // (1) verify that the class id actually has a field called
               // field
               debug!("class named %s", ty_to_str(tcx, base_t));
-              /*
-                check whether this is a self-reference or not, which
-                determines whether we look at all fields or only public
-                ones
-               */
-              let cls_items = if self_ref(fcx, base.id) {
-                  // base expr is "self" -- consider all fields
-                  ty::lookup_class_fields(tcx, base_id)
-              }
-              else {
-                  lookup_public_fields(tcx, base_id)
-              };
+              let cls_items = ty::lookup_class_fields(tcx, base_id);
               match lookup_field_ty(tcx, base_id, cls_items, field, &substs) {
                  Some(field_ty) => {
                     // (2) look up what field's type is, and return it
@@ -1370,8 +1359,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
                     let msg =
                         fmt!(
                             "attempted access of field `%s` on type `%s`, \
-                             but no public field or method with that name \
-                             was found",
+                             but no field or method with that name was found",
                             tcx.sess.str_of(field),
                             fcx.infcx().ty_to_str(t_err));
                     tcx.sess.span_err(expr.span, msg);
diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc
index da347abad87..6890ec0acdc 100644
--- a/src/rustc/rustc.rc
+++ b/src/rustc/rustc.rc
@@ -102,6 +102,7 @@ mod middle {
     mod const_eval;
     mod astencode;
     mod lang_items;
+    mod privacy;
 }
 
 mod front {
diff --git a/src/test/compile-fail/private-class-field.rs b/src/test/compile-fail/private-class-field.rs
deleted file mode 100644
index ae0ae7c4a57..00000000000
--- a/src/test/compile-fail/private-class-field.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// error-pattern:no public field or method with that name
-struct cat {
-  priv {
-    let mut meows : uint;
-  }
-
-  let how_hungry : int;
-
-  new(in_x : uint, in_y : int) { self.meows = in_x; self.how_hungry = in_y; }
-}
-
-fn main() {
-  let nyan : cat = cat(52u, 99);
-  assert (nyan.meows == 52u);
-}
diff --git a/src/test/compile-fail/private-class-field-cross-crate.rs b/src/test/compile-fail/private-struct-field-cross-crate.rs
index b96adc19cbb..c40b04004b4 100644
--- a/src/test/compile-fail/private-class-field-cross-crate.rs
+++ b/src/test/compile-fail/private-struct-field-cross-crate.rs
@@ -1,4 +1,3 @@
-// error-pattern:no public field or method with that name
 // xfail-fast
 // aux-build:cci_class.rs
 use cci_class;
@@ -6,5 +5,5 @@ import cci_class::kitties::*;
 
 fn main() {
   let nyan : cat = cat(52u, 99);
-  assert (nyan.meows == 52u);
+  assert (nyan.meows == 52u);   //~ ERROR field `meows` is private
 }
diff --git a/src/test/compile-fail/private-struct-field.rs b/src/test/compile-fail/private-struct-field.rs
new file mode 100644
index 00000000000..becef52fa61
--- /dev/null
+++ b/src/test/compile-fail/private-struct-field.rs
@@ -0,0 +1,14 @@
+mod cat {
+    struct Cat {
+        priv meows: uint;
+    }
+
+    fn new_cat() -> Cat {
+        Cat { meows: 52 }
+    }
+}
+
+fn main() {
+    let nyan = cat::new_cat();
+    assert nyan.meows == 52;    //~ ERROR field `meows` is private
+}