Allow explicit self-calls within classes

Allow writing self.f() within a class that has a method f. In a future
commit, this syntax will be required. For now, you can write either
self.f() or f().

I added a "privacy" field to all methods (whether class methods or not),
which allowed me to refactor the AST somewhat (getting rid of the
class_item type; now there's just class_member).
This commit is contained in:
Tim Chevalier 2012-03-28 18:50:33 -07:00
parent fe610f04d8
commit f7bbe537c1
18 changed files with 201 additions and 198 deletions

View file

@ -218,10 +218,9 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
} }
}, },
visit_class_item: fn@(_s: span, _p: ast::privacy, visit_class_item: fn@(c: @ast::class_member) {
c: ast::class_member) { alt c.node {
alt c { ast::instance_var(_, _, _, id,_) {
ast::instance_var(_, _, _, id) {
vfn(id) vfn(id)
} }
ast::class_method(_) { ast::class_method(_) {

View file

@ -431,7 +431,7 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
'u' { ast::unsafe_fn } 'u' { ast::unsafe_fn }
'f' { ast::impure_fn } 'f' { ast::impure_fn }
'p' { ast::pure_fn } 'p' { ast::pure_fn }
}}]; }, privacy: ast::pub}];
} }
@result @result
} }

View file

@ -83,13 +83,13 @@ fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
} }
fn encode_class_item_paths(ebml_w: ebml::writer, fn encode_class_item_paths(ebml_w: ebml::writer,
items: [@class_item], path: [str], &index: [entry<str>]) { items: [@class_member], path: [str], &index: [entry<str>]) {
for it in items { for it in items {
alt it.node.privacy { alt ast_util::class_member_privacy(it) {
priv { cont; } priv { cont; }
pub { pub {
let (id, ident) = alt it.node.decl { let (id, ident) = alt it.node {
instance_var(v, _, _, vid) { (vid, v) } instance_var(v, _, _, vid, _) { (vid, v) }
class_method(it) { (it.id, it.ident) } class_method(it) { (it.id, it.ident) }
}; };
add_to_index(ebml_w, path, index, ident); add_to_index(ebml_w, path, index, ident);
@ -368,7 +368,7 @@ fn encode_privacy(ebml_w: ebml::writer, privacy: privacy) {
/* Returns an index of items in this class */ /* Returns an index of items in this class */
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer, fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
id: node_id, path: ast_map::path, id: node_id, path: ast_map::path,
items: [@class_item], items: [@class_member],
global_index: @mut[entry<int>]) global_index: @mut[entry<int>])
-> [entry<int>] { -> [entry<int>] {
let index = @mut []; let index = @mut [];
@ -376,12 +376,12 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
for ci in items { for ci in items {
/* We encode both private and public fields -- need to include /* We encode both private and public fields -- need to include
private fields to get the offsets right */ private fields to get the offsets right */
alt ci.node.decl { alt ci.node {
instance_var(nm, _, mt, id) { instance_var(nm, _, mt, id, pr) {
*index += [{val: id, pos: ebml_w.writer.tell()}]; *index += [{val: id, pos: ebml_w.writer.tell()}];
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
#debug("encode_info_for_class: doing %s %d", nm, id); #debug("encode_info_for_class: doing %s %d", nm, id);
encode_privacy(ebml_w, ci.node.privacy); encode_privacy(ebml_w, pr);
encode_name(ebml_w, nm); encode_name(ebml_w, nm);
encode_path(ebml_w, path, ast_map::path_name(nm)); encode_path(ebml_w, path, ast_map::path_name(nm));
encode_type(ecx, ebml_w, node_id_to_type(tcx, id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
@ -390,18 +390,23 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
ebml_w.end_tag(); ebml_w.end_tag();
} }
class_method(m) { class_method(m) {
*index += [{val: m.id, pos: ebml_w.writer.tell()}]; alt m.privacy {
/* Not sure whether we really need to have two indices, pub {
but it works for now -- tjc */ *index += [{val: m.id, pos: ebml_w.writer.tell()}];
*global_index += [{val: m.id, pos: ebml_w.writer.tell()}]; /* Not sure whether we really need to have two indices,
let impl_path = path + [ast_map::path_name(m.ident)]; but it works for now -- tjc */
/* *global_index += [{val: m.id, pos: ebml_w.writer.tell()}];
Recall methods are (currently) monomorphic, and we don't let impl_path = path + [ast_map::path_name(m.ident)];
repeat the class's ty params in the method decl /*
*/ Recall methods are (currently) monomorphic, and we don't
#debug("encode_info_for_class: doing %s %d", m.ident, m.id); repeat the class's ty params in the method decl
encode_info_for_method(ecx, ebml_w, impl_path, */
should_inline(m.attrs), id, m, []); #debug("encode_info_for_class: doing %s %d", m.ident, m.id);
encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), id, m, []);
}
_ { /* don't encode private methods */ }
}
} }
} }
} }
@ -581,11 +586,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_def_id(ebml_w, local_def(f.id)); encode_def_id(ebml_w, local_def(f.id));
ebml_w.end_tag(); ebml_w.end_tag();
} }
for mt in ms { for m in ms {
alt mt.privacy { alt m.privacy {
priv { /* do nothing */ } priv { /* do nothing */ }
pub { pub {
let m = mt.meth;
ebml_w.start_tag(tag_item_method); ebml_w.start_tag(tag_item_method);
#debug("Writing %s %d", m.ident, m.id); #debug("Writing %s %d", m.ident, m.id);
encode_family(ebml_w, purity_fn_family(m.decl.purity)); encode_family(ebml_w, purity_fn_family(m.decl.purity));

View file

@ -182,10 +182,8 @@ fn map_item(i: @item, cx: ctx, v: vt) {
let p = extend(cx, i.ident); let p = extend(cx, i.ident);
for ci in items { for ci in items {
// only need to handle methods // only need to handle methods
alt ci.node.decl { alt ci.node {
class_method(m) { class_method(m) { map_method(d_id, p, m, cx); }
map_method(d_id, p, m, cx);
}
_ {} _ {}
} }
} }

View file

@ -216,9 +216,8 @@ fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
alt item.node { alt item.node {
item_class(tps, items, ctor) { item_class(tps, items, ctor) {
v.visit_ty_params(tps, cx, v); v.visit_ty_params(tps, cx, v);
vec::map::<@class_item, ()>(items, vec::map::<@class_member, ()>(items,
{|i| v.visit_class_item(i.span, {|i| v.visit_class_item(i, cx, v); });
i.node.privacy, i.node.decl, cx, v); });
v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec, v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec,
ctor.node.body, ctor.span, ctor.node.id, ctor.node.body, ctor.span, ctor.node.id,
@{in_ctor: some(ctor.node.self_id) with *cx}, v); @{in_ctor: some(ctor.node.self_id) with *cx}, v);

View file

@ -89,7 +89,7 @@ enum mod_index_entry {
mie_import_ident(node_id, span), mie_import_ident(node_id, span),
mie_item(@ast::item), mie_item(@ast::item),
mie_class_item(node_id, /* parent class name */ mie_class_item(node_id, /* parent class name */
@ast::class_item), /* class member */ @ast::class_member), /* class member */
mie_native_item(@ast::native_item), mie_native_item(@ast::native_item),
mie_enum_variant(/* variant index */uint, mie_enum_variant(/* variant index */uint,
/*parts of enum item*/ [variant], /*parts of enum item*/ [variant],
@ -533,14 +533,14 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
ctor_scope, v); ctor_scope, v);
/* visit the items */ /* visit the items */
for cm in members { for cm in members {
alt cm.node.decl { alt cm.node {
class_method(m) { class_method(m) {
let msc = cons(scope_method(m.self_id, tps + m.tps), let msc = cons(scope_method(m.self_id, tps + m.tps),
@class_scope); @class_scope);
visit_fn_with_scope(e, visit_fn_with_scope(e,
visit::fk_item_fn(m.ident, tps), m.decl, m.body, visit::fk_item_fn(m.ident, tps), m.decl, m.body,
m.span, m.id, msc, v); } m.span, m.id, msc, v); }
instance_var(_,t,_,_) { v.visit_ty(t, class_scope, v); } instance_var(_,t,_,_,_) { v.visit_ty(t, class_scope, v); }
} }
} }
} }
@ -1161,11 +1161,11 @@ fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl,
using the mod_index stuff using the mod_index stuff
*/ */
fn lookup_in_class(parent_id: def_id, fn lookup_in_class(parent_id: def_id,
members: [@class_item], name: ident) members: [@class_member], name: ident)
-> option<def> { -> option<def> {
for m in members { for m in members {
alt m.node.decl { alt m.node {
instance_var(v_name,_,_,id) { instance_var(v_name,_,_,id,_) {
if v_name == name { if v_name == name {
ret some(def_class_field(parent_id, local_def(id))); ret some(def_class_field(parent_id, local_def(id)));
} }
@ -1560,8 +1560,8 @@ fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
} }
} }
mie_class_item(parent_id, class_item) { mie_class_item(parent_id, class_item) {
alt class_item.node.decl { alt class_item.node {
instance_var(_,_,_,id) { instance_var(_,_,_,id,_) {
ret some(ast::def_class_field(local_def(parent_id), ret some(ast::def_class_field(local_def(parent_id),
local_def(id))); local_def(id)));
} }

View file

@ -4368,8 +4368,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
// Translate methods // Translate methods
let (_, ms) = ast_util::split_class_items(items); let (_, ms) = ast_util::split_class_items(items);
impl::trans_impl(ccx, *path, item.ident, impl::trans_impl(ccx, *path, item.ident, ms, tps);
vec::map(ms, {|m| m.meth}), tps);
} }
_ {/* fall through */ } _ {/* fall through */ }
} }

View file

@ -101,7 +101,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
item_class(tps, items, ctor) { item_class(tps, items, ctor) {
cx.rmap.insert(ctor.node.id, ()); cx.rmap.insert(ctor.node.id, ());
for vec::each(items) {|item| for vec::each(items) {|item|
alt item.node.decl { alt item.node {
class_method(m) { class_method(m) {
cx.rmap.insert(m.id, ()); cx.rmap.insert(m.id, ());
if tps.len() > 0u || if tps.len() > 0u ||

View file

@ -156,7 +156,8 @@ type param_bounds = @[param_bound];
type method = {ident: ast::ident, type method = {ident: ast::ident,
tps: @[param_bounds], tps: @[param_bounds],
fty: fn_ty, fty: fn_ty,
purity: ast::purity}; purity: ast::purity,
privacy: ast::privacy};
type constr_table = hashmap<ast::node_id, [constr]>; type constr_table = hashmap<ast::node_id, [constr]>;
@ -2165,7 +2166,7 @@ fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
alt cx.items.find(did.node) { alt cx.items.find(did.node) {
some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) { some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) {
let (_,ms) = split_class_items(items); let (_,ms) = split_class_items(items);
vec::map(ms, {|m| {name: m.meth.ident, id: m.meth.id, vec::map(ms, {|m| {name: m.ident, id: m.id,
privacy: m.privacy}}) privacy: m.privacy}})
} }
_ { _ {
@ -2176,17 +2177,19 @@ fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
/* Given a class def_id and a method name, return the method's /* Given a class def_id and a method name, return the method's
def_id. Needed so we can do static dispatch for methods def_id. Needed so we can do static dispatch for methods
Fails if the requested method is private */ Doesn't care about the method's privacy. (It's assumed that
the caller already checked that.)
*/
fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident, fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
sp: span) -> def_id { sp: span) -> def_id {
if check is_local(did) { if check is_local(did) {
let ms = lookup_class_method_ids(cx, did); let ms = lookup_class_method_ids(cx, did);
for m in ms { for m in ms {
if m.name == name && m.privacy == ast::pub { if m.name == name {
ret ast_util::local_def(m.id); ret ast_util::local_def(m.id);
} }
} }
cx.sess.span_fatal(sp, #fmt("Class doesn't have a public method \ cx.sess.span_fatal(sp, #fmt("Class doesn't have a method \
named %s", name)); named %s", name));
} }
else { else {
@ -2194,16 +2197,15 @@ fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
} }
} }
fn class_field_tys(items: [@class_item]) -> [field_ty] { fn class_field_tys(items: [@class_member]) -> [field_ty] {
let mut rslt = []; let mut rslt = [];
for it in items { for it in items {
alt it.node.decl { alt it.node {
instance_var(nm, _, cm, id) { instance_var(nm, _, cm, id, privacy) {
rslt += [{ident: nm, id: ast_util::local_def(id), rslt += [{ident: nm, id: ast_util::local_def(id),
privacy: it.node.privacy, mutability: cm}]; privacy: privacy, mutability: cm}];
}
class_method(_) {
} }
class_method(_) { }
} }
} }
rslt rslt

View file

@ -83,6 +83,22 @@ type fn_ctxt =
next_region_var_id: @mut int, next_region_var_id: @mut int,
ccx: @crate_ctxt}; ccx: @crate_ctxt};
// Determines whether the given node ID is a use of the def of
// the self ID for the current method, if there is one
fn self_ref(fcx: @fn_ctxt, id: ast::node_id) -> bool {
let node_def = alt fcx.ccx.tcx.def_map.find(id) {
none { ret false; }
some(d) { d } };
alt get_self_info(fcx.ccx) {
some(self_impl(_, slf_def)) {
alt node_def {
ast::def_self(slf_actual) { slf_def == slf_actual }
_ { false }
}
}
none { false }
}
}
fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> int { fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> int {
alt fcx.locals.find(id) { alt fcx.locals.find(id) {
@ -709,13 +725,14 @@ fn ty_param_bounds(tcx: ty::ctxt, mode: mode, params: [ast::ty_param])
fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method { fn ty_of_method(tcx: ty::ctxt, mode: mode, m: @ast::method) -> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps), {ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl), fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
purity: m.decl.purity} purity: m.decl.purity, privacy: m.privacy}
} }
fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method) fn ty_of_ty_method(tcx: ty::ctxt, mode: mode, m: ast::ty_method)
-> ty::method { -> ty::method {
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps), {ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl), fty: ty_of_fn_decl(tcx, mode, ast::proto_bare, m.decl),
purity: m.decl.purity} // assume public, because this is only invoked on iface methods
purity: m.decl.purity, privacy: ast::pub}
} }
// A convenience function to use a crate_ctxt to resolve names for // A convenience function to use a crate_ctxt to resolve names for
@ -939,9 +956,9 @@ mod collect {
} }
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) { ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
let (_,ms) = split_class_items(its); let (_,ms) = split_class_items(its);
// Only public methods need to be stored // All methods need to be stored, since lookup_method
let ps = ast_util::public_methods(ms); // relies on the same method cache for self-calls
store_methods::<@ast::method>(tcx, id, ps, {|m| store_methods::<@ast::method>(tcx, id, ms, {|m|
ty_of_method(tcx, m_collect, m)}); ty_of_method(tcx, m_collect, m)});
} }
} }
@ -1101,8 +1118,7 @@ mod collect {
mk_ty_params(tcx, tps).params); mk_ty_params(tcx, tps).params);
// Need to convert all methods so we can check internal // Need to convert all methods so we can check internal
// references to private methods // references to private methods
convert_methods(tcx, ast_util::ignore_privacy(methods), @[], convert_methods(tcx, methods, @[], some(selfty));
some(selfty));
} }
_ { _ {
// This call populates the type cache with the converted type // This call populates the type cache with the converted type
@ -2011,9 +2027,10 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
} }
fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id, fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id,
name: ast::ident, ty: ty::t, tps: [ty::t]) name: ast::ident, ty: ty::t, tps: [ty::t],
include_private: bool)
-> option<method_origin> { -> option<method_origin> {
alt lookup_method_inner(fcx, expr, name, ty) { alt lookup_method_inner(fcx, expr, name, ty, include_private) {
some({method_ty: fty, n_tps: method_n_tps, substs, origin, self_sub}) { some({method_ty: fty, n_tps: method_n_tps, substs, origin, self_sub}) {
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
let mut substs = substs; let mut substs = substs;
@ -2064,7 +2081,8 @@ enum method_kind {
} }
fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method], fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
tps: [ty::t], parent: method_kind, name: ast::ident, sp: span) tps: [ty::t], parent: method_kind, name: ast::ident, sp: span,
include_private: bool)
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t], -> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
origin: method_origin, self_sub: option<self_subst>}> { origin: method_origin, self_sub: option<self_subst>}> {
#debug("lookup_method_inner_: %? %? %s", ms, parent, name); #debug("lookup_method_inner_: %? %? %s", ms, parent, name);
@ -2080,6 +2098,10 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
tcx.sess.span_fatal( tcx.sess.span_fatal(
sp, "can not call a generic method through a \ sp, "can not call a generic method through a \
boxed iface"); boxed iface");
} else if m.privacy == ast::priv && !include_private {
tcx.sess.span_fatal(
sp, "Call to private method not allowed outside \
its defining class");
} }
ret some({method_ty: fty, ret some({method_ty: fty,
n_tps: vec::len(*m.tps), n_tps: vec::len(*m.tps),
@ -2089,7 +2111,7 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
// look up method named <name> // look up method named <name>
// its id is did // its id is did
let m_declared = ty::lookup_class_method_by_name(tcx, let m_declared = ty::lookup_class_method_by_name(tcx,
parent_id, name, sp); parent_id, name, sp);
method_static(m_declared) method_static(m_declared)
} }
an_iface(did) { method_iface(did, i) } an_iface(did) { method_iface(did, i) }
@ -2102,7 +2124,8 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
} }
fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr, fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
name: ast::ident, ty: ty::t) name: ast::ident, ty: ty::t,
include_private: bool)
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t], -> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
origin: method_origin, origin: method_origin,
self_sub: option<self_subst>}> { self_sub: option<self_subst>}> {
@ -2145,14 +2168,14 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
} }
ty::ty_iface(did, tps) { ty::ty_iface(did, tps) {
alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps, alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps,
an_iface(did), name, expr.span) { an_iface(did), name, expr.span, include_private) {
some(r) { ret some(r); } some(r) { ret some(r); }
none { } none { }
} }
} }
ty::ty_class(did, tps) { ty::ty_class(did, tps) {
alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps, alt lookup_method_inner_(tcx, *ty::iface_methods(tcx, did), tps,
cls(did), name, expr.span) { cls(did), name, expr.span, include_private) {
some(r) { ret some(r); } some(r) { ret some(r); }
none { } none { }
} }
@ -2499,7 +2522,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
opname: str, args: [option<@ast::expr>]) opname: str, args: [option<@ast::expr>])
-> option<(ty::t, bool)> { -> option<(ty::t, bool)> {
let callee_id = ast_util::op_expr_callee_id(op_ex); let callee_id = ast_util::op_expr_callee_id(op_ex);
alt lookup_method(fcx, op_ex, callee_id, opname, self_t, []) { alt lookup_method(fcx, op_ex, callee_id, opname, self_t, [], false) {
some(origin) { some(origin) {
let mut method_ty = ty::node_id_to_type(fcx.ccx.tcx, callee_id); let mut method_ty = ty::node_id_to_type(fcx.ccx.tcx, callee_id);
method_ty = universally_quantify_regions(fcx, region_env(), method_ty = universally_quantify_regions(fcx, region_env(),
@ -3108,6 +3131,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
} }
} }
ty::ty_class(base_id, _params) { ty::ty_class(base_id, _params) {
// This is just for fields -- the same code handles
// methods in both classes and ifaces
// (1) verify that the class id actually has a field called // (1) verify that the class id actually has a field called
// field // field
#debug("class named %s", ty_to_str(tcx, base_t)); #debug("class named %s", ty_to_str(tcx, base_t));
@ -3116,17 +3142,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
determines whether we look at all fields or only public determines whether we look at all fields or only public
ones ones
*/ */
let node_def = lookup_def(fcx, base.span, base.id); let cls_items = if self_ref(fcx, base.id) {
let cls_items = alt get_self_info(fcx.ccx) { // base expr is "self" -- consider all fields
some(self_impl(_, n_id)) if alt node_def { ty::lookup_class_fields(tcx, base_id)
ast::def_self(base_id) { base_id == n_id } }
_ { false }} { else {
// base expr is "self" -- consider all fields lookup_public_fields(tcx, base_id)
ty::lookup_class_fields(tcx, base_id)
}
_ { lookup_public_fields(tcx, base_id) }
}; };
alt lookup_field_ty(tcx, base_id, cls_items, field) { alt lookup_field_ty(tcx, base_id, cls_items, field) {
some(field_ty) { some(field_ty) {
// (2) look up what field's type is, and return it // (2) look up what field's type is, and return it
// FIXME: actually instantiate any type params // FIXME: actually instantiate any type params
@ -3140,7 +3163,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
} }
if !handled { if !handled {
let tps = vec::map(tys, {|ty| ast_ty_to_ty_crate(fcx.ccx, ty)}); let tps = vec::map(tys, {|ty| ast_ty_to_ty_crate(fcx.ccx, ty)});
alt lookup_method(fcx, expr, expr.id, field, expr_t, tps) { alt lookup_method(fcx, expr, expr.id, field, expr_t, tps,
self_ref(fcx, base.id)) {
some(origin) { some(origin) {
fcx.ccx.method_map.insert(id, origin); fcx.ccx.method_map.insert(id, origin);
} }
@ -3193,7 +3217,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
let p_ty = expr_ty(tcx, p); let p_ty = expr_ty(tcx, p);
alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, []) { alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, [], false) {
some(origin) { some(origin) {
fcx.ccx.method_map.insert(alloc_id, origin); fcx.ccx.method_map.insert(alloc_id, origin);
@ -3665,16 +3689,16 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method) {
false, none); false, none);
} }
fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map { fn class_types(ccx: @crate_ctxt, members: [@ast::class_member]) -> class_map {
let rslt = int_hash::<ty::t>(); let rslt = int_hash::<ty::t>();
for m in members { for m in members {
alt m.node.decl { alt m.node {
ast::instance_var(_,t,_,id) { ast::instance_var(_,t,_,id,_) {
rslt.insert(id, ast_ty_to_ty(ccx.tcx, m_collect, t)); rslt.insert(id, ast_ty_to_ty(ccx.tcx, m_collect, t));
} }
ast::class_method(mth) { ast::class_method(mth) {
rslt.insert(mth.id, ty::mk_fn(ccx.tcx, rslt.insert(mth.id, ty::mk_fn(ccx.tcx,
ty_of_method(ccx.tcx, m_collect, mth).fty)); ty_of_method(ccx.tcx, m_collect, mth).fty));
} }
} }
} }
@ -3682,10 +3706,9 @@ fn class_types(ccx: @crate_ctxt, members: [@ast::class_item]) -> class_map {
} }
fn check_class_member(ccx: @crate_ctxt, class_t: ty::t, fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
cm: ast::class_member) { cm: @ast::class_member) {
alt cm { alt cm.node {
ast::instance_var(_,t,_,_) { ast::instance_var(_,t,_,_,_) { }
}
ast::class_method(m) { ast::class_method(m) {
ccx.self_infos += [self_impl(class_t, m.self_id)]; ccx.self_infos += [self_impl(class_t, m.self_id)];
check_method(ccx, m); check_method(ccx, m);
@ -3729,8 +3752,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
ctor.node.body, ctor.node.id, false, none); ctor.node.body, ctor.node.id, false, none);
vec::pop(class_ccx.self_infos); vec::pop(class_ccx.self_infos);
// typecheck the members // typecheck the members
for m in members { check_class_member(class_ccx, class_t, for m in members { check_class_member(class_ccx, class_t, m); }
m.node.decl); }
} }
_ {/* nothing to do */ } _ {/* nothing to do */ }
} }

View file

@ -553,7 +553,9 @@ enum ret_style {
#[auto_serialize] #[auto_serialize]
type method = {ident: ident, attrs: [attribute], type method = {ident: ident, attrs: [attribute],
tps: [ty_param], decl: fn_decl, body: blk, tps: [ty_param], decl: fn_decl, body: blk,
id: node_id, span: span, self_id: node_id}; id: node_id, span: span, self_id: node_id,
privacy: privacy}; // privacy is always public, unless it's a
// class method
#[auto_serialize] #[auto_serialize]
type _mod = {view_items: [@view_item], items: [@item]}; type _mod = {view_items: [@view_item], items: [@item]};
@ -649,8 +651,8 @@ enum item_ {
item_res(fn_decl /* dtor */, [ty_param], blk, item_res(fn_decl /* dtor */, [ty_param], blk,
node_id /* dtor id */, node_id /* ctor id */), node_id /* dtor id */, node_id /* ctor id */),
item_class([ty_param], /* ty params for class */ item_class([ty_param], /* ty params for class */
[@class_item], /* methods, etc. */ [@class_member], /* methods, etc. */
/* (not including ctor) */ /* (not including ctor) */
class_ctor class_ctor
), ),
item_iface([ty_param], [ty_method]), item_iface([ty_param], [ty_method]),
@ -659,14 +661,11 @@ enum item_ {
} }
#[auto_serialize] #[auto_serialize]
type class_item_ = {privacy: privacy, decl: class_member}; type class_member = spanned<class_member_>;
#[auto_serialize] #[auto_serialize]
type class_item = spanned<class_item_>; enum class_member_ {
instance_var(ident, @ty, class_mutability, node_id, privacy),
#[auto_serialize]
enum class_member {
instance_var(ident, @ty, class_mutability, node_id),
class_method(@method) class_method(@method)
// without constrained types, have to duplicate some stuff. or factor out // without constrained types, have to duplicate some stuff. or factor out
// item to separate out things with type params? // item to separate out things with type params?

View file

@ -262,9 +262,9 @@ pure fn unguarded_pat(a: arm) -> option<[@pat]> {
// for reserving this id. // for reserving this id.
fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 } fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 }
pure fn class_item_ident(ci: @class_item) -> ident { pure fn class_item_ident(ci: @class_member) -> ident {
alt ci.node.decl { alt ci.node {
instance_var(i,_,_,_) { i } instance_var(i,_,_,_,_) { i }
class_method(it) { it.ident } class_method(it) { it.ident }
} }
} }
@ -272,31 +272,32 @@ pure fn class_item_ident(ci: @class_item) -> ident {
type ivar = {ident: ident, ty: @ty, cm: class_mutability, type ivar = {ident: ident, ty: @ty, cm: class_mutability,
id: node_id, privacy: privacy}; id: node_id, privacy: privacy};
type cmethod = {privacy: privacy, meth: @method}; fn public_methods(ms: [@method]) -> [@method] {
vec::filter(ms, {|m| alt m.privacy {
fn public_methods(cms: [cmethod]) -> [@method] { pub { true }
vec::filter_map(cms, {|cm| alt cm.privacy { _ { false }}})
pub { some(cm.meth) }
_ { none }}})
} }
fn ignore_privacy(cms: [cmethod]) -> [@method] { fn split_class_items(cs: [@class_member]) -> ([ivar], [@method]) {
vec::map(cms, {|cm| cm.meth})
}
fn split_class_items(cs: [@class_item]) -> ([ivar], [cmethod]) {
let mut vs = [], ms = []; let mut vs = [], ms = [];
for c in cs { for c in cs {
alt c.node.decl { alt c.node {
instance_var(i, t, cm, id) { instance_var(i, t, cm, id, privacy) {
vs += [{ident: i, ty: t, cm: cm, id: id, privacy: c.node.privacy}]; vs += [{ident: i, ty: t, cm: cm, id: id, privacy: privacy}];
} }
class_method(m) { ms += [{privacy: c.node.privacy, meth: m}]; } class_method(m) { ms += [m]; }
} }
} }
(vs, ms) (vs, ms)
} }
pure fn class_member_privacy(ci: @class_member) -> privacy {
alt ci.node {
instance_var(_, _, _, _, p) { p }
class_method(m) { m.privacy }
}
}
impl inlined_item_methods for inlined_item { impl inlined_item_methods for inlined_item {
fn ident() -> ident { fn ident() -> ident {
alt self { alt self {

View file

@ -27,7 +27,7 @@ type ast_fold_precursor =
fold_view_item: fn@(view_item_, ast_fold) -> view_item_, fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
fold_native_item: fn@(&&@native_item, ast_fold) -> @native_item, fold_native_item: fn@(&&@native_item, ast_fold) -> @native_item,
fold_item: fn@(&&@item, ast_fold) -> @item, fold_item: fn@(&&@item, ast_fold) -> @item,
fold_class_item: fn@(&&@class_item, ast_fold) -> @class_item, fold_class_item: fn@(&&@class_member, ast_fold) -> @class_member,
fold_item_underscore: fn@(item_, ast_fold) -> item_, fold_item_underscore: fn@(item_, ast_fold) -> item_,
fold_method: fn@(&&@method, ast_fold) -> @method, fold_method: fn@(&&@method, ast_fold) -> @method,
fold_block: fn@(blk_, span, ast_fold) -> (blk_, span), fold_block: fn@(blk_, span, ast_fold) -> (blk_, span),
@ -54,7 +54,7 @@ type a_f =
fold_view_item: fn@(&&@view_item) -> @view_item, fold_view_item: fn@(&&@view_item) -> @view_item,
fold_native_item: fn@(&&@native_item) -> @native_item, fold_native_item: fn@(&&@native_item) -> @native_item,
fold_item: fn@(&&@item) -> @item, fold_item: fn@(&&@item) -> @item,
fold_class_item: fn@(&&@class_item) -> @class_item, fold_class_item: fn@(&&@class_member) -> @class_member,
fold_item_underscore: fn@(item_) -> item_, fold_item_underscore: fn@(item_) -> item_,
fold_method: fn@(&&@method) -> @method, fold_method: fn@(&&@method) -> @method,
fold_block: fn@(blk) -> blk, fold_block: fn@(blk) -> blk,
@ -84,7 +84,7 @@ fn nf_crate_directive_dummy(&&_c: @crate_directive) -> @crate_directive {
fn nf_view_item_dummy(&&_v: @view_item) -> @view_item { fail; } fn nf_view_item_dummy(&&_v: @view_item) -> @view_item { fail; }
fn nf_native_item_dummy(&&_n: @native_item) -> @native_item { fail; } fn nf_native_item_dummy(&&_n: @native_item) -> @native_item { fail; }
fn nf_item_dummy(&&_i: @item) -> @item { fail; } fn nf_item_dummy(&&_i: @item) -> @item { fail; }
fn nf_class_item_dummy(&&_ci: @class_item) -> @class_item { fail; } fn nf_class_item_dummy(&&_ci: @class_member) -> @class_member { fail; }
fn nf_item_underscore_dummy(_i: item_) -> item_ { fail; } fn nf_item_underscore_dummy(_i: item_) -> item_ { fail; }
fn nf_method_dummy(&&_m: @method) -> @method { fail; } fn nf_method_dummy(&&_m: @method) -> @method { fail; }
fn nf_blk_dummy(_b: blk) -> blk { fail; } fn nf_blk_dummy(_b: blk) -> blk { fail; }
@ -240,18 +240,15 @@ fn noop_fold_item(&&i: @item, fld: ast_fold) -> @item {
span: fld.new_span(i.span)}; span: fld.new_span(i.span)};
} }
fn noop_fold_class_item(&&ci: @class_item, fld: ast_fold) fn noop_fold_class_item(&&ci: @class_member, fld: ast_fold)
-> @class_item { -> @class_member {
@{node: { @{node: alt ci.node {
privacy:ci.node.privacy, instance_var(ident, t, cm, id, p) {
decl: instance_var(ident, fld.fold_ty(t), cm, id, p)
alt ci.node.decl {
instance_var(ident, t, cm, id) {
instance_var(ident, fld.fold_ty(t), cm, id)
} }
class_method(m) { class_method(fld.fold_method(m)) } class_method(m) { class_method(fld.fold_method(m)) }
}}, },
span: fld.new_span(ci.span)} span: ci.span}
} }
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
@ -302,7 +299,8 @@ fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
body: fld.fold_block(m.body), body: fld.fold_block(m.body),
id: fld.new_id(m.id), id: fld.new_id(m.id),
span: fld.new_span(m.span), span: fld.new_span(m.span),
self_id: fld.new_id(m.self_id)}; self_id: fld.new_id(m.self_id),
privacy: m.privacy};
} }
@ -655,19 +653,16 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
ret afp.fold_item(i, f); ret afp.fold_item(i, f);
} }
fn f_class_item(afp: ast_fold_precursor, f: ast_fold, fn f_class_item(afp: ast_fold_precursor, f: ast_fold,
&&ci: @class_item) -> @class_item { &&ci: @class_member) -> @class_member {
@{node: @{node: alt ci.node {
{privacy:ci.node.privacy, instance_var(nm, t, mt, id, p) {
decl:
alt ci.node.decl {
instance_var(nm, t, mt, id) {
instance_var(nm, f_ty(afp, f, t), instance_var(nm, f_ty(afp, f, t),
mt, id) mt, id, p)
} }
class_method(m) { class_method(m) {
class_method(afp.fold_method(m, f)) class_method(afp.fold_method(m, f))
} }
}}, span: afp.new_span(ci.span)} }, span: afp.new_span(ci.span)}
} }
fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) -> fn f_item_underscore(afp: ast_fold_precursor, f: ast_fold, i: item_) ->
item_ { item_ {

View file

@ -1681,7 +1681,7 @@ fn parse_let(p: parser) -> @ast::decl {
} }
/* assumes "let" token has already been consumed */ /* assumes "let" token has already been consumed */
fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) { fn parse_instance_var(p:parser, pr: ast::privacy) -> @ast::class_member {
let mut is_mutbl = ast::class_immutable; let mut is_mutbl = ast::class_immutable;
let lo = p.span.lo; let lo = p.span.lo;
if eat_word(p, "mut") || eat_word(p, "mutable") { if eat_word(p, "mut") || eat_word(p, "mutable") {
@ -1693,8 +1693,8 @@ fn parse_instance_var(p:parser) -> (ast::class_member, codemap::span) {
let name = parse_ident(p); let name = parse_ident(p);
expect(p, token::COLON); expect(p, token::COLON);
let ty = parse_ty(p, false); let ty = parse_ty(p, false);
ret (ast::instance_var(name, ty, is_mutbl, p.get_id()), ret @{node: ast::instance_var(name, ty, is_mutbl, p.get_id(), pr),
ast_util::mk_sp(lo, p.last_span.hi)); span: ast_util::mk_sp(lo, p.last_span.hi)};
} }
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt { fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
@ -1986,7 +1986,7 @@ fn parse_method_name(p: parser) -> ast::ident {
} }
} }
fn parse_method(p: parser) -> @ast::method { fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
let attrs = parse_outer_attributes(p); let attrs = parse_outer_attributes(p);
let lo = p.span.lo, pur = parse_fn_purity(p); let lo = p.span.lo, pur = parse_fn_purity(p);
let ident = parse_method_name(p); let ident = parse_method_name(p);
@ -1996,7 +1996,7 @@ fn parse_method(p: parser) -> @ast::method {
let attrs = attrs + inner_attrs; let attrs = attrs + inner_attrs;
@{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body, @{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi), id: p.get_id(), span: ast_util::mk_sp(lo, body.span.hi),
self_id: p.get_id()} self_id: p.get_id(), privacy: pr}
} }
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
@ -2034,7 +2034,7 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
let ty = parse_ty(p, false); let ty = parse_ty(p, false);
let mut meths = []; let mut meths = [];
expect(p, token::LBRACE); expect(p, token::LBRACE);
while !eat(p, token::RBRACE) { meths += [parse_method(p)]; } while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; }
ret mk_item(p, lo, p.last_span.hi, ident, ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_impl(tps, ifce, ty, meths), attrs); ast::item_impl(tps, ifce, ty, meths), attrs);
} }
@ -2070,24 +2070,15 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
let class_path = ident_to_path(p.last_span, class_name); let class_path = ident_to_path(p.last_span, class_name);
let ty_params = parse_ty_params(p); let ty_params = parse_ty_params(p);
expect(p, token::LBRACE); expect(p, token::LBRACE);
let mut items: [@ast::class_item] = []; let mut ms: [@ast::class_member] = [];
let ctor_id = p.get_id(); let ctor_id = p.get_id();
let mut the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none; let mut the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none;
while p.token != token::RBRACE { while p.token != token::RBRACE {
alt parse_class_item(p, class_path) { alt parse_class_item(p, class_path) {
ctor_decl(a_fn_decl, blk, s) { ctor_decl(a_fn_decl, blk, s) {
the_ctor = some((a_fn_decl, blk, s)); the_ctor = some((a_fn_decl, blk, s));
} }
plain_decl(a_decl, s) { members(mms) { ms += mms; }
items += [@{node: {privacy: ast::pub, decl: a_decl},
span: s}];
}
priv_decls(some_decls) {
items += vec::map(some_decls, {|p|
let (d, s) = p;
@{node: {privacy: ast::priv, decl: d},
span: s}});
}
} }
} }
p.bump(); p.bump();
@ -2095,7 +2086,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
some((ct_d, ct_b, ct_s)) { some((ct_d, ct_b, ct_s)) {
ret mk_item(p, lo, p.last_span.hi, ret mk_item(p, lo, p.last_span.hi,
class_name, class_name,
ast::item_class(ty_params, items, ast::item_class(ty_params, ms,
{node: {id: ctor_id, {node: {id: ctor_id,
self_id: p.get_id(), self_id: p.get_id(),
dec: ct_d, dec: ct_d,
@ -2112,16 +2103,10 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
// lets us identify the constructor declaration at // lets us identify the constructor declaration at
// parse time // parse time
// we don't really want just the fn_decl...
enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span), enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
// assumed to be public members([@ast::class_member]) }
plain_decl(ast::class_member, codemap::span),
// contents of a priv section --
// parse_class_item ensures that
// none of these are a ctor decl
priv_decls([(ast::class_member, codemap::span)])}
fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents { fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
if eat_word(p, "new") { if eat_word(p, "new") {
let lo = p.last_span.lo; let lo = p.last_span.lo;
// Can ctors have attrs? // Can ctors have attrs?
@ -2140,28 +2125,28 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
let mut results = []; let mut results = [];
while p.token != token::RBRACE { while p.token != token::RBRACE {
if eat_word(p, "let") { if eat_word(p, "let") {
let a_var = parse_instance_var(p); let a_var = parse_instance_var(p, ast::priv);
expect(p, token::SEMI); expect(p, token::SEMI);
results += [a_var]; results += [a_var];
} }
else { else {
let m = parse_method(p); let m = parse_method(p, ast::priv);
results += [(ast::class_method(m), m.span)]; results += [@{node: ast::class_method(m), span: m.span}];
} }
} }
p.bump(); p.bump();
ret priv_decls(results); ret members(results);
} }
else { else {
// Probably need to parse attrs // Probably need to parse attrs
ret if eat_word(p, "let") { ret if eat_word(p, "let") {
let (a_var, a_span) = parse_instance_var(p); let ivar = parse_instance_var(p, ast::pub);
expect(p, token::SEMI); expect(p, token::SEMI);
plain_decl(a_var, a_span) members([ivar])
} }
else { else {
let m = parse_method(p); let m = parse_method(p, ast::pub);
plain_decl(ast::class_method(m), m.span) members([@{node: ast::class_method(m), span: m.span}])
} }
} }
} }

View file

@ -506,7 +506,8 @@ fn print_item(s: ps, &&item: @ast::item) {
*/ */
hardbreak_if_not_bol(s); hardbreak_if_not_bol(s);
maybe_print_comment(s, ci.span.lo); maybe_print_comment(s, ci.span.lo);
alt ci.node.privacy { let pr = ast_util::class_member_privacy(ci);
alt pr {
ast::priv { ast::priv {
head(s, "priv"); head(s, "priv");
bopen(s); bopen(s);
@ -514,8 +515,8 @@ fn print_item(s: ps, &&item: @ast::item) {
} }
_ {} _ {}
} }
alt ci.node.decl { alt ci.node {
ast::instance_var(nm, t, mt, _) { ast::instance_var(nm, t, mt, _,_) {
word_nbsp(s, "let"); word_nbsp(s, "let");
alt mt { alt mt {
ast::class_mutable { word_nbsp(s, "mut"); } ast::class_mutable { word_nbsp(s, "mut"); }
@ -530,7 +531,7 @@ fn print_item(s: ps, &&item: @ast::item) {
print_method(s, m); print_method(s, m);
} }
} }
alt ci.node.privacy { alt pr {
ast::priv { bclose(s, ci.span); } ast::priv { bclose(s, ci.span); }
_ {} _ {}
} }

View file

@ -55,7 +55,7 @@ type visitor<E> =
visit_ty_params: fn@([ty_param], E, vt<E>), visit_ty_params: fn@([ty_param], E, vt<E>),
visit_constr: fn@(@path, span, node_id, E, vt<E>), visit_constr: fn@(@path, span, node_id, E, vt<E>),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
visit_class_item: fn@(span, privacy, class_member, E, vt<E>)}; visit_class_item: fn@(@class_member, E, vt<E>)};
fn default_visitor<E>() -> visitor<E> { fn default_visitor<E>() -> visitor<E> {
ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _), ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _),
@ -73,7 +73,7 @@ fn default_visitor<E>() -> visitor<E> {
visit_ty_params: bind visit_ty_params::<E>(_, _, _), visit_ty_params: bind visit_ty_params::<E>(_, _, _),
visit_constr: bind visit_constr::<E>(_, _, _, _, _), visit_constr: bind visit_constr::<E>(_, _, _, _, _),
visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _), visit_fn: bind visit_fn::<E>(_, _, _, _, _, _, _),
visit_class_item: bind visit_class_item::<E>(_,_,_,_,_)}; visit_class_item: bind visit_class_item::<E>(_,_,_)};
} }
fn visit_crate<E>(c: crate, e: E, v: vt<E>) { fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
@ -139,7 +139,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
item_class(tps, members, ctor) { item_class(tps, members, ctor) {
v.visit_ty_params(tps, e, v); v.visit_ty_params(tps, e, v);
for m in members { for m in members {
v.visit_class_item(m.span, m.node.privacy, m.node.decl, e, v); v.visit_class_item(m, e, v);
} }
// make up a fake fn so as to call visit_fn on the ctor // make up a fake fn so as to call visit_fn on the ctor
v.visit_fn(fk_ctor(i.ident, tps), ctor.node.dec, v.visit_fn(fk_ctor(i.ident, tps), ctor.node.dec,
@ -155,10 +155,9 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
} }
} }
fn visit_class_item<E>(_s: span, _p: privacy, cm: class_member, fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
e:E, v:vt<E>) { alt cm.node {
alt cm { instance_var(_, t, _, _, _) {
instance_var(ident, t, mt, id) {
v.visit_ty(t, e, v); v.visit_ty(t, e, v);
} }
class_method(m) { class_method(m) {
@ -427,7 +426,7 @@ type simple_visitor =
visit_ty_params: fn@([ty_param]), visit_ty_params: fn@([ty_param]),
visit_constr: fn@(@path, span, node_id), visit_constr: fn@(@path, span, node_id),
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
visit_class_item: fn@(span, privacy, class_member)}; visit_class_item: fn@(@class_member)};
fn simple_ignore_ty(_t: @ty) {} fn simple_ignore_ty(_t: @ty) {}
@ -448,7 +447,7 @@ fn default_simple_visitor() -> simple_visitor {
visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { }, visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
_id: node_id) { }, _id: node_id) { },
visit_class_item: fn@(_s: span, _p: privacy, _c: class_member) {} visit_class_item: fn@(_c: @class_member) {}
}; };
} }
@ -523,11 +522,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
} else { } else {
bind v_ty(v.visit_ty, _, _, _) bind v_ty(v.visit_ty, _, _, _)
}; };
fn v_class_item(f: fn@(span, privacy, class_member), fn v_class_item(f: fn@(@class_member),
s:span, p:privacy, cm: class_member, &&e: (), cm: @class_member, &&e: (),
v: vt<()>) { v: vt<()>) {
f(s, p, cm); f(cm);
visit_class_item(s, p, cm, e, v); visit_class_item(cm, e, v);
} }
ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _), ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
visit_view_item: bind v_view_item(v.visit_view_item, _, _, _), visit_view_item: bind v_view_item(v.visit_view_item, _, _, _),
@ -546,7 +545,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _), visit_constr: bind v_constr(v.visit_constr, _, _, _, _, _),
visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _), visit_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _),
visit_class_item: bind v_class_item(v.visit_class_item, _, _, visit_class_item: bind v_class_item(v.visit_class_item, _, _,
_, _, _) _)
}); });
} }

View file

@ -1,4 +1,4 @@
// error-pattern:attempted access of field nap on type // error-pattern:Call to private method not allowed
class cat { class cat {
priv { priv {
let mut meows : uint; let mut meows : uint;

View file

@ -8,7 +8,7 @@ class cat {
fn play() { fn play() {
meows += 1u; meows += 1u;
nap(); self.nap();
} }
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; } new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
} }