about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-09-04 19:07:23 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-09-04 19:07:23 -0700
commit9b88b5fe3862c45318487c37c8a48d9605590ce0 (patch)
tree73e17ad3188011d44ee4efefadd9cca4bca6ec51
parentfba673b26bc029ef234f56e177559fd0b9e48507 (diff)
downloadrust-9b88b5fe3862c45318487c37c8a48d9605590ce0.tar.gz
rust-9b88b5fe3862c45318487c37c8a48d9605590ce0.zip
rustc: Don't allow private fields to be named in constructors or destructured
-rw-r--r--src/rustc/middle/privacy.rs54
-rw-r--r--src/test/compile-fail/private-struct-field-ctor.rs10
-rw-r--r--src/test/compile-fail/private-struct-field-pattern.rs18
3 files changed, 79 insertions, 3 deletions
diff --git a/src/rustc/middle/privacy.rs b/src/rustc/middle/privacy.rs
index b4b48f21405..0a2b2fff13d 100644
--- a/src/rustc/middle/privacy.rs
+++ b/src/rustc/middle/privacy.rs
@@ -3,8 +3,9 @@
 
 use /*mod*/ syntax::ast;
 use /*mod*/ syntax::visit;
-use syntax::ast::{expr_field, ident, item_class, item_impl, item_trait};
-use syntax::ast::{local_crate, node_id, private, provided, required};
+use syntax::ast::{expr_field, expr_struct, ident, item_class, item_impl};
+use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private};
+use syntax::ast::{provided, required};
 use syntax::ast_map::{node_item, node_method};
 use ty::ty_class;
 use typeck::{method_map, method_origin, method_param, method_static};
@@ -160,7 +161,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
                             match method_map.find(expr.id) {
                                 None => {
                                     debug!("(privacy checking) checking \
-                                            field");
+                                            field access");
                                     check_field(expr.span, id, ident);
                                 }
                                 Some(entry) => {
@@ -173,11 +174,58 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
                         _ => {}
                     }
                 }
+                expr_struct(_, fields, _) => {
+                    match ty::get(ty::expr_ty(tcx, expr)).struct {
+                        ty_class(id, _) => {
+                            if id.crate != local_crate ||
+                                    !privileged_items.contains(id.node) {
+                                for fields.each |field| {
+                                        debug!("(privacy checking) checking \
+                                                field in struct literal");
+                                    check_field(expr.span, id,
+                                                field.node.ident);
+                                }
+                            }
+                        }
+                        _ => {
+                            tcx.sess.span_bug(expr.span, ~"struct expr \
+                                                           didn't have \
+                                                           struct type?!");
+                        }
+                    }
+                }
                 _ => {}
             }
 
             visit::visit_expr(expr, method_map, visitor);
         },
+        visit_pat: |pattern, method_map, visitor| {
+            match pattern.node {
+                pat_struct(_, fields, _) => {
+                    match ty::get(ty::pat_ty(tcx, pattern)).struct {
+                        ty_class(id, _) => {
+                            if id.crate != local_crate ||
+                                    !privileged_items.contains(id.node) {
+                                for fields.each |field| {
+                                        debug!("(privacy checking) checking \
+                                                struct pattern");
+                                    check_field(pattern.span, id,
+                                                field.ident);
+                                }
+                            }
+                        }
+                        _ => {
+                            tcx.sess.span_bug(pattern.span,
+                                              ~"struct pattern didn't have \
+                                                struct type?!");
+                        }
+                    }
+                }
+                _ => {}
+            }
+
+            visit::visit_pat(pattern, method_map, visitor);
+        },
         .. *visit::default_visitor()
     });
     visit::visit_crate(*crate, method_map, visitor);
diff --git a/src/test/compile-fail/private-struct-field-ctor.rs b/src/test/compile-fail/private-struct-field-ctor.rs
new file mode 100644
index 00000000000..6d075cbd7ad
--- /dev/null
+++ b/src/test/compile-fail/private-struct-field-ctor.rs
@@ -0,0 +1,10 @@
+mod a {
+    struct Foo {
+        priv x: int
+    }
+}
+
+fn main() {
+    let s = a::Foo { x: 1 };    //~ ERROR field `x` is private
+}
+
diff --git a/src/test/compile-fail/private-struct-field-pattern.rs b/src/test/compile-fail/private-struct-field-pattern.rs
new file mode 100644
index 00000000000..cc3ebc92172
--- /dev/null
+++ b/src/test/compile-fail/private-struct-field-pattern.rs
@@ -0,0 +1,18 @@
+use a::Foo;
+
+mod a {
+    struct Foo {
+        priv x: int
+    }
+
+    fn make() -> Foo {
+        Foo { x: 3 }
+    }
+}
+
+fn main() {
+    match a::make() {
+        Foo { x: _ } => {}  //~ ERROR field `x` is private
+    }
+}
+