]> git.lizzy.rs Git - rust.git/commitdiff
Allow explicit self-calls within classes
authorTim Chevalier <chevalier@alum.wellesley.edu>
Thu, 29 Mar 2012 01:50:33 +0000 (18:50 -0700)
committerTim Chevalier <chevalier@alum.wellesley.edu>
Thu, 29 Mar 2012 03:30:07 +0000 (20:30 -0700)
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).

18 files changed:
src/rustc/metadata/astencode.rs
src/rustc/metadata/decoder.rs
src/rustc/metadata/encoder.rs
src/rustc/middle/ast_map.rs
src/rustc/middle/mutbl.rs
src/rustc/middle/resolve.rs
src/rustc/middle/trans/base.rs
src/rustc/middle/trans/reachable.rs
src/rustc/middle/ty.rs
src/rustc/middle/typeck.rs
src/rustc/syntax/ast.rs
src/rustc/syntax/ast_util.rs
src/rustc/syntax/fold.rs
src/rustc/syntax/parse/parser.rs
src/rustc/syntax/print/pprust.rs
src/rustc/syntax/visit.rs
src/test/compile-fail/private-method.rs
src/test/run-pass/private-method.rs

index 51c97ef261e5e1166294d9f16a43d65b04e51262..fab2c48dda93296e0e917c0a44c78da3a312a82d 100644 (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,
-                              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(_) {
index 0b67a16c0720b0d8e53e83ba102f013f3ba6becd..2c881260ffdcb510b4f9a580dd744783c9f821b5 100644 (file)
@@ -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
 }
index 2c67b907923234a95306b9da55dc3b8504fa7238..e8b127631609dac8b606826f8635bd3f2733ef46 100644 (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,
-     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,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 add_to_index_(item: @item, ebml_w: ebml::writer,
            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));
index 3b9a868776b73c2665050aaf9d99fe6a73d8c2ab..ee91b573daa6b9f802056e282a1e0db052328985 100644 (file)
@@ -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); }
              _ {}
            }
           }
index be06a16a0dccd4d102246832fdcdcbb0fe3fa858..45751bd4cfbf1a29b33922a20006eea54f0783e7 100644 (file)
@@ -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);
index 91aac1c7d6aac8714249f1486ef49e398cc78173..7f38205b3843cec4a6a8361b7d9b96416a7c289e 100644 (file)
@@ -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)));
               }
index 82eec9b8bd680fd1df8333fc8b1799a54deff9aa..f213519dac3bc3689b5f73211ea3eee91755d71e 100644 (file)
@@ -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 */ }
     }
index db0b6f923b0b4dbcfdbb4ff95ec5c6cef2979ffa..ca4ff733716893e09c60cce2cb2d1fe94aed3c23 100644 (file)
@@ -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 ||
index bfaf356a3e50e3aff3691fc56545b311609acefa..7396e54cf77be15b5b74d324d7d84c781190d4cd 100644 (file)
 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
index 75add819e39196f632ef9b955d4c06d15b4113b1..1cf89045a709a132743430f452d915892bf75c52 100644 (file)
@@ -83,6 +83,22 @@ enum self_info { self_impl(ty::t, ast::node_id) }
      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 @@ fn store_methods<T>(tcx: ty::ctxt, id: ast::node_id,
           }
           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 @@ fn convert(tcx: ty::ctxt, it: @ast::item) {
                                         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),
@@ -2089,7 +2111,7 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
                         // look up method named <name>
                         // 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<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 lookup_op_method(fcx: @fn_ctxt, op_ex: @ast::expr, self_t: ty::t,
                         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 get_node(f: spanned<field>) -> field { f.node }
             }
           }
           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 get_node(f: spanned<field>) -> field { f.node }
                 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 get_node(f: spanned<field>) -> field { f.node }
         }
         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 get_node(f: spanned<field>) -> field { f.node }
 
         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::<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) {
              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 */ }
     }
index 447d754895e7c17bafad5e845dbfeda149e04d86..c88f44d7153463ec233e7721116b25172daec4f0 100644 (file)
@@ -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<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?
index 4ab7c325a69044d2d65e729edb4ccd620923fb53..bf32bb0ebf38fcaa9af35811916902165339dfcc 100644 (file)
@@ -262,9 +262,9 @@ fn ident_to_path(s: span, i: ident) -> @path {
 // 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 @@ fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 }
 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 ignore_privacy(cms: [cmethod]) -> [@method] {
-    vec::map(cms, {|cm| cm.meth})
+fn public_methods(ms: [@method]) -> [@method] {
+    vec::filter(ms, {|m| alt m.privacy {
+                    pub { true }
+                    _   { false }}})
 }
 
-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 {
index 3f98ce5c29ed7c5650d678e213405fb32558bd0d..2cf567d74f1f3955e5a7d259da0ca0a9d23cd346 100644 (file)
@@ -27,7 +27,7 @@
      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 @@
      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 f_item(afp: ast_fold_precursor, f: ast_fold, &&i: @item) -> @item {
         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_ {
index 61cc675c492d63a63da2220c3144c5cdb8388c30..0ef54e0999310384c1feb6bf72ae51e30598e9d6 100644 (file)
@@ -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 wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
     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)])}
-
-    fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
+                      members([@ast::class_member]) }
+
+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 @@ fn parse_class_item(p:parser, class_name:@ast::path) -> class_contents {
             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}])
         }
     }
 }
index 5d259e9bf4a09e5b129b22fbc97d46dead07d233..a1c118c314415e68f5b7ed29c9d4bdbe3c8807a4 100644 (file)
@@ -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); }
                  _ {}
              }
index 7a84052fa90f14dd2c941aa4c34e437f6c5d5b7a..b4bcb3aaa31bed6b1203d3471dda169dc6a030a1 100644 (file)
@@ -55,7 +55,7 @@ fn tps_of_fn(fk: fn_kind) -> [ty_param] {
       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 @@ fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
       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 v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
     } 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 v_class_item(f: fn@(span, privacy, class_member),
                 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, _, _,
-                                                    _, _, _)
+                                                    _)
                });
 }
 
index 7e45660deb7164bf89f343a4a212d4d1adf97745..09f0f9b5af5b5ec950441586cb2e649948bb0c2f 100644 (file)
@@ -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;
index 2cc75e1ec3c82aaebeecfb1644081692832e4add..1d062f32b7a19e1e2b2320fa680214a884a9d552 100644 (file)
@@ -8,7 +8,7 @@ fn nap() { uint::range(1u, 10u) {|_i|}}
 
   fn play() {
     meows += 1u;
-    nap();
+    self.nap();
   }
   new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
 }