Skip to content

Commit f2efe5d

Browse files
committed
---
yaml --- r: 12120 b: refs/heads/master c: c282810 h: refs/heads/master v: v3
1 parent 9a91be4 commit f2efe5d

File tree

13 files changed

+186
-59
lines changed

13 files changed

+186
-59
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: a00538b3b3da226b751767ce282682d9de28fa75
2+
refs/heads/master: c282810ab04a57f7d3f476e9628b6b82184b19b2
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/rustc/metadata/csearch.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import std::map::hashmap;
1414
export get_symbol;
1515
export get_class_fields;
1616
export get_class_method;
17-
// export get_class_method_ids;
1817
export get_field_type;
1918
export get_type_param_count;
2019
export lookup_defs;
@@ -131,14 +130,6 @@ fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
131130
decoder::get_class_fields(cdata, def.node)
132131
}
133132

134-
/*
135-
fn get_class_method_ids(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
136-
let cstore = tcx.sess.cstore;
137-
let cdata = cstore::get_crate_data(cstore, def.crate);
138-
decoder::get_class_method_ids(cdata, def.node)
139-
}
140-
*/
141-
142133
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
143134
let cstore = tcx.sess.cstore;
144135
let cdata = cstore::get_crate_data(cstore, def.crate);

trunk/src/rustc/metadata/decoder.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import middle::trans::common::maps;
1717
import util::ppaux::ty_to_str;
1818

1919
export get_class_fields;
20-
// export get_class_method_ids;
2120
export get_symbol;
2221
export get_enum_variants;
2322
export get_type;
@@ -427,38 +426,38 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
427426

428427
// Helper function that gets either fields or methods
429428
fn get_class_members(cdata: cmd, id: ast::node_id,
430-
family: char) -> [ty::field_ty] {
429+
p: fn(char) -> bool) -> [ty::field_ty] {
431430
let data = cdata.data;
432431
let item = lookup_item(id, data);
433432
let mut result = [];
434433
ebml::tagged_docs(item, tag_item_field) {|an_item|
435-
if item_family(an_item) == family {
434+
let f = item_family(an_item);
435+
if p(f) {
436436
let name = item_name(an_item);
437437
let did = class_member_id(an_item, cdata);
438-
result += [{ident: name, id: did}];
438+
result += [{ident: name, id: did, privacy:
439+
// This won't work for methods, argh
440+
family_to_privacy(f)}];
439441
}
440442
}
441443
result
442444
}
443445

444-
445-
/* Take a node ID for a class, return a vector of the class's
446-
field names/IDs */
447-
fn get_class_fields(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
448-
get_class_members(cdata, id, 'g')
446+
pure fn family_to_privacy(family: char) -> ast::privacy {
447+
alt family {
448+
'g' { ast::pub }
449+
_ { ast::priv }
450+
}
449451
}
450452

451-
/*
452-
/* Take a node ID for a class, return a vector of the class's
453-
method names/IDs */
454-
fn get_class_method_ids(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
455-
get_class_members(cdata, id, 'h')
453+
/* 'g' for public field, 'j' for private field */
454+
fn get_class_fields(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
455+
get_class_members(cdata, id, {|f| f == 'g' || f == 'j'})
456456
}
457-
*/
458457

459458
fn family_has_type_params(fam_ch: char) -> bool {
460459
alt check fam_ch {
461-
'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }
460+
'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' { false }
462461
'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
463462
| 'a'
464463
{ true }

trunk/src/rustc/metadata/encoder.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,11 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
353353
ebml_w.end_tag();
354354
}
355355

356+
fn encode_privacy(ebml_w: ebml::writer, privacy: privacy) {
357+
encode_family(ebml_w, alt privacy {
358+
pub { 'g' } priv { 'j' }});
359+
}
360+
356361
/* Returns an index of items in this class */
357362
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
358363
id: node_id, path: ast_map::path,
@@ -369,7 +374,7 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
369374
*index += [{val: id, pos: ebml_w.writer.tell()}];
370375
ebml_w.start_tag(tag_items_data_item);
371376
#debug("encode_info_for_class: doing %s %d", nm, id);
372-
encode_family(ebml_w, 'g');
377+
encode_privacy(ebml_w, ci.node.privacy);
373378
encode_name(ebml_w, nm);
374379
encode_path(ebml_w, path, ast_map::path_name(nm));
375380
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
@@ -564,19 +569,25 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
564569
let (fs,ms) = ast_util::split_class_items(items);
565570
for f in fs {
566571
ebml_w.start_tag(tag_item_field);
567-
encode_family(ebml_w, 'g');
572+
encode_privacy(ebml_w, f.privacy);
568573
encode_name(ebml_w, f.ident);
569574
encode_def_id(ebml_w, local_def(f.id));
570575
ebml_w.end_tag();
571576
}
572-
for m in ms {
573-
ebml_w.start_tag(tag_item_method);
574-
#debug("Writing %s %d", m.ident, m.id);
575-
encode_family(ebml_w, purity_fn_family(m.decl.purity));
576-
encode_name(ebml_w, m.ident);
577-
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
578-
encode_def_id(ebml_w, local_def(m.id));
579-
ebml_w.end_tag();
577+
for mt in ms {
578+
alt mt.privacy {
579+
priv { /* do nothing */ }
580+
pub {
581+
let m = mt.meth;
582+
ebml_w.start_tag(tag_item_method);
583+
#debug("Writing %s %d", m.ident, m.id);
584+
encode_family(ebml_w, purity_fn_family(m.decl.purity));
585+
encode_name(ebml_w, m.ident);
586+
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
587+
encode_def_id(ebml_w, local_def(m.id));
588+
ebml_w.end_tag();
589+
}
590+
}
580591
}
581592
/* Each class has its own index -- encode it */
582593
let bkts = create_index(idx, hash_node_id);

trunk/src/rustc/middle/trans/base.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4271,7 +4271,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
42714271

42724272
// Translate methods
42734273
let (_, ms) = ast_util::split_class_items(items);
4274-
impl::trans_impl(ccx, *path, item.ident, ms, tps);
4274+
impl::trans_impl(ccx, *path, item.ident,
4275+
vec::map(ms, {|m| m.meth}), tps);
42754276
}
42764277
_ {/* fall through */ }
42774278
}

trunk/src/rustc/middle/ty.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export lookup_class_fields;
4545
export lookup_class_method_by_name;
4646
export lookup_field_type;
4747
export lookup_item_type;
48+
export lookup_public_fields;
4849
export method;
4950
export method_idx;
5051
export mk_class;
@@ -160,10 +161,10 @@ type constr_table = hashmap<ast::node_id, [constr]>;
160161

161162
type mt = {ty: t, mutbl: ast::mutability};
162163

163-
// Just use <field> for class fields?
164164
type field_ty = {
165165
ident: ident,
166166
id: def_id,
167+
privacy: ast::privacy
167168
};
168169

169170
// Contains information needed to resolve types and (in the future) look up
@@ -1996,14 +1997,26 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
19961997
}
19971998
}
19981999

2000+
fn lookup_public_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
2001+
vec::filter(lookup_class_fields(cx, did), is_public)
2002+
}
2003+
2004+
pure fn is_public(f: field_ty) -> bool {
2005+
alt f.privacy {
2006+
pub { true }
2007+
priv { false }
2008+
}
2009+
}
2010+
19992011
// Look up the list of method names and IDs for a given class
20002012
// Fails if the id is not bound to a class.
20012013
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
2002-
: is_local(did) -> [{name: ident, id: node_id}] {
2014+
: is_local(did) -> [{name: ident, id: node_id, privacy: privacy}] {
20032015
alt cx.items.find(did.node) {
20042016
some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) {
20052017
let (_,ms) = split_class_items(items);
2006-
vec::map(ms, {|m| {name: m.ident, id: m.id}})
2018+
vec::map(ms, {|m| {name: m.meth.ident, id: m.meth.id,
2019+
privacy: m.privacy}})
20072020
}
20082021
_ {
20092022
cx.sess.bug("lookup_class_method_ids: id not bound to a class");
@@ -2012,19 +2025,19 @@ fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
20122025
}
20132026

20142027
/* Given a class def_id and a method name, return the method's
2015-
def_id. Needed so we can do static dispatch for methods */
2028+
def_id. Needed so we can do static dispatch for methods
2029+
Fails if the requested method is private */
20162030
fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
2017-
sp: span) ->
2018-
def_id {
2031+
sp: span) -> def_id {
20192032
if check is_local(did) {
20202033
let ms = lookup_class_method_ids(cx, did);
20212034
for m in ms {
2022-
if m.name == name {
2035+
if m.name == name && m.privacy == ast::pub {
20232036
ret ast_util::local_def(m.id);
20242037
}
20252038
}
2026-
cx.sess.span_fatal(sp, #fmt("Class doesn't have a method named %s",
2027-
name));
2039+
cx.sess.span_fatal(sp, #fmt("Class doesn't have a public method \
2040+
named %s", name));
20282041
}
20292042
else {
20302043
csearch::get_class_method(cx.sess.cstore, did, name)
@@ -2036,7 +2049,8 @@ fn class_field_tys(items: [@class_item]) -> [field_ty] {
20362049
for it in items {
20372050
alt it.node.decl {
20382051
instance_var(nm, _, _, id) {
2039-
rslt += [{ident: nm, id: ast_util::local_def(id)}];
2052+
rslt += [{ident: nm, id: ast_util::local_def(id),
2053+
privacy: it.node.privacy}];
20402054
}
20412055
class_method(_) {
20422056
}

trunk/src/rustc/middle/typeck.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import pat_util::*;
1111
import middle::ty;
1212
import middle::ty::{node_id_to_type, arg, block_ty,
1313
expr_ty, field, node_type_table, mk_nil,
14-
ty_param_bounds_and_ty, lookup_class_fields};
14+
ty_param_bounds_and_ty, lookup_public_fields};
1515
import util::ppaux::ty_to_str;
1616
import std::smallintmap;
1717
import std::map::{hashmap, int_hash};
@@ -934,7 +934,9 @@ mod collect {
934934
}
935935
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
936936
let (_,ms) = split_class_items(its);
937-
store_methods::<@ast::method>(tcx, id, ms, {|m|
937+
// Handling all methods here
938+
let ps = ast_util::ignore_privacy(ms);
939+
store_methods::<@ast::method>(tcx, id, ps, {|m|
938940
ty_of_method(tcx, m_collect, m)});
939941
}
940942
}
@@ -1089,10 +1091,13 @@ mod collect {
10891091
for f in fields {
10901092
convert_class_item(tcx, f);
10911093
}
1094+
// The selfty is just the class type
10921095
let selfty = ty::mk_class(tcx, local_def(it.id),
10931096
mk_ty_params(tcx, tps).params);
1094-
// The selfty is just the class type
1095-
convert_methods(tcx, methods, @[], some(selfty));
1097+
// Need to convert all methods so we can check internal
1098+
// references to private methods
1099+
convert_methods(tcx, ast_util::ignore_privacy(methods), @[],
1100+
some(selfty));
10961101
}
10971102
_ {
10981103
// This call populates the type cache with the converted type
@@ -3095,7 +3100,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
30953100
// (1) verify that the class id actually has a field called
30963101
// field
30973102
#debug("class named %s", ty_to_str(tcx, base_t));
3098-
let cls_items = lookup_class_fields(tcx, base_id);
3103+
/*
3104+
This is an external reference, so only consider public
3105+
fields
3106+
*/
3107+
let cls_items = lookup_public_fields(tcx, base_id);
30993108
#debug("cls_items: %?", cls_items);
31003109
alt lookup_field_ty(tcx, base_id, cls_items, field) {
31013110
some(field_ty) {
@@ -3119,7 +3128,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
31193128
none {
31203129
let t_err = resolve_type_vars_if_possible(fcx, expr_t);
31213130
let msg = #fmt["attempted access of field %s on type %s, but \
3122-
no field or method with that name was found",
3131+
no public field or method with that name was found",
31233132
field, ty_to_str(tcx, t_err)];
31243133
tcx.sess.span_err(expr.span, msg);
31253134
// NB: Adding a bogus type to allow typechecking to continue
@@ -3613,9 +3622,8 @@ fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map {
36133622

36143623
fn check_class_member(ccx: @crate_ctxt, cm: ast::class_member) {
36153624
alt cm {
3616-
ast::instance_var(_,t,_,_) { // ??? Not sure
3625+
ast::instance_var(_,t,_,_) {
36173626
}
3618-
// not right yet -- need a scope
36193627
ast::class_method(m) { check_method(ccx, m); }
36203628
}
36213629
}

trunk/src/rustc/syntax/ast_util.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,16 +435,29 @@ pure fn class_item_ident(ci: @class_item) -> ident {
435435
}
436436
}
437437

438-
type ivar = {ident: ident, ty: @ty, cm: class_mutability, id: node_id};
438+
type ivar = {ident: ident, ty: @ty, cm: class_mutability,
439+
id: node_id, privacy: privacy};
439440

440-
fn split_class_items(cs: [@class_item]) -> ([ivar], [@method]) {
441+
type cmethod = {privacy: privacy, meth: @method};
442+
443+
fn public_methods(cms: [cmethod]) -> [@method] {
444+
vec::filter_map(cms, {|cm| alt cm.privacy {
445+
pub { some(cm.meth) }
446+
_ { none }}})
447+
}
448+
449+
fn ignore_privacy(cms: [cmethod]) -> [@method] {
450+
vec::map(cms, {|cm| cm.meth})
451+
}
452+
453+
fn split_class_items(cs: [@class_item]) -> ([ivar], [cmethod]) {
441454
let mut vs = [], ms = [];
442455
for c in cs {
443456
alt c.node.decl {
444457
instance_var(i, t, cm, id) {
445-
vs += [{ident: i, ty: t, cm: cm, id: id}];
458+
vs += [{ident: i, ty: t, cm: cm, id: id, privacy: c.node.privacy}];
446459
}
447-
class_method(m) { ms += [m]; }
460+
class_method(m) { ms += [{privacy: c.node.privacy, meth: m}]; }
448461
}
449462
}
450463
(vs, ms)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// error-pattern:assigning to immutable field
2+
class cat {
3+
priv {
4+
let mutable meows : uint;
5+
}
6+
7+
let how_hungry : int;
8+
9+
fn speak() { meows += 1u; }
10+
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
11+
}
12+
13+
fn main() {
14+
let nyan : cat = cat(52u, 99);
15+
nyan.speak = fn@() { log(error, "meow"); };
16+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// error-pattern:no public field or method with that name
2+
class cat {
3+
priv {
4+
let mutable meows : uint;
5+
}
6+
7+
let how_hungry : int;
8+
9+
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
10+
}
11+
12+
fn main() {
13+
let nyan : cat = cat(52u, 99);
14+
assert (nyan.meows == 52u);
15+
}
16+
/*
17+
other tests:
18+
not ok to refer to a private method outside a class
19+
ok to refer to private method within a class
20+
can't assign to a non-mutable var
21+
can't assign to a method
22+
23+
all the same tests, cross-crate
24+
*/

0 commit comments

Comments
 (0)