diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index 51c97ef261e..fab2c48dda9 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -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(_) { diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 0b67a16c072..2c881260ffd 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -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 } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 2c67b907923..e8b12763160 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -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]) { + items: [@class_member], path: [str], &index: [entry]) { 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]) -> [entry] { 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,18 +390,23 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer, ebml_w.end_tag(); } class_method(m) { - *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 */ - *global_index += [{val: m.id, pos: ebml_w.writer.tell()}]; - let impl_path = path + [ast_map::path_name(m.ident)]; - /* - Recall methods are (currently) monomorphic, and we don't - repeat the class's ty params in the method decl - */ - #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, []); + 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 */ + *global_index += [{val: m.id, pos: ebml_w.writer.tell()}]; + let impl_path = path + [ast_map::path_name(m.ident)]; + /* + Recall methods are (currently) monomorphic, and we don't + repeat the class's ty params in the method decl + */ + #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)); 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)); diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs index 3b9a868776b..ee91b573daa 100644 --- a/src/rustc/middle/ast_map.rs +++ b/src/rustc/middle/ast_map.rs @@ -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); } _ {} } } diff --git a/src/rustc/middle/mutbl.rs b/src/rustc/middle/mutbl.rs index be06a16a0dc..45751bd4cfb 100644 --- a/src/rustc/middle/mutbl.rs +++ b/src/rustc/middle/mutbl.rs @@ -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); diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 91aac1c7d6a..7f38205b384 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -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) { 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 { 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))); } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 82eec9b8bd6..f213519dac3 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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 */ } } diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index db0b6f923b0..ca4ff733716 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -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 || diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index bfaf356a3e5..7396e54cf77 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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; @@ -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 diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 75add819e39..1cf89045a70 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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 { - 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}> { #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), @@ -2089,7 +2111,7 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method], // look up method named // its id is did let m_declared = ty::lookup_class_method_by_name(tcx, - parent_id, name, sp); + parent_id, name, sp); method_static(m_declared) } 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, - 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}> { @@ -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,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 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 }} { - // base expr is "self" -- consider all fields - ty::lookup_class_fields(tcx, base_id) - } - _ { lookup_public_fields(tcx, base_id) } + let cls_items = if self_ref(fcx, base.id) { + // base expr is "self" -- consider all fields + ty::lookup_class_fields(tcx, base_id) + } + else { + 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) { // (2) look up what field's type is, and return it // 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 { 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,16 +3689,16 @@ 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::(); 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) { 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, - 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 */ } } diff --git a/src/rustc/syntax/ast.rs b/src/rustc/syntax/ast.rs index 447d754895e..c88f44d7153 100644 --- a/src/rustc/syntax/ast.rs +++ b/src/rustc/syntax/ast.rs @@ -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,8 +651,8 @@ 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. */ - /* (not including ctor) */ + [@class_member], /* methods, etc. */ + /* (not including ctor) */ class_ctor ), item_iface([ty_param], [ty_method]), @@ -659,14 +661,11 @@ enum item_ { } #[auto_serialize] -type class_item_ = {privacy: privacy, decl: class_member}; +type class_member = spanned; #[auto_serialize] -type class_item = spanned; - -#[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? diff --git a/src/rustc/syntax/ast_util.rs b/src/rustc/syntax/ast_util.rs index 4ab7c325a69..bf32bb0ebf3 100644 --- a/src/rustc/syntax/ast_util.rs +++ b/src/rustc/syntax/ast_util.rs @@ -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 { diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs index 3f98ce5c29e..2cf567d74f1 100644 --- a/src/rustc/syntax/fold.rs +++ b/src/rustc/syntax/fold.rs @@ -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_ { diff --git a/src/rustc/syntax/parse/parser.rs b/src/rustc/syntax/parse/parser.rs index 61cc675c492..0ef54e09993 100644 --- a/src/rustc/syntax/parse/parser.rs +++ b/src/rustc/syntax/parse/parser.rs @@ -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,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 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 { 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)); } - 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,16 +2103,10 @@ 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 { +fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents { if eat_word(p, "new") { let lo = p.last_span.lo; // Can ctors have attrs? @@ -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}]) } } } diff --git a/src/rustc/syntax/print/pprust.rs b/src/rustc/syntax/print/pprust.rs index 5d259e9bf4a..a1c118c3144 100644 --- a/src/rustc/syntax/print/pprust.rs +++ b/src/rustc/syntax/print/pprust.rs @@ -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); } _ {} } diff --git a/src/rustc/syntax/visit.rs b/src/rustc/syntax/visit.rs index 7a84052fa90..b4bcb3aaa31 100644 --- a/src/rustc/syntax/visit.rs +++ b/src/rustc/syntax/visit.rs @@ -55,7 +55,7 @@ type visitor = visit_ty_params: fn@([ty_param], E, vt), visit_constr: fn@(@path, span, node_id, E, vt), visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt), - visit_class_item: fn@(span, privacy, class_member, E, vt)}; + visit_class_item: fn@(@class_member, E, vt)}; fn default_visitor() -> visitor { ret @{visit_mod: bind visit_mod::(_, _, _, _, _), @@ -73,7 +73,7 @@ fn default_visitor() -> visitor { visit_ty_params: bind visit_ty_params::(_, _, _), visit_constr: bind visit_constr::(_, _, _, _, _), visit_fn: bind visit_fn::(_, _, _, _, _, _, _), - visit_class_item: bind visit_class_item::(_,_,_,_,_)}; + visit_class_item: bind visit_class_item::(_,_,_)}; } fn visit_crate(c: crate, e: E, v: vt) { @@ -139,7 +139,7 @@ fn visit_item(i: @item, e: E, v: vt) { 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(i: @item, e: E, v: vt) { } } -fn visit_class_item(_s: span, _p: privacy, cm: class_member, - e:E, v:vt) { - alt cm { - instance_var(ident, t, mt, id) { +fn visit_class_item(cm: @class_member, e:E, v:vt) { + 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, _, _, - _, _, _) + _) }); } diff --git a/src/test/compile-fail/private-method.rs b/src/test/compile-fail/private-method.rs index 7e45660deb7..09f0f9b5af5 100644 --- a/src/test/compile-fail/private-method.rs +++ b/src/test/compile-fail/private-method.rs @@ -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; diff --git a/src/test/run-pass/private-method.rs b/src/test/run-pass/private-method.rs index 2cc75e1ec3c..1d062f32b7a 100644 --- a/src/test/run-pass/private-method.rs +++ b/src/test/run-pass/private-method.rs @@ -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; } }