about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs51
-rw-r--r--src/libsyntax/ast_map.rs27
-rw-r--r--src/libsyntax/ast_util.rs41
-rw-r--r--src/libsyntax/ext/build.rs9
-rw-r--r--src/libsyntax/ext/deriving/generic.rs8
-rw-r--r--src/libsyntax/ext/deriving/ty.rs4
-rw-r--r--src/libsyntax/fold.rs9
-rw-r--r--src/libsyntax/parse/classify.rs4
-rw-r--r--src/libsyntax/parse/parser.rs70
-rw-r--r--src/libsyntax/print/pprust.rs53
-rw-r--r--src/libsyntax/visit.rs7
11 files changed, 135 insertions, 148 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 03b7f1891a1..10b1aad8138 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -10,10 +10,11 @@
 
 // The Rust abstract syntax tree.
 
-use codemap::{Span, Spanned};
+use codemap::{Span, Spanned, DUMMY_SP};
 use abi::AbiSet;
+use ast_util;
 use opt_vec::OptVec;
-use parse::token::{interner_get, str_to_ident};
+use parse::token::{interner_get, str_to_ident, special_idents};
 
 use std::cell::RefCell;
 use std::hashmap::HashMap;
@@ -236,7 +237,6 @@ pub enum MethodProvenance {
 pub enum Def {
     DefFn(DefId, Purity),
     DefStaticMethod(/* method */ DefId, MethodProvenance, Purity),
-    DefSelf(NodeId, bool /* is_mutbl */),
     DefSelfTy(/* trait id */ NodeId),
     DefMod(DefId),
     DefForeignMod(DefId),
@@ -357,7 +357,7 @@ pub enum BindingMode {
 pub enum Pat_ {
     PatWild,
     PatWildMulti,
-    // A pat_ident may either be a new bound variable,
+    // A PatIdent may either be a new bound variable,
     // or a nullary enum (in which case the second field
     // is None).
     // In the nullary enum case, the parser can't determine
@@ -366,7 +366,7 @@ pub enum Pat_ {
     // set (of "pat_idents that refer to nullary enums")
     PatIdent(BindingMode, Path, Option<@Pat>),
     PatEnum(Path, Option<~[@Pat]>), /* "none" means a * pattern where
-                                       * we don't bind the fields to names */
+                                     * we don't bind the fields to names */
     PatStruct(Path, ~[FieldPat], bool),
     PatTup(~[@Pat]),
     PatUniq(@Pat),
@@ -374,7 +374,7 @@ pub enum Pat_ {
     PatLit(@Expr),
     PatRange(@Expr, @Expr),
     // [a, b, ..i, y, z] is represented as
-    // pat_vec(~[a, b], Some(i), ~[y, z])
+    // PatVec(~[a, b], Some(i), ~[y, z])
     PatVec(~[@Pat], Option<@Pat>, ~[@Pat])
 }
 
@@ -526,7 +526,7 @@ pub struct Expr {
 impl Expr {
     pub fn get_callee_id(&self) -> Option<NodeId> {
         match self.node {
-            ExprMethodCall(callee_id, _, _, _, _, _) |
+            ExprMethodCall(callee_id, _, _, _, _) |
             ExprIndex(callee_id, _, _) |
             ExprBinary(callee_id, _, _, _) |
             ExprAssignOp(callee_id, _, _, _) |
@@ -550,7 +550,7 @@ pub enum Expr_ {
     ExprBox(@Expr, @Expr),
     ExprVec(~[@Expr], Mutability),
     ExprCall(@Expr, ~[@Expr], CallSugar),
-    ExprMethodCall(NodeId, @Expr, Ident, ~[P<Ty>], ~[@Expr], CallSugar),
+    ExprMethodCall(NodeId, Ident, ~[P<Ty>], ~[@Expr], CallSugar),
     ExprTup(~[@Expr]),
     ExprBinary(NodeId, BinOp, @Expr, @Expr),
     ExprUnary(NodeId, UnOp, @Expr),
@@ -579,8 +579,6 @@ pub enum Expr_ {
     /// of a function call.
     ExprPath(Path),
 
-    /// The special identifier `self`.
-    ExprSelf,
     ExprAddrOf(Mutability, @Expr),
     ExprBreak(Option<Name>),
     ExprAgain(Option<Name>),
@@ -783,7 +781,7 @@ pub enum IntTy {
 
 impl ToStr for IntTy {
     fn to_str(&self) -> ~str {
-        ::ast_util::int_ty_to_str(*self)
+        ast_util::int_ty_to_str(*self)
     }
 }
 
@@ -798,7 +796,7 @@ pub enum UintTy {
 
 impl ToStr for UintTy {
     fn to_str(&self) -> ~str {
-        ::ast_util::uint_ty_to_str(*self)
+        ast_util::uint_ty_to_str(*self)
     }
 }
 
@@ -810,7 +808,7 @@ pub enum FloatTy {
 
 impl ToStr for FloatTy {
     fn to_str(&self) -> ~str {
-        ::ast_util::float_ty_to_str(*self)
+        ast_util::float_ty_to_str(*self)
     }
 }
 
@@ -886,7 +884,7 @@ pub enum Ty_ {
     TyTup(~[P<Ty>]),
     TyPath(Path, Option<OptVec<TyParamBound>>, NodeId), // for #7264; see above
     TyTypeof(@Expr),
-    // ty_infer means the type should be inferred instead of it having been
+    // TyInfer means the type should be inferred instead of it having been
     // specified. This should only appear at the "top level" of a type and not
     // nested in one.
     TyInfer,
@@ -917,6 +915,26 @@ pub struct Arg {
     id: NodeId,
 }
 
+impl Arg {
+    pub fn new_self(span: Span, mutability: Mutability) -> Arg {
+        let path = ast_util::ident_to_path(span, special_idents::self_);
+        Arg {
+            // HACK(eddyb) fake type for the self argument.
+            ty: P(Ty {
+                id: DUMMY_NODE_ID,
+                node: TyInfer,
+                span: DUMMY_SP,
+            }),
+            pat: @Pat {
+                id: DUMMY_NODE_ID,
+                node: PatIdent(BindByValue(mutability), path, None),
+                span: span
+            },
+            id: DUMMY_NODE_ID
+        }
+    }
+}
+
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub struct FnDecl {
     inputs: ~[Arg],
@@ -952,10 +970,10 @@ pub enum RetStyle {
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum ExplicitSelf_ {
     SelfStatic,                                // no self
-    SelfValue(Mutability),                     // `self`, `mut self`
+    SelfValue,                                 // `self`
     SelfRegion(Option<Lifetime>, Mutability),  // `&'lt self`, `&'lt mut self`
     SelfBox,                                   // `@self`
-    SelfUniq(Mutability)                       // `~self`, `mut ~self`
+    SelfUniq                                   // `~self`
 }
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
@@ -971,7 +989,6 @@ pub struct Method {
     body: P<Block>,
     id: NodeId,
     span: Span,
-    self_id: NodeId,
     vis: Visibility,
 }
 
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 49bea6a33a9..bb66d620d29 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -17,7 +17,6 @@ use diagnostic::SpanHandler;
 use fold::Folder;
 use fold;
 use parse::token::{get_ident_interner, IdentInterner};
-use parse::token::special_idents;
 use print::pprust;
 use util::small_vector::SmallVector;
 
@@ -163,10 +162,7 @@ pub enum Node {
     NodeExpr(@Expr),
     NodeStmt(@Stmt),
     NodeArg(@Pat),
-    // HACK(eddyb) should always be a pattern, but `self` is not, and thus it
-    // is identified only by an ident and no span is available. In all other
-    // cases, node_span will return the proper span (required by borrowck).
-    NodeLocal(Ident, Option<@Pat>),
+    NodeLocal(@Pat),
     NodeBlock(P<Block>),
 
     /// NodeStructCtor represents a tuple struct.
@@ -246,10 +242,6 @@ impl<F> Ctx<F> {
         let mut map = self.map.map.borrow_mut();
         map.get().insert(id as uint, node);
     }
-
-    fn map_self(&self, m: @Method) {
-        self.insert(m.self_id, NodeLocal(special_idents::self_, None));
-    }
 }
 
 impl<F: FoldOps> Folder for Ctx<F> {
@@ -285,7 +277,6 @@ impl<F: FoldOps> Folder for Ctx<F> {
                 let impl_did = ast_util::local_def(i.id);
                 for &m in ms.iter() {
                     self.insert(m.id, NodeMethod(m, impl_did, p));
-                    self.map_self(m);
                 }
 
             }
@@ -332,7 +323,6 @@ impl<F: FoldOps> Folder for Ctx<F> {
                         }
                         Provided(m) => {
                             self.insert(m.id, NodeTraitMethod(@Provided(m), d_id, p));
-                            self.map_self(m);
                         }
                     }
                 }
@@ -348,9 +338,9 @@ impl<F: FoldOps> Folder for Ctx<F> {
     fn fold_pat(&mut self, pat: @Pat) -> @Pat {
         let pat = fold::noop_fold_pat(pat, self);
         match pat.node {
-            PatIdent(_, ref path, _) => {
+            PatIdent(..) => {
                 // Note: this is at least *potentially* a pattern...
-                self.insert(pat.id, NodeLocal(ast_util::path_to_ident(path), Some(pat)));
+                self.insert(pat.id, NodeLocal(pat));
             }
             _ => {}
         }
@@ -467,7 +457,6 @@ pub fn map_decoded_item<F: 'static + FoldOps>(diag: @SpanHandler,
                 NodeMethod(m, impl_did, @path)
             };
             cx.insert(m.id, entry);
-            cx.map_self(m);
         }
     }
 
@@ -525,8 +514,8 @@ pub fn node_id_to_str(map: Map, id: NodeId, itr: @IdentInterner) -> ~str {
       Some(NodeArg(pat)) => {
         format!("arg {} (id={})", pprust::pat_to_str(pat, itr), id)
       }
-      Some(NodeLocal(ident, _)) => {
-        format!("local (id={}, name={})", id, itr.get(ident.name))
+      Some(NodeLocal(pat)) => {
+        format!("local {} (id={})", pprust::pat_to_str(pat, itr), id)
       }
       Some(NodeBlock(block)) => {
         format!("block {} (id={})", pprust::block_to_str(block, itr), id)
@@ -559,11 +548,7 @@ pub fn node_span(items: Map, id: ast::NodeId) -> Span {
         Some(NodeVariant(variant, _, _)) => variant.span,
         Some(NodeExpr(expr)) => expr.span,
         Some(NodeStmt(stmt)) => stmt.span,
-        Some(NodeArg(pat)) => pat.span,
-        Some(NodeLocal(_, pat)) => match pat {
-            Some(pat) => pat.span,
-            None => fail!("node_span: cannot get span from NodeLocal (likely `self`)")
-        },
+        Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
         Some(NodeBlock(block)) => block.span,
         Some(NodeStructCtor(_, item, _)) => item.span,
         Some(NodeCalleeScope(expr)) => expr.span,
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index d3504f8d204..405de5c5542 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -60,19 +60,19 @@ pub fn variant_def_ids(d: Def) -> Option<(DefId, DefId)> {
 
 pub fn def_id_of_def(d: Def) -> DefId {
     match d {
-      DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
-      DefForeignMod(id) | DefStatic(id, _) |
-      DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
-      DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
-        id
-      }
-      DefArg(id, _) | DefLocal(id, _) | DefSelf(id, _) | DefSelfTy(id)
-      | DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
-      | DefTyParamBinder(id) | DefLabel(id) => {
-        local_def(id)
-      }
+        DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
+        DefForeignMod(id) | DefStatic(id, _) |
+        DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
+        DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
+            id
+        }
+        DefArg(id, _) | DefLocal(id, _) | DefSelfTy(id)
+        | DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
+        | DefTyParamBinder(id) | DefLabel(id) => {
+            local_def(id)
+        }
 
-      DefPrimTy(_) => fail!()
+        DefPrimTy(_) => fail!()
     }
 }
 
@@ -292,16 +292,6 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
     }
 }
 
-/* True if d is either a def_self, or a chain of def_upvars
- referring to a def_self */
-pub fn is_self(d: ast::Def) -> bool {
-  match d {
-    DefSelf(..)           => true,
-    DefUpvar(_, d, _, _) => is_self(*d),
-    _                     => false
-  }
-}
-
 /// Maps a binary operator to its precedence
 pub fn operator_prec(op: ast::BinOp) -> uint {
   match op {
@@ -504,11 +494,8 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
         self.operation.visit_id(node_id);
 
         match *function_kind {
-            visit::FkItemFn(_, generics, _, _) => {
-                self.visit_generics_helper(generics)
-            }
-            visit::FkMethod(_, generics, method) => {
-                self.operation.visit_id(method.self_id);
+            visit::FkItemFn(_, generics, _, _) |
+            visit::FkMethod(_, generics, _) => {
                 self.visit_generics_helper(generics)
             }
             visit::FkFnBlock => {}
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 3b2cc4ca6ed..3b43c96a184 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -18,6 +18,7 @@ use ext::quote::rt::*;
 use fold::Folder;
 use opt_vec;
 use opt_vec::OptVec;
+use parse::token::special_idents;
 
 pub struct Field {
     ident: ast::Ident,
@@ -478,7 +479,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr_path(self.path_ident(span, id))
     }
     fn expr_self(&self, span: Span) -> @ast::Expr {
-        self.expr(span, ast::ExprSelf)
+        self.expr_ident(span, special_idents::self_)
     }
 
     fn expr_binary(&self, sp: Span, op: ast::BinOp,
@@ -523,9 +524,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn expr_method_call(&self, span: Span,
                         expr: @ast::Expr,
                         ident: ast::Ident,
-                        args: ~[@ast::Expr]) -> @ast::Expr {
-        self.expr(span,
-                  ast::ExprMethodCall(ast::DUMMY_NODE_ID, expr, ident, ~[], args, ast::NoSugar))
+                        mut args: ~[@ast::Expr]) -> @ast::Expr {
+        args.unshift(expr);
+        self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args, ast::NoSugar))
     }
     fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
         self.expr(b.span, ast::ExprBlock(b))
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 1f778779fbd..e1fb80049e0 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -551,9 +551,14 @@ impl<'a> MethodDef<'a> {
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(trait_.cx, trait_.span, type_ident, generics);
 
+        let self_arg = match explicit_self.node {
+            ast::SelfStatic => None,
+            _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable))
+        };
         let args = arg_types.move_iter().map(|(name, ty)| {
             trait_.cx.arg(trait_.span, name, ty)
-        }).collect();
+        });
+        let args = self_arg.move_iter().chain(args).collect();
 
         let ret_type = self.get_ret_ty(trait_, generics, type_ident);
 
@@ -578,7 +583,6 @@ impl<'a> MethodDef<'a> {
             body: body_block,
             id: ast::DUMMY_NODE_ID,
             span: trait_.span,
-            self_id: ast::DUMMY_NODE_ID,
             vis: ast::Inherited,
         }
     }
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index c2b32b45ce4..b22dcfe0da2 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -244,13 +244,13 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
     let self_path = cx.expr_self(span);
     match *self_ptr {
         None => {
-            (self_path, respan(span, ast::SelfValue(ast::MutImmutable)))
+            (self_path, respan(span, ast::SelfValue))
         }
         Some(ref ptr) => {
             let self_ty = respan(
                 span,
                 match *ptr {
-                    Send => ast::SelfUniq(ast::MutImmutable),
+                    Send => ast::SelfUniq,
                     Managed => ast::SelfBox,
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 7a86dd6e4ce..c739fb911ba 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -306,9 +306,7 @@ pub trait Folder {
 
     fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
         match *es {
-            SelfStatic | SelfValue(_) | SelfUniq(_) | SelfBox => {
-                *es
-            }
+            SelfStatic | SelfValue | SelfUniq | SelfBox => *es,
             SelfRegion(ref lifetime, m) => {
                 SelfRegion(fold_opt_lifetime(lifetime, self), m)
             }
@@ -666,7 +664,6 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> @Method {
         body: folder.fold_block(m.body),
         id: folder.new_id(m.id),
         span: folder.new_span(m.span),
-        self_id: folder.new_id(m.self_id),
         vis: m.vis
     }
 }
@@ -737,10 +734,9 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
                      args.map(|&x| folder.fold_expr(x)),
                      blk)
         }
-        ExprMethodCall(callee_id, f, i, ref tps, ref args, blk) => {
+        ExprMethodCall(callee_id, i, ref tps, ref args, blk) => {
             ExprMethodCall(
                 folder.new_id(callee_id),
-                folder.fold_expr(f),
                 folder.fold_ident(i),
                 tps.map(|&x| folder.fold_ty(x)),
                 args.map(|&x| folder.fold_expr(x)),
@@ -811,7 +807,6 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
                       folder.fold_expr(er))
         }
         ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
-        ExprSelf => ExprSelf,
         ExprLogLevel => ExprLogLevel,
         ExprBreak(opt_ident) => ExprBreak(opt_ident),
         ExprAgain(opt_ident) => ExprAgain(opt_ident),
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index 1204cbc2eea..61c80919b6e 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -31,8 +31,8 @@ pub fn expr_requires_semi_to_be_stmt(e: @ast::Expr) -> bool {
       | ast::ExprForLoop(..)
       | ast::ExprCall(_, _, ast::DoSugar)
       | ast::ExprCall(_, _, ast::ForSugar)
-      | ast::ExprMethodCall(_, _, _, _, _, ast::DoSugar)
-      | ast::ExprMethodCall(_, _, _, _, _, ast::ForSugar) => false,
+      | ast::ExprMethodCall(_, _, _, _, ast::DoSugar)
+      | ast::ExprMethodCall(_, _, _, _, ast::ForSugar) => false,
       _ => true
     }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e110ebae093..17590ccf523 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -27,8 +27,8 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
 use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
 use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
-use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc, ExprRepeat};
-use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary};
+use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
+use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprVstore, ExprVstoreSlice, ExprVstoreBox};
 use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl};
 use ast::{ExprVstoreUniq, Onceness, Once, Many};
@@ -1093,7 +1093,6 @@ impl Parser {
                     body: body,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
-                    self_id: ast::DUMMY_NODE_ID,
                     vis: vis,
                 })
               }
@@ -1687,13 +1686,9 @@ impl Parser {
         ExprCall(f, args, sugar)
     }
 
-    pub fn mk_method_call(&mut self,
-                      rcvr: @Expr,
-                      ident: Ident,
-                      tps: ~[P<Ty>],
-                      args: ~[@Expr],
+    fn mk_method_call(&mut self, ident: Ident, tps: ~[P<Ty>], args: ~[@Expr],
                       sugar: CallSugar) -> ast::Expr_ {
-        ExprMethodCall(ast::DUMMY_NODE_ID, rcvr, ident, tps, args, sugar)
+        ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args, sugar)
     }
 
     pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
@@ -1794,7 +1789,8 @@ impl Parser {
 
             return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
         } else if self.eat_keyword(keywords::Self) {
-            ex = ExprSelf;
+            let path = ast_util::ident_to_path(mk_sp(lo, hi), special_idents::self_);
+            ex = ExprPath(path);
             hi = self.span.hi;
         } else if self.eat_keyword(keywords::If) {
             return self.parse_if_expr();
@@ -1993,7 +1989,7 @@ impl Parser {
                     // expr.f() method call
                     match self.token {
                         token::LPAREN => {
-                            let es = self.parse_unspanned_seq(
+                            let mut es = self.parse_unspanned_seq(
                                 &token::LPAREN,
                                 &token::RPAREN,
                                 seq_sep_trailing_disallowed(token::COMMA),
@@ -2001,7 +1997,8 @@ impl Parser {
                             );
                             hi = self.span.hi;
 
-                            let nd = self.mk_method_call(e, i, tys, es, NoSugar);
+                            es.unshift(e);
+                            let nd = self.mk_method_call(i, tys, es, NoSugar);
                             e = self.mk_expr(lo, hi, nd);
                         }
                         _ => {
@@ -2569,16 +2566,15 @@ impl Parser {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append((*args).clone(), [last_arg]);
+                let args = vec::append_one((*args).clone(), last_arg);
                 self.mk_expr(lo, block.span.hi, ExprCall(f, args, sugar))
             }
-            ExprMethodCall(_, f, i, ref tps, ref args, NoSugar) => {
+            ExprMethodCall(_, i, ref tps, ref args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append((*args).clone(), [last_arg]);
-                let method_call = self.mk_method_call(f,
-                                                      i,
+                let args = vec::append_one((*args).clone(), last_arg);
+                let method_call = self.mk_method_call(i,
                                                       (*tps).clone(),
                                                       args,
                                                       sugar);
@@ -2588,10 +2584,9 @@ impl Parser {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let method_call = self.mk_method_call(f,
-                                                      i,
+                let method_call = self.mk_method_call(i,
                                                       (*tps).clone(),
-                                                      ~[last_arg],
+                                                      ~[f, last_arg],
                                                       sugar);
                 self.mk_expr(lo, block.span.hi, method_call)
             }
@@ -3712,6 +3707,7 @@ impl Parser {
         // A bit of complexity and lookahead is needed here in order to be
         // backwards compatible.
         let lo = self.span.lo;
+        let mut mutbl_self = MutImmutable;
         let explicit_self = match self.token {
             token::BINOP(token::AND) => {
                 maybe_parse_borrowed_explicit_self(self)
@@ -3720,57 +3716,60 @@ impl Parser {
                 maybe_parse_explicit_self(SelfBox, self)
             }
             token::TILDE => {
-                maybe_parse_explicit_self(SelfUniq(MutImmutable), self)
+                maybe_parse_explicit_self(SelfUniq, self)
             }
             token::IDENT(..) if self.is_self_ident() => {
                 self.bump();
-                SelfValue(MutImmutable)
+                SelfValue
             }
             token::BINOP(token::STAR) => {
                 // Possibly "*self" or "*mut self" -- not supported. Try to avoid
                 // emitting cryptic "unexpected token" errors.
                 self.bump();
-                let mutability = if Parser::token_is_mutability(&self.token) {
+                let _mutability = if Parser::token_is_mutability(&self.token) {
                     self.parse_mutability()
                 } else { MutImmutable };
                 if self.is_self_ident() {
                     self.span_err(self.span, "cannot pass self by unsafe pointer");
                     self.bump();
                 }
-                SelfValue(mutability)
+                SelfValue
             }
             _ if Parser::token_is_mutability(&self.token) &&
                     self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
-                let mutability = self.parse_mutability();
+                mutbl_self = self.parse_mutability();
                 self.expect_self_ident();
-                SelfValue(mutability)
+                SelfValue
             }
             _ if Parser::token_is_mutability(&self.token) &&
                     self.look_ahead(1, |t| *t == token::TILDE) &&
                     self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
-                let mutability = self.parse_mutability();
+                mutbl_self = self.parse_mutability();
                 self.bump();
                 self.expect_self_ident();
-                SelfUniq(mutability)
+                SelfUniq
             }
             _ => SelfStatic
         };
 
+        let explicit_self_sp = mk_sp(lo, self.span.hi);
+
         // If we parsed a self type, expect a comma before the argument list.
-        let fn_inputs;
-        if explicit_self != SelfStatic {
+        let fn_inputs = if explicit_self != SelfStatic {
             match self.token {
                 token::COMMA => {
                     self.bump();
                     let sep = seq_sep_trailing_disallowed(token::COMMA);
-                    fn_inputs = self.parse_seq_to_before_end(
+                    let mut fn_inputs = self.parse_seq_to_before_end(
                         &token::RPAREN,
                         sep,
                         parse_arg_fn
                     );
+                    fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self));
+                    fn_inputs
                 }
                 token::RPAREN => {
-                    fn_inputs = ~[];
+                    ~[Arg::new_self(explicit_self_sp, mutbl_self)]
                 }
                 _ => {
                     let token_str = self.this_token_to_str();
@@ -3780,10 +3779,8 @@ impl Parser {
             }
         } else {
             let sep = seq_sep_trailing_disallowed(token::COMMA);
-            fn_inputs = self.parse_seq_to_before_end(&token::RPAREN,
-                                                     sep,
-                                                     parse_arg_fn);
-        }
+            self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+        };
 
         self.expect(&token::RPAREN);
 
@@ -3918,7 +3915,6 @@ impl Parser {
             body: body,
             id: ast::DUMMY_NODE_ID,
             span: mk_sp(lo, hi),
-            self_id: ast::DUMMY_NODE_ID,
             vis: visa,
         }
     }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 36a87658c11..d3c194b6af6 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1213,10 +1213,10 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) {
         print_expr(s, func);
         print_call_post(s, sugar, &blk, &mut base_args);
       }
-      ast::ExprMethodCall(_, func, ident, ref tys, ref args, sugar) => {
-        let mut base_args = (*args).clone();
+      ast::ExprMethodCall(_, ident, ref tys, ref args, sugar) => {
+        let mut base_args = args.slice_from(1).to_owned();
         let blk = print_call_pre(s, sugar, &mut base_args);
-        print_expr(s, func);
+        print_expr(s, args[0]);
         word(&mut s.s, ".");
         print_ident(s, ident);
         if tys.len() > 0u {
@@ -1445,7 +1445,6 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) {
         word(&mut s.s, "]");
       }
       ast::ExprPath(ref path) => print_path(s, path, true),
-      ast::ExprSelf => word(&mut s.s, "self"),
       ast::ExprBreak(opt_ident) => {
         word(&mut s.s, "break");
         space(&mut s.s);
@@ -1749,19 +1748,20 @@ pub fn print_pat(s: &mut State, pat: &ast::Pat) {
 }
 
 pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_, intr: @IdentInterner) -> ~str {
-    to_str(explicit_self, |a, &b| { print_explicit_self(a, b); () }, intr)
+    to_str(explicit_self, |a, &b| { print_explicit_self(a, b, ast::MutImmutable); () }, intr)
 }
 
 // Returns whether it printed anything
-pub fn print_explicit_self(s: &mut State, explicit_self: ast::ExplicitSelf_) -> bool {
+fn print_explicit_self(s: &mut State,
+                       explicit_self: ast::ExplicitSelf_,
+                       mutbl: ast::Mutability) -> bool {
+    print_mutability(s, mutbl);
     match explicit_self {
         ast::SelfStatic => { return false; }
-        ast::SelfValue(m) => {
-            print_mutability(s, m);
+        ast::SelfValue => {
             word(&mut s.s, "self");
         }
-        ast::SelfUniq(m) => {
-            print_mutability(s, m);
+        ast::SelfUniq => {
             word(&mut s.s, "~self");
         }
         ast::SelfRegion(ref lt, m) => {
@@ -1799,11 +1799,25 @@ pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl,
     // self type and the args all in the same box.
     rbox(s, 0u, Inconsistent);
     let mut first = true;
-    for explicit_self in opt_explicit_self.iter() {
-        first = !print_explicit_self(s, *explicit_self);
+    for &explicit_self in opt_explicit_self.iter() {
+        let m = match explicit_self {
+            ast::SelfStatic => ast::MutImmutable,
+            _ => match decl.inputs[0].pat.node {
+                ast::PatIdent(ast::BindByValue(m), _, _) => m,
+                _ => ast::MutImmutable
+            }
+        };
+        first = !print_explicit_self(s, explicit_self, m);
     }
 
-    for arg in decl.inputs.iter() {
+    // HACK(eddyb) ignore the separately printed self argument.
+    let args = if first {
+        decl.inputs.as_slice()
+    } else {
+        decl.inputs.slice_from(1)
+    };
+
+    for arg in args.iter() {
         if first { first = false; } else { word_space(s, ","); }
         print_arg(s, arg);
     }
@@ -2090,18 +2104,7 @@ pub fn print_ty_fn(s: &mut State,
         popen(s);
     }
 
-    // It is unfortunate to duplicate the commasep logic, but we want the
-    // self type and the args all in the same box.
-    rbox(s, 0u, Inconsistent);
-    let mut first = true;
-    for explicit_self in opt_explicit_self.iter() {
-        first = !print_explicit_self(s, *explicit_self);
-    }
-    for arg in decl.inputs.iter() {
-        if first { first = false; } else { word_space(s, ","); }
-        print_arg(s, arg);
-    }
-    end(s);
+    print_fn_args(s, decl, opt_explicit_self);
 
     if opt_sigil == Some(ast::BorrowedSigil) {
         word(&mut s.s, "|");
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 484f8dce1f7..5e7ad3af526 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -186,7 +186,7 @@ fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                explicit_self: &ExplicitSelf,
                                                env: E) {
     match explicit_self.node {
-        SelfStatic | SelfValue(_) | SelfBox | SelfUniq(_) => {}
+        SelfStatic | SelfValue | SelfBox | SelfUniq => {}
         SelfRegion(ref lifetime, _) => {
             visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
         }
@@ -654,12 +654,11 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             }
             visitor.visit_expr(callee_expression, env.clone())
         }
-        ExprMethodCall(_, callee, _, ref types, ref arguments, _) => {
+        ExprMethodCall(_, _, ref types, ref arguments, _) => {
             walk_exprs(visitor, *arguments, env.clone());
             for &typ in types.iter() {
                 visitor.visit_ty(typ, env.clone())
             }
-            visitor.visit_expr(callee, env.clone())
         }
         ExprBinary(_, _, left_expression, right_expression) => {
             visitor.visit_expr(left_expression, env.clone());
@@ -734,7 +733,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
         ExprPath(ref path) => {
             visitor.visit_path(path, expression.id, env.clone())
         }
-        ExprSelf | ExprBreak(_) | ExprAgain(_) => {}
+        ExprBreak(_) | ExprAgain(_) => {}
         ExprRet(optional_expression) => {
             walk_expr_opt(visitor, optional_expression, env.clone())
         }