diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-09-04 19:07:23 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-09-04 19:07:23 -0700 |
| commit | 9b88b5fe3862c45318487c37c8a48d9605590ce0 (patch) | |
| tree | 73e17ad3188011d44ee4efefadd9cca4bca6ec51 | |
| parent | fba673b26bc029ef234f56e177559fd0b9e48507 (diff) | |
| download | rust-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.rs | 54 | ||||
| -rw-r--r-- | src/test/compile-fail/private-struct-field-ctor.rs | 10 | ||||
| -rw-r--r-- | src/test/compile-fail/private-struct-field-pattern.rs | 18 |
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 + } +} + |
