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:
parent
fe610f04d8
commit
f7bbe537c1
18 changed files with 201 additions and 198 deletions
|
@ -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,
|
||||
c: ast::class_member) {
|
||||
alt c {
|
||||
ast::instance_var(_, _, _, id) {
|
||||
visit_class_item: fn@(c: @ast::class_member) {
|
||||
alt c.node {
|
||||
ast::instance_var(_, _, _, id,_) {
|
||||
vfn(id)
|
||||
}
|
||||
ast::class_method(_) {
|
||||
|
|
|
@ -431,7 +431,7 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
|||
'u' { ast::unsafe_fn }
|
||||
'f' { ast::impure_fn }
|
||||
'p' { ast::pure_fn }
|
||||
}}];
|
||||
}, privacy: ast::pub}];
|
||||
}
|
||||
@result
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
items: [@class_item], path: [str], &index: [entry<str>]) {
|
||||
items: [@class_member], path: [str], &index: [entry<str>]) {
|
||||
for it in items {
|
||||
alt it.node.privacy {
|
||||
alt ast_util::class_member_privacy(it) {
|
||||
priv { cont; }
|
||||
pub {
|
||||
let (id, ident) = alt it.node.decl {
|
||||
instance_var(v, _, _, vid) { (vid, v) }
|
||||
let (id, ident) = alt it.node {
|
||||
instance_var(v, _, _, vid, _) { (vid, v) }
|
||||
class_method(it) { (it.id, it.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 */
|
||||
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||
id: node_id, path: ast_map::path,
|
||||
items: [@class_item],
|
||||
items: [@class_member],
|
||||
global_index: @mut[entry<int>])
|
||||
-> [entry<int>] {
|
||||
let index = @mut [];
|
||||
|
@ -376,12 +376,12 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
|||
for ci in items {
|
||||
/* We encode both private and public fields -- need to include
|
||||
private fields to get the offsets right */
|
||||
alt ci.node.decl {
|
||||
instance_var(nm, _, mt, id) {
|
||||
alt ci.node {
|
||||
instance_var(nm, _, mt, id, pr) {
|
||||
*index += [{val: id, pos: ebml_w.writer.tell()}];
|
||||
ebml_w.start_tag(tag_items_data_item);
|
||||
#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_path(ebml_w, path, ast_map::path_name(nm));
|
||||
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
|
||||
|
@ -390,6 +390,8 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
|||
ebml_w.end_tag();
|
||||
}
|
||||
class_method(m) {
|
||||
alt m.privacy {
|
||||
pub {
|
||||
*index += [{val: m.id, pos: ebml_w.writer.tell()}];
|
||||
/* Not sure whether we really need to have two indices,
|
||||
but it works for now -- tjc */
|
||||
|
@ -403,6 +405,9 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
|||
encode_info_for_method(ecx, ebml_w, impl_path,
|
||||
should_inline(m.attrs), id, m, []);
|
||||
}
|
||||
_ { /* don't encode private methods */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*index
|
||||
|
@ -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));
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
for mt in ms {
|
||||
alt mt.privacy {
|
||||
for m in ms {
|
||||
alt m.privacy {
|
||||
priv { /* do nothing */ }
|
||||
pub {
|
||||
let m = mt.meth;
|
||||
ebml_w.start_tag(tag_item_method);
|
||||
#debug("Writing %s %d", m.ident, m.id);
|
||||
encode_family(ebml_w, purity_fn_family(m.decl.purity));
|
||||
|
|
|
@ -182,10 +182,8 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
|||
let p = extend(cx, i.ident);
|
||||
for ci in items {
|
||||
// only need to handle methods
|
||||
alt ci.node.decl {
|
||||
class_method(m) {
|
||||
map_method(d_id, p, m, cx);
|
||||
}
|
||||
alt ci.node {
|
||||
class_method(m) { map_method(d_id, p, m, cx); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,9 +216,8 @@ fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
|
|||
alt item.node {
|
||||
item_class(tps, items, ctor) {
|
||||
v.visit_ty_params(tps, cx, v);
|
||||
vec::map::<@class_item, ()>(items,
|
||||
{|i| v.visit_class_item(i.span,
|
||||
i.node.privacy, i.node.decl, cx, v); });
|
||||
vec::map::<@class_member, ()>(items,
|
||||
{|i| v.visit_class_item(i, cx, v); });
|
||||
v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec,
|
||||
ctor.node.body, ctor.span, ctor.node.id,
|
||||
@{in_ctor: some(ctor.node.self_id) with *cx}, v);
|
||||
|
|
|
@ -89,7 +89,7 @@ enum mod_index_entry {
|
|||
mie_import_ident(node_id, span),
|
||||
mie_item(@ast::item),
|
||||
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_enum_variant(/* variant index */uint,
|
||||
/*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);
|
||||
/* visit the items */
|
||||
for cm in members {
|
||||
alt cm.node.decl {
|
||||
alt cm.node {
|
||||
class_method(m) {
|
||||
let msc = cons(scope_method(m.self_id, tps + m.tps),
|
||||
@class_scope);
|
||||
visit_fn_with_scope(e,
|
||||
visit::fk_item_fn(m.ident, tps), m.decl, m.body,
|
||||
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
|
||||
*/
|
||||
fn lookup_in_class(parent_id: def_id,
|
||||
members: [@class_item], name: ident)
|
||||
members: [@class_member], name: ident)
|
||||
-> option<def> {
|
||||
for m in members {
|
||||
alt m.node.decl {
|
||||
instance_var(v_name,_,_,id) {
|
||||
alt m.node {
|
||||
instance_var(v_name,_,_,id,_) {
|
||||
if v_name == name {
|
||||
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) {
|
||||
alt class_item.node.decl {
|
||||
instance_var(_,_,_,id) {
|
||||
alt class_item.node {
|
||||
instance_var(_,_,_,id,_) {
|
||||
ret some(ast::def_class_field(local_def(parent_id),
|
||||
local_def(id)));
|
||||
}
|
||||
|
|
|
@ -4368,8 +4368,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
|||
|
||||
// Translate methods
|
||||
let (_, ms) = ast_util::split_class_items(items);
|
||||
impl::trans_impl(ccx, *path, item.ident,
|
||||
vec::map(ms, {|m| m.meth}), tps);
|
||||
impl::trans_impl(ccx, *path, item.ident, ms, tps);
|
||||
}
|
||||
_ {/* fall through */ }
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
|||
item_class(tps, items, ctor) {
|
||||
cx.rmap.insert(ctor.node.id, ());
|
||||
for vec::each(items) {|item|
|
||||
alt item.node.decl {
|
||||
alt item.node {
|
||||
class_method(m) {
|
||||
cx.rmap.insert(m.id, ());
|
||||
if tps.len() > 0u ||
|
||||
|
|
|
@ -156,7 +156,8 @@ type param_bounds = @[param_bound];
|
|||
type method = {ident: ast::ident,
|
||||
tps: @[param_bounds],
|
||||
fty: fn_ty,
|
||||
purity: ast::purity};
|
||||
purity: ast::purity,
|
||||
privacy: ast::privacy};
|
||||
|
||||
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) {
|
||||
some(ast_map::node_item(@{node: item_class(_,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}})
|
||||
}
|
||||
_ {
|
||||
|
@ -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
|
||||
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,
|
||||
sp: span) -> def_id {
|
||||
if check is_local(did) {
|
||||
let ms = lookup_class_method_ids(cx, did);
|
||||
for m in ms {
|
||||
if m.name == name && m.privacy == ast::pub {
|
||||
if m.name == name {
|
||||
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));
|
||||
}
|
||||
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 = [];
|
||||
for it in items {
|
||||
alt it.node.decl {
|
||||
instance_var(nm, _, cm, id) {
|
||||
alt it.node {
|
||||
instance_var(nm, _, cm, id, privacy) {
|
||||
rslt += [{ident: nm, id: ast_util::local_def(id),
|
||||
privacy: it.node.privacy, mutability: cm}];
|
||||
}
|
||||
class_method(_) {
|
||||
privacy: privacy, mutability: cm}];
|
||||
}
|
||||
class_method(_) { }
|
||||
}
|
||||
}
|
||||
rslt
|
||||
|
|
|
@ -83,6 +83,22 @@ type fn_ctxt =
|
|||
next_region_var_id: @mut int,
|
||||
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 {
|
||||
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 {
|
||||
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
|
||||
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)
|
||||
-> ty::method {
|
||||
{ident: m.ident, tps: ty_param_bounds(tcx, mode, m.tps),
|
||||
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
|
||||
|
@ -939,9 +956,9 @@ mod collect {
|
|||
}
|
||||
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
|
||||
let (_,ms) = split_class_items(its);
|
||||
// Only public methods need to be stored
|
||||
let ps = ast_util::public_methods(ms);
|
||||
store_methods::<@ast::method>(tcx, id, ps, {|m|
|
||||
// All methods need to be stored, since lookup_method
|
||||
// relies on the same method cache for self-calls
|
||||
store_methods::<@ast::method>(tcx, id, ms, {|m|
|
||||
ty_of_method(tcx, m_collect, m)});
|
||||
}
|
||||
}
|
||||
|
@ -1101,8 +1118,7 @@ mod collect {
|
|||
mk_ty_params(tcx, tps).params);
|
||||
// Need to convert all methods so we can check internal
|
||||
// references to private methods
|
||||
convert_methods(tcx, ast_util::ignore_privacy(methods), @[],
|
||||
some(selfty));
|
||||
convert_methods(tcx, methods, @[], some(selfty));
|
||||
}
|
||||
_ {
|
||||
// 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,
|
||||
name: ast::ident, ty: ty::t, tps: [ty::t])
|
||||
name: ast::ident, ty: ty::t, tps: [ty::t],
|
||||
include_private: bool)
|
||||
-> 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}) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let mut substs = substs;
|
||||
|
@ -2064,7 +2081,8 @@ enum method_kind {
|
|||
}
|
||||
|
||||
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],
|
||||
origin: method_origin, self_sub: option<self_subst>}> {
|
||||
#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(
|
||||
sp, "can not call a generic method through a \
|
||||
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,
|
||||
n_tps: vec::len(*m.tps),
|
||||
|
@ -2102,7 +2124,8 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
|
|||
}
|
||||
|
||||
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],
|
||||
origin: method_origin,
|
||||
self_sub: option<self_subst>}> {
|
||||
|
@ -2145,14 +2168,14 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
|
|||
}
|
||||
ty::ty_iface(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); }
|
||||
none { }
|
||||
}
|
||||
}
|
||||
ty::ty_class(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); }
|
||||
none { }
|
||||
}
|
||||
|
@ -2499,7 +2522,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
opname: str, args: [option<@ast::expr>])
|
||||
-> option<(ty::t, bool)> {
|
||||
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) {
|
||||
let mut method_ty = ty::node_id_to_type(fcx.ccx.tcx, callee_id);
|
||||
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) {
|
||||
// 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
|
||||
// field
|
||||
#debug("class named %s", ty_to_str(tcx, base_t));
|
||||
|
@ -3116,15 +3142,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
determines whether we look at all fields or only public
|
||||
ones
|
||||
*/
|
||||
let node_def = lookup_def(fcx, base.span, base.id);
|
||||
let cls_items = alt get_self_info(fcx.ccx) {
|
||||
some(self_impl(_, n_id)) if alt node_def {
|
||||
ast::def_self(base_id) { base_id == n_id }
|
||||
_ { false }} {
|
||||
let cls_items = if self_ref(fcx, base.id) {
|
||||
// base expr is "self" -- consider all fields
|
||||
ty::lookup_class_fields(tcx, base_id)
|
||||
}
|
||||
_ { lookup_public_fields(tcx, base_id) }
|
||||
else {
|
||||
lookup_public_fields(tcx, base_id)
|
||||
};
|
||||
alt lookup_field_ty(tcx, base_id, cls_items, field) {
|
||||
some(field_ty) {
|
||||
|
@ -3140,7 +3163,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
}
|
||||
if !handled {
|
||||
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) {
|
||||
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);
|
||||
|
||||
alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, []) {
|
||||
alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, [], false) {
|
||||
some(origin) {
|
||||
fcx.ccx.method_map.insert(alloc_id, origin);
|
||||
|
||||
|
@ -3665,11 +3689,11 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method) {
|
|||
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>();
|
||||
for m in members {
|
||||
alt m.node.decl {
|
||||
ast::instance_var(_,t,_,id) {
|
||||
alt m.node {
|
||||
ast::instance_var(_,t,_,id,_) {
|
||||
rslt.insert(id, ast_ty_to_ty(ccx.tcx, m_collect, t));
|
||||
}
|
||||
ast::class_method(mth) {
|
||||
|
@ -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,
|
||||
cm: ast::class_member) {
|
||||
alt cm {
|
||||
ast::instance_var(_,t,_,_) {
|
||||
}
|
||||
cm: @ast::class_member) {
|
||||
alt cm.node {
|
||||
ast::instance_var(_,t,_,_,_) { }
|
||||
ast::class_method(m) {
|
||||
ccx.self_infos += [self_impl(class_t, m.self_id)];
|
||||
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);
|
||||
vec::pop(class_ccx.self_infos);
|
||||
// typecheck the members
|
||||
for m in members { check_class_member(class_ccx, class_t,
|
||||
m.node.decl); }
|
||||
for m in members { check_class_member(class_ccx, class_t, m); }
|
||||
}
|
||||
_ {/* nothing to do */ }
|
||||
}
|
||||
|
|
|
@ -553,7 +553,9 @@ enum ret_style {
|
|||
#[auto_serialize]
|
||||
type method = {ident: ident, attrs: [attribute],
|
||||
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]
|
||||
type _mod = {view_items: [@view_item], items: [@item]};
|
||||
|
@ -649,7 +651,7 @@ enum item_ {
|
|||
item_res(fn_decl /* dtor */, [ty_param], blk,
|
||||
node_id /* dtor id */, node_id /* ctor id */),
|
||||
item_class([ty_param], /* ty params for class */
|
||||
[@class_item], /* methods, etc. */
|
||||
[@class_member], /* methods, etc. */
|
||||
/* (not including ctor) */
|
||||
class_ctor
|
||||
),
|
||||
|
@ -659,14 +661,11 @@ enum item_ {
|
|||
}
|
||||
|
||||
#[auto_serialize]
|
||||
type class_item_ = {privacy: privacy, decl: class_member};
|
||||
type class_member = spanned<class_member_>;
|
||||
|
||||
#[auto_serialize]
|
||||
type class_item = spanned<class_item_>;
|
||||
|
||||
#[auto_serialize]
|
||||
enum class_member {
|
||||
instance_var(ident, @ty, class_mutability, node_id),
|
||||
enum class_member_ {
|
||||
instance_var(ident, @ty, class_mutability, node_id, privacy),
|
||||
class_method(@method)
|
||||
// without constrained types, have to duplicate some stuff. or factor out
|
||||
// item to separate out things with type params?
|
||||
|
|
|
@ -262,9 +262,9 @@ pure fn unguarded_pat(a: arm) -> option<[@pat]> {
|
|||
// for reserving this id.
|
||||
fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 }
|
||||
|
||||
pure fn class_item_ident(ci: @class_item) -> ident {
|
||||
alt ci.node.decl {
|
||||
instance_var(i,_,_,_) { i }
|
||||
pure fn class_item_ident(ci: @class_member) -> ident {
|
||||
alt ci.node {
|
||||
instance_var(i,_,_,_,_) { i }
|
||||
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,
|
||||
id: node_id, privacy: privacy};
|
||||
|
||||
type cmethod = {privacy: privacy, meth: @method};
|
||||
|
||||
fn public_methods(cms: [cmethod]) -> [@method] {
|
||||
vec::filter_map(cms, {|cm| alt cm.privacy {
|
||||
pub { some(cm.meth) }
|
||||
_ { none }}})
|
||||
fn public_methods(ms: [@method]) -> [@method] {
|
||||
vec::filter(ms, {|m| alt m.privacy {
|
||||
pub { true }
|
||||
_ { false }}})
|
||||
}
|
||||
|
||||
fn ignore_privacy(cms: [cmethod]) -> [@method] {
|
||||
vec::map(cms, {|cm| cm.meth})
|
||||
}
|
||||
|
||||
fn split_class_items(cs: [@class_item]) -> ([ivar], [cmethod]) {
|
||||
fn split_class_items(cs: [@class_member]) -> ([ivar], [@method]) {
|
||||
let mut vs = [], ms = [];
|
||||
for c in cs {
|
||||
alt c.node.decl {
|
||||
instance_var(i, t, cm, id) {
|
||||
vs += [{ident: i, ty: t, cm: cm, id: id, privacy: c.node.privacy}];
|
||||
alt c.node {
|
||||
instance_var(i, t, cm, id, 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)
|
||||
}
|
||||
|
||||
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 {
|
||||
fn ident() -> ident {
|
||||
alt self {
|
||||
|
|
|
@ -27,7 +27,7 @@ type ast_fold_precursor =
|
|||
fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
|
||||
fold_native_item: fn@(&&@native_item, ast_fold) -> @native_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_method: fn@(&&@method, ast_fold) -> @method,
|
||||
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_native_item: fn@(&&@native_item) -> @native_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_method: fn@(&&@method) -> @method,
|
||||
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_native_item_dummy(&&_n: @native_item) -> @native_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_method_dummy(&&_m: @method) -> @method { 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)};
|
||||
}
|
||||
|
||||
fn noop_fold_class_item(&&ci: @class_item, fld: ast_fold)
|
||||
-> @class_item {
|
||||
@{node: {
|
||||
privacy:ci.node.privacy,
|
||||
decl:
|
||||
alt ci.node.decl {
|
||||
instance_var(ident, t, cm, id) {
|
||||
instance_var(ident, fld.fold_ty(t), cm, id)
|
||||
fn noop_fold_class_item(&&ci: @class_member, fld: ast_fold)
|
||||
-> @class_member {
|
||||
@{node: alt ci.node {
|
||||
instance_var(ident, t, cm, id, p) {
|
||||
instance_var(ident, fld.fold_ty(t), cm, id, p)
|
||||
}
|
||||
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_ {
|
||||
|
@ -302,7 +299,8 @@ fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
|
|||
body: fld.fold_block(m.body),
|
||||
id: fld.new_id(m.id),
|
||||
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);
|
||||
}
|
||||
fn f_class_item(afp: ast_fold_precursor, f: ast_fold,
|
||||
&&ci: @class_item) -> @class_item {
|
||||
@{node:
|
||||
{privacy:ci.node.privacy,
|
||||
decl:
|
||||
alt ci.node.decl {
|
||||
instance_var(nm, t, mt, id) {
|
||||
&&ci: @class_member) -> @class_member {
|
||||
@{node: alt ci.node {
|
||||
instance_var(nm, t, mt, id, p) {
|
||||
instance_var(nm, f_ty(afp, f, t),
|
||||
mt, id)
|
||||
mt, id, p)
|
||||
}
|
||||
class_method(m) {
|
||||
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_) ->
|
||||
item_ {
|
||||
|
|
|
@ -1681,7 +1681,7 @@ fn parse_let(p: parser) -> @ast::decl {
|
|||
}
|
||||
|
||||
/* 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 lo = p.span.lo;
|
||||
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);
|
||||
expect(p, token::COLON);
|
||||
let ty = parse_ty(p, false);
|
||||
ret (ast::instance_var(name, ty, is_mutbl, p.get_id()),
|
||||
ast_util::mk_sp(lo, p.last_span.hi));
|
||||
ret @{node: ast::instance_var(name, ty, is_mutbl, p.get_id(), pr),
|
||||
span: ast_util::mk_sp(lo, p.last_span.hi)};
|
||||
}
|
||||
|
||||
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 lo = p.span.lo, pur = parse_fn_purity(p);
|
||||
let ident = parse_method_name(p);
|
||||
|
@ -1996,7 +1996,7 @@ fn parse_method(p: parser) -> @ast::method {
|
|||
let attrs = attrs + inner_attrs;
|
||||
@{ident: ident, attrs: attrs, tps: tps, decl: decl, body: body,
|
||||
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 {
|
||||
|
@ -2034,7 +2034,7 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
let ty = parse_ty(p, false);
|
||||
let mut meths = [];
|
||||
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,
|
||||
ast::item_impl(tps, ifce, ty, meths), attrs);
|
||||
}
|
||||
|
@ -2070,7 +2070,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
let class_path = ident_to_path(p.last_span, class_name);
|
||||
let ty_params = parse_ty_params(p);
|
||||
expect(p, token::LBRACE);
|
||||
let mut items: [@ast::class_item] = [];
|
||||
let mut ms: [@ast::class_member] = [];
|
||||
let ctor_id = p.get_id();
|
||||
let mut the_ctor : option<(ast::fn_decl, ast::blk, codemap::span)> = none;
|
||||
while p.token != token::RBRACE {
|
||||
|
@ -2078,16 +2078,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
ctor_decl(a_fn_decl, blk, s) {
|
||||
the_ctor = some((a_fn_decl, blk, s));
|
||||
}
|
||||
plain_decl(a_decl, s) {
|
||||
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}});
|
||||
}
|
||||
members(mms) { ms += mms; }
|
||||
}
|
||||
}
|
||||
p.bump();
|
||||
|
@ -2095,7 +2086,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
some((ct_d, ct_b, ct_s)) {
|
||||
ret mk_item(p, lo, p.last_span.hi,
|
||||
class_name,
|
||||
ast::item_class(ty_params, items,
|
||||
ast::item_class(ty_params, ms,
|
||||
{node: {id: ctor_id,
|
||||
self_id: p.get_id(),
|
||||
dec: ct_d,
|
||||
|
@ -2112,14 +2103,8 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
|||
|
||||
// lets us identify the constructor declaration at
|
||||
// parse time
|
||||
// we don't really want just the fn_decl...
|
||||
enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
|
||||
// assumed to be public
|
||||
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)])}
|
||||
members([@ast::class_member]) }
|
||||
|
||||
fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
|
||||
if eat_word(p, "new") {
|
||||
|
@ -2140,28 +2125,28 @@ enum class_contents { ctor_decl(ast::fn_decl, ast::blk, codemap::span),
|
|||
let mut results = [];
|
||||
while p.token != token::RBRACE {
|
||||
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);
|
||||
results += [a_var];
|
||||
}
|
||||
else {
|
||||
let m = parse_method(p);
|
||||
results += [(ast::class_method(m), m.span)];
|
||||
let m = parse_method(p, ast::priv);
|
||||
results += [@{node: ast::class_method(m), span: m.span}];
|
||||
}
|
||||
}
|
||||
p.bump();
|
||||
ret priv_decls(results);
|
||||
ret members(results);
|
||||
}
|
||||
else {
|
||||
// Probably need to parse attrs
|
||||
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);
|
||||
plain_decl(a_var, a_span)
|
||||
members([ivar])
|
||||
}
|
||||
else {
|
||||
let m = parse_method(p);
|
||||
plain_decl(ast::class_method(m), m.span)
|
||||
let m = parse_method(p, ast::pub);
|
||||
members([@{node: ast::class_method(m), span: m.span}])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -506,7 +506,8 @@ fn print_item(s: ps, &&item: @ast::item) {
|
|||
*/
|
||||
hardbreak_if_not_bol(s);
|
||||
maybe_print_comment(s, ci.span.lo);
|
||||
alt ci.node.privacy {
|
||||
let pr = ast_util::class_member_privacy(ci);
|
||||
alt pr {
|
||||
ast::priv {
|
||||
head(s, "priv");
|
||||
bopen(s);
|
||||
|
@ -514,8 +515,8 @@ fn print_item(s: ps, &&item: @ast::item) {
|
|||
}
|
||||
_ {}
|
||||
}
|
||||
alt ci.node.decl {
|
||||
ast::instance_var(nm, t, mt, _) {
|
||||
alt ci.node {
|
||||
ast::instance_var(nm, t, mt, _,_) {
|
||||
word_nbsp(s, "let");
|
||||
alt mt {
|
||||
ast::class_mutable { word_nbsp(s, "mut"); }
|
||||
|
@ -530,7 +531,7 @@ fn print_item(s: ps, &&item: @ast::item) {
|
|||
print_method(s, m);
|
||||
}
|
||||
}
|
||||
alt ci.node.privacy {
|
||||
alt pr {
|
||||
ast::priv { bclose(s, ci.span); }
|
||||
_ {}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ type visitor<E> =
|
|||
visit_ty_params: fn@([ty_param], 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_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> {
|
||||
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_constr: bind visit_constr::<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>) {
|
||||
|
@ -139,7 +139,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
|||
item_class(tps, members, ctor) {
|
||||
v.visit_ty_params(tps, e, v);
|
||||
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
|
||||
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,
|
||||
e:E, v:vt<E>) {
|
||||
alt cm {
|
||||
instance_var(ident, t, mt, id) {
|
||||
fn visit_class_item<E>(cm: @class_member, e:E, v:vt<E>) {
|
||||
alt cm.node {
|
||||
instance_var(_, t, _, _, _) {
|
||||
v.visit_ty(t, e, v);
|
||||
}
|
||||
class_method(m) {
|
||||
|
@ -427,7 +426,7 @@ type simple_visitor =
|
|||
visit_ty_params: fn@([ty_param]),
|
||||
visit_constr: fn@(@path, 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) {}
|
||||
|
||||
|
@ -448,7 +447,7 @@ fn default_simple_visitor() -> simple_visitor {
|
|||
visit_constr: fn@(_p: @path, _sp: span, _id: node_id) { },
|
||||
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
|
||||
_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 {
|
||||
bind v_ty(v.visit_ty, _, _, _)
|
||||
};
|
||||
fn v_class_item(f: fn@(span, privacy, class_member),
|
||||
s:span, p:privacy, cm: class_member, &&e: (),
|
||||
fn v_class_item(f: fn@(@class_member),
|
||||
cm: @class_member, &&e: (),
|
||||
v: vt<()>) {
|
||||
f(s, p, cm);
|
||||
visit_class_item(s, p, cm, e, v);
|
||||
f(cm);
|
||||
visit_class_item(cm, e, v);
|
||||
}
|
||||
ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
|
||||
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_fn: bind v_fn(v.visit_fn, _, _, _, _, _, _, _),
|
||||
visit_class_item: bind v_class_item(v.visit_class_item, _, _,
|
||||
_, _, _)
|
||||
_)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// error-pattern:attempted access of field nap on type
|
||||
// error-pattern:Call to private method not allowed
|
||||
class cat {
|
||||
priv {
|
||||
let mut meows : uint;
|
||||
|
|
|
@ -8,7 +8,7 @@ class cat {
|
|||
|
||||
fn play() {
|
||||
meows += 1u;
|
||||
nap();
|
||||
self.nap();
|
||||
}
|
||||
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue