about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-09-04 14:48:32 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-09-04 14:50:46 -0700
commit127144bf38f5bf81112bb304efb95a80d54bcaac (patch)
tree725c4184d1820dc893f777e33880a76027dafe87 /src/rustc
parent8182497359237cf2d842bc614eae2bf24bc2517a (diff)
downloadrust-127144bf38f5bf81112bb304efb95a80d54bcaac.tar.gz
rust-127144bf38f5bf81112bb304efb95a80d54bcaac.zip
rustc: Implement private fields for max/min classes
Diffstat (limited to 'src/rustc')
-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
6 files changed, 83 insertions, 21 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 {