about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-26 07:16:39 -0800
committerbors <bors@rust-lang.org>2014-02-26 07:16:39 -0800
commit05a2d32acd7e682854a188697ee404cbd001bf38 (patch)
treead01af5adf976b29f72956c05de0dc395e45412f
parent6c41f993d390a0a8d9f42cfca4f365b6f93d0c26 (diff)
parent05e4d944a9f7db17e759cd4e09fb82357b8cee28 (diff)
downloadrust-05a2d32acd7e682854a188697ee404cbd001bf38.tar.gz
rust-05a2d32acd7e682854a188697ee404cbd001bf38.zip
auto merge of #12571 : eddyb/rust/kill-callee-id, r=nikomatsakis
Every method call and overloaded operator had a `callee_id` that was be used to store the method type and type substitutions, that information is now stored in the `method_map`, alongside the method's origin.
-rw-r--r--src/librustc/front/feature_gate.rs2
-rw-r--r--src/librustc/middle/astencode.rs107
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs18
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs21
-rw-r--r--src/librustc/middle/borrowck/mod.rs6
-rw-r--r--src/librustc/middle/borrowck/move_data.rs2
-rw-r--r--src/librustc/middle/cfg/construct.rs22
-rw-r--r--src/librustc/middle/cfg/mod.rs2
-rw-r--r--src/librustc/middle/check_const.rs10
-rw-r--r--src/librustc/middle/check_match.rs6
-rw-r--r--src/librustc/middle/const_eval.rs12
-rw-r--r--src/librustc/middle/dataflow.rs35
-rw-r--r--src/librustc/middle/dead.rs21
-rw-r--r--src/librustc/middle/effect.rs18
-rw-r--r--src/librustc/middle/kind.rs35
-rw-r--r--src/librustc/middle/lint.rs27
-rw-r--r--src/librustc/middle/liveness.rs24
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/moves.rs25
-rw-r--r--src/librustc/middle/privacy.rs26
-rw-r--r--src/librustc/middle/reachable.rs19
-rw-r--r--src/librustc/middle/region.rs10
-rw-r--r--src/librustc/middle/resolve.rs2
-rw-r--r--src/librustc/middle/trans/callee.rs68
-rw-r--r--src/librustc/middle/trans/cleanup.rs2
-rw-r--r--src/librustc/middle/trans/common.rs8
-rw-r--r--src/librustc/middle/trans/consts.rs6
-rw-r--r--src/librustc/middle/trans/debuginfo.rs14
-rw-r--r--src/librustc/middle/trans/expr.rs61
-rw-r--r--src/librustc/middle/trans/meth.rs89
-rw-r--r--src/librustc/middle/trans/monomorphize.rs4
-rw-r--r--src/librustc/middle/ty.rs14
-rw-r--r--src/librustc/middle/typeck/check/method.rs72
-rw-r--r--src/librustc/middle/typeck/check/mod.rs121
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs48
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs27
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs114
-rw-r--r--src/librustc/middle/typeck/mod.rs25
-rw-r--r--src/librustc/util/ppaux.rs30
-rw-r--r--src/libsyntax/ast.rs23
-rw-r--r--src/libsyntax/ast_map.rs13
-rw-r--r--src/libsyntax/ast_util.rs6
-rw-r--r--src/libsyntax/ext/build.rs9
-rw-r--r--src/libsyntax/fold.rs23
-rw-r--r--src/libsyntax/parse/parser.rs10
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs11
47 files changed, 593 insertions, 669 deletions
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 813bceafed5..4450fbb04a9 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -255,7 +255,7 @@ impl Visitor<()> for Context {
 
     fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
         match e.node {
-            ast::ExprUnary(_, ast::UnBox, _) => {
+            ast::ExprUnary(ast::UnBox, _) => {
                 self.gate_box(e.span);
             }
             _ => {}
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 8cc52627fcc..f6f51f10764 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -21,7 +21,7 @@ use metadata::tydecode;
 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
                          RegionParameter};
 use metadata::tyencode;
-use middle::typeck::method_origin;
+use middle::typeck::{MethodCallee, MethodOrigin};
 use middle::{ty, typeck, moves};
 use middle;
 use util::ppaux::ty_to_str;
@@ -50,7 +50,7 @@ use writer = serialize::ebml::writer;
 // Auxiliary maps of things to be encoded
 pub struct Maps {
     root_map: middle::borrowck::root_map,
-    method_map: middle::typeck::method_map,
+    method_map: middle::typeck::MethodMap,
     vtable_map: middle::typeck::vtable_map,
     capture_map: middle::moves::CaptureMap,
 }
@@ -574,30 +574,68 @@ impl tr for moves::CaptureVar {
 }
 
 // ______________________________________________________________________
-// Encoding and decoding of method_origin
+// Encoding and decoding of MethodCallee
 
-impl tr for method_origin {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
+trait read_method_callee_helper {
+    fn read_method_callee(&mut self, xcx: @ExtendedDecodeContext) -> MethodCallee;
+}
+
+fn encode_method_callee(ecx: &e::EncodeContext,
+                        ebml_w: &mut writer::Encoder,
+                        method: &MethodCallee) {
+    ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
+        ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
+            method.origin.encode(ebml_w);
+        });
+        ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
+            ebml_w.emit_ty(ecx, method.ty);
+        });
+        ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
+            ebml_w.emit_substs(ecx, &method.substs);
+        });
+    })
+}
+
+impl<'a> read_method_callee_helper for reader::Decoder<'a> {
+    fn read_method_callee(&mut self, xcx: @ExtendedDecodeContext) -> MethodCallee {
+        self.read_struct("MethodCallee", 3, |this| {
+            MethodCallee {
+                origin: this.read_struct_field("origin", 0, |this| {
+                    let method_origin: MethodOrigin =
+                        Decodable::decode(this);
+                    method_origin.tr(xcx)
+                }),
+                ty: this.read_struct_field("ty", 1, |this| {
+                    this.read_ty(xcx)
+                }),
+                substs: this.read_struct_field("substs", 2, |this| {
+                    this.read_substs(xcx)
+                })
+            }
+        })
+    }
+}
+
+impl tr for MethodOrigin {
+    fn tr(&self, xcx: @ExtendedDecodeContext) -> MethodOrigin {
         match *self {
-          typeck::method_static(did) => {
-              typeck::method_static(did.tr(xcx))
-          }
-          typeck::method_param(ref mp) => {
-            typeck::method_param(
-                typeck::method_param {
-                    trait_id: mp.trait_id.tr(xcx),
-                    .. *mp
-                }
-            )
-          }
-          typeck::method_object(ref mo) => {
-            typeck::method_object(
-                typeck::method_object {
-                    trait_id: mo.trait_id.tr(xcx),
-                    .. *mo
-                }
-            )
-          }
+            typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
+            typeck::MethodParam(ref mp) => {
+                typeck::MethodParam(
+                    typeck::MethodParam {
+                        trait_id: mp.trait_id.tr(xcx),
+                        .. *mp
+                    }
+                )
+            }
+            typeck::MethodObject(ref mo) => {
+                typeck::MethodObject(
+                    typeck::MethodObject {
+                        trait_id: mo.trait_id.tr(xcx),
+                        .. *mo
+                    }
+                )
+            }
         }
     }
 }
@@ -993,17 +1031,13 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         }
     }
 
-    {
-        let method_map = maps.method_map.borrow();
-        let r = method_map.get().find(&id);
-        for &origin in r.iter() {
-            ebml_w.tag(c::tag_table_method_map, |ebml_w| {
-                ebml_w.id(id);
-                ebml_w.tag(c::tag_table_val, |ebml_w| {
-                    origin.encode(ebml_w);
-                })
+    for &method in maps.method_map.borrow().get().find(&id).iter() {
+        ebml_w.tag(c::tag_table_method_map, |ebml_w| {
+            ebml_w.id(id);
+            ebml_w.tag(c::tag_table_val, |ebml_w| {
+                encode_method_callee(ecx, ebml_w, method)
             })
-        }
+        })
     }
 
     {
@@ -1337,9 +1371,8 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
                         ty_param_defs.get().insert(id, bounds);
                     }
                     c::tag_table_method_map => {
-                        let origin: method_origin = Decodable::decode(val_dsr);
-                        let mut method_map = dcx.maps.method_map.borrow_mut();
-                        method_map.get().insert(id, origin.tr(xcx));
+                        let method = val_dsr.read_method_callee(xcx);
+                        dcx.maps.method_map.borrow_mut().get().insert(id, method);
                     }
                     c::tag_table_vtable_map => {
                         let vtable_res =
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 590229a6652..f974b324f05 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -784,7 +784,6 @@ impl<'a> CheckLoanCtxt<'a> {
     pub fn check_call(&self,
                       _expr: &ast::Expr,
                       _callee: Option<@ast::Expr>,
-                      _callee_id: ast::NodeId,
                       _callee_span: Span,
                       _args: &[@ast::Expr]) {
         // NB: This call to check for conflicting loans is not truly
@@ -828,23 +827,22 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
           this.check_captured_variables(expr.id, expr.span)
       }
       ast::ExprAssign(dest, _) |
-      ast::ExprAssignOp(_, _, dest, _) => {
+      ast::ExprAssignOp(_, dest, _) => {
         this.check_assignment(dest);
       }
       ast::ExprCall(f, ref args) => {
-        this.check_call(expr, Some(f), f.id, f.span, *args);
+        this.check_call(expr, Some(f), f.span, *args);
       }
-      ast::ExprMethodCall(callee_id, _, _, ref args) => {
-        this.check_call(expr, None, callee_id, expr.span, *args);
+      ast::ExprMethodCall(_, _, ref args) => {
+        this.check_call(expr, None, expr.span, *args);
       }
-      ast::ExprIndex(callee_id, _, rval) |
-      ast::ExprBinary(callee_id, _, _, rval)
+      ast::ExprIndex(_, rval) | ast::ExprBinary(_, _, rval)
       if method_map.get().contains_key(&expr.id) => {
-        this.check_call(expr, None, callee_id, expr.span, [rval]);
+        this.check_call(expr, None, expr.span, [rval]);
       }
-      ast::ExprUnary(callee_id, _, _) | ast::ExprIndex(callee_id, _, _)
+      ast::ExprUnary(_, _) | ast::ExprIndex(_, _)
       if method_map.get().contains_key(&expr.id) => {
-        this.check_call(expr, None, callee_id, expr.span, []);
+        this.check_call(expr, None, expr.span, []);
       }
       ast::ExprInlineAsm(ref ia) => {
           for &(_, out) in ia.outputs.iter() {
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index 263ed47b29e..202ea497868 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -181,20 +181,9 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
 
     this.id_range.add(ex.id);
 
-    {
-        let r = ex.get_callee_id();
-        for callee_id in r.iter() {
-            this.id_range.add(*callee_id);
-        }
-    }
-
     // If this expression is borrowed, have to ensure it remains valid:
-    {
-        let adjustments = tcx.adjustments.borrow();
-        let r = adjustments.get().find(&ex.id);
-        for &adjustments in r.iter() {
-            this.guarantee_adjustments(ex, *adjustments);
-        }
+    for &adjustments in tcx.adjustments.borrow().get().find(&ex.id).iter() {
+        this.guarantee_adjustments(ex, *adjustments);
     }
 
     // If this expression is a move, gather it:
@@ -225,7 +214,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
         visit::walk_expr(this, ex, ());
       }
 
-      ast::ExprAssign(l, _) | ast::ExprAssignOp(_, _, l, _) => {
+      ast::ExprAssign(l, _) | ast::ExprAssignOp(_, l, _) => {
           let l_cmt = this.bccx.cat_expr(l);
           match opt_loan_path(l_cmt) {
               Some(l_lp) => {
@@ -252,8 +241,8 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
         visit::walk_expr(this, ex, ());
       }
 
-      ast::ExprIndex(_, _, arg) |
-      ast::ExprBinary(_, _, _, arg)
+      ast::ExprIndex(_, arg) |
+      ast::ExprBinary(_, _, arg)
       if method_map.get().contains_key(&ex.id) => {
           // Arguments in method calls are always passed by ref.
           //
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 6a47743a03f..94c3867b318 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -70,7 +70,7 @@ impl Visitor<()> for BorrowckCtxt {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    moves_map: moves::MovesMap,
                    moved_variables_set: moves::MovedVariablesSet,
                    capture_map: moves::CaptureMap,
@@ -156,7 +156,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
 pub struct BorrowckCtxt {
     tcx: ty::ctxt,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     moves_map: moves::MovesMap,
     moved_variables_set: moves::MovedVariablesSet,
     capture_map: moves::CaptureMap,
@@ -909,7 +909,7 @@ impl Repr for LoanPath {
 
 struct TcxTyper {
     tcx: ty::ctxt,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
 }
 
 impl mc::Typer for TcxTyper {
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 5034976c9f9..35368645eb3 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -565,7 +565,7 @@ impl MoveData {
 impl FlowedMoveData {
     pub fn new(move_data: MoveData,
                tcx: ty::ctxt,
-               method_map: typeck::method_map,
+               method_map: typeck::MethodMap,
                id_range: ast_util::IdRange,
                body: &ast::Block)
                -> FlowedMoveData {
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index d575c949421..12853fe6742 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -19,7 +19,7 @@ use syntax::opt_vec;
 
 struct CFGBuilder {
     tcx: ty::ctxt,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     exit_map: HashMap<ast::NodeId, CFGIndex>,
     graph: CFGGraph,
     loop_scopes: ~[LoopScope],
@@ -32,7 +32,7 @@ struct LoopScope {
 }
 
 pub fn construct(tcx: ty::ctxt,
-                 method_map: typeck::method_map,
+                 method_map: typeck::MethodMap,
                  blk: &ast::Block) -> CFG {
     let mut cfg_builder = CFGBuilder {
         exit_map: HashMap::new(),
@@ -305,7 +305,7 @@ impl CFGBuilder {
                 expr_exit
             }
 
-            ast::ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
+            ast::ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
                 //
                 //     [pred]
                 //       |
@@ -355,16 +355,16 @@ impl CFGBuilder {
                 self.call(expr, pred, func, *args)
             }
 
-            ast::ExprMethodCall(_, _, _, ref args) => {
+            ast::ExprMethodCall(_, _, ref args) => {
                 self.call(expr, pred, args[0], args.slice_from(1))
             }
 
-            ast::ExprIndex(_, l, r) |
-            ast::ExprBinary(_, _, l, r) if self.is_method_call(expr) => {
+            ast::ExprIndex(l, r) |
+            ast::ExprBinary(_, l, r) if self.is_method_call(expr) => {
                 self.call(expr, pred, l, [r])
             }
 
-            ast::ExprUnary(_, _, e) if self.is_method_call(expr) => {
+            ast::ExprUnary(_, e) if self.is_method_call(expr) => {
                 self.call(expr, pred, e, [])
             }
 
@@ -384,12 +384,12 @@ impl CFGBuilder {
             }
 
             ast::ExprAssign(l, r) |
-            ast::ExprAssignOp(_, _, l, r) => {
+            ast::ExprAssignOp(_, l, r) => {
                 self.straightline(expr, pred, [r, l])
             }
 
-            ast::ExprIndex(_, l, r) |
-            ast::ExprBinary(_, _, l, r) => { // NB: && and || handled earlier
+            ast::ExprIndex(l, r) |
+            ast::ExprBinary(_, l, r) => { // NB: && and || handled earlier
                 self.straightline(expr, pred, [l, r])
             }
 
@@ -399,7 +399,7 @@ impl CFGBuilder {
 
             ast::ExprAddrOf(_, e) |
             ast::ExprCast(e, _) |
-            ast::ExprUnary(_, _, e) |
+            ast::ExprUnary(_, e) |
             ast::ExprParen(e) |
             ast::ExprVstore(e, _) |
             ast::ExprField(e, _, _) => {
diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs
index b0ee26f6f23..d6d54b604c8 100644
--- a/src/librustc/middle/cfg/mod.rs
+++ b/src/librustc/middle/cfg/mod.rs
@@ -54,7 +54,7 @@ pub struct CFGIndices {
 
 impl CFG {
     pub fn new(tcx: ty::ctxt,
-               method_map: typeck::method_map,
+               method_map: typeck::MethodMap,
                blk: &ast::Block) -> CFG {
         construct::construct(tcx, method_map, blk)
     }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 75337a27a6c..864b4473336 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -23,7 +23,7 @@ use syntax::visit;
 struct CheckCrateVisitor {
     sess: Session,
     def_map: resolve::DefMap,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     tcx: ty::ctxt,
 }
 
@@ -43,7 +43,7 @@ impl Visitor<bool> for CheckCrateVisitor {
 pub fn check_crate(sess: Session,
                    krate: &Crate,
                    def_map: resolve::DefMap,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    tcx: ty::ctxt) {
     let mut v = CheckCrateVisitor {
         sess: sess,
@@ -102,14 +102,14 @@ pub fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
 pub fn check_expr(v: &mut CheckCrateVisitor,
                   sess: Session,
                   def_map: resolve::DefMap,
-                  method_map: typeck::method_map,
+                  method_map: typeck::MethodMap,
                   tcx: ty::ctxt,
                   e: &Expr,
                   is_const: bool) {
     if is_const {
         match e.node {
-          ExprUnary(_, UnDeref, _) => { }
-          ExprUnary(_, UnBox, _) | ExprUnary(_, UnUniq, _) => {
+          ExprUnary(UnDeref, _) => { }
+          ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
             sess.span_err(e.span,
                           "cannot do allocations in constant expressions");
             return;
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index c0789e0aa85..7292633eec0 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -15,7 +15,7 @@ use middle::const_eval::{eval_const_expr, const_val, const_bool, const_float};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
-use middle::typeck::method_map;
+use middle::typeck::MethodMap;
 use middle::moves;
 use util::ppaux::ty_to_str;
 
@@ -31,7 +31,7 @@ use syntax::visit::{Visitor, FnKind};
 
 struct MatchCheckCtxt {
     tcx: ty::ctxt,
-    method_map: method_map,
+    method_map: MethodMap,
     moves_map: moves::MovesMap
 }
 
@@ -52,7 +52,7 @@ impl Visitor<()> for CheckMatchVisitor {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: method_map,
+                   method_map: MethodMap,
                    moves_map: moves::MovesMap,
                    krate: &Crate) {
     let cx = @MatchCheckCtxt {tcx: tcx,
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 5322aac8c23..0b516a7f05f 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -225,10 +225,10 @@ impl ConstEvalVisitor {
                 }
             }
 
-            ast::ExprUnary(_, _, inner) | ast::ExprParen(inner) =>
+            ast::ExprUnary(_, inner) | ast::ExprParen(inner) =>
                 self.classify(inner),
 
-            ast::ExprBinary(_, _, a, b) =>
+            ast::ExprBinary(_, a, b) =>
                 join(self.classify(a), self.classify(b)),
 
             ast::ExprTup(ref es) |
@@ -262,7 +262,7 @@ impl ConstEvalVisitor {
 
             ast::ExprField(base, _, _) => self.classify(base),
 
-            ast::ExprIndex(_, base, idx) =>
+            ast::ExprIndex(base, idx) =>
                 join(self.classify(base), self.classify(idx)),
 
             ast::ExprAddrOf(ast::MutImmutable, base) => self.classify(base),
@@ -336,7 +336,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
     use middle::ty;
     fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
     match e.node {
-      ExprUnary(_, UnNeg, inner) => {
+      ExprUnary(UnNeg, inner) => {
         match eval_const_expr_partial(tcx, inner) {
           Ok(const_float(f)) => Ok(const_float(-f)),
           Ok(const_int(i)) => Ok(const_int(-i)),
@@ -346,7 +346,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
           ref err => ((*err).clone())
         }
       }
-      ExprUnary(_, UnNot, inner) => {
+      ExprUnary(UnNot, inner) => {
         match eval_const_expr_partial(tcx, inner) {
           Ok(const_int(i)) => Ok(const_int(!i)),
           Ok(const_uint(i)) => Ok(const_uint(!i)),
@@ -354,7 +354,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
           _ => Err(~"not on float or string")
         }
       }
-      ExprBinary(_, op, a, b) => {
+      ExprBinary(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 e71079b6dd0..e81e6b0f96d 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -32,7 +32,7 @@ use util::ppaux::Repr;
 #[deriving(Clone)]
 pub struct DataFlowContext<O> {
     priv tcx: ty::ctxt,
-    priv method_map: typeck::method_map,
+    priv method_map: typeck::MethodMap,
 
     /// the data flow operator
     priv oper: O,
@@ -122,7 +122,7 @@ impl<O:DataFlowOperator> pprust::PpAnn for DataFlowContext<O> {
 
 impl<O:DataFlowOperator> DataFlowContext<O> {
     pub fn new(tcx: ty::ctxt,
-               method_map: typeck::method_map,
+               method_map: typeck::MethodMap,
                oper: O,
                id_range: IdRange,
                bits_per_id: uint) -> DataFlowContext<O> {
@@ -556,7 +556,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
             }
 
             ast::ExprAssign(l, r) |
-            ast::ExprAssignOp(_, _, l, r) => {
+            ast::ExprAssignOp(_, l, r) => {
                 self.walk_expr(r, in_out, loop_scopes);
                 self.walk_expr(l, in_out, loop_scopes);
             }
@@ -579,35 +579,35 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
 
             ast::ExprCall(f, ref args) => {
                 self.walk_expr(f, in_out, loop_scopes);
-                self.walk_call(f.id, expr.id, *args, in_out, loop_scopes);
+                self.walk_call(expr.id, *args, in_out, loop_scopes);
             }
 
-            ast::ExprMethodCall(callee_id, _, _, ref args) => {
-                self.walk_call(callee_id, expr.id, *args, in_out, loop_scopes);
+            ast::ExprMethodCall(_, _, ref args) => {
+                self.walk_call(expr.id, *args, in_out, loop_scopes);
             }
 
-            ast::ExprIndex(callee_id, l, r) |
-            ast::ExprBinary(callee_id, _, l, r) if self.is_method_call(expr) => {
-                self.walk_call(callee_id, expr.id, [l, r], in_out, loop_scopes);
+            ast::ExprIndex(l, r) |
+            ast::ExprBinary(_, l, r) if self.is_method_call(expr) => {
+                self.walk_call(expr.id, [l, r], in_out, loop_scopes);
             }
 
-            ast::ExprUnary(callee_id, _, e) if self.is_method_call(expr) => {
-                self.walk_call(callee_id, expr.id, [e], in_out, loop_scopes);
+            ast::ExprUnary(_, e) if self.is_method_call(expr) => {
+                self.walk_call(expr.id, [e], in_out, loop_scopes);
             }
 
             ast::ExprTup(ref exprs) => {
                 self.walk_exprs(*exprs, in_out, loop_scopes);
             }
 
-            ast::ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
+            ast::ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
                 self.walk_expr(l, in_out, loop_scopes);
                 let temp = in_out.to_owned();
                 self.walk_expr(r, in_out, loop_scopes);
                 join_bits(&self.dfcx.oper, temp, in_out);
             }
 
-            ast::ExprIndex(_, l, r) |
-            ast::ExprBinary(_, _, l, r) => {
+            ast::ExprIndex(l, r) |
+            ast::ExprBinary(_, l, r) => {
                 self.walk_exprs([l, r], in_out, loop_scopes);
             }
 
@@ -617,7 +617,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
 
             ast::ExprAddrOf(_, e) |
             ast::ExprCast(e, _) |
-            ast::ExprUnary(_, _, e) |
+            ast::ExprUnary(_, e) |
             ast::ExprParen(e) |
             ast::ExprVstore(e, _) |
             ast::ExprField(e, _, _) => {
@@ -715,7 +715,6 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
     }
 
     fn walk_call(&mut self,
-                 _callee_id: ast::NodeId,
                  call_id: ast::NodeId,
                  args: &[@ast::Expr],
                  in_out: &mut [uint],
@@ -723,8 +722,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
         self.walk_exprs(args, in_out, loop_scopes);
 
         // FIXME(#6268) nested method calls
-        // self.merge_with_entry_set(callee_id, in_out);
-        // self.dfcx.apply_gen_kill(callee_id, in_out);
+        // self.merge_with_entry_set(in_out);
+        // self.dfcx.apply_gen_kill(in_out);
 
         let return_ty = ty::node_id_to_type(self.tcx(), call_id);
         let fails = ty::type_is_bot(return_ty);
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 9cc5a49600f..7d66c80dea0 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -49,14 +49,14 @@ fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
 
 struct MarkSymbolVisitor {
     worklist: ~[ast::NodeId],
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     tcx: ty::ctxt,
     live_symbols: ~HashSet<ast::NodeId>,
 }
 
 impl MarkSymbolVisitor {
     fn new(tcx: ty::ctxt,
-           method_map: typeck::method_map,
+           method_map: typeck::MethodMap,
            worklist: ~[ast::NodeId]) -> MarkSymbolVisitor {
         MarkSymbolVisitor {
             worklist: worklist,
@@ -92,22 +92,21 @@ impl MarkSymbolVisitor {
 
     fn lookup_and_handle_method(&mut self, id: &ast::NodeId,
                                 span: codemap::Span) {
-        let method_map = self.method_map.borrow();
-        match method_map.get().find(id) {
-            Some(&origin) => {
-                match origin {
-                    typeck::method_static(def_id) => {
+        match self.method_map.borrow().get().find(id) {
+            Some(method) => {
+                match method.origin {
+                    typeck::MethodStatic(def_id) => {
                         match ty::provided_source(self.tcx, def_id) {
                             Some(p_did) => self.check_def_id(p_did),
                             None => self.check_def_id(def_id)
                         }
                     }
-                    typeck::method_param(typeck::method_param {
+                    typeck::MethodParam(typeck::MethodParam {
                         trait_id: trait_id,
                         method_num: index,
                         ..
                     })
-                    | typeck::method_object(typeck::method_object {
+                    | typeck::MethodObject(typeck::MethodObject {
                         trait_id: trait_id,
                         method_num: index,
                         ..
@@ -285,7 +284,7 @@ fn create_and_seed_worklist(tcx: ty::ctxt,
 }
 
 fn find_live(tcx: ty::ctxt,
-             method_map: typeck::method_map,
+             method_map: typeck::MethodMap,
              exported_items: &privacy::ExportedItems,
              reachable_symbols: &HashSet<ast::NodeId>,
              krate: &ast::Crate)
@@ -408,7 +407,7 @@ impl Visitor<()> for DeadVisitor {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    reachable_symbols: &HashSet<ast::NodeId>,
                    krate: &ast::Crate) {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 9f239098e81..bac706e5a86 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -12,7 +12,7 @@
 /// `unsafe`.
 
 use middle::ty;
-use middle::typeck::method_map;
+use middle::typeck::MethodMap;
 use util::ppaux;
 
 use syntax::ast;
@@ -39,7 +39,7 @@ struct EffectCheckVisitor {
     tcx: ty::ctxt,
 
     /// The method map.
-    method_map: method_map,
+    method_map: MethodMap,
     /// Whether we're in an unsafe context.
     unsafe_context: UnsafeContext,
 }
@@ -65,7 +65,7 @@ impl EffectCheckVisitor {
 
     fn check_str_index(&mut self, e: @ast::Expr) {
         let base_type = match e.node {
-            ast::ExprIndex(_, base, _) => ty::node_id_to_type(self.tcx, base.id),
+            ast::ExprIndex(base, _) => ty::node_id_to_type(self.tcx, base.id),
             _ => return
         };
         debug!("effect: checking index with base type {}",
@@ -137,8 +137,8 @@ impl Visitor<()> for EffectCheckVisitor {
 
     fn visit_expr(&mut self, expr: &ast::Expr, _:()) {
         match expr.node {
-            ast::ExprMethodCall(callee_id, _, _, _) => {
-                let base_type = ty::node_id_to_type(self.tcx, callee_id);
+            ast::ExprMethodCall(_, _, _) => {
+                let base_type = self.method_map.borrow().get().get(&expr.id).ty;
                 debug!("effect: method call case, base type is {}",
                        ppaux::ty_to_str(self.tcx, base_type));
                 if type_is_unsafe_function(base_type) {
@@ -154,7 +154,7 @@ impl Visitor<()> for EffectCheckVisitor {
                     self.require_unsafe(expr.span, "call to unsafe function")
                 }
             }
-            ast::ExprUnary(_, ast::UnDeref, base) => {
+            ast::ExprUnary(ast::UnDeref, base) => {
                 let base_type = ty::node_id_to_type(self.tcx, base.id);
                 debug!("effect: unary case, base type is {}",
                         ppaux::ty_to_str(self.tcx, base_type));
@@ -166,7 +166,7 @@ impl Visitor<()> for EffectCheckVisitor {
                     _ => {}
                 }
             }
-            ast::ExprAssign(base, _) | ast::ExprAssignOp(_, _, base, _) => {
+            ast::ExprAssign(base, _) | ast::ExprAssignOp(_, base, _) => {
                 self.check_str_index(base);
             }
             ast::ExprAddrOf(ast::MutMutable, base) => {
@@ -190,9 +190,7 @@ impl Visitor<()> for EffectCheckVisitor {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
-                   method_map: method_map,
-                   krate: &ast::Crate) {
+pub fn check_crate(tcx: ty::ctxt, method_map: MethodMap, krate: &ast::Crate) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
         method_map: method_map,
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 9be0a1b0fd3..f4c9911c243 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -53,7 +53,7 @@ use syntax::visit::Visitor;
 #[deriving(Clone)]
 pub struct Context {
     tcx: ty::ctxt,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
 }
 
 impl Visitor<()> for Context {
@@ -76,7 +76,7 @@ impl Visitor<()> for Context {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    krate: &Crate) {
     let mut ctx = Context {
         tcx: tcx,
@@ -264,13 +264,14 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
     debug!("kind::check_expr({})", expr_to_str(e));
 
     // Handle any kind bounds on type parameters
-    let type_parameter_id = match e.get_callee_id() {
-        Some(callee_id) => callee_id,
-        None => e.id,
-    };
     {
+        let method_map = cx.method_map.borrow();
+        let method = method_map.get().find(&e.id);
         let node_type_substs = cx.tcx.node_type_substs.borrow();
-        let r = node_type_substs.get().find(&type_parameter_id);
+        let r = match method {
+            Some(method) => Some(&method.substs.tps),
+            None => node_type_substs.get().find(&e.id)
+        };
         for ts in r.iter() {
             let def_map = cx.tcx.def_map.borrow();
             let type_param_defs = match e.node {
@@ -285,9 +286,9 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
 
                 // Even though the callee_id may have been the id with
                 // node_type_substs, e.id is correct here.
-                match cx.method_map.borrow().get().find(&e.id) {
-                    Some(origin) => {
-                        ty::method_call_type_param_defs(cx.tcx, *origin)
+                match method {
+                    Some(method) => {
+                        ty::method_call_type_param_defs(cx.tcx, method.origin)
                     }
                     None => {
                         cx.tcx.sess.span_bug(e.span,
@@ -306,13 +307,13 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
                       type_param_defs.repr(cx.tcx));
             }
             for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
-                check_typaram_bounds(cx, type_parameter_id, e.span, ty, type_param_def)
+                check_typaram_bounds(cx, e.span, ty, type_param_def)
             }
         }
     }
 
     match e.node {
-        ExprUnary(_, UnBox, interior) => {
+        ExprUnary(UnBox, interior) => {
             let interior_type = ty::expr_ty(cx.tcx, interior);
             let _ = check_durable(cx.tcx, interior_type, interior.span);
         }
@@ -373,7 +374,7 @@ fn check_ty(cx: &mut Context, aty: &Ty) {
                 let generics = ty::lookup_item_type(cx.tcx, did).generics;
                 let type_param_defs = generics.type_param_defs();
                 for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
-                    check_typaram_bounds(cx, aty.id, aty.span, ty, type_param_def)
+                    check_typaram_bounds(cx, aty.span, ty, type_param_def)
                 }
             }
         }
@@ -400,11 +401,9 @@ pub fn check_builtin_bounds(cx: &Context,
 }
 
 pub fn check_typaram_bounds(cx: &Context,
-                    _type_parameter_id: NodeId,
-                    sp: Span,
-                    ty: ty::t,
-                    type_param_def: &ty::TypeParameterDef)
-{
+                            sp: Span,
+                            ty: ty::t,
+                            type_param_def: &ty::TypeParameterDef) {
     check_builtin_bounds(cx,
                          ty,
                          type_param_def.bounds.builtin_bounds,
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 242b9906c72..c3e57bd9c60 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -405,7 +405,7 @@ struct Context<'a> {
     tcx: ty::ctxt,
     // maps from an expression id that corresponds to a method call to the
     // details of the method to be invoked
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     // Items exported by the crate; used by the missing_doc lint.
     exported_items: &'a privacy::ExportedItems,
     // The id of the current `ast::StructDef` being walked.
@@ -674,7 +674,7 @@ fn check_unused_casts(cx: &Context, e: &ast::Expr) {
 
 fn check_type_limits(cx: &Context, e: &ast::Expr) {
     return match e.node {
-        ast::ExprBinary(_, binop, l, r) => {
+        ast::ExprBinary(binop, l, r) => {
             if is_comparison(binop) && !check_limits(cx.tcx, binop, l, r) {
                 cx.span_lint(TypeLimits, e.span,
                              "comparison is useless due to type limits");
@@ -1176,7 +1176,7 @@ fn check_unnecessary_parens_expr(cx: &Context, e: &ast::Expr) {
         ast::ExprMatch(head, _) => (head, "`match` head expression"),
         ast::ExprRet(Some(value)) => (value, "`return` value"),
         ast::ExprAssign(_, value) => (value, "assigned value"),
-        ast::ExprAssignOp(_, _, _, value) => (value, "assigned value"),
+        ast::ExprAssignOp(_, _, value) => (value, "assigned value"),
         _ => return
     };
     check_unnecessary_parens_core(cx, value, msg);
@@ -1263,8 +1263,8 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
                 _ => return
             }
         }
-        ast::ExprUnary(_, ast::UnUniq, _) |
-        ast::ExprUnary(_, ast::UnBox, _) => BoxAllocation,
+        ast::ExprUnary(ast::UnUniq, _) |
+        ast::ExprUnary(ast::UnBox, _) => BoxAllocation,
 
         _ => return
     };
@@ -1411,11 +1411,10 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
             }
         }
         ast::ExprMethodCall(..) => {
-            let method_map = cx.method_map.borrow();
-            match method_map.get().find(&e.id) {
-                Some(&origin) => {
-                    match origin {
-                        typeck::method_static(def_id) => {
+            match cx.method_map.borrow().get().find(&e.id) {
+                Some(method) => {
+                    match method.origin {
+                        typeck::MethodStatic(def_id) => {
                             // If this implements a trait method, get def_id
                             // of the method inside trait definition.
                             // Otherwise, use the current def_id (which refers
@@ -1423,12 +1422,12 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
                             ty::trait_method_of_method(
                                 cx.tcx, def_id).unwrap_or(def_id)
                         }
-                        typeck::method_param(typeck::method_param {
+                        typeck::MethodParam(typeck::MethodParam {
                             trait_id: trait_id,
                             method_num: index,
                             ..
                         })
-                        | typeck::method_object(typeck::method_object {
+                        | typeck::MethodObject(typeck::MethodObject {
                             trait_id: trait_id,
                             method_num: index,
                             ..
@@ -1531,7 +1530,7 @@ impl<'a> Visitor<()> for Context<'a> {
 
     fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
         match e.node {
-            ast::ExprUnary(_, ast::UnNeg, expr) => {
+            ast::ExprUnary(ast::UnNeg, expr) => {
                 // propagate negation, if the negation itself isn't negated
                 if self.negated_expr_id != e.id {
                     self.negated_expr_id = expr.id;
@@ -1646,7 +1645,7 @@ impl<'a> IdVisitingOperation for Context<'a> {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    krate: &ast::Crate) {
     let mut cx = Context {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 7293c3a3cee..eb123a91119 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -174,7 +174,7 @@ impl Visitor<@IrMaps> for LivenessVisitor {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: typeck::method_map,
+                   method_map: typeck::MethodMap,
                    capture_map: moves::CaptureMap,
                    krate: &Crate) {
     let mut visitor = LivenessVisitor;
@@ -253,7 +253,7 @@ enum VarKind {
 
 struct IrMaps {
     tcx: ty::ctxt,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     capture_map: moves::CaptureMap,
 
     num_live_nodes: Cell<uint>,
@@ -266,7 +266,7 @@ struct IrMaps {
 }
 
 fn IrMaps(tcx: ty::ctxt,
-          method_map: typeck::method_map,
+          method_map: typeck::MethodMap,
           capture_map: moves::CaptureMap)
        -> IrMaps {
     IrMaps {
@@ -534,7 +534,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
         visit::walk_expr(v, expr, this);
       }
       ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
-      ExprBinary(_, op, _, _) if ast_util::lazy_binop(op) => {
+      ExprBinary(op, _, _) if ast_util::lazy_binop(op) => {
         this.add_live_node_for_node(expr.id, ExprNode(expr.span));
         visit::walk_expr(v, expr, this);
       }
@@ -1179,7 +1179,7 @@ impl Liveness {
             self.propagate_through_expr(r, succ)
           }
 
-          ExprAssignOp(_, _, l, r) => {
+          ExprAssignOp(_, l, r) => {
             // see comment on lvalues in
             // propagate_through_lvalue_components()
             let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ);
@@ -1219,10 +1219,10 @@ impl Liveness {
             self.propagate_through_expr(f, succ)
           }
 
-          ExprMethodCall(callee_id, _, _, ref args) => {
+          ExprMethodCall(_, _, 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, callee_id));
+            let t_ret = ty::node_id_to_type(self.tcx, expr.id);
             let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
                        else {succ};
             self.propagate_through_exprs(*args, succ)
@@ -1232,7 +1232,7 @@ impl Liveness {
             self.propagate_through_exprs(*exprs, succ)
           }
 
-          ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
+          ExprBinary(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);
@@ -1242,15 +1242,15 @@ impl Liveness {
             self.propagate_through_expr(l, ln)
           }
 
-          ExprIndex(_, l, r) |
-          ExprBinary(_, _, l, r) |
+          ExprIndex(l, r) |
+          ExprBinary(_, l, r) |
           ExprBox(l, r) => {
             self.propagate_through_exprs([l, r], succ)
           }
 
           ExprAddrOf(_, e) |
           ExprCast(e, _) |
-          ExprUnary(_, _, e) |
+          ExprUnary(_, e) |
           ExprParen(e) => {
             self.propagate_through_expr(e, succ)
           }
@@ -1508,7 +1508,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
         visit::walk_expr(this, expr, ());
       }
 
-      ExprAssignOp(_, _, l, _) => {
+      ExprAssignOp(_, l, _) => {
         this.check_lvalue(l);
 
         visit::walk_expr(this, expr, ());
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 0882e8eb692..fe66ec88f8f 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -432,7 +432,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
 
         let expr_ty = if_ok!(self.expr_ty(expr));
         match expr.node {
-          ast::ExprUnary(_, ast::UnDeref, e_base) => {
+          ast::ExprUnary(ast::UnDeref, e_base) => {
             if self.typer.is_method_call(expr.id) {
                 return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
             }
@@ -450,7 +450,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
             Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
           }
 
-          ast::ExprIndex(_, base, _) => {
+          ast::ExprIndex(base, _) => {
             if self.typer.is_method_call(expr.id) {
                 return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
             }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 1705e3a5160..4864f72d8fc 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -130,7 +130,7 @@ and so on.
 use middle::pat_util::{pat_bindings};
 use middle::freevars;
 use middle::ty;
-use middle::typeck::method_map;
+use middle::typeck::MethodMap;
 use util::ppaux;
 use util::ppaux::Repr;
 use util::common::indenter;
@@ -182,7 +182,7 @@ pub struct MoveMaps {
 #[deriving(Clone)]
 struct VisitContext {
     tcx: ty::ctxt,
-    method_map: method_map,
+    method_map: MethodMap,
     move_maps: MoveMaps
 }
 
@@ -208,7 +208,7 @@ impl visit::Visitor<()> for VisitContext {
 }
 
 pub fn compute_moves(tcx: ty::ctxt,
-                     method_map: method_map,
+                     method_map: MethodMap,
                      krate: &Crate) -> MoveMaps
 {
     let mut visit_cx = VisitContext {
@@ -361,7 +361,7 @@ impl VisitContext {
                 }
             }
 
-            ExprUnary(_, UnDeref, base) => {       // *base
+            ExprUnary(UnDeref, base) => {      // *base
                 if !self.use_overloaded_operator(expr, base, [])
                 {
                     // Moving out of *base moves out of base.
@@ -369,12 +369,12 @@ impl VisitContext {
                 }
             }
 
-            ExprField(base, _, _) => {        // base.f
+            ExprField(base, _, _) => {         // base.f
                 // Moving out of base.f moves out of base.
                 self.use_expr(base, comp_mode);
             }
 
-            ExprIndex(_, lhs, rhs) => {          // lhs[rhs]
+            ExprIndex(lhs, rhs) => {           // lhs[rhs]
                 if !self.use_overloaded_operator(expr, lhs, [rhs])
                 {
                     self.use_expr(lhs, comp_mode);
@@ -409,11 +409,11 @@ impl VisitContext {
                     }
                 }
                 self.use_expr(callee, mode);
-                self.use_fn_args(callee.id, *args);
+                self.use_fn_args(*args);
             }
 
-            ExprMethodCall(callee_id, _, _, ref args) => { // callee.m(args)
-                self.use_fn_args(callee_id, *args);
+            ExprMethodCall(_, _, ref args) => { // callee.m(args)
+                self.use_fn_args(*args);
             }
 
             ExprStruct(_, ref fields, opt_with) => {
@@ -521,14 +521,14 @@ impl VisitContext {
 
             ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
 
-            ExprUnary(_, _, lhs) => {
+            ExprUnary(_, lhs) => {
                 if !self.use_overloaded_operator(expr, lhs, [])
                 {
                     self.consume_expr(lhs);
                 }
             }
 
-            ExprBinary(_, _, lhs, rhs) => {
+            ExprBinary(_, lhs, rhs) => {
                 if !self.use_overloaded_operator(expr, lhs, [rhs])
                 {
                     self.consume_expr(lhs);
@@ -555,7 +555,7 @@ impl VisitContext {
                 self.consume_expr(base);
             }
 
-            ExprAssignOp(_, _, lhs, rhs) => {
+            ExprAssignOp(_, lhs, rhs) => {
                 // FIXME(#4712) --- Overloaded operators?
                 //
                 // if !self.use_overloaded_operator(expr, DoDerefArgs, lhs, [rhs])
@@ -668,7 +668,6 @@ impl VisitContext {
     }
 
     pub fn use_fn_args(&mut self,
-                       _: NodeId,
                        arg_exprs: &[@Expr]) {
         //! Uses the argument expressions.
         for arg_expr in arg_exprs.iter() {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 1899b52cca8..453160dc001 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -18,8 +18,8 @@ use collections::{HashSet, HashMap};
 use metadata::csearch;
 use middle::resolve;
 use middle::ty;
-use middle::typeck::{method_map, method_origin, method_param};
-use middle::typeck::{method_static, method_object};
+use middle::typeck::{MethodMap, MethodOrigin, MethodParam};
+use middle::typeck::{MethodStatic, MethodObject};
 
 use syntax::ast;
 use syntax::ast_map;
@@ -31,7 +31,7 @@ use syntax::opt_vec;
 use syntax::visit;
 use syntax::visit::Visitor;
 
-type Context<'a> = (&'a method_map, &'a resolve::ExportMap2);
+type Context<'a> = (&'a MethodMap, &'a resolve::ExportMap2);
 
 /// A set of AST nodes exported by the crate.
 pub type ExportedItems = HashSet<ast::NodeId>;
@@ -347,7 +347,7 @@ struct PrivacyVisitor<'a> {
     curitem: ast::NodeId,
     in_fn: bool,
     in_foreign: bool,
-    method_map: &'a method_map,
+    method_map: &'a MethodMap,
     parents: HashMap<ast::NodeId, ast::NodeId>,
     external_exports: resolve::ExternalExports,
     last_private_map: resolve::LastPrivateMap,
@@ -738,16 +738,16 @@ impl<'a> PrivacyVisitor<'a> {
     }
 
     // Checks that a method is in scope.
-    fn check_method(&mut self, span: Span, origin: &method_origin,
+    fn check_method(&mut self, span: Span, origin: MethodOrigin,
                     ident: ast::Ident) {
-        match *origin {
-            method_static(method_id) => {
+        match origin {
+            MethodStatic(method_id) => {
                 self.check_static_method(span, method_id, ident)
             }
             // Trait methods are always all public. The only controlling factor
             // is whether the trait itself is accessible or not.
-            method_param(method_param { trait_id: trait_id, .. }) |
-            method_object(method_object { trait_id: trait_id, .. }) => {
+            MethodParam(MethodParam { trait_id: trait_id, .. }) |
+            MethodObject(MethodObject { trait_id: trait_id, .. }) => {
                 self.report_error(self.ensure_public(span, trait_id, None, "source trait"));
             }
         }
@@ -785,7 +785,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
                     _ => {}
                 }
             }
-            ast::ExprMethodCall(_, ident, _, ref args) => {
+            ast::ExprMethodCall(ident, _, ref args) => {
                 // see above
                 let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
                 match ty::get(t).sty {
@@ -796,9 +796,9 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
                                                        "method call not in \
                                                         method map");
                             }
-                            Some(origin) => {
+                            Some(method) => {
                                 debug!("(privacy checking) checking impl method");
-                                self.check_method(expr.span, origin, ident);
+                                self.check_method(expr.span, method.origin, ident);
                             }
                         }
                     }
@@ -1170,7 +1170,7 @@ impl SanePrivacyVisitor {
 }
 
 pub fn check_crate(tcx: ty::ctxt,
-                   method_map: &method_map,
+                   method_map: &MethodMap,
                    exp_map2: &resolve::ExportMap2,
                    external_exports: resolve::ExternalExports,
                    last_private_map: resolve::LastPrivateMap,
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 26104331a10..4b2bc5c966f 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -86,7 +86,7 @@ struct ReachableContext {
     tcx: ty::ctxt,
     // The method map, which links node IDs of method call expressions to the
     // methods they've been resolved to.
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     // The set of items which must be exported in the linkage sense.
     reachable_symbols: @RefCell<HashSet<ast::NodeId>>,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
@@ -96,7 +96,7 @@ struct ReachableContext {
 
 struct MarkSymbolVisitor {
     worklist: @RefCell<~[ast::NodeId]>,
-    method_map: typeck::method_map,
+    method_map: typeck::MethodMap,
     tcx: ty::ctxt,
     reachable_symbols: @RefCell<HashSet<ast::NodeId>>,
 }
@@ -147,9 +147,8 @@ impl Visitor<()> for MarkSymbolVisitor {
                 }
             }
             ast::ExprMethodCall(..) => {
-                let method_map = self.method_map.borrow();
-                match method_map.get().find(&expr.id) {
-                    Some(&typeck::method_static(def_id)) => {
+                match self.method_map.borrow().get().get(&expr.id).origin {
+                    typeck::MethodStatic(def_id) => {
                         if is_local(def_id) {
                             if ReachableContext::
                                 def_id_represents_local_inlined_item(
@@ -168,11 +167,7 @@ impl Visitor<()> for MarkSymbolVisitor {
                             }
                         }
                     }
-                    Some(_) => {}
-                    None => {
-                        self.tcx.sess.span_bug(expr.span,
-                            "method call expression not in method map?!")
-                    }
+                    _ => {}
                 }
             }
             _ => {}
@@ -189,7 +184,7 @@ impl Visitor<()> for MarkSymbolVisitor {
 
 impl ReachableContext {
     // Creates a new reachability computation context.
-    fn new(tcx: ty::ctxt, method_map: typeck::method_map) -> ReachableContext {
+    fn new(tcx: ty::ctxt, method_map: typeck::MethodMap) -> ReachableContext {
         ReachableContext {
             tcx: tcx,
             method_map: method_map,
@@ -398,7 +393,7 @@ impl ReachableContext {
 }
 
 pub fn find_reachable(tcx: ty::ctxt,
-                      method_map: typeck::method_map,
+                      method_map: typeck::MethodMap,
                       exported_items: &privacy::ExportedItems)
                       -> @RefCell<HashSet<ast::NodeId>> {
     let reachable_context = ReachableContext::new(tcx, method_map);
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index c06ad66f606..9e1552ae35e 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -512,8 +512,8 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
         // scopes, meaning that temporaries cannot outlive them.
         // This ensures fixed size stacks.
 
-        ast::ExprBinary(_, ast::BiAnd, _, r) |
-        ast::ExprBinary(_, ast::BiOr, _, r) => {
+        ast::ExprBinary(ast::BiAnd, _, r) |
+        ast::ExprBinary(ast::BiOr, _, r) => {
             // For shortcircuiting operators, mark the RHS as a terminating
             // scope since it only executes conditionally.
             visitor.region_maps.mark_as_terminating_scope(r.id);
@@ -756,7 +756,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
                         visitor, subexpr, blk_id);
                 }
             }
-            ast::ExprUnary(_, ast::UnUniq, subexpr) => {
+            ast::ExprUnary(ast::UnUniq, subexpr) => {
                 record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
             }
             ast::ExprCast(subexpr, _) |
@@ -811,9 +811,9 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
 
             match expr.node {
                 ast::ExprAddrOf(_, ref subexpr) |
-                ast::ExprUnary(_, ast::UnDeref, ref subexpr) |
+                ast::ExprUnary(ast::UnDeref, ref subexpr) |
                 ast::ExprField(ref subexpr, _, _) |
-                ast::ExprIndex(_, ref subexpr, _) |
+                ast::ExprIndex(ref subexpr, _) |
                 ast::ExprParen(ref subexpr) => {
                     let subexpr: &'a @Expr = subexpr; // FIXME(#11586)
                     expr = &**subexpr;
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 5dc18bc08f1..8f0261dfb91 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -5257,7 +5257,7 @@ impl Resolver {
                 let traits = self.search_for_traits_containing_method(ident);
                 self.trait_map.insert(expr.id, traits);
             }
-            ExprMethodCall(_, ident, _, _) => {
+            ExprMethodCall(ident, _, _) => {
                 debug!("(recording candidate traits for expr) recording \
                         traits for {}",
                        expr.id);
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index cfba7f03fc9..3c44c607e7f 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -118,7 +118,7 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
         match def {
             ast::DefFn(did, _) |
             ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
-                fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
+                fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id, false))
             }
             ast::DefStaticMethod(impl_did,
                                    ast::FromTrait(trait_did),
@@ -132,10 +132,10 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
                 assert!(ty::enum_variant_with_id(bcx.tcx(),
                                                       tid,
                                                       vid).args.len() > 0u);
-                fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id))
+                fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id, false))
             }
             ast::DefStruct(def_id) => {
-                fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id))
+                fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id, false))
             }
             ast::DefStatic(..) |
             ast::DefArg(..) |
@@ -158,16 +158,8 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
     }
 }
 
-pub fn trans_fn_ref_to_callee<'a>(
-                              bcx: &'a Block<'a>,
-                              def_id: ast::DefId,
-                              ref_id: ast::NodeId)
-                              -> Callee<'a> {
-    Callee {bcx: bcx,
-            data: Fn(trans_fn_ref(bcx, def_id, ref_id))}
-}
-
-pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
+pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId,
+                    ref_id: ast::NodeId, is_method: bool)
                     -> ValueRef {
     /*!
      *
@@ -177,23 +169,22 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
 
     let _icx = push_ctxt("trans_fn_ref");
 
-    let type_params = node_id_type_params(bcx, ref_id);
+    let type_params = node_id_type_params(bcx, ref_id, is_method);
     let vtables = node_vtables(bcx, ref_id);
     debug!("trans_fn_ref(def_id={}, ref_id={:?}, type_params={}, vtables={})",
            def_id.repr(bcx.tcx()), ref_id, type_params.repr(bcx.tcx()),
            vtables.repr(bcx.tcx()));
-    trans_fn_ref_with_vtables(bcx, def_id, ref_id, type_params, vtables)
+    trans_fn_ref_with_vtables(bcx, def_id, ref_id, is_method, type_params, vtables)
 }
 
-pub fn trans_fn_ref_with_vtables_to_callee<'a>(
-                                           bcx: &'a Block<'a>,
+fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
                                            def_id: ast::DefId,
                                            ref_id: ast::NodeId,
                                            type_params: &[ty::t],
                                            vtables: Option<typeck::vtable_res>)
                                            -> Callee<'a> {
     Callee {bcx: bcx,
-            data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id,
+            data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id, false,
                                                type_params, vtables))}
 }
 
@@ -243,6 +234,7 @@ pub fn trans_fn_ref_with_vtables(
         bcx: &Block,       //
         def_id: ast::DefId,   // def id of fn
         ref_id: ast::NodeId,  // node id of use of fn; may be zero if N/A
+        is_method: bool,
         type_params: &[ty::t], // values for fn's ty params
         vtables: Option<typeck::vtable_res>) // vtables for the call
      -> ValueRef {
@@ -388,7 +380,12 @@ pub fn trans_fn_ref_with_vtables(
         if must_cast && ref_id != 0 {
             // Monotype of the REFERENCE to the function (type params
             // are subst'd)
-            let ref_ty = common::node_id_type(bcx, ref_id);
+            let ref_ty = if is_method {
+                let t = bcx.ccx().maps.method_map.borrow().get().get(&ref_id).ty;
+                monomorphize_type(bcx, t)
+            } else {
+                node_id_type(bcx, ref_id)
+            };
 
             val = PointerCast(
                 bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
@@ -461,41 +458,22 @@ pub fn trans_call<'a>(
 }
 
 pub fn trans_method_call<'a>(
-                         in_cx: &'a Block<'a>,
+                         bcx: &'a Block<'a>,
                          call_ex: &ast::Expr,
-                         callee_id: ast::NodeId,
                          rcvr: &ast::Expr,
                          args: CallArgs,
                          dest: expr::Dest)
                          -> &'a Block<'a> {
     let _icx = push_ctxt("trans_method_call");
-    debug!("trans_method_call(call_ex={})", call_ex.repr(in_cx.tcx()));
+    debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx()));
+    let method_ty = bcx.ccx().maps.method_map.borrow().get().get(&call_ex.id).ty;
     trans_call_inner(
-        in_cx,
+        bcx,
         Some(common::expr_info(call_ex)),
-        node_id_type(in_cx, callee_id),
-        expr_ty(in_cx, call_ex),
+        monomorphize_type(bcx, method_ty),
+        expr_ty(bcx, call_ex),
         |cx, arg_cleanup_scope| {
-            let origin_opt = {
-                let mut method_map = cx.ccx().maps.method_map.borrow_mut();
-                method_map.get().find_copy(&call_ex.id)
-            };
-            match origin_opt {
-                Some(origin) => {
-                    debug!("origin for {}: {}",
-                           call_ex.repr(in_cx.tcx()),
-                           origin.repr(in_cx.tcx()));
-
-                    meth::trans_method_callee(cx,
-                                              callee_id,
-                                              rcvr,
-                                              origin,
-                                              arg_cleanup_scope)
-                }
-                None => {
-                    cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
-                }
-            }
+            meth::trans_method_callee(cx, call_ex.id, rcvr, arg_cleanup_scope)
         },
         args,
         Some(dest)).bcx
diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs
index 5bbb9749a59..dfff05966cb 100644
--- a/src/librustc/middle/trans/cleanup.rs
+++ b/src/librustc/middle/trans/cleanup.rs
@@ -673,7 +673,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
 
         // The exception handling personality function.
         let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
-        let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0);
+        let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0, false);
 
         // The only landing pad clause will be 'cleanup'
         let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u);
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 74d21f114ef..037ea3e14f3 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -807,9 +807,13 @@ pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
     monomorphize_type(bcx, t)
 }
 
-pub fn node_id_type_params(bcx: &Block, id: ast::NodeId) -> ~[ty::t] {
+pub fn node_id_type_params(bcx: &Block, id: ast::NodeId, is_method: bool) -> ~[ty::t] {
     let tcx = bcx.tcx();
-    let params = ty::node_id_to_type_params(tcx, id);
+    let params = if is_method {
+        bcx.ccx().maps.method_map.borrow().get().get(&id).substs.tps.clone()
+    } else {
+        ty::node_id_to_type_params(tcx, id)
+    };
 
     if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
         bcx.sess().bug(
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index fc5e48a161f..b3c3b22c1f5 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -310,7 +310,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
           ast::ExprLit(lit) => {
               (consts::const_lit(cx, e, (*lit).clone()), true)
           }
-          ast::ExprBinary(_, b, e1, e2) => {
+          ast::ExprBinary(b, e1, e2) => {
             let (te1, _) = const_expr(cx, e1, is_local);
             let (te2, _) = const_expr(cx, e2, is_local);
 
@@ -392,7 +392,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
               },
             }, true)
           },
-          ast::ExprUnary(_, u, e) => {
+          ast::ExprUnary(u, e) => {
             let (te, _) = const_expr(cx, e, is_local);
             let ty = ty::expr_ty(cx.tcx, e);
             let is_float = ty::type_is_fp(ty);
@@ -429,7 +429,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
               })
           }
 
-          ast::ExprIndex(_, base, index) => {
+          ast::ExprIndex(base, index) => {
               let bt = ty::expr_ty_adjusted(cx.tcx, base);
               let (bv, inlineable) = const_expr(cx, base, is_local);
               let iv = match const_eval::eval_const_expr(cx.tcx, index) {
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 564aab5d31d..9dc119b024f 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -2539,15 +2539,13 @@ fn populate_scope_map(cx: &CrateContext,
                 None => ()
             },
 
-            ast::ExprUnary(node_id, _, sub_exp) => {
-                scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
+            ast::ExprUnary(_, sub_exp) => {
                 walk_expr(cx, sub_exp, scope_stack, scope_map);
             }
 
-            ast::ExprAssignOp(node_id, _, lhs, rhs) |
-            ast::ExprIndex(node_id, lhs, rhs)        |
-            ast::ExprBinary(node_id, _, lhs, rhs)    => {
-                scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
+            ast::ExprAssignOp(_, lhs, rhs) |
+            ast::ExprIndex(lhs, rhs)        |
+            ast::ExprBinary(_, lhs, rhs)    => {
                 walk_expr(cx, lhs, scope_stack, scope_map);
                 walk_expr(cx, rhs, scope_stack, scope_map);
             }
@@ -2638,9 +2636,7 @@ fn populate_scope_map(cx: &CrateContext,
                 }
             }
 
-            ast::ExprMethodCall(node_id, _, _, ref args) => {
-                scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
-
+            ast::ExprMethodCall(_, _, ref args) => {
                 for arg_exp in args.iter() {
                     walk_expr(cx, *arg_exp, scope_stack, scope_map);
                 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index e3724ab4d11..987d60957d1 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -442,7 +442,7 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
         ast::ExprField(base, ident, _) => {
             trans_rec_field(bcx, base, ident)
         }
-        ast::ExprIndex(_, base, idx) => {
+        ast::ExprIndex(base, idx) => {
             trans_index(bcx, expr, base, idx)
         }
         ast::ExprVstore(contents, ast::ExprVstoreUniq) => {
@@ -461,20 +461,17 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
             return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
         }
         ast::ExprLit(lit) => trans_immediate_lit(bcx, expr, (*lit).clone()),
-        ast::ExprBinary(_, op, lhs, rhs) => {
+        ast::ExprBinary(op, lhs, rhs) => {
             // if overloaded, would be RvalueDpsExpr
-            {
-                let method_map = bcx.ccx().maps.method_map.borrow();
-                assert!(!method_map.get().contains_key(&expr.id));
-            }
+            assert!(!bcx.ccx().maps.method_map.borrow().get().contains_key(&expr.id));
 
             trans_binary(bcx, expr, op, lhs, rhs)
         }
-        ast::ExprUnary(_, ast::UnDeref, base) => {
+        ast::ExprUnary(ast::UnDeref, base) => {
             let basedatum = unpack_datum!(bcx, trans(bcx, base));
             deref_once(bcx, expr, basedatum, 0)
         }
-        ast::ExprUnary(_, op, x) => {
+        ast::ExprUnary(op, x) => {
             trans_unary_datum(bcx, expr, op, x)
         }
         ast::ExprAddrOf(_, x) => {
@@ -698,8 +695,8 @@ fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>,
                 src_datum.store_to(bcx, dst_datum.val)
             }
         }
-        ast::ExprAssignOp(callee_id, op, dst, src) => {
-            trans_assign_op(bcx, expr, callee_id, op, dst, src)
+        ast::ExprAssignOp(op, dst, src) => {
+            trans_assign_op(bcx, expr, op, dst, src)
         }
         ast::ExprInlineAsm(ref a) => {
             asm::trans_inline_asm(bcx, a)
@@ -780,26 +777,24 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
             closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest)
         }
         ast::ExprCall(f, ref args) => {
-            callee::trans_call(bcx, expr, f,
-                               callee::ArgExprs(*args), expr.id, dest)
+            callee::trans_call(bcx, expr, f, callee::ArgExprs(*args), expr.id, dest)
         }
-        ast::ExprMethodCall(callee_id, _, _, ref args) => {
-            callee::trans_method_call(bcx, expr, callee_id, args[0],
-                                      callee::ArgExprs(*args), dest)
+        ast::ExprMethodCall(_, _, ref args) => {
+            callee::trans_method_call(bcx, expr, args[0], callee::ArgExprs(*args), dest)
         }
-        ast::ExprBinary(callee_id, _, lhs, rhs) => {
+        ast::ExprBinary(_, lhs, rhs) => {
             // if not overloaded, would be RvalueDatumExpr
-            trans_overloaded_op(bcx, expr, callee_id, lhs,
+            trans_overloaded_op(bcx, expr, lhs,
                                 Some(&*rhs), expr_ty(bcx, expr), dest)
         }
-        ast::ExprUnary(callee_id, _, subexpr) => {
+        ast::ExprUnary(_, subexpr) => {
             // if not overloaded, would be RvalueDatumExpr
-            trans_overloaded_op(bcx, expr, callee_id, subexpr,
+            trans_overloaded_op(bcx, expr, subexpr,
                                 None, expr_ty(bcx, expr), dest)
         }
-        ast::ExprIndex(callee_id, base, idx) => {
+        ast::ExprIndex(base, idx) => {
             // if not overloaded, would be RvalueDatumExpr
-            trans_overloaded_op(bcx, expr, callee_id, base,
+            trans_overloaded_op(bcx, expr, base,
                                 Some(&*idx), expr_ty(bcx, expr), dest)
         }
         ast::ExprCast(val, _) => {
@@ -815,8 +810,8 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
                 }
             }
         }
-        ast::ExprAssignOp(callee_id, op, dst, src) => {
-            trans_assign_op(bcx, expr, callee_id, op, dst, src)
+        ast::ExprAssignOp(op, dst, src) => {
+            trans_assign_op(bcx, expr, op, dst, src)
         }
         ast::ExprBox(_, contents) => {
             // Special case for `Gc<T>` for now. The other case, for unique
@@ -851,7 +846,7 @@ fn trans_def_dps_unadjusted<'a>(
             let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
             if variant_info.args.len() > 0u {
                 // N-ary variant.
-                let llfn = callee::trans_fn_ref(bcx, vid, ref_expr.id);
+                let llfn = callee::trans_fn_ref(bcx, vid, ref_expr.id, false);
                 Store(bcx, llfn, lldest);
                 return bcx;
             } else {
@@ -884,15 +879,14 @@ fn trans_def_dps_unadjusted<'a>(
 
 fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
                                ref_expr: &ast::Expr,
-                               def: ast::Def) -> DatumBlock<'a, Expr>
-{
+                               def: ast::Def) -> DatumBlock<'a, Expr> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
     let llfn = match def {
         ast::DefFn(did, _) |
         ast::DefStruct(did) | ast::DefVariant(_, did, _) |
         ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
-            callee::trans_fn_ref(bcx, did, ref_expr.id)
+            callee::trans_fn_ref(bcx, did, ref_expr.id, false)
         }
         ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => {
             meth::trans_static_method_callee(bcx, impl_did,
@@ -1496,26 +1490,20 @@ fn trans_binary<'a>(
 fn trans_overloaded_op<'a, 'b>(
                        bcx: &'a Block<'a>,
                        expr: &ast::Expr,
-                       callee_id: ast::NodeId,
                        rcvr: &'b ast::Expr,
                        arg: Option<&'b ast::Expr>,
                        ret_ty: ty::t,
                        dest: Dest)
                        -> &'a Block<'a> {
-    let origin = {
-        let method_map = bcx.ccx().maps.method_map.borrow();
-        method_map.get().get_copy(&expr.id)
-    };
-    let fty = node_id_type(bcx, callee_id);
+    let method_ty = bcx.ccx().maps.method_map.borrow().get().get(&expr.id).ty;
     callee::trans_call_inner(bcx,
                              Some(expr_info(expr)),
-                             fty,
+                             monomorphize_type(bcx, method_ty),
                              ret_ty,
                              |bcx, arg_cleanup_scope| {
                                 meth::trans_method_callee(bcx,
-                                                          callee_id,
+                                                          expr.id,
                                                           rcvr,
-                                                          origin,
                                                           arg_cleanup_scope)
                              },
                              callee::ArgAutorefSecond(rcvr, arg),
@@ -1666,7 +1654,6 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
 fn trans_assign_op<'a>(
                    bcx: &'a Block<'a>,
                    expr: &ast::Expr,
-                   _callee_id: ast::NodeId,
                    op: ast::BinOp,
                    dst: &ast::Expr,
                    src: @ast::Expr)
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 7fa116cafd0..a9473d9f480 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -93,24 +93,32 @@ pub fn trans_method(ccx: @CrateContext, method: &ast::Method,
 
 pub fn trans_method_callee<'a>(
                            bcx: &'a Block<'a>,
-                           callee_id: ast::NodeId,
+                           expr_id: ast::NodeId,
                            this: &ast::Expr,
-                           origin: typeck::method_origin,
                            arg_cleanup_scope: cleanup::ScopeId)
                            -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_method_callee");
 
-    debug!("trans_method_callee(callee_id={:?}, origin={})",
-           callee_id, origin.repr(bcx.tcx()));
+    let (origin, method_ty) = match bcx.ccx().maps.method_map
+                                       .borrow().get().find(&expr_id) {
+        Some(method) => {
+            debug!("trans_method_callee(expr_id={:?}, method={})",
+                expr_id, method.repr(bcx.tcx()));
+            (method.origin, method.ty)
+        }
+        None => {
+            bcx.tcx().sess.span_bug(this.span, "method call expr wasn't in method map")
+        }
+    };
 
     match origin {
-        typeck::method_static(did) => {
+        typeck::MethodStatic(did) => {
             Callee {
                 bcx: bcx,
-                data: Fn(callee::trans_fn_ref(bcx, did, callee_id))
+                data: Fn(callee::trans_fn_ref(bcx, did, expr_id, true))
             }
         }
-        typeck::method_param(typeck::method_param {
+        typeck::MethodParam(typeck::MethodParam {
             trait_id: trait_id,
             method_num: off,
             param_num: p,
@@ -123,7 +131,7 @@ pub fn trans_method_callee<'a>(
                         trait_id);
 
                     let vtbl = find_vtable(bcx.tcx(), substs, p, b);
-                    trans_monomorphized_callee(bcx, callee_id,
+                    trans_monomorphized_callee(bcx, expr_id,
                                                trait_id, off, vtbl)
                 }
                 // how to get rid of this?
@@ -131,9 +139,9 @@ pub fn trans_method_callee<'a>(
             }
         }
 
-        typeck::method_object(ref mt) => {
+        typeck::MethodObject(ref mt) => {
             trans_trait_callee(bcx,
-                               callee_id,
+                               monomorphize_type(bcx, method_ty),
                                mt.real_index,
                                this,
                                arg_cleanup_scope)
@@ -144,16 +152,16 @@ pub fn trans_method_callee<'a>(
 pub fn trans_static_method_callee(bcx: &Block,
                                   method_id: ast::DefId,
                                   trait_id: ast::DefId,
-                                  callee_id: ast::NodeId)
+                                  expr_id: ast::NodeId)
                                   -> ValueRef {
     let _icx = push_ctxt("meth::trans_static_method_callee");
     let ccx = bcx.ccx();
 
     debug!("trans_static_method_callee(method_id={:?}, trait_id={}, \
-            callee_id={:?})",
+            expr_id={:?})",
            method_id,
            ty::item_path_str(bcx.tcx(), trait_id),
-           callee_id);
+           expr_id);
     let _indenter = indenter();
 
     ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
@@ -188,13 +196,10 @@ pub fn trans_static_method_callee(bcx: &Block,
     } else {
         csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
     };
-    debug!("trans_static_method_callee: method_id={:?}, callee_id={:?}, \
-            name={}", method_id, callee_id, token::get_name(mname));
+    debug!("trans_static_method_callee: method_id={:?}, expr_id={:?}, \
+            name={}", method_id, expr_id, token::get_name(mname));
 
-    let vtbls = {
-        let vtable_map = ccx.maps.vtable_map.borrow();
-        vtable_map.get().get_copy(&callee_id)
-    };
+    let vtbls = ccx.maps.vtable_map.borrow().get().get_copy(&expr_id);
     let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
 
     match vtbls[bound_index][0] {
@@ -204,14 +209,14 @@ pub fn trans_static_method_callee(bcx: &Block,
             let mth_id = method_with_name(ccx, impl_did, mname);
             let (callee_substs, callee_origins) =
                 combine_impl_and_methods_tps(
-                    bcx, mth_id, callee_id,
+                    bcx, mth_id, expr_id, false,
                     *rcvr_substs, rcvr_origins);
 
-            let llfn = trans_fn_ref_with_vtables(bcx, mth_id, callee_id,
-                                                 callee_substs,
+            let llfn = trans_fn_ref_with_vtables(bcx, mth_id, expr_id,
+                                                 false, callee_substs,
                                                  Some(callee_origins));
 
-            let callee_ty = node_id_type(bcx, callee_id);
+            let callee_ty = node_id_type(bcx, expr_id);
             let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
             PointerCast(bcx, llfn, llty)
         }
@@ -246,13 +251,13 @@ pub fn method_with_name(ccx: &CrateContext,
 }
 
 fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
-                                  callee_id: ast::NodeId,
+                                  expr_id: ast::NodeId,
                                   trait_id: ast::DefId,
                                   n_method: uint,
                                   vtbl: typeck::vtable_origin)
                                   -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_monomorphized_callee");
-    return match vtbl {
+    match vtbl {
       typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
           let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
@@ -262,13 +267,14 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
           // those from the impl and those from the method:
           let (callee_substs, callee_origins) =
               combine_impl_and_methods_tps(
-                  bcx, mth_id, callee_id,
+                  bcx, mth_id, expr_id, true,
                   *rcvr_substs, rcvr_origins);
 
           // translate the function
           let llfn = trans_fn_ref_with_vtables(bcx,
                                                mth_id,
-                                               callee_id,
+                                               expr_id,
+                                               true,
                                                callee_substs,
                                                Some(callee_origins));
 
@@ -277,16 +283,16 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
       typeck::vtable_param(..) => {
           fail!("vtable_param left in monomorphized function's vtable substs");
       }
-    };
-
+    }
 }
 
-pub fn combine_impl_and_methods_tps(bcx: &Block,
-                                    mth_did: ast::DefId,
-                                    callee_id: ast::NodeId,
-                                    rcvr_substs: &[ty::t],
-                                    rcvr_origins: typeck::vtable_res)
-                                    -> (~[ty::t], typeck::vtable_res) {
+fn combine_impl_and_methods_tps(bcx: &Block,
+                                mth_did: ast::DefId,
+                                expr_id: ast::NodeId,
+                                is_method: bool,
+                                rcvr_substs: &[ty::t],
+                                rcvr_origins: typeck::vtable_res)
+                                -> (~[ty::t], typeck::vtable_res) {
     /*!
     *
     * Creates a concatenated set of substitutions which includes
@@ -307,7 +313,7 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
     let ccx = bcx.ccx();
     let method = ty::method(ccx.tcx, mth_did);
     let n_m_tps = method.generics.type_param_defs().len();
-    let node_substs = node_id_type_params(bcx, callee_id);
+    let node_substs = node_id_type_params(bcx, expr_id, is_method);
     debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx));
     let ty_substs
         = vec::append(rcvr_substs.to_owned(),
@@ -319,7 +325,7 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
 
     // Now, do the same work for the vtables.  The vtables might not
     // exist, in which case we need to make them.
-    let r_m_origins = match node_vtables(bcx, callee_id) {
+    let r_m_origins = match node_vtables(bcx, expr_id) {
         Some(vt) => vt,
         None => @vec::from_elem(node_substs.len(), @~[])
     };
@@ -327,11 +333,11 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
         = @vec::append(rcvr_origins.to_owned(),
                        r_m_origins.tailn(r_m_origins.len() - n_m_tps));
 
-    return (ty_substs, vtables);
+    (ty_substs, vtables)
 }
 
 fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
-                          callee_id: ast::NodeId,
+                          method_ty: ty::t,
                           n_method: uint,
                           self_expr: &ast::Expr,
                           arg_cleanup_scope: cleanup::ScopeId)
@@ -371,8 +377,7 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
         self_datum.val
     };
 
-    let callee_ty = node_id_type(bcx, callee_id);
-    trans_trait_callee_from_llval(bcx, callee_ty, n_method, llval)
+    trans_trait_callee_from_llval(bcx, method_ty, n_method, llval)
 }
 
 pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
@@ -540,7 +545,7 @@ fn emit_vtable_methods(bcx: &Block,
                    token::get_ident(ident));
             C_null(Type::nil().ptr_to())
         } else {
-            trans_fn_ref_with_vtables(bcx, m_id, 0, substs, Some(vtables))
+            trans_fn_ref_with_vtables(bcx, m_id, 0, false, substs, Some(vtables))
         }
     })
 }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 488287e1c68..7e047ae8c10 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -33,8 +33,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                       vtables: Option<typeck::vtable_res>,
                       self_vtables: Option<typeck::vtable_param_res>,
                       ref_id: Option<ast::NodeId>)
-    -> (ValueRef, bool)
-{
+    -> (ValueRef, bool) {
     debug!("monomorphic_fn(\
             fn_id={}, \
             real_substs={}, \
@@ -280,7 +279,6 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         ast_map::NodeStmt(..) |
         ast_map::NodeArg(..) |
         ast_map::NodeBlock(..) |
-        ast_map::NodeCalleeScope(..) |
         ast_map::NodeLocal(..) => {
             ccx.tcx.sess.bug(format!("can't monomorphize a {:?}", map_node))
         }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index c3b9b898de2..6db83ff32b6 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3254,19 +3254,19 @@ pub fn expr_has_ty_params(cx: ctxt, expr: &ast::Expr) -> bool {
     return node_id_has_type_params(cx, expr.id);
 }
 
-pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::method_origin)
+pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::MethodOrigin)
                                    -> Rc<~[TypeParameterDef]> {
     match origin {
-        typeck::method_static(did) => {
+        typeck::MethodStatic(did) => {
             // n.b.: When we encode impl methods, the bounds
             // that we encode include both the impl bounds
             // and then the method bounds themselves...
             ty::lookup_item_type(tcx, did).generics.type_param_defs
         }
-        typeck::method_param(typeck::method_param {
+        typeck::MethodParam(typeck::MethodParam {
             trait_id: trt_id,
             method_num: n_mth, ..}) |
-        typeck::method_object(typeck::method_object {
+        typeck::MethodObject(typeck::MethodObject {
             trait_id: trt_id,
             method_num: n_mth, ..}) => {
             // ...trait methods bounds, in contrast, include only the
@@ -3295,7 +3295,7 @@ pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def {
 }
 
 pub fn expr_is_lval(tcx: ctxt,
-                    method_map: typeck::method_map,
+                    method_map: typeck::MethodMap,
                     e: &ast::Expr) -> bool {
     match expr_kind(tcx, method_map, e) {
         LvalueExpr => true,
@@ -3316,7 +3316,7 @@ pub enum ExprKind {
 }
 
 pub fn expr_kind(tcx: ctxt,
-                 method_map: typeck::method_map,
+                 method_map: typeck::MethodMap,
                  expr: &ast::Expr) -> ExprKind {
     {
         let method_map = method_map.borrow();
@@ -3372,7 +3372,7 @@ pub fn expr_kind(tcx: ctxt,
             }
         }
 
-        ast::ExprUnary(_, ast::UnDeref, _) |
+        ast::ExprUnary(ast::UnDeref, _) |
         ast::ExprField(..) |
         ast::ExprIndex(..) => {
             LvalueExpr
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 4695521d0d9..aff41ce1979 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -89,8 +89,9 @@ use middle::typeck::check::{structurally_resolved_type};
 use middle::typeck::check::vtable;
 use middle::typeck::check;
 use middle::typeck::infer;
-use middle::typeck::{method_origin, method_param};
-use middle::typeck::{method_static, method_object};
+use middle::typeck::MethodCallee;
+use middle::typeck::{MethodOrigin, MethodParam};
+use middle::typeck::{MethodStatic, MethodObject};
 use middle::typeck::{param_numbered, param_self, param_index};
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
 use util::common::indenter;
@@ -101,7 +102,7 @@ use collections::HashSet;
 use std::result;
 use std::vec;
 use syntax::ast::{DefId, SelfValue, SelfRegion};
-use syntax::ast::{SelfUniq, SelfStatic, NodeId};
+use syntax::ast::{SelfUniq, SelfStatic};
 use syntax::ast::{MutMutable, MutImmutable};
 use syntax::ast;
 use syntax::parse::token;
@@ -124,20 +125,17 @@ pub fn lookup(
         // In a call `a.b::<X, Y, ...>(...)`:
         expr: &ast::Expr,                   // The expression `a.b(...)`.
         self_expr: &ast::Expr,              // The expression `a`.
-        callee_id: NodeId,                  /* Where to store `a.b`'s type,
-                                             * also the scope of the call */
         m_name: ast::Name,                  // The name `b`.
         self_ty: ty::t,                     // The type of `a`.
         supplied_tps: &[ty::t],             // The list of types X, Y, ... .
         deref_args: check::DerefArgs,       // Whether we autopointer first.
         check_traits: CheckTraitsFlag,      // Whether we check traits only.
         autoderef_receiver: AutoderefReceiverFlag)
-     -> Option<method_origin> {
+     -> Option<MethodCallee> {
     let lcx = LookupContext {
         fcx: fcx,
         expr: expr,
         self_expr: self_expr,
-        callee_id: callee_id,
         m_name: m_name,
         supplied_tps: supplied_tps,
         impl_dups: @RefCell::new(HashSet::new()),
@@ -173,19 +171,16 @@ pub fn lookup_in_trait(
         // In a call `a.b::<X, Y, ...>(...)`:
         expr: &ast::Expr,                   // The expression `a.b(...)`.
         self_expr: &ast::Expr,              // The expression `a`.
-        callee_id: NodeId,                  /* Where to store `a.b`'s type,
-                                             * also the scope of the call */
         m_name: ast::Name,                  // The name `b`.
         trait_did: DefId,                   // The trait to limit the lookup to.
         self_ty: ty::t,                     // The type of `a`.
         supplied_tps: &[ty::t],             // The list of types X, Y, ... .
         autoderef_receiver: AutoderefReceiverFlag)
-     -> Option<method_origin> {
+     -> Option<MethodCallee> {
     let lcx = LookupContext {
         fcx: fcx,
         expr: expr,
         self_expr: self_expr,
-        callee_id: callee_id,
         m_name: m_name,
         supplied_tps: supplied_tps,
         impl_dups: @RefCell::new(HashSet::new()),
@@ -210,7 +205,6 @@ pub struct LookupContext<'a> {
     fcx: @FnCtxt,
     expr: &'a ast::Expr,
     self_expr: &'a ast::Expr,
-    callee_id: NodeId,
     m_name: ast::Name,
     supplied_tps: &'a [ty::t],
     impl_dups: @RefCell<HashSet<DefId>>,
@@ -230,7 +224,7 @@ pub struct Candidate {
     rcvr_match_condition: RcvrMatchCondition,
     rcvr_substs: ty::substs,
     method_ty: @ty::Method,
-    origin: method_origin,
+    origin: MethodOrigin,
 }
 
 /// This type represents the conditions under which the receiver is
@@ -248,7 +242,7 @@ enum RcvrMatchCondition {
 }
 
 impl<'a> LookupContext<'a> {
-    fn search(&self, self_ty: ty::t) -> Option<method_origin> {
+    fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
         let mut self_ty = self_ty;
         let mut autoderefs = 0;
         loop {
@@ -464,7 +458,7 @@ impl<'a> LookupContext<'a> {
                 rcvr_match_condition: RcvrMatchesIfObject(did),
                 rcvr_substs: new_trait_ref.substs.clone(),
                 method_ty: @m,
-                origin: method_object(method_object {
+                origin: MethodObject(MethodObject {
                         trait_id: new_trait_ref.def_id,
                         object_trait_id: did,
                         method_num: method_num,
@@ -518,7 +512,7 @@ impl<'a> LookupContext<'a> {
                     rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
                     rcvr_substs: trait_ref.substs.clone(),
                     method_ty: m,
-                    origin: method_param(method_param {
+                    origin: MethodParam(MethodParam {
                         trait_id: trait_ref.def_id,
                         method_num: method_num,
                         param_num: param,
@@ -626,7 +620,7 @@ impl<'a> LookupContext<'a> {
             rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
             method_ty: method,
-            origin: method_static(method.def_id)
+            origin: MethodStatic(method.def_id)
         });
     }
 
@@ -636,7 +630,7 @@ impl<'a> LookupContext<'a> {
     fn search_for_autoderefd_method(&self,
                                         self_ty: ty::t,
                                         autoderefs: uint)
-                                        -> Option<method_origin> {
+                                        -> Option<MethodCallee> {
         let (self_ty, autoadjust) =
             self.consider_reborrow(self_ty, autoderefs);
         match self.search_for_method(self_ty) {
@@ -732,7 +726,7 @@ impl<'a> LookupContext<'a> {
     fn search_for_autosliced_method(&self,
                                     self_ty: ty::t,
                                     autoderefs: uint)
-                                    -> Option<method_origin> {
+                                    -> Option<MethodCallee> {
         /*!
          *
          * Searches for a candidate by converting things like
@@ -807,7 +801,7 @@ impl<'a> LookupContext<'a> {
     }
 
     fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
-                                  -> Option<method_origin> {
+                                  -> Option<MethodCallee> {
         /*!
          *
          * Converts any type `T` to `&M T` where `M` is an
@@ -843,7 +837,7 @@ impl<'a> LookupContext<'a> {
             autoderefs: uint,
             mutbls: &[ast::Mutability],
             mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
-            -> Option<method_origin> {
+            -> Option<MethodCallee> {
         // This is hokey. We should have mutability inference as a
         // variable.  But for now, try &const, then &, then &mut:
         let region =
@@ -867,7 +861,7 @@ impl<'a> LookupContext<'a> {
     }
 
     fn search_for_method(&self, rcvr_ty: ty::t)
-                         -> Option<method_origin> {
+                         -> Option<MethodCallee> {
         debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
         let _indenter = indenter();
 
@@ -899,7 +893,7 @@ impl<'a> LookupContext<'a> {
     fn consider_candidates(&self,
                            rcvr_ty: ty::t,
                            candidates: &mut ~[Candidate])
-                           -> Option<method_origin> {
+                           -> Option<MethodCallee> {
         // FIXME(pcwalton): Do we need to clone here?
         let relevant_candidates: ~[Candidate] =
             candidates.iter().map(|c| (*c).clone()).
@@ -938,7 +932,7 @@ impl<'a> LookupContext<'a> {
                        candidate_a, candidate_b);
                 let candidates_same = match (&candidate_a.origin,
                                              &candidate_b.origin) {
-                    (&method_param(ref p1), &method_param(ref p2)) => {
+                    (&MethodParam(ref p1), &MethodParam(ref p2)) => {
                         let same_trait = p1.trait_id == p2.trait_id;
                         let same_method = p1.method_num == p2.method_num;
                         let same_param = p1.param_num == p2.param_num;
@@ -970,7 +964,7 @@ impl<'a> LookupContext<'a> {
     }
 
     fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
-                         -> method_origin {
+                         -> MethodCallee {
         // This method performs two sets of substitutions, one after the other:
         // 1. Substitute values for any type/lifetime parameters from the impl and
         //    method declaration into the method type. This is the function type
@@ -1031,7 +1025,7 @@ impl<'a> LookupContext<'a> {
 
         let fn_sig = &bare_fn_ty.sig;
         let inputs = match candidate.origin {
-            method_object(..) => {
+            MethodObject(..) => {
                 // For annoying reasons, we've already handled the
                 // substitution of self for object calls.
                 let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
@@ -1079,9 +1073,11 @@ impl<'a> LookupContext<'a> {
             }
         }
 
-        self.fcx.write_ty(self.callee_id, fty);
-        self.fcx.write_substs(self.callee_id, all_substs);
-        candidate.origin
+        MethodCallee {
+            origin: candidate.origin,
+            ty: fty,
+            substs: all_substs
+        }
     }
 
     fn construct_transformed_self_ty_for_object(
@@ -1154,10 +1150,10 @@ impl<'a> LookupContext<'a> {
          */
 
         match candidate.origin {
-            method_static(..) | method_param(..) => {
+            MethodStatic(..) | MethodParam(..) => {
                 return; // not a call to a trait instance
             }
-            method_object(..) => {}
+            MethodObject(..) => {}
         }
 
         match candidate.method_ty.explicit_self {
@@ -1213,14 +1209,14 @@ impl<'a> LookupContext<'a> {
         // No code can call the finalize method explicitly.
         let bad;
         match candidate.origin {
-            method_static(method_id) => {
+            MethodStatic(method_id) => {
                 let destructors = self.tcx().destructors.borrow();
                 bad = destructors.get().contains(&method_id);
             }
             // FIXME: does this properly enforce this on everything now
             // that self has been merged in? -sully
-            method_param(method_param { trait_id: trait_id, .. }) |
-            method_object(method_object { trait_id: trait_id, .. }) => {
+            MethodParam(MethodParam { trait_id: trait_id, .. }) |
+            MethodObject(MethodObject { trait_id: trait_id, .. }) => {
                 let destructor_for_type = self.tcx()
                                               .destructor_for_type
                                               .borrow();
@@ -1316,9 +1312,9 @@ impl<'a> LookupContext<'a> {
         }
     }
 
-    fn report_candidate(&self, idx: uint, origin: &method_origin) {
+    fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
         match *origin {
-            method_static(impl_did) => {
+            MethodStatic(impl_did) => {
                 // If it is an instantiated default method, use the original
                 // default method for error reporting.
                 let did = match provided_source(self.tcx(), impl_did) {
@@ -1327,10 +1323,10 @@ impl<'a> LookupContext<'a> {
                 };
                 self.report_static_candidate(idx, did)
             }
-            method_param(ref mp) => {
+            MethodParam(ref mp) => {
                 self.report_param_candidate(idx, (*mp).trait_id)
             }
-            method_object(ref mo) => {
+            MethodObject(ref mo) => {
                 self.report_trait_candidate(idx, mo.trait_id)
             }
         }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 0b26bb1b218..9b8ce481de9 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -106,7 +106,7 @@ use middle::typeck::infer;
 use middle::typeck::rscope::RegionScope;
 use middle::typeck::{lookup_def_ccx};
 use middle::typeck::no_params;
-use middle::typeck::{require_same_types, method_map, vtable_map};
+use middle::typeck::{require_same_types, MethodMap, vtable_map};
 use middle::lang_items::TypeIdLangItem;
 use util::common::{block_query, indenter, loop_query};
 use util::ppaux;
@@ -160,7 +160,7 @@ pub struct Inherited {
     node_types: RefCell<HashMap<ast::NodeId, ty::t>>,
     node_type_substs: RefCell<HashMap<ast::NodeId, ty::substs>>,
     adjustments: RefCell<HashMap<ast::NodeId, @ty::AutoAdjustment>>,
-    method_map: method_map,
+    method_map: MethodMap,
     vtable_map: vtable_map,
     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
 }
@@ -1088,8 +1088,7 @@ impl FnCtxt {
     }
 
     pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
-        let node_types = self.inh.node_types.borrow();
-        match node_types.get().find(&id) {
+        match self.inh.node_types.borrow().get().find(&id) {
             Some(&t) => t,
             None => {
                 self.tcx().sess.bug(
@@ -1100,9 +1099,20 @@ impl FnCtxt {
         }
     }
 
+    pub fn method_ty(&self, id: ast::NodeId) -> ty::t {
+        match self.inh.method_map.borrow().get().find(&id) {
+            Some(method) => method.ty,
+            None => {
+                self.tcx().sess.bug(
+                    format!("no method entry for node {}: {} in fcx {}",
+                            id, self.tcx().map.node_to_str(id),
+                            self.tag()));
+            }
+        }
+    }
+
     pub fn node_ty_substs(&self, id: ast::NodeId) -> ty::substs {
-        let mut node_type_substs = self.inh.node_type_substs.borrow_mut();
-        match node_type_substs.get().find(&id) {
+        match self.inh.node_type_substs.borrow().get().find(&id) {
             Some(ts) => (*ts).clone(),
             None => {
                 self.tcx().sess.bug(
@@ -1113,6 +1123,18 @@ impl FnCtxt {
         }
     }
 
+    pub fn method_ty_substs(&self, id: ast::NodeId) -> ty::substs {
+        match self.inh.method_map.borrow().get().find(&id) {
+            Some(method) => method.substs.clone(),
+            None => {
+                self.tcx().sess.bug(
+                    format!("no method entry for node {}: {} in fcx {}",
+                            id, self.tcx().map.node_to_str(id),
+                            self.tag()));
+            }
+        }
+    }
+
     pub fn opt_node_ty_substs(&self,
                               id: ast::NodeId,
                               f: |&ty::substs| -> bool)
@@ -1776,7 +1798,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
     // A generic function for doing all of the checking for call expressions
     fn check_call(fcx: @FnCtxt,
-                  callee_id: ast::NodeId,
                   call_expr: &ast::Expr,
                   f: &ast::Expr,
                   args: &[@ast::Expr]) {
@@ -1787,13 +1808,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         // Store the type of `f` as the type of the callee
         let fn_ty = fcx.expr_ty(f);
 
-        // FIXME(#6273) should write callee type AFTER regions have
-        // been subst'd.  However, it is awkward to deal with this
-        // 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(callee_id, fn_ty);
-
         // Extract the function signature from `in_fty`.
         let fn_sty = structure_of(fcx, f.span, fn_ty);
 
@@ -1834,7 +1848,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
     // Checks a method call.
     fn check_method_call(fcx: @FnCtxt,
-                         callee_id: ast::NodeId,
                          expr: &ast::Expr,
                          method_name: ast::Ident,
                          args: &[@ast::Expr],
@@ -1848,20 +1861,16 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                                                 fcx.expr_ty(rcvr));
 
         let tps = tps.map(|&ast_ty| fcx.to_ty(ast_ty));
-        match method::lookup(fcx,
-                             expr,
-                             rcvr,
-                             callee_id,
-                             method_name.name,
-                             expr_t,
-                             tps,
-                             DontDerefArgs,
-                             CheckTraitsAndInherentMethods,
-                             AutoderefReceiver) {
-            Some(ref entry) => {
-                let method_map = fcx.inh.method_map;
-                let mut method_map = method_map.borrow_mut();
-                method_map.get().insert(expr.id, (*entry));
+        let fn_ty = match method::lookup(fcx, expr, rcvr,
+                                         method_name.name,
+                                         expr_t, tps,
+                                         DontDerefArgs,
+                                         CheckTraitsAndInherentMethods,
+                                         AutoderefReceiver) {
+            Some(method) => {
+                let method_ty = method.ty;
+                fcx.inh.method_map.borrow_mut().get().insert(expr.id, method);
+                method_ty
             }
             None => {
                 debug!("(checking method call) failing expr is {}", expr.id);
@@ -1877,12 +1886,11 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
                 // Add error type for the result
                 fcx.write_error(expr.id);
-                fcx.write_error(callee_id);
+                ty::mk_err()
             }
-        }
+        };
 
         // Call the generic checker.
-        let fn_ty = fcx.node_ty(callee_id);
         let ret_ty = check_method_argument_types(fcx, expr.span,
                                                  fn_ty, expr, args,
                                                  DontDerefArgs);
@@ -1932,7 +1940,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
     }
 
     fn lookup_op_method(fcx: @FnCtxt,
-                        callee_id: ast::NodeId,
                         op_ex: &ast::Expr,
                         self_t: ty::t,
                         opname: ast::Name,
@@ -1940,18 +1947,17 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                         args: &[@ast::Expr],
                         autoderef_receiver: AutoderefReceiverFlag,
                         unbound_method: ||) -> ty::t {
-        let origin = match trait_did {
+        let method = match trait_did {
             Some(trait_did) => {
-                method::lookup_in_trait(fcx, op_ex, args[0], callee_id, opname,
-                                        trait_did, self_t, [], autoderef_receiver)
+                method::lookup_in_trait(fcx, op_ex, args[0], opname, trait_did,
+                                        self_t, [], autoderef_receiver)
             }
             None => None
         };
-        match origin {
-            Some(origin) => {
-                let method_ty = fcx.node_ty(callee_id);
-                let method_map = fcx.inh.method_map;
-                method_map.borrow_mut().get().insert(op_ex.id, origin);
+        match method {
+            Some(method) => {
+                let method_ty = method.ty;
+                fcx.inh.method_map.borrow_mut().get().insert(op_ex.id, method);
                 check_method_argument_types(fcx, op_ex.span,
                                             method_ty, op_ex,
                                             args, DoDerefArgs)
@@ -1971,7 +1977,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
     // could be either an expr_binop or an expr_assign_binop
     fn check_binop(fcx: @FnCtxt,
-                   callee_id: ast::NodeId,
                    expr: &ast::Expr,
                    op: ast::BinOp,
                    lhs: @ast::Expr,
@@ -2023,7 +2028,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
 
         // Check for overloaded operators if not an assignment.
         let result_t = if is_binop_assignment == SimpleBinop {
-            check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs)
+            check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
         } else {
             fcx.type_error_message(expr.span,
                                    |actual| {
@@ -2045,7 +2050,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
     }
 
     fn check_user_binop(fcx: @FnCtxt,
-                        callee_id: ast::NodeId,
                         ex: &ast::Expr,
                         lhs_expr: @ast::Expr,
                         lhs_resolved_t: ty::t,
@@ -2075,7 +2079,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                 return ty::mk_err();
             }
         };
-        lookup_op_method(fcx, callee_id, ex, lhs_resolved_t, token::intern(name),
+        lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
                          trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
             fcx.type_error_message(ex.span, |actual| {
                 format!("binary operation `{}` cannot be applied to type `{}`",
@@ -2085,14 +2089,13 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
     }
 
     fn check_user_unop(fcx: @FnCtxt,
-                       callee_id: ast::NodeId,
                        op_str: &str,
                        mname: &str,
                        trait_did: Option<ast::DefId>,
                        ex: &ast::Expr,
                        rhs_expr: @ast::Expr,
                        rhs_t: ty::t) -> ty::t {
-       lookup_op_method(fcx, callee_id, ex, rhs_t, token::intern(mname),
+       lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
                         trait_did, [rhs_expr], DontAutoderefReceiver, || {
             fcx.type_error_message(ex.span, |actual| {
                 format!("cannot apply unary operator `{}` to type `{}`", op_str, actual)
@@ -2264,7 +2267,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         match method::lookup(fcx,
                              expr,
                              base,
-                             expr.id,
                              field,
                              expr_t,
                              tps,
@@ -2620,8 +2622,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         let typ = check_lit(fcx, lit);
         fcx.write_ty(id, typ);
       }
-      ast::ExprBinary(callee_id, op, lhs, rhs) => {
-        check_binop(fcx, callee_id, expr, op, lhs, rhs, SimpleBinop);
+      ast::ExprBinary(op, lhs, rhs) => {
+        check_binop(fcx, expr, op, lhs, rhs, SimpleBinop);
 
         let lhs_ty = fcx.expr_ty(lhs);
         let rhs_ty = fcx.expr_ty(rhs);
@@ -2634,8 +2636,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             fcx.write_bot(id);
         }
       }
-      ast::ExprAssignOp(callee_id, op, lhs, rhs) => {
-        check_binop(fcx, callee_id, expr, op, lhs, rhs, BinopAssignment);
+      ast::ExprAssignOp(op, lhs, rhs) => {
+        check_binop(fcx, expr, op, lhs, rhs, BinopAssignment);
 
         let lhs_t = fcx.expr_ty(lhs);
         let result_t = fcx.expr_ty(expr);
@@ -2654,7 +2656,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             fcx.write_nil(expr.id);
         }
       }
-      ast::ExprUnary(callee_id, unop, oprnd) => {
+      ast::ExprUnary(unop, oprnd) => {
         let exp_inner = unpack_expected(fcx, expected, |sty| {
             match unop {
                 ast::UnBox | ast::UnUniq => match *sty {
@@ -2710,7 +2712,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
                          ty::get(oprnd_t).sty == ty::ty_bool) {
-                        oprnd_t = check_user_unop(fcx, callee_id, "!", "not",
+                        oprnd_t = check_user_unop(fcx, "!", "not",
                                                   tcx.lang_items.not_trait(),
                                                   expr, oprnd, oprnd_t);
                     }
@@ -2720,7 +2722,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
                          ty::type_is_fp(oprnd_t)) {
-                        oprnd_t = check_user_unop(fcx, callee_id, "-", "neg",
+                        oprnd_t = check_user_unop(fcx, "-", "neg",
                                                   tcx.lang_items.neg_trait(),
                                                   expr, oprnd, oprnd_t);
                     }
@@ -2883,7 +2885,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         fcx.write_ty(id, fcx.node_ty(b.id));
       }
       ast::ExprCall(f, ref args) => {
-          check_call(fcx, expr.id, expr, f, *args);
+          check_call(fcx, expr, f, *args);
           let f_ty = fcx.expr_ty(f);
           let (args_bot, args_err) = args.iter().fold((false, false),
              |(rest_bot, rest_err), a| {
@@ -2898,8 +2900,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
               fcx.write_bot(id);
           }
       }
-      ast::ExprMethodCall(callee_id, ident, ref tps, ref args) => {
-        check_method_call(fcx, callee_id, expr, ident, *args, *tps);
+      ast::ExprMethodCall(ident, ref tps, ref args) => {
+        check_method_call(fcx, expr, ident, *args, *tps);
         let arg_tys = args.map(|a| fcx.expr_ty(*a));
         let (args_bot, args_err) = arg_tys.iter().fold((false, false),
              |(rest_bot, rest_err), a| {
@@ -3100,7 +3102,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
       ast::ExprField(base, field, ref tys) => {
         check_field(fcx, expr, base, field.name, *tys);
       }
-      ast::ExprIndex(callee_id, base, idx) => {
+      ast::ExprIndex(base, idx) => {
           check_expr(fcx, base);
           check_expr(fcx, idx);
           let raw_base_t = fcx.expr_ty(base);
@@ -3133,7 +3135,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
                                                None);
                       };
                       let ret_ty = lookup_op_method(fcx,
-                                                    callee_id,
                                                     expr,
                                                     resolved,
                                                     token::intern("index"),
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 38400772778..5e2ad9fc35b 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -226,6 +226,12 @@ impl Rcx {
         self.resolve_type(t)
     }
 
+    /// Try to resolve the callee type for the given method call.
+    pub fn resolve_method_type(&mut self, id: ast::NodeId) -> ty::t {
+        let t = self.fcx.method_ty(id);
+        self.resolve_type(t)
+    }
+
     /// Try to resolve the type for the given node.
     pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
         let ty_unadjusted = self.resolve_node_type(expr.id);
@@ -378,10 +384,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
            expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
 
-    let has_method_map = {
-        let method_map = rcx.fcx.inh.method_map;
-        method_map.get().contains_key(&expr.id)
-    };
+    let has_method_map = rcx.fcx.inh.method_map.get().contains_key(&expr.id);
 
     // Check any autoderefs or autorefs that appear.
     {
@@ -434,13 +437,13 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     match expr.node {
         ast::ExprCall(callee, ref args) => {
             constrain_callee(rcx, callee.id, expr, callee);
-            constrain_call(rcx, callee.id, expr, None, *args, false);
+            constrain_call(rcx, Some(callee.id), expr, None, *args, false);
 
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprMethodCall(callee_id, _, _, ref args) => {
-            constrain_call(rcx, callee_id, expr, Some(args[0]),
+        ast::ExprMethodCall(_, _, ref args) => {
+            constrain_call(rcx, None, expr, Some(args[0]),
                            args.slice_from(1), false);
 
             visit::walk_expr(rcx, expr, ());
@@ -451,9 +454,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprAssignOp(callee_id, _, lhs, rhs) => {
+        ast::ExprAssignOp(_, lhs, rhs) => {
             if has_method_map {
-                constrain_call(rcx, callee_id, expr, Some(lhs), [rhs], true);
+                constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
             }
 
             adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
@@ -461,25 +464,25 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprIndex(callee_id, lhs, rhs) |
-        ast::ExprBinary(callee_id, _, lhs, rhs) if has_method_map => {
+        ast::ExprIndex(lhs, rhs) |
+        ast::ExprBinary(_, 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, callee_id, expr, Some(lhs), [rhs], true);
+            constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
 
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprUnary(callee_id, _, lhs) if has_method_map => {
+        ast::ExprUnary(_, lhs) if has_method_map => {
             // As above.
-            constrain_call(rcx, callee_id, expr, Some(lhs), [], true);
+            constrain_call(rcx, None, expr, Some(lhs), [], true);
 
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprUnary(_, ast::UnDeref, base) => {
+        ast::ExprUnary(ast::UnDeref, 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);
@@ -487,7 +490,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             visit::walk_expr(rcx, expr, ());
         }
 
-        ast::ExprIndex(_, vec_expr, _) => {
+        ast::ExprIndex(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);
@@ -711,8 +714,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 fn constrain_callee(rcx: &mut Rcx,
                     callee_id: ast::NodeId,
                     call_expr: &ast::Expr,
-                    callee_expr: &ast::Expr)
-{
+                    callee_expr: &ast::Expr) {
     let call_region = ty::ReScope(call_expr.id);
 
     let callee_ty = rcx.resolve_node_type(callee_id);
@@ -736,12 +738,11 @@ 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::NodeId,
+                  fn_expr_id: Option<ast::NodeId>,
                   call_expr: &ast::Expr,
                   receiver: Option<@ast::Expr>,
                   arg_exprs: &[@ast::Expr],
-                  implicitly_ref_args: bool)
-{
+                  implicitly_ref_args: bool) {
     //! Invoked on every call site (i.e., normal calls, method calls,
     //! and overloaded operators). Constrains the regions which appear
     //! in the type of the function. Also constrains the regions that
@@ -756,7 +757,10 @@ fn constrain_call(rcx: &mut Rcx,
             receiver.repr(tcx),
             arg_exprs.repr(tcx),
             implicitly_ref_args);
-    let callee_ty = rcx.resolve_node_type(callee_id);
+    let callee_ty = match fn_expr_id {
+        Some(id) => rcx.resolve_node_type(id),
+        None => rcx.resolve_method_type(call_expr.id)
+    };
     if ty::type_is_error(callee_ty) {
         // Bail, as function type is unknown
         return;
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 588dbec8a83..a9ea968fe1d 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -537,11 +537,10 @@ fn connect_trait_tps(vcx: &VtableContext,
     relate_trait_refs(vcx, location_info, impl_trait_ref, trait_ref);
 }
 
-fn insert_vtables(fcx: &FnCtxt, callee_id: ast::NodeId, vtables: vtable_res) {
-    debug!("insert_vtables(callee_id={}, vtables={:?})",
-           callee_id, vtables.repr(fcx.tcx()));
-    let mut vtable_map = fcx.inh.vtable_map.borrow_mut();
-    vtable_map.get().insert(callee_id, vtables);
+fn insert_vtables(fcx: &FnCtxt, expr_id: ast::NodeId, vtables: vtable_res) {
+    debug!("insert_vtables(expr_id={}, vtables={:?})",
+           expr_id, vtables.repr(fcx.tcx()));
+    fcx.inh.vtable_map.borrow_mut().get().insert(expr_id, vtables);
 }
 
 pub fn location_info_for_expr(expr: &ast::Expr) -> LocationInfo {
@@ -692,23 +691,23 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
       }
 
       // Must resolve bounds on methods with bounded params
-      ast::ExprBinary(callee_id, _, _, _) |
-      ast::ExprUnary(callee_id, _, _) |
-      ast::ExprAssignOp(callee_id, _, _, _) |
-      ast::ExprIndex(callee_id, _, _) |
-      ast::ExprMethodCall(callee_id, _, _, _) => {
+      ast::ExprBinary(_, _, _) |
+      ast::ExprUnary(_, _) |
+      ast::ExprAssignOp(_, _, _) |
+      ast::ExprIndex(_, _) |
+      ast::ExprMethodCall(_, _, _) => {
         match fcx.inh.method_map.borrow().get().find(&ex.id) {
-          Some(origin) => {
+          Some(method) => {
             debug!("vtable resolution on parameter bounds for method call {}",
                    ex.repr(fcx.tcx()));
-            let type_param_defs = ty::method_call_type_param_defs(cx.tcx, *origin);
+            let type_param_defs = ty::method_call_type_param_defs(cx.tcx, method.origin);
             if has_trait_bounds(*type_param_defs.borrow()) {
-                let substs = fcx.node_ty_substs(callee_id);
+                let substs = fcx.method_ty_substs(ex.id);
                 let vcx = fcx.vtable_context();
                 let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
                                            *type_param_defs.borrow(), &substs, is_early);
                 if !is_early {
-                    insert_vtables(fcx, callee_id, vtbls);
+                    insert_vtables(fcx, ex.id, vtbls);
                 }
             }
           }
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index c05afcf859a..ec230761d35 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -20,6 +20,7 @@ use middle::typeck::check::FnCtxt;
 use middle::typeck::infer::{force_all, resolve_all, resolve_region};
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
+use middle::typeck::MethodCallee;
 use middle::typeck::{vtable_res, vtable_origin};
 use middle::typeck::{vtable_static, vtable_param};
 use middle::typeck::write_substs_to_tcx;
@@ -61,39 +62,54 @@ fn resolve_type_vars_in_types(fcx: @FnCtxt, sp: Span, tys: &[ty::t])
     })
 }
 
-fn resolve_method_map_entry(fcx: @FnCtxt, id: ast::NodeId) {
+fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
+    let fcx = wbcx.fcx;
+    let tcx = fcx.ccx.tcx;
+
     // Resolve any method map entry
-    let method_map_entry_opt = {
-        let method_map = fcx.inh.method_map.borrow();
-        method_map.get().find_copy(&id)
-    };
-    match method_map_entry_opt {
-        None => {}
-        Some(mme) => {
-            debug!("writeback::resolve_method_map_entry(id={:?}, entry={:?})", id, mme);
-            let mut method_map = fcx.ccx.method_map.borrow_mut();
-            method_map.get().insert(id, mme);
+    match fcx.inh.method_map.borrow().get().find(&id) {
+        Some(method) => {
+            debug!("writeback::resolve_method_map_entry(id={:?}, entry={:?})",
+                   id, method.repr(tcx));
+            let method_ty = match resolve_type_vars_in_type(fcx, sp, method.ty) {
+                Some(t) => t,
+                None => {
+                    wbcx.success = false;
+                    return;
+                }
+            };
+            let mut new_tps = ~[];
+            for &subst in method.substs.tps.iter() {
+                match resolve_type_vars_in_type(fcx, sp, subst) {
+                    Some(t) => new_tps.push(t),
+                    None => { wbcx.success = false; return; }
+                }
+            }
+            let new_method = MethodCallee {
+                origin: method.origin,
+                ty: method_ty,
+                substs: ty::substs {
+                    tps: new_tps,
+                    regions: ty::ErasedRegions,
+                    self_ty: None
+                }
+            };
+            fcx.ccx.method_map.borrow_mut().get().insert(id, new_method);
         }
+        None => {}
     }
 }
 
 fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
-    // Resolve any method map entry
-    {
-        let origins_opt = {
-            let vtable_map = fcx.inh.vtable_map.borrow();
-            vtable_map.get().find_copy(&id)
-        };
-        match origins_opt {
-            None => {}
-            Some(origins) => {
-                let r_origins = resolve_origins(fcx, sp, origins);
-                let mut vtable_map = fcx.ccx.vtable_map.borrow_mut();
-                vtable_map.get().insert(id, r_origins);
-                debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
-                       id, r_origins.repr(fcx.tcx()));
-            }
+    // Resolve any vtable map entry
+    match fcx.inh.vtable_map.borrow().get().find_copy(&id) {
+        Some(origins) => {
+            let r_origins = resolve_origins(fcx, sp, origins);
+            fcx.ccx.vtable_map.borrow_mut().get().insert(id, r_origins);
+            debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
+                    id, r_origins.repr(fcx.tcx()));
         }
+        None => {}
     }
 
     fn resolve_origins(fcx: @FnCtxt, sp: Span,
@@ -241,21 +257,6 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
     }
 }
 
-fn maybe_resolve_type_vars_for_node(wbcx: &mut WbCtxt,
-                                    sp: Span,
-                                    id: ast::NodeId)
-                                 -> Option<ty::t> {
-    let contained = {
-        let node_types = wbcx.fcx.inh.node_types.borrow();
-        node_types.get().contains_key(&id)
-    };
-    if contained {
-        resolve_type_vars_for_node(wbcx, sp, id)
-    } else {
-        None
-    }
-}
-
 struct WbCtxt {
     fcx: @FnCtxt,
 
@@ -276,22 +277,8 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
     }
 
     resolve_type_vars_for_node(wbcx, e.span, e.id);
-
-    resolve_method_map_entry(wbcx.fcx, e.id);
-    {
-        let r = e.get_callee_id();
-        for callee_id in r.iter() {
-            resolve_method_map_entry(wbcx.fcx, *callee_id);
-        }
-    }
-
+    resolve_method_map_entry(wbcx, e.span, e.id);
     resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
-    {
-        let r = e.get_callee_id();
-        for callee_id in r.iter() {
-            resolve_vtable_map_entry(wbcx.fcx, e.span, *callee_id);
-        }
-    }
 
     match e.node {
         ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
@@ -299,20 +286,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
                 let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
             }
         }
-
-        ast::ExprBinary(callee_id, _, _, _) |
-        ast::ExprUnary(callee_id, _, _) |
-        ast::ExprAssignOp(callee_id, _, _, _) |
-        ast::ExprIndex(callee_id, _, _) => {
-            maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id);
-        }
-
-        ast::ExprMethodCall(callee_id, _, _, _) => {
-            // We must always have written in a callee ID type for these.
-            resolve_type_vars_for_node(wbcx, e.span, callee_id);
-        }
-
-        _ => ()
+        _ => {}
     }
 
     visit::walk_expr(wbcx, e, ());
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index d4e2660b4a0..c04e4f24b0d 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -93,22 +93,22 @@ pub enum param_index {
 }
 
 #[deriving(Clone, Encodable, Decodable)]
-pub enum method_origin {
+pub enum MethodOrigin {
     // fully statically resolved method
-    method_static(ast::DefId),
+    MethodStatic(ast::DefId),
 
     // method invoked on a type parameter with a bounded trait
-    method_param(method_param),
+    MethodParam(MethodParam),
 
     // method invoked on a trait instance
-    method_object(method_object),
+    MethodObject(MethodObject),
 
 }
 
 // details for a method invoked with a receiver whose type is a type parameter
 // with a bounded trait.
 #[deriving(Clone, Encodable, Decodable)]
-pub struct method_param {
+pub struct MethodParam {
     // the trait containing the method to be invoked
     trait_id: ast::DefId,
 
@@ -125,7 +125,7 @@ pub struct method_param {
 
 // details for a method invoked with a receiver whose type is an object
 #[deriving(Clone, Encodable, Decodable)]
-pub struct method_object {
+pub struct MethodObject {
     // the (super)trait containing the method to be invoked
     trait_id: ast::DefId,
 
@@ -142,9 +142,16 @@ pub struct method_object {
     real_index: uint,
 }
 
+#[deriving(Clone)]
+pub struct MethodCallee {
+    origin: MethodOrigin,
+    ty: ty::t,
+    substs: ty::substs
+}
+
 // maps from an expression id that corresponds to a method call to the details
 // of the method to be invoked
-pub type method_map = @RefCell<HashMap<ast::NodeId, method_origin>>;
+pub type MethodMap = @RefCell<HashMap<ast::NodeId, MethodCallee>>;
 
 pub type vtable_param_res = @~[vtable_origin];
 // Resolutions for bounds of all parameters, left to right, for a given path.
@@ -215,7 +222,7 @@ pub type impl_vtable_map = RefCell<HashMap<ast::DefId, impl_res>>;
 pub struct CrateCtxt {
     // A mapping from method call sites to traits that have that method.
     trait_map: resolve::TraitMap,
-    method_map: method_map,
+    method_map: MethodMap,
     vtable_map: vtable_map,
     tcx: ty::ctxt
 }
@@ -436,7 +443,7 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
 pub fn check_crate(tcx: ty::ctxt,
                    trait_map: resolve::TraitMap,
                    krate: &ast::Crate)
-                -> (method_map, vtable_map) {
+                -> (MethodMap, vtable_map) {
     let time_passes = tcx.sess.time_passes();
     let ccx = @CrateCtxt {
         trait_map: trait_map,
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index e430015b221..b47143869e9 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -74,9 +74,6 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
           Some(ast_map::NodeBlock(ref blk)) => {
             explain_span(cx, "block", blk.span)
           }
-          Some(ast_map::NodeCalleeScope(expr)) => {
-              explain_span(cx, "callee", expr.span)
-          }
           Some(ast_map::NodeExpr(expr)) => {
             match expr.node {
               ast::ExprCall(..) => explain_span(cx, "call", expr.span),
@@ -870,25 +867,34 @@ impl Repr for ty::FnSig {
     }
 }
 
-impl Repr for typeck::method_origin {
+impl Repr for typeck::MethodCallee {
+    fn repr(&self, tcx: ctxt) -> ~str {
+        format!("MethodCallee \\{origin: {}, ty: {}, {}\\}",
+            self.origin.repr(tcx),
+            self.ty.repr(tcx),
+            self.substs.repr(tcx))
+    }
+}
+
+impl Repr for typeck::MethodOrigin {
     fn repr(&self, tcx: ctxt) -> ~str {
         match self {
-            &typeck::method_static(def_id) => {
-                format!("method_static({})", def_id.repr(tcx))
+            &typeck::MethodStatic(def_id) => {
+                format!("MethodStatic({})", def_id.repr(tcx))
             }
-            &typeck::method_param(ref p) => {
+            &typeck::MethodParam(ref p) => {
                 p.repr(tcx)
             }
-            &typeck::method_object(ref p) => {
+            &typeck::MethodObject(ref p) => {
                 p.repr(tcx)
             }
         }
     }
 }
 
-impl Repr for typeck::method_param {
+impl Repr for typeck::MethodParam {
     fn repr(&self, tcx: ctxt) -> ~str {
-        format!("method_param({},{:?},{:?},{:?})",
+        format!("MethodParam({},{:?},{:?},{:?})",
              self.trait_id.repr(tcx),
              self.method_num,
              self.param_num,
@@ -896,9 +902,9 @@ impl Repr for typeck::method_param {
     }
 }
 
-impl Repr for typeck::method_object {
+impl Repr for typeck::MethodObject {
     fn repr(&self, tcx: ctxt) -> ~str {
-        format!("method_object({},{:?},{:?})",
+        format!("MethodObject({},{:?},{:?})",
              self.trait_id.repr(tcx),
              self.method_num,
              self.real_index)
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index c095cec1e7d..f6dca713e71 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -521,19 +521,6 @@ pub struct Expr {
     span: Span,
 }
 
-impl Expr {
-    pub fn get_callee_id(&self) -> Option<NodeId> {
-        match self.node {
-            ExprMethodCall(callee_id, _, _, _) |
-            ExprIndex(callee_id, _, _) |
-            ExprBinary(callee_id, _, _, _) |
-            ExprAssignOp(callee_id, _, _, _) |
-            ExprUnary(callee_id, _, _) => Some(callee_id),
-            _ => None,
-        }
-    }
-}
-
 #[deriving(Clone, Eq, Encodable, Decodable, Hash)]
 pub enum Expr_ {
     ExprVstore(@Expr, ExprVstore),
@@ -541,10 +528,10 @@ pub enum Expr_ {
     ExprBox(@Expr, @Expr),
     ExprVec(~[@Expr], Mutability),
     ExprCall(@Expr, ~[@Expr]),
-    ExprMethodCall(NodeId, Ident, ~[P<Ty>], ~[@Expr]),
+    ExprMethodCall(Ident, ~[P<Ty>], ~[@Expr]),
     ExprTup(~[@Expr]),
-    ExprBinary(NodeId, BinOp, @Expr, @Expr),
-    ExprUnary(NodeId, UnOp, @Expr),
+    ExprBinary(BinOp, @Expr, @Expr),
+    ExprUnary(UnOp, @Expr),
     ExprLit(@Lit),
     ExprCast(@Expr, P<Ty>),
     ExprIf(@Expr, P<Block>, Option<@Expr>),
@@ -560,9 +547,9 @@ pub enum Expr_ {
     ExprBlock(P<Block>),
 
     ExprAssign(@Expr, @Expr),
-    ExprAssignOp(NodeId, BinOp, @Expr, @Expr),
+    ExprAssignOp(BinOp, @Expr, @Expr),
     ExprField(@Expr, Ident, ~[P<Ty>]),
-    ExprIndex(NodeId, @Expr, @Expr),
+    ExprIndex(@Expr, @Expr),
 
     /// Expression that looks like a "name". For example,
     /// `std::vec::from_elem::<uint>` is an ExprPath that's the "name" part
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 9194cfb0694..31c258b36c0 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -107,7 +107,6 @@ pub enum Node {
 
     /// NodeStructCtor represents a tuple struct.
     NodeStructCtor(@StructDef),
-    NodeCalleeScope(@Expr),
 }
 
 // The odd layout is to bring down the total size.
@@ -128,7 +127,6 @@ enum MapEntry {
     EntryLocal(NodeId, @Pat),
     EntryBlock(NodeId, P<Block>),
     EntryStructCtor(NodeId, @StructDef),
-    EntryCalleeScope(NodeId, @Expr),
 
     // Roots for node trees.
     RootCrate,
@@ -155,7 +153,6 @@ impl MapEntry {
             EntryLocal(id, _) => id,
             EntryBlock(id, _) => id,
             EntryStructCtor(id, _) => id,
-            EntryCalleeScope(id, _) => id,
             _ => return None
         })
     }
@@ -173,7 +170,6 @@ impl MapEntry {
             EntryLocal(_, p) => NodeLocal(p),
             EntryBlock(_, p) => NodeBlock(p),
             EntryStructCtor(_, p) => NodeStructCtor(p),
-            EntryCalleeScope(_, p) => NodeCalleeScope(p),
             _ => return None
         })
     }
@@ -368,7 +364,6 @@ impl Map {
             Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
             Some(NodeBlock(block)) => block.span,
             Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
-            Some(NodeCalleeScope(expr)) => expr.span,
             _ => fail!("node_span: could not find span for id {}", id),
         }
     }
@@ -493,11 +488,6 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
 
         self.insert(expr.id, EntryExpr(self.parent, expr));
 
-        // Expressions which are or might be calls:
-        for callee_id in expr.get_callee_id().iter() {
-            self.insert(*callee_id, EntryCalleeScope(self.parent, expr));
-        }
-
         expr
     }
 
@@ -650,9 +640,6 @@ fn node_id_to_str(map: &Map, id: NodeId) -> ~str {
         Some(NodeExpr(expr)) => {
             format!("expr {} (id={})", pprust::expr_to_str(expr), id)
         }
-        Some(NodeCalleeScope(expr)) => {
-            format!("callee_scope {} (id={})", pprust::expr_to_str(expr), id)
-        }
         Some(NodeStmt(stmt)) => {
             format!("stmt {} (id={})", pprust::stmt_to_str(stmt), id)
         }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index f6066e5385d..f9d7696565a 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -450,12 +450,6 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
 
 
     fn visit_expr(&mut self, expression: &Expr, env: ()) {
-        {
-            let optional_callee_id = expression.get_callee_id();
-            for callee_id in optional_callee_id.iter() {
-                self.operation.visit_id(*callee_id)
-            }
-        }
         self.operation.visit_id(expression.id);
         visit::walk_expr(self, expression, env)
     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 33cdf4d9add..1ddd579a2f1 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -502,15 +502,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
     fn expr_binary(&self, sp: Span, op: ast::BinOp,
                    lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
-        self.expr(sp, ast::ExprBinary(ast::DUMMY_NODE_ID, op, lhs, rhs))
+        self.expr(sp, ast::ExprBinary(op, lhs, rhs))
     }
 
     fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
         self.expr_unary(sp, ast::UnDeref, e)
     }
-    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr)
-        -> @ast::Expr {
-        self.expr(sp, ast::ExprUnary(ast::DUMMY_NODE_ID, op, e))
+    fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr) -> @ast::Expr {
+        self.expr(sp, ast::ExprUnary(op, e))
     }
 
     fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
@@ -543,7 +542,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                         ident: ast::Ident,
                         mut args: ~[@ast::Expr]) -> @ast::Expr {
         args.unshift(expr);
-        self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args))
+        self.expr(span, ast::ExprMethodCall(ident, ~[], args))
     }
     fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
         self.expr(b.span, ast::ExprBlock(b))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5f6eb86c3c8..e62abac443e 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -749,21 +749,19 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
             ExprCall(folder.fold_expr(f),
                      args.map(|&x| folder.fold_expr(x)))
         }
-        ExprMethodCall(callee_id, i, ref tps, ref args) => {
+        ExprMethodCall(i, ref tps, ref args) => {
             ExprMethodCall(
-                folder.new_id(callee_id),
                 folder.fold_ident(i),
                 tps.map(|&x| folder.fold_ty(x)),
                 args.map(|&x| folder.fold_expr(x)))
         }
-        ExprBinary(callee_id, binop, lhs, rhs) => {
-            ExprBinary(folder.new_id(callee_id),
-                       binop,
+        ExprBinary(binop, lhs, rhs) => {
+            ExprBinary(binop,
                        folder.fold_expr(lhs),
                        folder.fold_expr(rhs))
         }
-        ExprUnary(callee_id, binop, ohs) => {
-            ExprUnary(folder.new_id(callee_id), binop, folder.fold_expr(ohs))
+        ExprUnary(binop, ohs) => {
+            ExprUnary(binop, folder.fold_expr(ohs))
         }
         ExprLit(_) => e.node.clone(),
         ExprCast(expr, ty) => {
@@ -802,9 +800,8 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
         ExprAssign(el, er) => {
             ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
         }
-        ExprAssignOp(callee_id, op, el, er) => {
-            ExprAssignOp(folder.new_id(callee_id),
-                         op,
+        ExprAssignOp(op, el, er) => {
+            ExprAssignOp(op,
                          folder.fold_expr(el),
                          folder.fold_expr(er))
         }
@@ -813,10 +810,8 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
                       folder.fold_ident(id),
                       tys.map(|&x| folder.fold_ty(x)))
         }
-        ExprIndex(callee_id, el, er) => {
-            ExprIndex(folder.new_id(callee_id),
-                      folder.fold_expr(el),
-                      folder.fold_expr(er))
+        ExprIndex(el, er) => {
+            ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
         }
         ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
         ExprLogLevel => ExprLogLevel,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cbe371a06a5..2fd6d34adf1 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1683,11 +1683,11 @@ impl Parser {
     }
 
     pub fn mk_unary(&mut self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
-        ExprUnary(ast::DUMMY_NODE_ID, unop, expr)
+        ExprUnary(unop, expr)
     }
 
     pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
-        ExprBinary(ast::DUMMY_NODE_ID, binop, lhs, rhs)
+        ExprBinary(binop, lhs, rhs)
     }
 
     pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr]) -> ast::Expr_ {
@@ -1695,11 +1695,11 @@ impl Parser {
     }
 
     fn mk_method_call(&mut self, ident: Ident, tps: ~[P<Ty>], args: ~[@Expr]) -> ast::Expr_ {
-        ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args)
+        ExprMethodCall(ident, tps, args)
     }
 
     pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
-        ExprIndex(ast::DUMMY_NODE_ID, expr, idx)
+        ExprIndex(expr, idx)
     }
 
     pub fn mk_field(&mut self, expr: @Expr, ident: Ident, tys: ~[P<Ty>]) -> ast::Expr_ {
@@ -1707,7 +1707,7 @@ impl Parser {
     }
 
     pub fn mk_assign_op(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
-        ExprAssignOp(ast::DUMMY_NODE_ID, binop, lhs, rhs)
+        ExprAssignOp(binop, lhs, rhs)
     }
 
     pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, m: Mac_) -> @Expr {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8fb813407d0..688494ec5ee 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1235,7 +1235,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
         try!(print_expr(s, func));
         try!(print_call_post(s, *args));
       }
-      ast::ExprMethodCall(_, ident, ref tys, ref args) => {
+      ast::ExprMethodCall(ident, ref tys, ref args) => {
         let base_args = args.slice_from(1);
         try!(print_expr(s, args[0]));
         try!(word(&mut s.s, "."));
@@ -1247,13 +1247,13 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
         }
         try!(print_call_post(s, base_args));
       }
-      ast::ExprBinary(_, op, lhs, rhs) => {
+      ast::ExprBinary(op, lhs, rhs) => {
         try!(print_expr(s, lhs));
         try!(space(&mut s.s));
         try!(word_space(s, ast_util::binop_to_str(op)));
         try!(print_expr(s, rhs));
       }
-      ast::ExprUnary(_, op, expr) => {
+      ast::ExprUnary(op, expr) => {
         try!(word(&mut s.s, ast_util::unop_to_str(op)));
         try!(print_expr(s, expr));
       }
@@ -1442,7 +1442,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
         try!(word_space(s, "="));
         try!(print_expr(s, rhs));
       }
-      ast::ExprAssignOp(_, op, lhs, rhs) => {
+      ast::ExprAssignOp(op, lhs, rhs) => {
         try!(print_expr(s, lhs));
         try!(space(&mut s.s));
         try!(word(&mut s.s, ast_util::binop_to_str(op)));
@@ -1459,7 +1459,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
             try!(word(&mut s.s, ">"));
         }
       }
-      ast::ExprIndex(_, expr, index) => {
+      ast::ExprIndex(expr, index) => {
         try!(print_expr(s, expr));
         try!(word(&mut s.s, "["));
         try!(print_expr(s, index));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index feab4e0e84d..248ba593c1f 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -658,18 +658,17 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             }
             visitor.visit_expr(callee_expression, env.clone())
         }
-        ExprMethodCall(_, _, 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())
             }
         }
-        ExprBinary(_, _, left_expression, right_expression) => {
+        ExprBinary(_, left_expression, right_expression) => {
             visitor.visit_expr(left_expression, env.clone());
             visitor.visit_expr(right_expression, env.clone())
         }
-        ExprAddrOf(_, subexpression) |
-        ExprUnary(_, _, subexpression) => {
+        ExprAddrOf(_, subexpression) | ExprUnary(_, subexpression) => {
             visitor.visit_expr(subexpression, env.clone())
         }
         ExprLit(_) => {}
@@ -719,7 +718,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             visitor.visit_expr(right_hand_expression, env.clone());
             visitor.visit_expr(left_hand_expression, env.clone())
         }
-        ExprAssignOp(_, _, left_expression, right_expression) => {
+        ExprAssignOp(_, left_expression, right_expression) => {
             visitor.visit_expr(right_expression, env.clone());
             visitor.visit_expr(left_expression, env.clone())
         }
@@ -729,7 +728,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
                 visitor.visit_ty(typ, env.clone())
             }
         }
-        ExprIndex(_, main_expression, index_expression) => {
+        ExprIndex(main_expression, index_expression) => {
             visitor.visit_expr(main_expression, env.clone());
             visitor.visit_expr(index_expression, env.clone())
         }