about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libfuzzer/fuzzer.rc7
-rw-r--r--src/librustc/front/test.rs4
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs16
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs11
-rw-r--r--src/librustc/middle/check_const.rs6
-rw-r--r--src/librustc/middle/const_eval.rs12
-rw-r--r--src/librustc/middle/dataflow.rs26
-rw-r--r--src/librustc/middle/effect.rs6
-rw-r--r--src/librustc/middle/kind.rs7
-rw-r--r--src/librustc/middle/lint.rs2
-rw-r--r--src/librustc/middle/liveness.rs19
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/moves.rs16
-rw-r--r--src/librustc/middle/privacy.rs27
-rw-r--r--src/librustc/middle/resolve.rs36
-rw-r--r--src/librustc/middle/trans/callee.rs5
-rw-r--r--src/librustc/middle/trans/common.rs2
-rw-r--r--src/librustc/middle/trans/consts.rs6
-rw-r--r--src/librustc/middle/trans/expr.rs35
-rw-r--r--src/librustc/middle/trans/reachable.rs11
-rw-r--r--src/librustc/middle/trans/type_use.rs30
-rw-r--r--src/librustc/middle/ty.rs2
-rw-r--r--src/librustc/middle/typeck/check/mod.rs47
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs38
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs13
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs22
-rw-r--r--src/librustc/util/ppaux.rs1
-rw-r--r--src/libsyntax/ast.rs26
-rw-r--r--src/libsyntax/ast_map.rs14
-rw-r--r--src/libsyntax/ast_util.rs6
-rw-r--r--src/libsyntax/ext/asm.rs2
-rw-r--r--src/libsyntax/ext/build.rs9
-rw-r--r--src/libsyntax/ext/concat_idents.rs1
-rw-r--r--src/libsyntax/ext/log_syntax.rs1
-rw-r--r--src/libsyntax/fold.rs38
-rw-r--r--src/libsyntax/parse/classify.rs4
-rw-r--r--src/libsyntax/parse/mod.rs17
-rw-r--r--src/libsyntax/parse/parser.rs77
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs10
40 files changed, 337 insertions, 289 deletions
diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc
index 9280be146f9..c6410d16c74 100644
--- a/src/libfuzzer/fuzzer.rc
+++ b/src/libfuzzer/fuzzer.rc
@@ -78,7 +78,6 @@ pub fn common_exprs() -> ~[@ast::expr] {
     fn dse(e: ast::expr_) -> @ast::expr {
         @ast::expr {
             id: 0,
-            callee_id: -1,
             node: e,
             span: codemap::dummy_sp(),
         }
@@ -94,9 +93,9 @@ pub fn common_exprs() -> ~[@ast::expr] {
      dse(ast::expr_lit(@dsl(ast::lit_nil))),
      dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
      dse(ast::expr_lit(@dsl(ast::lit_bool(true)))),
-     dse(ast::expr_unary(ast::box(ast::m_imm),
+     dse(ast::expr_unary(-1, ast::box(ast::m_imm),
                          dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))),
-     dse(ast::expr_unary(ast::uniq(ast::m_imm),
+     dse(ast::expr_unary(-1, ast::uniq(ast::m_imm),
                          dse(ast::expr_lit(@dsl(ast::lit_bool(true))))))
     ]
 }
@@ -128,7 +127,7 @@ pub fn safe_to_use_expr(e: @ast::expr, tm: test_mode) -> bool {
           //ast::expr_cast(_, _) { false }
 
           // https://github.com/mozilla/rust/issues/1458
-          ast::expr_call(_, _, _) => { false }
+          ast::expr_call(*) => { false }
 
           _ => { true }
         }
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 08a19577308..8cd8a989352 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -394,14 +394,12 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr {
     let sess = cx.sess;
     let inner_expr = @ast::expr {
         id: sess.next_node_id(),
-        callee_id: sess.next_node_id(),
         node: ast::expr_vec(descs, ast::m_imm),
         span: dummy_sp(),
     };
 
     @ast::expr {
         id: sess.next_node_id(),
-        callee_id: sess.next_node_id(),
         node: ast::expr_vstore(inner_expr, ast::expr_vstore_slice),
         span: dummy_sp(),
     }
@@ -423,7 +421,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
 
     let name_expr = @ast::expr {
           id: cx.sess.next_node_id(),
-          callee_id: cx.sess.next_node_id(),
           node: ast::expr_lit(@name_lit),
           span: span
     };
@@ -432,7 +429,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr {
 
     let fn_expr = @ast::expr {
         id: cx.sess.next_node_id(),
-        callee_id: cx.sess.next_node_id(),
         node: ast::expr_path(fn_path),
         span: span,
     };
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 5d0def6f60a..7890e1b9f35 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -707,29 +707,29 @@ fn check_loans_in_expr<'a>(expr: @ast::expr,
           }
       }
       ast::expr_assign(dest, _) |
-      ast::expr_assign_op(_, dest, _) => {
+      ast::expr_assign_op(_, _, dest, _) => {
         this.check_assignment(dest);
       }
       ast::expr_call(f, ref args, _) => {
         this.check_call(expr, Some(f), f.id, f.span, *args);
       }
-      ast::expr_method_call(_, _, _, ref args, _) => {
-        this.check_call(expr, None, expr.callee_id, expr.span, *args);
+      ast::expr_method_call(callee_id, _, _, _, ref args, _) => {
+        this.check_call(expr, None, callee_id, expr.span, *args);
       }
-      ast::expr_index(_, rval) |
-      ast::expr_binary(_, _, rval)
+      ast::expr_index(callee_id, _, rval) |
+      ast::expr_binary(callee_id, _, _, rval)
       if this.bccx.method_map.contains_key(&expr.id) => {
         this.check_call(expr,
                         None,
-                        expr.callee_id,
+                        callee_id,
                         expr.span,
                         [rval]);
       }
-      ast::expr_unary(*) | ast::expr_index(*)
+      ast::expr_unary(callee_id, _, _) | ast::expr_index(callee_id, _, _)
       if this.bccx.method_map.contains_key(&expr.id) => {
         this.check_call(expr,
                         None,
-                        expr.callee_id,
+                        callee_id,
                         expr.span,
                         []);
       }
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index 83d039b7520..448f35faa46 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -175,7 +175,10 @@ fn gather_loans_in_expr(ex: @ast::expr,
            ex.id, pprust::expr_to_str(ex, tcx.sess.intr()));
 
     this.id_range.add(ex.id);
-    this.id_range.add(ex.callee_id);
+
+    for ex.get_callee_id().each |callee_id| {
+        this.id_range.add(*callee_id);
+    }
 
     // If this expression is borrowed, have to ensure it remains valid:
     for tcx.adjustments.find(&ex.id).each |&adjustments| {
@@ -201,7 +204,7 @@ fn gather_loans_in_expr(ex: @ast::expr,
         visit::visit_expr(ex, this, vt);
       }
 
-      ast::expr_assign(l, _) | ast::expr_assign_op(_, l, _) => {
+      ast::expr_assign(l, _) | ast::expr_assign_op(_, _, l, _) => {
           let l_cmt = this.bccx.cat_expr(l);
           match opt_loan_path(l_cmt) {
               Some(l_lp) => {
@@ -228,8 +231,8 @@ fn gather_loans_in_expr(ex: @ast::expr,
         visit::visit_expr(ex, this, vt);
       }
 
-      ast::expr_index(_, arg) |
-      ast::expr_binary(_, _, arg)
+      ast::expr_index(_, _, arg) |
+      ast::expr_binary(_, _, _, arg)
       if this.bccx.method_map.contains_key(&ex.id) => {
           // Arguments in method calls are always passed by ref.
           //
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 01398db4324..0cffc9c52c2 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -91,14 +91,14 @@ pub fn check_expr(sess: Session,
                   v: visit::vt<bool>) {
     if is_const {
         match e.node {
-          expr_unary(deref, _) => { }
-          expr_unary(box(_), _) | expr_unary(uniq(_), _) => {
+          expr_unary(_, deref, _) => { }
+          expr_unary(_, box(_), _) | expr_unary(_, uniq(_), _) => {
             sess.span_err(e.span,
                           "disallowed operator in constant expression");
             return;
           }
           expr_lit(@codemap::spanned {node: lit_str(_), _}) => { }
-          expr_binary(_, _, _) | expr_unary(_, _) => {
+          expr_binary(*) | expr_unary(*) => {
             if method_map.contains_key(&e.id) {
                 sess.span_err(e.span, "user-defined operators are not \
                                        allowed in constant expressions");
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index d68bbf8cdb3..7e8e5bffb57 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -93,12 +93,12 @@ pub fn classify(e: @expr,
               }
 
               ast::expr_copy(inner) |
-              ast::expr_unary(_, inner) |
+              ast::expr_unary(_, _, inner) |
               ast::expr_paren(inner) => {
                 classify(inner, tcx)
               }
 
-              ast::expr_binary(_, a, b) => {
+              ast::expr_binary(_, _, a, b) => {
                 join(classify(a, tcx),
                      classify(b, tcx))
               }
@@ -141,7 +141,7 @@ pub fn classify(e: @expr,
                 classify(base, tcx)
               }
 
-              ast::expr_index(base, idx) => {
+              ast::expr_index(_, base, idx) => {
                 join(classify(base, tcx),
                      classify(idx, tcx))
               }
@@ -251,7 +251,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
     use middle::ty;
     fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
     match e.node {
-      expr_unary(neg, inner) => {
+      expr_unary(_, neg, inner) => {
         match eval_const_expr_partial(tcx, inner) {
           Ok(const_float(f)) => Ok(const_float(-f)),
           Ok(const_int(i)) => Ok(const_int(-i)),
@@ -261,7 +261,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
           ref err => (/*bad*/copy *err)
         }
       }
-      expr_unary(not, inner) => {
+      expr_unary(_, not, inner) => {
         match eval_const_expr_partial(tcx, inner) {
           Ok(const_int(i)) => Ok(const_int(!i)),
           Ok(const_uint(i)) => Ok(const_uint(!i)),
@@ -269,7 +269,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
           _ => Err(~"Not on float or string")
         }
       }
-      expr_binary(op, a, b) => {
+      expr_binary(_, op, a, b) => {
         match (eval_const_expr_partial(tcx, a),
                eval_const_expr_partial(tcx, b)) {
           (Ok(const_float(a)), Ok(const_float(b))) => {
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index cd60279873a..aedc0e1db5e 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -639,7 +639,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
             }
 
             ast::expr_assign(l, r) |
-            ast::expr_assign_op(_, l, r) => {
+            ast::expr_assign_op(_, _, l, r) => {
                 self.walk_expr(r, in_out, loop_scopes);
                 self.walk_expr(l, in_out, loop_scopes);
             }
@@ -661,23 +661,23 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
             }
 
             ast::expr_call(f, ref args, _) => {
-                self.walk_call(expr.callee_id, expr.id,
+                self.walk_call(f.id, expr.id,
                                f, *args, in_out, loop_scopes);
             }
 
-            ast::expr_method_call(rcvr, _, _, ref args, _) => {
-                self.walk_call(expr.callee_id, expr.id,
+            ast::expr_method_call(callee_id, rcvr, _, _, ref args, _) => {
+                self.walk_call(callee_id, expr.id,
                                rcvr, *args, in_out, loop_scopes);
             }
 
-            ast::expr_index(l, r) |
-            ast::expr_binary(_, l, r) if self.is_method_call(expr) => {
-                self.walk_call(expr.callee_id, expr.id,
+            ast::expr_index(callee_id, l, r) |
+            ast::expr_binary(callee_id, _, l, r) if self.is_method_call(expr) => {
+                self.walk_call(callee_id, expr.id,
                                l, [r], in_out, loop_scopes);
             }
 
-            ast::expr_unary(_, e) if self.is_method_call(expr) => {
-                self.walk_call(expr.callee_id, expr.id,
+            ast::expr_unary(callee_id, _, e) if self.is_method_call(expr) => {
+                self.walk_call(callee_id, expr.id,
                                e, [], in_out, loop_scopes);
             }
 
@@ -685,7 +685,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
                 self.walk_exprs(*exprs, in_out, loop_scopes);
             }
 
-            ast::expr_binary(op, l, r) if ast_util::lazy_binop(op) => {
+            ast::expr_binary(_, op, l, r) if ast_util::lazy_binop(op) => {
                 self.walk_expr(l, in_out, loop_scopes);
                 let temp = reslice(in_out).to_vec();
                 self.walk_expr(r, in_out, loop_scopes);
@@ -693,8 +693,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
             }
 
             ast::expr_log(l, r) |
-            ast::expr_index(l, r) |
-            ast::expr_binary(_, l, r) => {
+            ast::expr_index(_, l, r) |
+            ast::expr_binary(_, _, l, r) => {
                 self.walk_exprs([l, r], in_out, loop_scopes);
             }
 
@@ -708,7 +708,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
             ast::expr_loop_body(e) |
             ast::expr_do_body(e) |
             ast::expr_cast(e, _) |
-            ast::expr_unary(_, e) |
+            ast::expr_unary(_, _, e) |
             ast::expr_paren(e) |
             ast::expr_vstore(e, _) |
             ast::expr_field(e, _, _) => {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index d809e653f69..895c6cc477f 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -111,8 +111,8 @@ pub fn check_crate(tcx: ty::ctxt,
 
         visit_expr: |expr, _, visitor| {
             match expr.node {
-                expr_method_call(*) => {
-                    let base_type = ty::node_id_to_type(tcx, expr.callee_id);
+                expr_method_call(callee_id, _, _, _, _, _) => {
+                    let base_type = ty::node_id_to_type(tcx, callee_id);
                     debug!("effect: method call case, base type is %s",
                            ppaux::ty_to_str(tcx, base_type));
                     if type_is_unsafe_function(base_type) {
@@ -128,7 +128,7 @@ pub fn check_crate(tcx: ty::ctxt,
                         require_unsafe(expr.span, "call to unsafe function")
                     }
                 }
-                expr_unary(deref, base) => {
+                expr_unary(_, deref, base) => {
                     let base_type = ty::node_id_to_type(tcx, base.id);
                     debug!("effect: unary case, base type is %s",
                            ppaux::ty_to_str(tcx, base_type));
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 8493965049e..48983dcadc8 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -241,10 +241,9 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
     debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr()));
 
     // Handle any kind bounds on type parameters
-    let type_parameter_id = match e.node {
-        expr_index(*)|expr_assign_op(*)|
-        expr_unary(*)|expr_binary(*)|expr_method_call(*) => e.callee_id,
-        _ => e.id
+    let type_parameter_id = match e.get_callee_id() {
+        Some(callee_id) => callee_id,
+        None => e.id,
     };
     for cx.tcx.node_type_substs.find(&type_parameter_id).each |ts| {
         let type_param_defs = match e.node {
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index c460ec89e4e..703516251dc 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -675,7 +675,7 @@ fn lint_type_limits() -> visit::vt<@mut Context> {
     visit::mk_vt(@visit::Visitor {
         visit_expr: |e, cx: @mut Context, vt| {
             match e.node {
-                ast::expr_binary(ref binop, @ref l, @ref r) => {
+                ast::expr_binary(_, ref binop, @ref l, @ref r) => {
                     if is_comparison(*binop)
                         && !check_limits(cx, *binop, l, r) {
                         cx.span_lint(type_limits, e.span,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a9d9d55563a..6e60851ad14 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -499,7 +499,7 @@ fn visit_expr(expr: @expr, this: @mut IrMaps, vt: vt<@mut IrMaps>) {
         this.add_live_node_for_node(expr.id, ExprNode(expr.span));
         visit::visit_expr(expr, this, vt);
       }
-      expr_binary(op, _, _) if ast_util::lazy_binop(op) => {
+      expr_binary(_, op, _, _) if ast_util::lazy_binop(op) => {
         this.add_live_node_for_node(expr.id, ExprNode(expr.span));
         visit::visit_expr(expr, this, vt);
       }
@@ -1138,7 +1138,7 @@ impl Liveness {
             self.propagate_through_expr(r, succ)
           }
 
-          expr_assign_op(_, l, r) => {
+          expr_assign_op(_, _, l, r) => {
             // see comment on lvalues in
             // propagate_through_lvalue_components()
             let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ);
@@ -1178,11 +1178,10 @@ impl Liveness {
             self.propagate_through_expr(f, succ)
           }
 
-          expr_method_call(rcvr, _, _, ref args, _) => {
+          expr_method_call(callee_id, rcvr, _, _, ref args, _) => {
             // calling a method with bot return type means that the method
             // will fail, and hence the successors can be ignored
-            let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx,
-                                                          expr.callee_id));
+            let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, callee_id));
             let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
                        else {succ};
             let succ = self.propagate_through_exprs(*args, succ);
@@ -1193,7 +1192,7 @@ impl Liveness {
             self.propagate_through_exprs(*exprs, succ)
           }
 
-          expr_binary(op, l, r) if ast_util::lazy_binop(op) => {
+          expr_binary(_, op, l, r) if ast_util::lazy_binop(op) => {
             let r_succ = self.propagate_through_expr(r, succ);
 
             let ln = self.live_node(expr.id, expr.span);
@@ -1204,8 +1203,8 @@ impl Liveness {
           }
 
           expr_log(l, r) |
-          expr_index(l, r) |
-          expr_binary(_, l, r) => {
+          expr_index(_, l, r) |
+          expr_binary(_, _, l, r) => {
             self.propagate_through_exprs([l, r], succ)
           }
 
@@ -1214,7 +1213,7 @@ impl Liveness {
           expr_loop_body(e) |
           expr_do_body(e) |
           expr_cast(e, _) |
-          expr_unary(_, e) |
+          expr_unary(_, _, e) |
           expr_paren(e) => {
             self.propagate_through_expr(e, succ)
           }
@@ -1456,7 +1455,7 @@ fn check_expr(expr: @expr, this: @Liveness, vt: vt<@Liveness>) {
         visit::visit_expr(expr, this, vt);
       }
 
-      expr_assign_op(_, l, _) => {
+      expr_assign_op(_, _, l, _) => {
         this.check_lvalue(l, vt);
 
         visit::visit_expr(expr, this, vt);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 194ea9ac32d..f54e1e623ec 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -389,7 +389,7 @@ impl mem_categorization_ctxt {
 
         let expr_ty = self.expr_ty(expr);
         match expr.node {
-          ast::expr_unary(ast::deref, e_base) => {
+          ast::expr_unary(_, ast::deref, e_base) => {
             if self.method_map.contains_key(&expr.id) {
                 return self.cat_rvalue(expr, expr_ty);
             }
@@ -407,7 +407,7 @@ impl mem_categorization_ctxt {
             self.cat_field(expr, base_cmt, f_name, self.expr_ty(expr))
           }
 
-          ast::expr_index(base, _) => {
+          ast::expr_index(_, base, _) => {
             if self.method_map.contains_key(&expr.id) {
                 return self.cat_rvalue(expr, expr_ty);
             }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 2e7ceba3366..caa18b2834f 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -310,7 +310,7 @@ impl VisitContext {
                 }
             }
 
-            expr_unary(deref, base) => {       // *base
+            expr_unary(_, deref, base) => {       // *base
                 if !self.use_overloaded_operator(
                     expr, base, [], visitor)
                 {
@@ -324,7 +324,7 @@ impl VisitContext {
                 self.use_expr(base, comp_mode, visitor);
             }
 
-            expr_index(lhs, rhs) => {          // lhs[rhs]
+            expr_index(_, lhs, rhs) => {          // lhs[rhs]
                 if !self.use_overloaded_operator(
                     expr, lhs, [rhs], visitor)
                 {
@@ -338,11 +338,11 @@ impl VisitContext {
                 self.use_fn_args(callee.id, *args, visitor);
             }
 
-            expr_method_call(callee, _, _, ref args, _) => { // callee.m(args)
+            expr_method_call(callee_id, rcvr, _, _, ref args, _) => { // callee.m(args)
                 // Implicit self is equivalent to & mode, but every
                 // other kind should be + mode.
-                self.use_receiver(callee, visitor);
-                self.use_fn_args(expr.callee_id, *args, visitor);
+                self.use_receiver(rcvr, visitor);
+                self.use_fn_args(callee_id, *args, visitor);
             }
 
             expr_struct(_, ref fields, opt_with) => {
@@ -444,7 +444,7 @@ impl VisitContext {
                 self.consume_block(blk, visitor);
             }
 
-            expr_unary(_, lhs) => {
+            expr_unary(_, _, lhs) => {
                 if !self.use_overloaded_operator(
                     expr, lhs, [], visitor)
                 {
@@ -452,7 +452,7 @@ impl VisitContext {
                 }
             }
 
-            expr_binary(_, lhs, rhs) => {
+            expr_binary(_, _, lhs, rhs) => {
                 if !self.use_overloaded_operator(
                     expr, lhs, [rhs], visitor)
                 {
@@ -480,7 +480,7 @@ impl VisitContext {
                 self.consume_expr(base, visitor);
             }
 
-            expr_assign_op(_, lhs, rhs) => {
+            expr_assign_op(_, _, lhs, rhs) => {
                 // FIXME(#4712) --- Overloaded operators?
                 //
                 // if !self.use_overloaded_operator(
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 0f00e9d596e..1e596ee6b36 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -432,32 +432,23 @@ pub fn check_crate(tcx: ty::ctxt,
         visit_expr: |expr, method_map: &method_map, visitor| {
             match expr.node {
                 expr_field(base, ident, _) => {
+                    // Method calls are now a special syntactic form,
+                    // so `a.b` should always be a field.
+                    assert!(!method_map.contains_key(&expr.id));
+
                     // With type_autoderef, make sure we don't
                     // allow pointers to violate privacy
                     match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
                                                           base))).sty {
                         ty_struct(id, _)
-                        if id.crate != local_crate ||
-                           !privileged_items.contains(&(id.node)) => {
-                            match method_map.find(&expr.id) {
-                                None => {
-                                    debug!("(privacy checking) checking \
-                                            field access");
-                                    check_field(expr.span, id, ident);
-                                }
-                                Some(ref entry) => {
-                                    debug!("(privacy checking) checking \
-                                            impl method");
-                                    check_method(expr.span,
-                                                 &entry.origin,
-                                                 ident);
-                                }
-                            }
+                        if id.crate != local_crate || !privileged_items.contains(&(id.node)) => {
+                            debug!("(privacy checking) checking field access");
+                            check_field(expr.span, id, ident);
                         }
                         _ => {}
                     }
                 }
-                expr_method_call(base, ident, _, _, _) => {
+                expr_method_call(_, base, ident, _, _, _) => {
                     // Ditto
                     match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
                                                           base))).sty {
@@ -529,7 +520,7 @@ pub fn check_crate(tcx: ty::ctxt,
                         }
                     }
                 }
-                expr_unary(ast::deref, operand) => {
+                expr_unary(_, ast::deref, operand) => {
                     // In *e, we need to check that if e's type is an
                     // enum type t, then t's first variant is public or
                     // privileged. (We can assume it has only one variant
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index b8faa0740b8..a1eb0726c3d 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -4969,67 +4969,71 @@ impl Resolver {
                                                          expr: @expr) {
         match expr.node {
             expr_field(_, ident, _) => {
+                // FIXME(#6890): Even though you can't treat a method like a
+                // field, we need to add any trait methods we find that match
+                // the field name so that we can do some nice error reporting
+                // later on in typeck.
                 let traits = self.search_for_traits_containing_method(ident);
                 self.trait_map.insert(expr.id, @mut traits);
             }
-            expr_method_call(_, ident, _, _, _) => {
+            expr_method_call(_, _, ident, _, _, _) => {
                 let traits = self.search_for_traits_containing_method(ident);
                 self.trait_map.insert(expr.id, @mut traits);
             }
-            expr_binary(add, _, _) | expr_assign_op(add, _, _) => {
+            expr_binary(_, add, _, _) | expr_assign_op(_, add, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.add_trait());
             }
-            expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => {
+            expr_binary(_, subtract, _, _) | expr_assign_op(_, subtract, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.sub_trait());
             }
-            expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => {
+            expr_binary(_, mul, _, _) | expr_assign_op(_, mul, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.mul_trait());
             }
-            expr_binary(div, _, _) | expr_assign_op(div, _, _) => {
+            expr_binary(_, div, _, _) | expr_assign_op(_, div, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.div_trait());
             }
-            expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => {
+            expr_binary(_, rem, _, _) | expr_assign_op(_, rem, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.rem_trait());
             }
-            expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => {
+            expr_binary(_, bitxor, _, _) | expr_assign_op(_, bitxor, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.bitxor_trait());
             }
-            expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => {
+            expr_binary(_, bitand, _, _) | expr_assign_op(_, bitand, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.bitand_trait());
             }
-            expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => {
+            expr_binary(_, bitor, _, _) | expr_assign_op(_, bitor, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.bitor_trait());
             }
-            expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => {
+            expr_binary(_, shl, _, _) | expr_assign_op(_, shl, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.shl_trait());
             }
-            expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => {
+            expr_binary(_, shr, _, _) | expr_assign_op(_, shr, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.shr_trait());
             }
-            expr_binary(lt, _, _) | expr_binary(le, _, _) |
-            expr_binary(ge, _, _) | expr_binary(gt, _, _) => {
+            expr_binary(_, lt, _, _) | expr_binary(_, le, _, _) |
+            expr_binary(_, ge, _, _) | expr_binary(_, gt, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.ord_trait());
             }
-            expr_binary(eq, _, _) | expr_binary(ne, _, _) => {
+            expr_binary(_, eq, _, _) | expr_binary(_, ne, _, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.eq_trait());
             }
-            expr_unary(neg, _) => {
+            expr_unary(_, neg, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.neg_trait());
             }
-            expr_unary(not, _) => {
+            expr_unary(_, not, _) => {
                 self.add_fixed_trait_for_expr(expr.id,
                                               self.lang_items.not_trait());
             }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 557388cf11c..767b02d13e2 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -328,6 +328,7 @@ pub fn trans_call(in_cx: block,
 
 pub fn trans_method_call(in_cx: block,
                          call_ex: @ast::expr,
+                         callee_id: ast::node_id,
                          rcvr: @ast::expr,
                          args: CallArgs,
                          dest: expr::Dest)
@@ -339,7 +340,7 @@ pub fn trans_method_call(in_cx: block,
     trans_call_inner(
         in_cx,
         call_ex.info(),
-        node_id_type(in_cx, call_ex.callee_id),
+        node_id_type(in_cx, callee_id),
         expr_ty(in_cx, call_ex),
         |cx| {
             match cx.ccx().maps.method_map.find_copy(&call_ex.id) {
@@ -349,7 +350,7 @@ pub fn trans_method_call(in_cx: block,
                            origin.repr(in_cx.tcx()));
 
                     meth::trans_method_callee(cx,
-                                              call_ex.callee_id,
+                                              callee_id,
                                               rcvr,
                                               origin)
                 }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 7080487e7f8..717cae096f6 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -611,7 +611,7 @@ pub trait get_node_info {
 impl get_node_info for @ast::expr {
     fn info(&self) -> Option<NodeInfo> {
         Some(NodeInfo {id: self.id,
-                       callee_id: Some(self.callee_id),
+                       callee_id: self.get_callee_id(),
                        span: self.span})
     }
 }
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index d47fc184cf3..62704fd1eb0 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -251,7 +251,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
         let _icx = cx.insn_ctxt("const_expr");
         return match e.node {
           ast::expr_lit(lit) => consts::const_lit(cx, e, *lit),
-          ast::expr_binary(b, e1, e2) => {
+          ast::expr_binary(_, b, e1, e2) => {
             let te1 = const_expr(cx, e1);
             let te2 = const_expr(cx, e2);
 
@@ -333,7 +333,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
               },
             };
           },
-          ast::expr_unary(u, e) => {
+          ast::expr_unary(_, u, e) => {
             let te = const_expr(cx, e);
             let ty = ty::expr_ty(cx.tcx, e);
             let is_float = ty::type_is_fp(ty);
@@ -372,7 +372,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
               }
           }
 
-          ast::expr_index(base, index) => {
+          ast::expr_index(_, base, index) => {
               let bt = ty::expr_ty_adjusted(cx.tcx, base);
               let bv = const_expr(cx, base);
               let iv = match const_eval::eval_const_expr(cx.tcx, index) {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index fa8c3cd8879..90275f9a9c2 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -470,13 +470,13 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
         ast::expr_lit(lit) => {
             return trans_immediate_lit(bcx, expr, *lit);
         }
-        ast::expr_binary(op, lhs, rhs) => {
+        ast::expr_binary(_, op, lhs, rhs) => {
             // if overloaded, would be RvalueDpsExpr
             assert!(!bcx.ccx().maps.method_map.contains_key(&expr.id));
 
             return trans_binary(bcx, expr, op, lhs, rhs);
         }
-        ast::expr_unary(op, x) => {
+        ast::expr_unary(_, op, x) => {
             return trans_unary_datum(bcx, expr, op, x);
         }
         ast::expr_addr_of(_, x) => {
@@ -535,8 +535,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
             return src_datum.store_to_datum(
                 bcx, src.id, DROP_EXISTING, dst_datum);
         }
-        ast::expr_assign_op(op, dst, src) => {
-            return trans_assign_op(bcx, expr, op, dst, src);
+        ast::expr_assign_op(callee_id, op, dst, src) => {
+            return trans_assign_op(bcx, expr, callee_id, op, dst, src);
         }
         ast::expr_paren(a) => {
             return trans_rvalue_stmt_unadjusted(bcx, a);
@@ -641,35 +641,39 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
             return callee::trans_call(
                 bcx, expr, f, callee::ArgExprs(*args), expr.id, dest);
         }
-        ast::expr_method_call(rcvr, _, _, ref args, _) => {
+        ast::expr_method_call(callee_id, rcvr, _, _, ref args, _) => {
             return callee::trans_method_call(bcx,
                                              expr,
+                                             callee_id,
                                              rcvr,
                                              callee::ArgExprs(*args),
                                              dest);
         }
-        ast::expr_binary(_, lhs, rhs) => {
+        ast::expr_binary(callee_id, _, lhs, rhs) => {
             // if not overloaded, would be RvalueDatumExpr
             return trans_overloaded_op(bcx,
                                        expr,
+                                       callee_id,
                                        lhs,
                                        ~[rhs],
                                        expr_ty(bcx, expr),
                                        dest);
         }
-        ast::expr_unary(_, subexpr) => {
+        ast::expr_unary(callee_id, _, subexpr) => {
             // if not overloaded, would be RvalueDatumExpr
             return trans_overloaded_op(bcx,
                                        expr,
+                                       callee_id,
                                        subexpr,
                                        ~[],
                                        expr_ty(bcx, expr),
                                        dest);
         }
-        ast::expr_index(base, idx) => {
+        ast::expr_index(callee_id, base, idx) => {
             // if not overloaded, would be RvalueDatumExpr
             return trans_overloaded_op(bcx,
                                        expr,
+                                       callee_id,
                                        base,
                                        ~[idx],
                                        expr_ty(bcx, expr),
@@ -687,8 +691,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
                 }
             }
         }
-        ast::expr_assign_op(op, dst, src) => {
-            return trans_assign_op(bcx, expr, op, dst, src);
+        ast::expr_assign_op(callee_id, op, dst, src) => {
+            return trans_assign_op(bcx, expr, callee_id, op, dst, src);
         }
         _ => {
             bcx.tcx().sess.span_bug(
@@ -822,10 +826,10 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
         ast::expr_field(base, ident, _) => {
             trans_rec_field(bcx, base, ident)
         }
-        ast::expr_index(base, idx) => {
+        ast::expr_index(_, base, idx) => {
             trans_index(bcx, expr, base, idx)
         }
-        ast::expr_unary(ast::deref, base) => {
+        ast::expr_unary(_, ast::deref, base) => {
             let basedatum = unpack_datum!(bcx, trans_to_datum(bcx, base));
             basedatum.deref(bcx, expr, 0)
         }
@@ -1514,20 +1518,21 @@ fn trans_binary(bcx: block,
 
 fn trans_overloaded_op(bcx: block,
                        expr: @ast::expr,
+                       callee_id: ast::node_id,
                        rcvr: @ast::expr,
                        args: ~[@ast::expr],
                        ret_ty: ty::t,
                        dest: Dest)
                        -> block {
     let origin = bcx.ccx().maps.method_map.get_copy(&expr.id);
-    let fty = node_id_type(bcx, expr.callee_id);
+    let fty = node_id_type(bcx, callee_id);
     callee::trans_call_inner(bcx,
                              expr.info(),
                              fty,
                              ret_ty,
                              |bcx| {
                                 meth::trans_method_callee(bcx,
-                                                          expr.callee_id,
+                                                          callee_id,
                                                           rcvr,
                                                           origin)
                              },
@@ -1652,6 +1657,7 @@ fn trans_imm_cast(bcx: block, expr: @ast::expr,
 
 fn trans_assign_op(bcx: block,
                    expr: @ast::expr,
+                   callee_id: ast::node_id,
                    op: ast::binop,
                    dst: @ast::expr,
                    src: @ast::expr) -> block
@@ -1670,6 +1676,7 @@ fn trans_assign_op(bcx: block,
         let scratch = scratch_datum(bcx, dst_datum.ty, false);
         let bcx = trans_overloaded_op(bcx,
                                       expr,
+                                      callee_id,
                                       dst,
                                       ~[src],
                                       dst_datum.ty,
diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs
index 62360771f55..237ba1f49bb 100644
--- a/src/librustc/middle/trans/reachable.rs
+++ b/src/librustc/middle/trans/reachable.rs
@@ -192,17 +192,6 @@ fn traverse_inline_body(cx: @mut ctx, body: &blk) {
                          expr_to_str(e, cx.tcx.sess.intr())))
             }
           }
-          expr_field(_, _, _) => {
-            match cx.method_map.find(&e.id) {
-              Some(&typeck::method_map_entry {
-                  origin: typeck::method_static(did),
-                  _
-                }) => {
-                traverse_def_id(cx, did);
-              }
-              _ => ()
-            }
-          }
           expr_method_call(*) => {
             match cx.method_map.find(&e.id) {
               Some(&typeck::method_map_entry {
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 77b2586781f..318612bd15b 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -273,8 +273,8 @@ pub fn mark_for_method_call(cx: Context, e_id: node_id, callee_id: node_id) {
 pub fn mark_for_expr(cx: Context, e: @expr) {
     match e.node {
       expr_vstore(_, _) | expr_vec(_, _) | expr_struct(*) | expr_tup(_) |
-      expr_unary(box(_), _) | expr_unary(uniq(_), _) |
-      expr_binary(add, _, _) | expr_copy(_) | expr_repeat(*) => {
+      expr_unary(_, box(_), _) | expr_unary(_, uniq(_), _) |
+      expr_binary(_, add, _, _) | expr_copy(_) | expr_repeat(*) => {
         node_type_needs(cx, use_repr, e.id);
       }
       expr_cast(base, _) => {
@@ -288,7 +288,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
             _ => ()
         }
       }
-      expr_binary(op, lhs, _) => {
+      expr_binary(_, op, lhs, _) => {
         match op {
           eq | lt | le | ne | ge | gt => {
             node_type_needs(cx, use_tydesc, lhs.id)
@@ -317,16 +317,24 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
               }
           }
       }
-      expr_assign(val, _) | expr_assign_op(_, val, _) |
+      expr_assign(val, _) | expr_assign_op(_, _, val, _) |
       expr_ret(Some(val)) => {
         node_type_needs(cx, use_repr, val.id);
       }
-      expr_index(base, _) | expr_field(base, _, _) => {
+      expr_index(callee_id, base, _) => {
         // FIXME (#2537): could be more careful and not count fields after
         // the chosen field.
         let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
         type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
-        mark_for_method_call(cx, e.id, e.callee_id);
+        mark_for_method_call(cx, e.id, callee_id);
+      }
+      expr_field(base, _, _) => {
+        // Method calls are now a special syntactic form,
+        // so `a.b` should always be a field.
+        assert!(!cx.ccx.maps.method_map.contains_key(&e.id));
+
+        let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
+        type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
       }
       expr_log(_, val) => {
         node_type_needs(cx, use_tydesc, val.id);
@@ -336,14 +344,14 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
               type_needs(cx, use_repr, *a);
           }
       }
-      expr_method_call(rcvr, _, _, _, _) => {
+      expr_method_call(callee_id, rcvr, _, _, _, _) => {
         let base_ty = ty::node_id_to_type(cx.ccx.tcx, rcvr.id);
         type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
 
-        for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, e.callee_id)).each |a| {
+        for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, callee_id)).each |a| {
             type_needs(cx, use_repr, *a);
         }
-        mark_for_method_call(cx, e.id, e.callee_id);
+        mark_for_method_call(cx, e.id, callee_id);
       }
 
       expr_inline_asm(ref ia) => {
@@ -358,8 +366,8 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
       expr_paren(e) => mark_for_expr(cx, e),
 
       expr_match(*) | expr_block(_) | expr_if(*) | expr_while(*) |
-      expr_break(_) | expr_again(_) | expr_unary(_, _) | expr_lit(_) |
-      expr_mac(_) | expr_addr_of(_, _) | expr_ret(_) | expr_loop(_, _) |
+      expr_break(_) | expr_again(_) | expr_unary(*) | expr_lit(_) |
+      expr_mac(_) | expr_addr_of(*) | expr_ret(_) | expr_loop(*) |
       expr_loop_body(_) | expr_do_body(_) => ()
     }
 }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index f02f117bd36..506bbd9473a 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3253,7 +3253,7 @@ pub fn expr_kind(tcx: ctxt,
             }
         }
 
-        ast::expr_unary(ast::deref, _) |
+        ast::expr_unary(_, ast::deref, _) |
         ast::expr_field(*) |
         ast::expr_index(*) => {
             LvalueExpr
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index ac39e614165..439ff1f413b 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1310,6 +1310,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
     // A generic function for doing all of the checking for call expressions
     fn check_call(fcx: @mut FnCtxt,
+                  callee_id: ast::node_id,
                   call_expr: @ast::expr,
                   f: @ast::expr,
                   args: &[@ast::expr],
@@ -1326,7 +1327,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         // now. Best thing would I think be to just have a separate
         // "callee table" that contains the FnSig and not a general
         // purpose ty::t
-        fcx.write_ty(call_expr.callee_id, fn_ty);
+        fcx.write_ty(callee_id, fn_ty);
 
         // Extract the function signature from `in_fty`.
         let fn_sty = structure_of(fcx, f.span, fn_ty);
@@ -1363,6 +1364,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
     // Checks a method call.
     fn check_method_call(fcx: @mut FnCtxt,
+                         callee_id: ast::node_id,
                          expr: @ast::expr,
                          rcvr: @ast::expr,
                          method_name: ast::ident,
@@ -1380,7 +1382,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         match method::lookup(fcx,
                              expr,
                              rcvr,
-                             expr.callee_id,
+                             callee_id,
                              method_name,
                              expr_t,
                              tps,
@@ -1404,12 +1406,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
                 // Add error type for the result
                 fcx.write_error(expr.id);
-                fcx.write_error(expr.callee_id);
+                fcx.write_error(callee_id);
             }
         }
 
         // Call the generic checker.
-        let fn_ty = fcx.node_ty(expr.callee_id);
+        let fn_ty = fcx.node_ty(callee_id);
         let ret_ty = check_method_argument_types(fcx, expr.span,
                                                  fn_ty, expr, args, sugar,
                                                  DontDerefArgs);
@@ -1444,6 +1446,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
     }
 
     fn lookup_op_method(fcx: @mut FnCtxt,
+                        callee_id: ast::node_id,
                         op_ex: @ast::expr,
                         self_ex: @ast::expr,
                         self_t: ty::t,
@@ -1456,10 +1459,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                        )
                      -> ty::t {
         match method::lookup(fcx, op_ex, self_ex,
-                             op_ex.callee_id, opname, self_t, [],
+                             callee_id, opname, self_t, [],
                              deref_args, CheckTraitsOnly, autoderef_receiver) {
             Some(ref origin) => {
-                let method_ty = fcx.node_ty(op_ex.callee_id);
+                let method_ty = fcx.node_ty(callee_id);
                 let method_map = fcx.inh.method_map;
                 method_map.insert(op_ex.id, *origin);
                 check_method_argument_types(fcx, op_ex.span,
@@ -1481,6 +1484,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
     // could be either a expr_binop or an expr_assign_binop
     fn check_binop(fcx: @mut FnCtxt,
+                   callee_id: ast::node_id,
                    expr: @ast::expr,
                    op: ast::binop,
                    lhs: @ast::expr,
@@ -1536,7 +1540,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
         }
 
-        let result_t = check_user_binop(fcx, expr, lhs, lhs_t, op, rhs,
+        let result_t = check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs,
                                        expected_result);
         fcx.write_ty(expr.id, result_t);
         if ty::type_is_error(result_t) {
@@ -1545,6 +1549,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
     }
 
     fn check_user_binop(fcx: @mut FnCtxt,
+                        callee_id: ast::node_id,
                         ex: @ast::expr,
                         lhs_expr: @ast::expr,
                         lhs_resolved_t: ty::t,
@@ -1561,7 +1566,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                              ast_util::binop_to_str(op), actual)},
                             lhs_resolved_t, None)
                 };
-                return lookup_op_method(fcx, ex, lhs_expr, lhs_resolved_t,
+                return lookup_op_method(fcx, callee_id, ex, lhs_expr, lhs_resolved_t,
                                        fcx.tcx().sess.ident_of(*name),
                                        ~[rhs], DoDerefArgs, DontAutoderefReceiver, if_op_unbound,
                                        expected_result);
@@ -1586,6 +1591,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
     }
 
     fn check_user_unop(fcx: @mut FnCtxt,
+                       callee_id: ast::node_id,
                        op_str: &str,
                        mname: &str,
                        ex: @ast::expr,
@@ -1594,7 +1600,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                        expected_t: Option<ty::t>)
                     -> ty::t {
        lookup_op_method(
-            fcx, ex, rhs_expr, rhs_t,
+            fcx, callee_id, ex, rhs_expr, rhs_t,
             fcx.tcx().sess.ident_of(mname), ~[],
             DoDerefArgs, DontAutoderefReceiver,
             || {
@@ -2221,8 +2227,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         let typ = check_lit(fcx, lit);
         fcx.write_ty(id, typ);
       }
-      ast::expr_binary(op, lhs, rhs) => {
-        check_binop(fcx, expr, op, lhs, rhs, expected);
+      ast::expr_binary(callee_id, op, lhs, rhs) => {
+        check_binop(fcx, callee_id, expr, op, lhs, rhs, expected);
         let lhs_ty = fcx.expr_ty(lhs);
         let rhs_ty = fcx.expr_ty(rhs);
         if ty::type_is_error(lhs_ty) ||
@@ -2234,8 +2240,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             fcx.write_bot(id);
         }
       }
-      ast::expr_assign_op(op, lhs, rhs) => {
-        check_binop(fcx, expr, op, lhs, rhs, expected);
+      ast::expr_assign_op(callee_id, op, lhs, rhs) => {
+        check_binop(fcx, callee_id, expr, op, lhs, rhs, expected);
         let lhs_t = fcx.expr_ty(lhs);
         let result_t = fcx.expr_ty(expr);
         demand::suptype(fcx, expr.span, result_t, lhs_t);
@@ -2248,7 +2254,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             fcx.write_nil(expr.id);
         }
       }
-      ast::expr_unary(unop, oprnd) => {
+      ast::expr_unary(callee_id, unop, oprnd) => {
         let exp_inner = do unpack_expected(fcx, expected) |sty| {
             match unop {
               ast::box(_) | ast::uniq(_) => match *sty {
@@ -2307,7 +2313,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
                          ty::get(oprnd_t).sty == ty::ty_bool) {
-                        oprnd_t = check_user_unop(fcx,
+                        oprnd_t = check_user_unop(fcx, callee_id,
                             "!", "not", expr, oprnd, oprnd_t,
                                                   expected);
                     }
@@ -2317,7 +2323,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
                          ty::type_is_fp(oprnd_t)) {
-                        oprnd_t = check_user_unop(fcx,
+                        oprnd_t = check_user_unop(fcx, callee_id,
                             "-", "neg", expr, oprnd, oprnd_t, expected);
                     }
                 }
@@ -2553,7 +2559,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         fcx.write_ty(id, fcx.node_ty(b.node.id));
       }
       ast::expr_call(f, ref args, sugar) => {
-          check_call(fcx, expr, f, *args, sugar);
+          check_call(fcx, expr.id, expr, f, *args, sugar);
           let f_ty = fcx.expr_ty(f);
           let (args_bot, args_err) = args.foldl((false, false),
              |&(rest_bot, rest_err), a| {
@@ -2568,8 +2574,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
               fcx.write_bot(id);
           }
       }
-      ast::expr_method_call(rcvr, ident, ref tps, ref args, sugar) => {
-        check_method_call(fcx, expr, rcvr, ident, *args, *tps, sugar);
+      ast::expr_method_call(callee_id, rcvr, ident, ref tps, ref args, sugar) => {
+        check_method_call(fcx, callee_id, expr, rcvr, ident, *args, *tps, sugar);
         let f_ty = fcx.expr_ty(rcvr);
         let arg_tys = args.map(|a| fcx.expr_ty(*a));
         let (args_bot, args_err) = arg_tys.foldl((false, false),
@@ -2751,7 +2757,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
       ast::expr_field(base, field, ref tys) => {
         check_field(fcx, expr, base, field, *tys);
       }
-      ast::expr_index(base, idx) => {
+      ast::expr_index(callee_id, base, idx) => {
           check_expr(fcx, base);
           check_expr(fcx, idx);
           let raw_base_t = fcx.expr_ty(base);
@@ -2785,6 +2791,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                                None);
                       };
                       let ret_ty = lookup_op_method(fcx,
+                                                    callee_id,
                                                     expr,
                                                     base,
                                                     resolved,
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 4c088cd9cbd..58749b92ddc 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -256,8 +256,8 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) {
         ast::expr_unary(*) if has_method_map => {
             tcx.region_maps.record_cleanup_scope(expr.id);
         }
-        ast::expr_binary(ast::and, lhs, rhs) |
-        ast::expr_binary(ast::or, lhs, rhs) => {
+        ast::expr_binary(_, ast::and, lhs, rhs) |
+        ast::expr_binary(_, ast::or, lhs, rhs) => {
             tcx.region_maps.record_cleanup_scope(lhs.id);
             tcx.region_maps.record_cleanup_scope(rhs.id);
         }
@@ -306,36 +306,36 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) {
 
     match expr.node {
         ast::expr_call(callee, ref args, _) => {
-            constrain_callee(rcx, expr, callee);
-            constrain_call(rcx, expr, None, *args, false);
+            constrain_callee(rcx, callee.id, expr, callee);
+            constrain_call(rcx, callee.id, expr, None, *args, false);
         }
 
-        ast::expr_method_call(arg0, _, _, ref args, _) => {
-            constrain_call(rcx, expr, Some(arg0), *args, false);
+        ast::expr_method_call(callee_id, arg0, _, _, ref args, _) => {
+            constrain_call(rcx, callee_id, expr, Some(arg0), *args, false);
         }
 
-        ast::expr_index(lhs, rhs) |
-        ast::expr_assign_op(_, lhs, rhs) |
-        ast::expr_binary(_, lhs, rhs) if has_method_map => {
+        ast::expr_index(callee_id, lhs, rhs) |
+        ast::expr_assign_op(callee_id, _, lhs, rhs) |
+        ast::expr_binary(callee_id, _, lhs, rhs) if has_method_map => {
             // As `expr_method_call`, but the call is via an
             // overloaded op.  Note that we (sadly) currently use an
             // implicit "by ref" sort of passing style here.  This
             // should be converted to an adjustment!
-            constrain_call(rcx, expr, Some(lhs), [rhs], true);
+            constrain_call(rcx, callee_id, expr, Some(lhs), [rhs], true);
         }
 
-        ast::expr_unary(_, lhs) if has_method_map => {
+        ast::expr_unary(callee_id, _, lhs) if has_method_map => {
             // As above.
-            constrain_call(rcx, expr, Some(lhs), [], true);
+            constrain_call(rcx, callee_id, expr, Some(lhs), [], true);
         }
 
-        ast::expr_unary(ast::deref, base) => {
+        ast::expr_unary(_, ast::deref, base) => {
             // For *a, the lifetime of a must enclose the deref
             let base_ty = rcx.resolve_node_type(base.id);
             constrain_derefs(rcx, expr, 1, base_ty);
         }
 
-        ast::expr_index(vec_expr, _) => {
+        ast::expr_index(_, vec_expr, _) => {
             // For a[b], the lifetime of a must enclose the deref
             let vec_type = rcx.resolve_expr_type_adjusted(vec_expr);
             constrain_index(rcx, expr, vec_type);
@@ -404,6 +404,7 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) {
 }
 
 fn constrain_callee(rcx: @mut Rcx,
+                    callee_id: ast::node_id,
                     call_expr: @ast::expr,
                     callee_expr: @ast::expr)
 {
@@ -411,7 +412,7 @@ fn constrain_callee(rcx: @mut Rcx,
 
     let call_region = ty::re_scope(call_expr.id);
 
-    let callee_ty = rcx.resolve_node_type(call_expr.callee_id);
+    let callee_ty = rcx.resolve_node_type(callee_id);
     match ty::get(callee_ty).sty {
         ty::ty_bare_fn(*) => { }
         ty::ty_closure(ref closure_ty) => {
@@ -444,6 +445,7 @@ fn constrain_callee(rcx: @mut Rcx,
 fn constrain_call(rcx: @mut Rcx,
                   // might be expr_call, expr_method_call, or an overloaded
                   // operator
+                  callee_id: ast::node_id,
                   call_expr: @ast::expr,
                   receiver: Option<@ast::expr>,
                   arg_exprs: &[@ast::expr],
@@ -457,7 +459,7 @@ fn constrain_call(rcx: @mut Rcx,
     let tcx = rcx.fcx.tcx();
     debug!("constrain_call(call_expr=%s, implicitly_ref_args=%?)",
            call_expr.repr(tcx), implicitly_ref_args);
-    let callee_ty = rcx.resolve_node_type(call_expr.callee_id);
+    let callee_ty = rcx.resolve_node_type(callee_id);
     let fn_sig = ty::ty_fn_sig(callee_ty);
 
     // `callee_region` is the scope representing the time in which the
@@ -964,14 +966,14 @@ pub mod guarantor {
 
         debug!("guarantor(expr=%s)", rcx.fcx.expr_to_str(expr));
         match expr.node {
-            ast::expr_unary(ast::deref, b) => {
+            ast::expr_unary(_, ast::deref, b) => {
                 let cat = categorize(rcx, b);
                 guarantor_of_deref(&cat)
             }
             ast::expr_field(b, _, _) => {
                 categorize(rcx, b).guarantor
             }
-            ast::expr_index(b, _) => {
+            ast::expr_index(_, b, _) => {
                 let cat = categorize(rcx, b);
                 guarantor_of_deref(&cat)
             }
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 9333d2e7b9d..1ef905de0c2 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -512,19 +512,16 @@ pub fn early_resolve_expr(ex: @ast::expr,
       }
 
       // Must resolve bounds on methods with bounded params
-      ast::expr_binary(*) |
-      ast::expr_unary(*) | ast::expr_assign_op(*) |
-      ast::expr_index(*) | ast::expr_method_call(*) => {
+      ast::expr_binary(callee_id, _, _, _) |
+      ast::expr_unary(callee_id, _, _) |
+      ast::expr_assign_op(callee_id, _, _, _) |
+      ast::expr_index(callee_id, _, _) |
+      ast::expr_method_call(callee_id, _, _, _, _, _) => {
         match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) {
           Some(type_param_defs) => {
             debug!("vtable resolution on parameter bounds for method call %s",
                    ex.repr(fcx.tcx()));
             if has_trait_bounds(*type_param_defs) {
-                let callee_id = match ex.node {
-                  ast::expr_field(_, _, _) => ex.id,
-                  _ => ex.callee_id
-                };
-
                 let substs = fcx.node_ty_substs(callee_id);
                 let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
                 let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 29c1eaa2838..9c8c83d35c4 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -217,10 +217,16 @@ fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) {
     }
 
     resolve_type_vars_for_node(wbcx, e.span, e.id);
+
     resolve_method_map_entry(wbcx.fcx, e.span, e.id);
-    resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id);
+    for e.get_callee_id().each |callee_id| {
+        resolve_method_map_entry(wbcx.fcx, e.span, *callee_id);
+    }
+
     resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
-    resolve_vtable_map_entry(wbcx.fcx, e.span, e.callee_id);
+    for e.get_callee_id().each |callee_id| {
+        resolve_vtable_map_entry(wbcx.fcx, e.span, *callee_id);
+    }
 
     match e.node {
         ast::expr_fn_block(ref decl, _) => {
@@ -229,14 +235,16 @@ fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) {
             }
         }
 
-        ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*) |
-        ast::expr_index(*) => {
-            maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
+        ast::expr_binary(callee_id, _, _, _) |
+        ast::expr_unary(callee_id, _, _) |
+        ast::expr_assign_op(callee_id, _, _, _) |
+        ast::expr_index(callee_id, _, _) => {
+            maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id);
         }
 
-        ast::expr_method_call(*) => {
+        ast::expr_method_call(callee_id, _, _, _, _, _) => {
             // We must always have written in a callee ID type for these.
-            resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
+            resolve_type_vars_for_node(wbcx, e.span, callee_id);
         }
 
         _ => ()
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 5c5cc98bb9c..4ffa4d0d25e 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -182,7 +182,6 @@ pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
                  cx.sess.codemap.span_to_str(expr.span))
           }
           ast::expr_assign_op(*) |
-          ast::expr_field(*) |
           ast::expr_unary(*) |
           ast::expr_binary(*) |
           ast::expr_index(*) => {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index ac9734ebaa3..dcb41629958 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -436,13 +436,23 @@ pub enum blk_check_mode { default_blk, unsafe_blk, }
 #[deriving(Eq, Encodable, Decodable)]
 pub struct expr {
     id: node_id,
-    // Extra node ID is only used for index, assign_op, unary, binary, method
-    // call
-    callee_id: node_id,
     node: expr_,
     span: span,
 }
 
+pub impl expr {
+    fn get_callee_id(&self) -> Option<node_id> {
+        match self.node {
+            expr_method_call(callee_id, _, _, _, _, _) |
+            expr_index(callee_id, _, _) |
+            expr_binary(callee_id, _, _, _) |
+            expr_assign_op(callee_id, _, _, _) |
+            expr_unary(callee_id, _, _) => Some(callee_id),
+            _ => None,
+        }
+    }
+}
+
 #[deriving(Eq, Encodable, Decodable)]
 pub enum CallSugar {
     NoSugar,
@@ -455,10 +465,10 @@ pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
     expr_call(@expr, ~[@expr], CallSugar),
-    expr_method_call(@expr, ident, ~[@Ty], ~[@expr], CallSugar),
+    expr_method_call(node_id, @expr, ident, ~[@Ty], ~[@expr], CallSugar),
     expr_tup(~[@expr]),
-    expr_binary(binop, @expr, @expr),
-    expr_unary(unop, @expr),
+    expr_binary(node_id, binop, @expr, @expr),
+    expr_unary(node_id, unop, @expr),
     expr_lit(@lit),
     expr_cast(@expr, @Ty),
     expr_if(@expr, blk, Option<@expr>),
@@ -479,9 +489,9 @@ pub enum expr_ {
 
     expr_copy(@expr),
     expr_assign(@expr, @expr),
-    expr_assign_op(binop, @expr, @expr),
+    expr_assign_op(node_id, binop, @expr, @expr),
     expr_field(@expr, ident, ~[@Ty]),
-    expr_index(@expr, @expr),
+    expr_index(node_id, @expr, @expr),
     expr_path(@Path),
 
     /// The special identifier `self`.
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 48c2df5a894..58769ede961 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -317,17 +317,9 @@ pub fn map_struct_def(
 
 pub fn map_expr(ex: @expr, cx: @mut Ctx, v: visit::vt<@mut Ctx>) {
     cx.map.insert(ex.id, node_expr(ex));
-    match ex.node {
-        // Expressions which are or might be calls:
-        ast::expr_call(*) |
-        ast::expr_method_call(*) |
-        ast::expr_index(*) |
-        ast::expr_binary(*) |
-        ast::expr_assign_op(*) |
-        ast::expr_unary(*) => {
-            cx.map.insert(ex.callee_id, node_callee_scope(ex));
-        }
-        _ => {}
+    // Expressions which are or might be calls:
+    for ex.get_callee_id().each |callee_id| {
+        cx.map.insert(*callee_id, node_callee_scope(ex));
     }
     visit::visit_expr(ex, cx, v);
 }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 4da2d500dd8..eab8c0a12d3 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -193,7 +193,7 @@ pub fn float_ty_to_str(t: float_ty) -> ~str {
 }
 
 pub fn is_call_expr(e: @expr) -> bool {
-    match e.node { expr_call(_, _, _) => true, _ => false }
+    match e.node { expr_call(*) => true, _ => false }
 }
 
 // This makes def_id hashable
@@ -460,7 +460,9 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
         },
 
         visit_expr: |e, t, vt| {
-            vfn(e.callee_id, t);
+            for e.get_callee_id().each |callee_id| {
+                vfn(*callee_id, t);
+            }
             vfn(e.id, t);
             visit::visit_expr(e, t, vt);
         },
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 874c10fae5f..7f8f2be6f6e 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -82,7 +82,6 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
 
                     let out = @ast::expr {
                         id: cx.next_id(),
-                        callee_id: cx.next_id(),
                         span: out.span,
                         node: ast::expr_addr_of(ast::m_mutbl, out)
                     };
@@ -179,7 +178,6 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
 
     MRExpr(@ast::expr {
         id: cx.next_id(),
-        callee_id: cx.next_id(),
         node: ast::expr_inline_asm(ast::inline_asm {
             asm: @asm,
             clobbers: @cons,
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 85bebebf0f6..c2fa888995a 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -414,7 +414,6 @@ impl AstBuilder for @ExtCtxt {
     fn expr(&self, span: span, node: ast::expr_) -> @ast::expr {
         @ast::expr {
             id: self.next_id(),
-            callee_id: self.next_id(),
             node: node,
             span: span,
         }
@@ -433,8 +432,7 @@ impl AstBuilder for @ExtCtxt {
 
     fn expr_binary(&self, sp: span, op: ast::binop,
                    lhs: @ast::expr, rhs: @ast::expr) -> @ast::expr {
-        self.next_id(); // see ast_util::op_expr_callee_id
-        self.expr(sp, ast::expr_binary(op, lhs, rhs))
+        self.expr(sp, ast::expr_binary(self.next_id(), op, lhs, rhs))
     }
 
     fn expr_deref(&self, sp: span, e: @ast::expr) -> @ast::expr {
@@ -442,8 +440,7 @@ impl AstBuilder for @ExtCtxt {
     }
     fn expr_unary(&self, sp: span, op: ast::unop, e: @ast::expr)
         -> @ast::expr {
-        self.next_id(); // see ast_util::op_expr_callee_id
-        self.expr(sp, ast::expr_unary(op, e))
+        self.expr(sp, ast::expr_unary(self.next_id(), op, e))
     }
 
     fn expr_copy(&self, sp: span, e: @ast::expr) -> @ast::expr {
@@ -480,7 +477,7 @@ impl AstBuilder for @ExtCtxt {
                         ident: ast::ident,
                         args: ~[@ast::expr]) -> @ast::expr {
         self.expr(span,
-                  ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
+                  ast::expr_method_call(self.next_id(), expr, ident, ~[], args, ast::NoSugar))
     }
     fn expr_blk(&self, b: ast::blk) -> @ast::expr {
         self.expr(b.span, ast::expr_block(b))
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index 788f047773a..358f4041dd0 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -37,7 +37,6 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
 
     let e = @ast::expr {
         id: cx.next_id(),
-        callee_id: cx.next_id(),
         node: ast::expr_path(
             @ast::Path {
                  span: sp,
diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs
index 95cf4a18ab4..598537c97e8 100644
--- a/src/libsyntax/ext/log_syntax.rs
+++ b/src/libsyntax/ext/log_syntax.rs
@@ -33,7 +33,6 @@ pub fn expand_syntax_ext(cx: @ExtCtxt,
     //trivial expression
     MRExpr(@ast::expr {
         id: cx.next_id(),
-        callee_id: cx.next_id(),
         node: ast::expr_lit(@codemap::spanned {
             node: ast::lit_nil,
             span: sp
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 27a10c36ead..5800254eaa4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -463,8 +463,9 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
                 blk
             )
         }
-        expr_method_call(f, i, ref tps, ref args, blk) => {
+        expr_method_call(callee_id, f, i, ref tps, ref args, blk) => {
             expr_method_call(
+                fld.new_id(callee_id),
                 fld.fold_expr(f),
                 fld.fold_ident(i),
                 tps.map(|x| fld.fold_ty(*x)),
@@ -472,10 +473,21 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
                 blk
             )
         }
-        expr_binary(binop, lhs, rhs) => {
-            expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs))
+        expr_binary(callee_id, binop, lhs, rhs) => {
+            expr_binary(
+                fld.new_id(callee_id),
+                binop,
+                fld.fold_expr(lhs),
+                fld.fold_expr(rhs)
+            )
+        }
+        expr_unary(callee_id, binop, ohs) => {
+            expr_unary(
+                fld.new_id(callee_id),
+                binop,
+                fld.fold_expr(ohs)
+            )
         }
-        expr_unary(binop, ohs) => expr_unary(binop, fld.fold_expr(ohs)),
         expr_loop_body(f) => expr_loop_body(fld.fold_expr(f)),
         expr_do_body(f) => expr_do_body(fld.fold_expr(f)),
         expr_lit(_) => copy *e,
@@ -514,8 +526,13 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
         expr_assign(el, er) => {
             expr_assign(fld.fold_expr(el), fld.fold_expr(er))
         }
-        expr_assign_op(op, el, er) => {
-            expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
+        expr_assign_op(callee_id, op, el, er) => {
+            expr_assign_op(
+                fld.new_id(callee_id),
+                op,
+                fld.fold_expr(el),
+                fld.fold_expr(er)
+            )
         }
         expr_field(el, id, ref tys) => {
             expr_field(
@@ -523,8 +540,12 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
                 tys.map(|x| fld.fold_ty(*x))
             )
         }
-        expr_index(el, er) => {
-            expr_index(fld.fold_expr(el), fld.fold_expr(er))
+        expr_index(callee_id, el, er) => {
+            expr_index(
+                fld.new_id(callee_id),
+                fld.fold_expr(el),
+                fld.fold_expr(er)
+            )
         }
         expr_path(pth) => expr_path(fld.fold_path(pth)),
         expr_self => expr_self,
@@ -801,7 +822,6 @@ impl ast_fold for AstFoldFns {
         let (n, s) = (self.fold_expr)(&x.node, x.span, self as @ast_fold);
         @expr {
             id: (self.new_id)(x.id),
-            callee_id: (self.new_id)(x.callee_id),
             node: n,
             span: (self.new_span)(s),
         }
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index e04914c0f1e..62b36b12f26 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::expr_loop(*)
       | ast::expr_call(_, _, ast::DoSugar)
       | ast::expr_call(_, _, ast::ForSugar)
-      | ast::expr_method_call(_, _, _, _, ast::DoSugar)
-      | ast::expr_method_call(_, _, _, _, ast::ForSugar) => false,
+      | ast::expr_method_call(_, _, _, _, _, ast::DoSugar)
+      | ast::expr_method_call(_, _, _, _, _, ast::ForSugar) => false,
       _ => true
     }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 9d5cb131fec..9c716f5631f 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -385,7 +385,6 @@ mod test {
     #[test] fn path_exprs_1 () {
         assert_eq!(string_to_expr(@~"a"),
                    @ast::expr{id:1,
-                              callee_id:2,
                               node:ast::expr_path(@ast::Path {span:sp(0,1),
                                                               global:false,
                                                               idents:~[intern("a")],
@@ -397,7 +396,6 @@ mod test {
     #[test] fn path_exprs_2 () {
         assert_eq!(string_to_expr(@~"::a::b"),
                    @ast::expr{id:1,
-                               callee_id:2,
                                node:ast::expr_path(
                                    @ast::Path {span:sp(0,6),
                                                global:true,
@@ -445,10 +443,9 @@ mod test {
 
     #[test] fn ret_expr() {
         assert_eq!(string_to_expr(@~"return d"),
-                   @ast::expr{id:3,
-                              callee_id:4,
+                   @ast::expr{id:2,
                               node:ast::expr_ret(
-                                  Some(@ast::expr{id:1,callee_id:2,
+                                  Some(@ast::expr{id:1,
                                                   node:ast::expr_path(
                                                       @ast::Path{span:sp(7,8),
                                                                  global:false,
@@ -465,7 +462,6 @@ mod test {
                    @spanned{
                        node: ast::stmt_expr(@ast::expr{
                            id: 1,
-                           callee_id: 2,
                            node: ast::expr_path(
                                @ast::Path{
                                    span:sp(0,1),
@@ -474,7 +470,7 @@ mod test {
                                    rp:None,
                                    types: ~[]}),
                            span: sp(0,1)},
-                                            3), // fixme
+                                            2), // fixme
                        span: sp(0,1)})
 
     }
@@ -538,7 +534,7 @@ mod test {
                   Some(
                       @ast::item{ident:intern("a"),
                             attrs:~[],
-                            id: 10, // fixme
+                            id: 9, // fixme
                             node: ast::item_fn(ast::fn_decl{
                                 inputs: ~[ast::arg{
                                     is_mutbl: false,
@@ -583,7 +579,6 @@ mod test {
                                             stmts: ~[@spanned{
                                                 node: ast::stmt_semi(@ast::expr{
                                                     id: 6,
-                                                    callee_id: 7,
                                                     node: ast::expr_path(
                                                         @ast::Path{
                                                             span:sp(17,18),
@@ -592,10 +587,10 @@ mod test {
                                                             rp:None,
                                                             types: ~[]}),
                                                     span: sp(17,18)},
-                                                                     8), // fixme
+                                                                     7), // fixme
                                                 span: sp(17,18)}],
                                             expr: None,
-                                            id: 9, // fixme
+                                            id: 8, // fixme
                                             rules: ast::default_blk // no idea
                                         }}),
                             vis: ast::inherited,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 00ad12ce402..f013dfaceba 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -926,7 +926,7 @@ impl Parser {
 
         if minus_present {
             let minus_hi = self.span.hi;
-            self.mk_expr(minus_lo, minus_hi, expr_unary(neg, expr))
+            self.mk_expr(minus_lo, minus_hi, self.mk_unary(neg, expr))
         } else {
             expr
         }
@@ -1168,16 +1168,47 @@ impl Parser {
     pub fn mk_expr(&self, lo: BytePos, hi: BytePos, node: expr_) -> @expr {
         @expr {
             id: self.get_id(),
-            callee_id: self.get_id(),
             node: node,
             span: mk_sp(lo, hi),
         }
     }
 
+    pub fn mk_unary(&self, unop: ast::unop, expr: @expr) -> ast::expr_ {
+        expr_unary(self.get_id(), unop, expr)
+    }
+
+    pub fn mk_binary(&self, binop: ast::binop, lhs: @expr, rhs: @expr) -> ast::expr_ {
+        expr_binary(self.get_id(), binop, lhs, rhs)
+    }
+
+    pub fn mk_call(&self, f: @expr, args: ~[@expr], sugar: CallSugar) -> ast::expr_ {
+        expr_call(f, args, sugar)
+    }
+
+    pub fn mk_method_call(&self,
+                      rcvr: @expr,
+                      ident: ident,
+                      tps: ~[@Ty],
+                      args: ~[@expr],
+                      sugar: CallSugar) -> ast::expr_ {
+        expr_method_call(self.get_id(), rcvr, ident, tps, args, sugar)
+    }
+
+    pub fn mk_index(&self, expr: @expr, idx: @expr) -> ast::expr_ {
+        expr_index(self.get_id(), expr, idx)
+    }
+
+    pub fn mk_field(&self, expr: @expr, ident: ident, tys: ~[@Ty]) -> ast::expr_ {
+        expr_field(expr, ident, tys)
+    }
+
+    pub fn mk_assign_op(&self, binop: ast::binop, lhs: @expr, rhs: @expr) -> ast::expr_ {
+        expr_assign_op(self.get_id(), binop, lhs, rhs)
+    }
+
     pub fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @expr {
         @expr {
             id: self.get_id(),
-            callee_id: self.get_id(),
             node: expr_mac(codemap::spanned {node: m, span: mk_sp(lo, hi)}),
             span: mk_sp(lo, hi),
         }
@@ -1192,7 +1223,6 @@ impl Parser {
 
         @expr {
             id: self.get_id(),
-            callee_id: self.get_id(),
             node: expr_lit(lv_lit),
             span: *span,
         }
@@ -1454,11 +1484,11 @@ impl Parser {
                             );
                             hi = self.span.hi;
 
-                            let nd = expr_method_call(e, i, tys, es, NoSugar);
+                            let nd = self.mk_method_call(e, i, tys, es, NoSugar);
                             e = self.mk_expr(lo, hi, nd);
                         }
                         _ => {
-                            e = self.mk_expr(lo, hi, expr_field(e, i, tys));
+                            e = self.mk_expr(lo, hi, self.mk_field(e, i, tys));
                         }
                     }
                   }
@@ -1478,7 +1508,7 @@ impl Parser {
                 );
                 hi = self.span.hi;
 
-                let nd = expr_call(e, es, NoSugar);
+                let nd = self.mk_call(e, es, NoSugar);
                 e = self.mk_expr(lo, hi, nd);
               }
 
@@ -1488,7 +1518,7 @@ impl Parser {
                 let ix = self.parse_expr();
                 hi = ix.span.hi;
                 self.expect(&token::RBRACKET);
-                e = self.mk_expr(lo, hi, expr_index(e, ix));
+                e = self.mk_expr(lo, hi, self.mk_index(e, ix));
               }
 
               _ => return e
@@ -1703,7 +1733,7 @@ impl Parser {
             self.bump();
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
-            ex = expr_unary(not, e);
+            ex = self.mk_unary(not, e);
           }
           token::BINOP(b) => {
             match b {
@@ -1711,13 +1741,13 @@ impl Parser {
                 self.bump();
                 let e = self.parse_prefix_expr();
                 hi = e.span.hi;
-                ex = expr_unary(neg, e);
+                ex = self.mk_unary(neg, e);
               }
               token::STAR => {
                 self.bump();
                 let e = self.parse_prefix_expr();
                 hi = e.span.hi;
-                ex = expr_unary(deref, e);
+                ex = self.mk_unary(deref, e);
               }
               token::AND => {
                 self.bump();
@@ -1758,7 +1788,7 @@ impl Parser {
               expr_vec(*) |
               expr_lit(@codemap::spanned { node: lit_str(_), span: _}) |
               expr_repeat(*) if m == m_imm => expr_vstore(e, expr_vstore_box),
-              _ => expr_unary(box(m), e)
+              _ => self.mk_unary(box(m), e)
             };
           }
           token::TILDE => {
@@ -1776,7 +1806,7 @@ impl Parser {
               expr_lit(@codemap::spanned { node: lit_str(_), span: _}) |
               expr_repeat(*)
               if m == m_imm => expr_vstore(e, expr_vstore_uniq),
-              _ => expr_unary(uniq(m), e)
+              _ => self.mk_unary(uniq(m), e)
             };
           }
           _ => return self.parse_dot_or_call_expr()
@@ -1810,7 +1840,7 @@ impl Parser {
                         let expr = self.parse_prefix_expr();
                         let rhs = self.parse_more_binops(expr, cur_prec);
                         let bin = self.mk_expr(lhs.span.lo, rhs.span.hi,
-                                               expr_binary(cur_op, lhs, rhs));
+                                               self.mk_binary(cur_op, lhs, rhs));
                         self.parse_more_binops(bin, min_prec)
                     } else {
                         lhs
@@ -1860,7 +1890,7 @@ impl Parser {
                   token::SHR => aop = shr
               }
               self.mk_expr(lo, rhs.span.hi,
-                           expr_assign_op(aop, lhs, rhs))
+                           self.mk_assign_op(aop, lhs, rhs))
           }
           token::LARROW => {
               self.obsolete(*self.span, ObsoleteBinaryMove);
@@ -1992,30 +2022,30 @@ impl Parser {
                 let args = vec::append(copy *args, [last_arg]);
                 self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
             }
-            expr_method_call(f, i, ref tps, ref args, NoSugar) => {
+            expr_method_call(_, f, 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(copy *args, [last_arg]);
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i, copy *tps,
-                                              args, sugar))
+                             self.mk_method_call(f, i, copy *tps, args, sugar))
             }
             expr_field(f, i, ref tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i,
-                                              copy *tps, ~[last_arg], sugar))
+                             self.mk_method_call(f, i, copy *tps, ~[last_arg], sugar))
             }
             expr_path(*) | expr_call(*) | expr_method_call(*) |
                 expr_paren(*) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                self.mk_expr(lo.lo, last_arg.span.hi,
-                             expr_call(e, ~[last_arg], sugar))
+                self.mk_expr(
+                    lo.lo,
+                    last_arg.span.hi,
+                    self.mk_call(e, ~[last_arg], sugar))
             }
             _ => {
                 // There may be other types of expressions that can
@@ -2274,7 +2304,6 @@ impl Parser {
               }) => {
                 let vst = @expr {
                     id: self.get_id(),
-                    callee_id: self.get_id(),
                     node: expr_vstore(e, expr_vstore_box),
                     span: mk_sp(lo, hi),
                 };
@@ -2297,7 +2326,6 @@ impl Parser {
               }) => {
                 let vst = @expr {
                     id: self.get_id(),
-                    callee_id: self.get_id(),
                     node: expr_vstore(e, expr_vstore_uniq),
                     span: mk_sp(lo, hi),
                 };
@@ -2320,7 +2348,6 @@ impl Parser {
                   }) => {
                       let vst = @expr {
                           id: self.get_id(),
-                          callee_id: self.get_id(),
                           node: expr_vstore(e, expr_vstore_slice),
                           span: mk_sp(lo, hi)
                       };
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f29876b8708..7ab38a6ba5f 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1164,7 +1164,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         print_expr(s, func);
         print_call_post(s, sugar, &blk, &mut base_args);
       }
-      ast::expr_method_call(func, ident, ref tys, ref args, sugar) => {
+      ast::expr_method_call(_, func, ident, ref tys, ref args, sugar) => {
         let mut base_args = copy *args;
         let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
@@ -1177,13 +1177,13 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         }
         print_call_post(s, sugar, &blk, &mut base_args);
       }
-      ast::expr_binary(op, lhs, rhs) => {
+      ast::expr_binary(_, op, lhs, rhs) => {
         print_expr(s, lhs);
         space(s.s);
         word_space(s, ast_util::binop_to_str(op));
         print_expr(s, rhs);
       }
-      ast::expr_unary(op, expr) => {
+      ast::expr_unary(_, op, expr) => {
         word(s.s, ast_util::unop_to_str(op));
         print_expr(s, expr);
       }
@@ -1335,7 +1335,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         word_space(s, "=");
         print_expr(s, rhs);
       }
-      ast::expr_assign_op(op, lhs, rhs) => {
+      ast::expr_assign_op(_, op, lhs, rhs) => {
         print_expr(s, lhs);
         space(s.s);
         word(s.s, ast_util::binop_to_str(op));
@@ -1352,7 +1352,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
             word(s.s, ">");
         }
       }
-      ast::expr_index(expr, index) => {
+      ast::expr_index(_, expr, index) => {
         print_expr(s, expr);
         word(s.s, "[");
         print_expr(s, index);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index a2b89243cfd..0cb22737a53 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -471,16 +471,16 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
             visit_exprs(*args, e, v);
             (v.visit_expr)(callee, e, v);
         }
-        expr_method_call(callee, _, ref tys, ref args, _) => {
+        expr_method_call(_, callee, _, ref tys, ref args, _) => {
             visit_exprs(*args, e, v);
             for tys.each |tp| { (v.visit_ty)(*tp, e, v); }
             (v.visit_expr)(callee, e, v);
         }
-        expr_binary(_, a, b) => {
+        expr_binary(_, _, a, b) => {
             (v.visit_expr)(a, e, v);
             (v.visit_expr)(b, e, v);
         }
-        expr_addr_of(_, x) | expr_unary(_, x) |
+        expr_addr_of(_, x) | expr_unary(_, _, x) |
         expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, e, v),
         expr_lit(_) => (),
         expr_cast(x, t) => {
@@ -518,7 +518,7 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
             (v.visit_expr)(a, e, v);
         }
         expr_copy(a) => (v.visit_expr)(a, e, v),
-        expr_assign_op(_, a, b) => {
+        expr_assign_op(_, _, a, b) => {
             (v.visit_expr)(b, e, v);
             (v.visit_expr)(a, e, v);
         }
@@ -526,7 +526,7 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
             (v.visit_expr)(x, e, v);
             for tys.each |tp| { (v.visit_ty)(*tp, e, v); }
         }
-        expr_index(a, b) => {
+        expr_index(_, a, b) => {
             (v.visit_expr)(a, e, v);
             (v.visit_expr)(b, e, v);
         }