Skip to content

Commit 127144b

Browse files
committed
rustc: Implement private fields for max/min classes
1 parent 8182497 commit 127144b

File tree

9 files changed

+98
-38
lines changed

9 files changed

+98
-38
lines changed

src/rustc/driver/driver.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
221221

222222
if upto == cu_typeck { return {crate: crate, tcx: Some(ty_cx)}; }
223223

224+
time(time_passes, ~"privacy checking", ||
225+
middle::privacy::check_crate(ty_cx, crate));
226+
224227
time(time_passes, ~"loop checking", ||
225228
middle::check_loop::check_crate(ty_cx, crate));
226229

src/rustc/middle/privacy.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// A pass that checks to make sure private fields and methods aren't used
2+
// outside their scopes.
3+
4+
use /*mod*/ syntax::ast;
5+
use /*mod*/ syntax::visit;
6+
use syntax::ast::{expr_field, ident, item_class, local_crate, node_id};
7+
use syntax::ast::{private};
8+
use ty::ty_class;
9+
10+
use core::util::ignore;
11+
use dvec::DVec;
12+
use send_map::linear::LinearMap;
13+
14+
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
15+
let privileged_structs = @DVec();
16+
17+
let add_privileged_structs = |items: &[@ast::item]| {
18+
let mut count = 0;
19+
for items.each |item| {
20+
match item.node {
21+
item_class(*) => {
22+
privileged_structs.push(item.id);
23+
count += 1;
24+
}
25+
_ => {}
26+
}
27+
}
28+
count
29+
};
30+
31+
let visitor = visit::mk_vt(@{
32+
visit_mod: |the_module, span, node_id, env, visitor| {
33+
let n_added = add_privileged_structs(the_module.items);
34+
35+
visit::visit_mod(the_module, span, node_id, env, visitor);
36+
37+
for n_added.times {
38+
ignore(privileged_structs.pop());
39+
}
40+
},
41+
visit_expr: |expr, env, visitor| {
42+
match expr.node {
43+
expr_field(base, ident, _) => {
44+
match ty::get(ty::expr_ty(tcx, base)).struct {
45+
ty_class(id, _)
46+
if id.crate != local_crate ||
47+
!privileged_structs.contains(id.node) => {
48+
let fields = ty::lookup_class_fields(tcx, id);
49+
for fields.each |field| {
50+
if field.ident != ident { again; }
51+
if field.vis == private {
52+
tcx.sess.span_err(expr.span,
53+
fmt!("field `%s` is \
54+
private",
55+
*tcx.sess
56+
.parse_sess
57+
.interner
58+
.get(ident)));
59+
}
60+
break;
61+
}
62+
}
63+
_ => {}
64+
}
65+
}
66+
_ => {}
67+
}
68+
69+
visit::visit_expr(expr, env, visitor);
70+
}
71+
with *visit::default_visitor()
72+
});
73+
visit::visit_crate(*crate, (), visitor);
74+
}
75+

src/rustc/middle/ty.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,10 +3160,6 @@ fn lookup_class_field(cx: ctxt, parent: ast::def_id, field_id: ast::def_id)
31603160
}
31613161
}
31623162
3163-
fn lookup_public_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
3164-
vec::filter(lookup_class_fields(cx, did), is_public)
3165-
}
3166-
31673163
pure fn is_public(f: field_ty) -> bool {
31683164
// XXX: This is wrong.
31693165
match f.vis {

src/rustc/middle/typeck.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ use util::common::may_break;
5151
use syntax::codemap::span;
5252
use pat_util::{pat_is_variant, pat_id_map};
5353
use middle::ty;
54-
use middle::ty::{arg, field, node_type_table, mk_nil,
55-
ty_param_bounds_and_ty, lookup_public_fields,
56-
vstore_uniq};
54+
use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
55+
use middle::ty::{vstore_uniq};
5756
use std::smallintmap;
5857
use std::map;
5958
use std::map::{hashmap, int_hash};

src/rustc/middle/typeck/check.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,18 +1317,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
13171317
// (1) verify that the class id actually has a field called
13181318
// field
13191319
debug!("class named %s", ty_to_str(tcx, base_t));
1320-
/*
1321-
check whether this is a self-reference or not, which
1322-
determines whether we look at all fields or only public
1323-
ones
1324-
*/
1325-
let cls_items = if self_ref(fcx, base.id) {
1326-
// base expr is "self" -- consider all fields
1327-
ty::lookup_class_fields(tcx, base_id)
1328-
}
1329-
else {
1330-
lookup_public_fields(tcx, base_id)
1331-
};
1320+
let cls_items = ty::lookup_class_fields(tcx, base_id);
13321321
match lookup_field_ty(tcx, base_id, cls_items, field, &substs) {
13331322
Some(field_ty) => {
13341323
// (2) look up what field's type is, and return it
@@ -1370,8 +1359,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
13701359
let msg =
13711360
fmt!(
13721361
"attempted access of field `%s` on type `%s`, \
1373-
but no public field or method with that name \
1374-
was found",
1362+
but no field or method with that name was found",
13751363
tcx.sess.str_of(field),
13761364
fcx.infcx().ty_to_str(t_err));
13771365
tcx.sess.span_err(expr.span, msg);

src/rustc/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ mod middle {
102102
mod const_eval;
103103
mod astencode;
104104
mod lang_items;
105+
mod privacy;
105106
}
106107

107108
mod front {

src/test/compile-fail/private-class-field.rs

Lines changed: 0 additions & 15 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
// error-pattern:no public field or method with that name
21
// xfail-fast
32
// aux-build:cci_class.rs
43
use cci_class;
54
import cci_class::kitties::*;
65

76
fn main() {
87
let nyan : cat = cat(52u, 99);
9-
assert (nyan.meows == 52u);
8+
assert (nyan.meows == 52u); //~ ERROR field `meows` is private
109
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
mod cat {
2+
struct Cat {
3+
priv meows: uint;
4+
}
5+
6+
fn new_cat() -> Cat {
7+
Cat { meows: 52 }
8+
}
9+
}
10+
11+
fn main() {
12+
let nyan = cat::new_cat();
13+
assert nyan.meows == 52; //~ ERROR field `meows` is private
14+
}

0 commit comments

Comments
 (0)