about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-05-20 16:11:07 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-01 08:59:47 +0300
commit552ab37a100231f8f2416b5ecc7e350c17e6487f (patch)
tree013fe2efb07f5f00e0b8066ff23c0e8918e859c5
parent9eae6ba7fad883300c83d77782ae78b0db6f3bb7 (diff)
rustc: replace method_map with Def::Method and node_substs entries.
-rw-r--r--src/librustc/cfg/construct.rs4
-rw-r--r--src/librustc/ich/impls_ty.rs6
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/middle/effect.rs4
-rw-r--r--src/librustc/middle/expr_use_visitor.rs6
-rw-r--r--src/librustc/middle/liveness.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/reachable.rs3
-rw-r--r--src/librustc/ty/context.rs25
-rw-r--r--src/librustc/ty/sty.rs2
-rw-r--r--src/librustc_lint/builtin.rs29
-rw-r--r--src/librustc_mir/hair/cx/expr.rs51
-rw-r--r--src/librustc_passes/consts.rs8
-rw-r--r--src/librustc_save_analysis/lib.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs19
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/check/regionck.rs20
-rw-r--r--src/librustc_typeck/check/writeback.rs40
20 files changed, 120 insertions, 119 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index affc84382a5..85b1858c875 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -355,11 +355,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             }
 
             hir::ExprIndex(ref l, ref r) |
-            hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr.id) => {
+            hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr) => {
                 self.call(expr, pred, &l, Some(&**r).into_iter())
             }
 
-            hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr.id) => {
+            hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr) => {
                 self.call(expr, pred, &e, None::<hir::Expr>.iter())
             }
 
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 2615fdd86d6..e607a6bf74a 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -598,11 +598,10 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
                                           hcx: &mut StableHashingContext<'a, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
         let ty::TypeckTables {
-            ref type_relative_path_defs,
+            ref type_dependent_defs,
             ref node_types,
             ref node_substs,
             ref adjustments,
-            ref method_map,
             ref upvar_capture_map,
             ref closure_tys,
             ref closure_kinds,
@@ -619,11 +618,10 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
+            ich::hash_stable_nodemap(hcx, hasher, type_dependent_defs);
             ich::hash_stable_nodemap(hcx, hasher, node_types);
             ich::hash_stable_nodemap(hcx, hasher, node_substs);
             ich::hash_stable_nodemap(hcx, hasher, adjustments);
-            ich::hash_stable_nodemap(hcx, hasher, method_map);
             ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
                 let ty::UpvarId {
                     var_id,
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index ebae3933bdd..6077b7863e2 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn lookup_and_handle_method(&mut self, id: ast::NodeId) {
-        self.check_def_id(self.tables.method_map[&id].def_id);
+        self.check_def_id(self.tables.type_dependent_defs[&id].def_id());
     }
 
     fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index c9593e54a86..74e1225f394 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -173,8 +173,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         match expr.node {
             hir::ExprMethodCall(..) => {
-                let method = self.tables.method_map[&expr.id];
-                let base_type = self.tcx.type_of(method.def_id);
+                let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
+                let base_type = self.tcx.type_of(def_id);
                 debug!("effect: method call case, base type is {:?}",
                         base_type);
                 if type_is_unsafe_function(base_type) {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 45afc17f339..340a929331f 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -563,8 +563,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
             }
             ty::TyError => { }
             _ => {
-                let method = self.mc.infcx.tables.borrow().method_map[&call.id];
-                match OverloadedCallType::from_method_id(self.tcx(), method.def_id) {
+                let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id();
+                match OverloadedCallType::from_method_id(self.tcx(), def_id) {
                     FnMutOverloadedCall => {
                         let call_scope_r = self.tcx().node_scope_region(call.id);
                         self.borrow_expr(callee,
@@ -849,7 +849,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                                 pass_args: PassArgs)
                                 -> bool
     {
-        if !self.mc.infcx.tables.borrow().is_method_call(expr.id) {
+        if !self.mc.infcx.tables.borrow().is_method_call(expr) {
             return false;
         }
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 6a74af6eb8a..c6a42be6135 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1045,7 +1045,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
           hir::ExprAssignOp(_, ref l, ref r) => {
             // an overloaded assign op is like a method call
-            if self.tables.is_method_call(expr.id) {
+            if self.tables.is_method_call(expr) {
                 let succ = self.propagate_through_expr(&l, succ);
                 self.propagate_through_expr(&r, succ)
             } else {
@@ -1366,7 +1366,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
       }
 
       hir::ExprAssignOp(_, ref l, _) => {
-        if !this.tables.is_method_call(expr.id) {
+        if !this.tables.is_method_call(expr) {
             this.check_lvalue(&l);
         }
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index cc65777bfce..f971700b2c8 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -515,7 +515,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         let expr_ty = self.expr_ty(expr)?;
         match expr.node {
           hir::ExprUnary(hir::UnDeref, ref e_base) => {
-            if self.infcx.tables.borrow().is_method_call(expr.id) {
+            if self.infcx.tables.borrow().is_method_call(expr) {
                 self.cat_overloaded_lvalue(expr, e_base, false)
             } else {
                 let base_cmt = self.cat_expr(&e_base)?;
@@ -538,7 +538,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
           }
 
           hir::ExprIndex(ref base, _) => {
-            if self.infcx.tables.borrow().is_method_call(expr.id()) {
+            if self.infcx.tables.borrow().is_method_call(expr) {
                 // If this is an index implemented by a method call, then it
                 // will include an implicit deref of the result.
                 // The call to index() returns a `&T` value, which
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index e5cc7aae4e9..c2f69147e3a 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -110,8 +110,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
                 Some(self.tables.qpath_def(qpath, expr.id))
             }
             hir::ExprMethodCall(..) => {
-                let def_id = self.tables.method_map[&expr.id].def_id;
-                Some(Def::Method(def_id))
+                Some(self.tables.type_dependent_defs[&expr.id])
             }
             _ => None
         };
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index a0ad3da45e0..f0cee2fe2b1 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -206,8 +206,9 @@ pub struct CommonTypes<'tcx> {
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TypeckTables<'tcx> {
-    /// Resolved definitions for `<T>::X` associated paths.
-    pub type_relative_path_defs: NodeMap<Def>,
+    /// Resolved definitions for `<T>::X` associated paths and
+    /// method calls, including those of overloaded operators.
+    pub type_dependent_defs: NodeMap<Def>,
 
     /// Stores the types for various nodes in the AST.  Note that this table
     /// is not guaranteed to be populated until after typeck.  See
@@ -222,8 +223,6 @@ pub struct TypeckTables<'tcx> {
 
     pub adjustments: NodeMap<ty::adjustment::Adjustment<'tcx>>,
 
-    pub method_map: NodeMap<ty::MethodCallee<'tcx>>,
-
     /// Borrows
     pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>,
 
@@ -271,11 +270,10 @@ pub struct TypeckTables<'tcx> {
 impl<'tcx> TypeckTables<'tcx> {
     pub fn empty() -> TypeckTables<'tcx> {
         TypeckTables {
-            type_relative_path_defs: NodeMap(),
+            type_dependent_defs: NodeMap(),
             node_types: FxHashMap(),
             node_substs: NodeMap(),
             adjustments: NodeMap(),
-            method_map: FxHashMap(),
             upvar_capture_map: FxHashMap(),
             closure_tys: NodeMap(),
             closure_kinds: NodeMap(),
@@ -294,7 +292,7 @@ impl<'tcx> TypeckTables<'tcx> {
         match *qpath {
             hir::QPath::Resolved(_, ref path) => path.def,
             hir::QPath::TypeRelative(..) => {
-                self.type_relative_path_defs.get(&id).cloned().unwrap_or(Def::Err)
+                self.type_dependent_defs.get(&id).cloned().unwrap_or(Def::Err)
             }
         }
     }
@@ -357,8 +355,17 @@ impl<'tcx> TypeckTables<'tcx> {
             .map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
     }
 
-    pub fn is_method_call(&self, expr_id: NodeId) -> bool {
-        self.method_map.contains_key(&expr_id)
+    pub fn is_method_call(&self, expr: &hir::Expr) -> bool {
+        // Only paths and method calls/overloaded operators have
+        // entries in type_dependent_defs, ignore the former here.
+        if let hir::ExprPath(_) = expr.node {
+            return false;
+        }
+
+        match self.type_dependent_defs.get(&expr.id) {
+            Some(&Def::Method(_)) => true,
+            _ => false
+        }
     }
 
     pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index df7c2e567f7..76132cab2cd 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -141,8 +141,6 @@ pub enum TypeVariants<'tcx> {
     TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>),
 
     /// A pointer to a function.  Written as `fn() -> i32`.
-    /// FIXME: This is currently also used to represent the callee of a method;
-    /// see ty::MethodCallee etc.
     TyFnPtr(PolyFnSig<'tcx>),
 
     /// A trait, defined with `trait`.
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 8a374358bb9..04645214ce8 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -881,17 +881,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                                       -> bool {
             use rustc::ty::adjustment::*;
 
-            // Check for method calls and overloaded operators.
-            if let Some(m) = cx.tables.method_map.get(&id).cloned() {
-                if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) {
-                    return true;
-                }
-            }
+            // Ignore non-expressions.
+            let expr = if let hir_map::NodeExpr(e) = cx.tcx.hir.get(id) {
+                e
+            } else {
+                return false;
+            };
 
             // Check for overloaded autoderef method calls.
-            if let Some(Adjustment {
+            if let Some(&Adjustment {
                 kind: Adjust::DerefRef { ref autoderefs, .. }, ..
-            }) = cx.tables.adjustments.get(&id).cloned() {
+            }) = cx.tables.adjustments.get(&id) {
                 for &overloaded in autoderefs {
                     if let Some(m) = overloaded {
                         if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) {
@@ -901,9 +901,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                 }
             }
 
+            // Check for method calls and overloaded operators.
+            if cx.tables.is_method_call(expr) {
+                let def_id = cx.tables.type_dependent_defs[&id].def_id();
+                let substs = cx.tables.node_substs(id);
+                if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) {
+                    return true;
+                }
+            }
+
             // Check for calls to methods via explicit paths (e.g. `T::method()`).
-            match cx.tcx.hir.get(id) {
-                hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
+            match expr.node {
+                hir::ExprCall(ref callee, _) => {
                     let def = if let hir::ExprPath(ref qpath) = callee.node {
                         cx.tables.qpath_def(qpath, callee.id)
                     } else {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index c11cd38fe34..cd540f309b0 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -118,7 +118,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                         overloaded_lvalue(cx,
                                           self,
                                           mt.ty,
-                                          method,
+                                          Some(method),
                                           PassArgs::ByRef,
                                           expr.to_ref(),
                                           vec![])
@@ -244,8 +244,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         // Here comes the interesting stuff:
         hir::ExprMethodCall(.., ref args) => {
             // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
-            let method = cx.tables().method_map[&expr.id];
-            let expr = method_callee(cx, expr, method);
+            let expr = method_callee(cx, expr, None);
             let args = args.iter()
                 .map(|e| e.to_ref())
                 .collect();
@@ -257,7 +256,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprCall(ref fun, ref args) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 // The callee is something implementing Fn, FnMut, or FnOnce.
                 // Find the actual method implementation being called and
                 // build the appropriate UFCS call expression with the
@@ -265,7 +264,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
                 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
 
-                let method = method_callee(cx, expr, method);
+                let method = method_callee(cx, expr, None);
 
                 let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
                 let tupled_args = Expr {
@@ -346,7 +345,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprAssignOp(op, ref lhs, ref rhs) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 let pass_args = if op.node.is_by_value() {
                     PassArgs::ByValue
                 } else {
@@ -354,7 +353,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 };
                 overloaded_operator(cx,
                                     expr,
-                                    method,
+                                    None,
                                     pass_args,
                                     lhs.to_ref(),
                                     vec![rhs])
@@ -370,7 +369,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) },
 
         hir::ExprBinary(op, ref lhs, ref rhs) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 let pass_args = if op.node.is_by_value() {
                     PassArgs::ByValue
                 } else {
@@ -378,7 +377,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 };
                 overloaded_operator(cx,
                                     expr,
-                                    method,
+                                    None,
                                     pass_args,
                                     lhs.to_ref(),
                                     vec![rhs])
@@ -430,11 +429,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprIndex(ref lhs, ref index) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 overloaded_lvalue(cx,
                                   expr,
                                   expr_ty,
-                                  method,
+                                  None,
                                   PassArgs::ByValue,
                                   lhs.to_ref(),
                                   vec![index])
@@ -447,11 +446,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 overloaded_lvalue(cx,
                                   expr,
                                   expr_ty,
-                                  method,
+                                  None,
                                   PassArgs::ByValue,
                                   arg.to_ref(),
                                   vec![])
@@ -461,10 +460,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 overloaded_operator(cx,
                                     expr,
-                                    method,
+                                    None,
                                     PassArgs::ByValue,
                                     arg.to_ref(),
                                     vec![])
@@ -477,10 +476,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
-            if let Some(&method) = cx.tables().method_map.get(&expr.id) {
+            if cx.tables().is_method_call(expr) {
                 overloaded_operator(cx,
                                     expr,
-                                    method,
+                                    None,
                                     PassArgs::ByValue,
                                     arg.to_ref(),
                                     vec![])
@@ -699,17 +698,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
 fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                  expr: &hir::Expr,
-                                 callee: ty::MethodCallee<'tcx>)
+                                 custom_callee: Option<ty::MethodCallee<'tcx>>)
                                  -> Expr<'tcx> {
     let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
+    let (def_id, substs) = custom_callee.map(|m| (m.def_id, m.substs)).unwrap_or_else(|| {
+        (cx.tables().type_dependent_defs[&expr.id].def_id(),
+         cx.tables().node_substs(expr.id))
+    });
     Expr {
         temp_lifetime: temp_lifetime,
         temp_lifetime_was_shrunk: was_shrunk,
-        ty: cx.tcx.type_of(callee.def_id).subst(cx.tcx, callee.substs),
+        ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs),
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
-                value: ConstVal::Function(callee.def_id, callee.substs),
+                value: ConstVal::Function(def_id, substs),
             },
         },
     }
@@ -942,7 +945,7 @@ enum PassArgs {
 
 fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                        expr: &'tcx hir::Expr,
-                                       method: ty::MethodCallee<'tcx>,
+                                       custom_callee: Option<ty::MethodCallee<'tcx>>,
                                        pass_args: PassArgs,
                                        receiver: ExprRef<'tcx>,
                                        args: Vec<&'tcx P<hir::Expr>>)
@@ -985,7 +988,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     }
 
     // now create the call itself
-    let fun = method_callee(cx, expr, method);
+    let fun = method_callee(cx, expr, custom_callee);
     ExprKind::Call {
         ty: fun.ty,
         fun: fun.to_ref(),
@@ -996,7 +999,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                      expr: &'tcx hir::Expr,
                                      lvalue_ty: Ty<'tcx>,
-                                     method: ty::MethodCallee<'tcx>,
+                                     custom_callee: Option<ty::MethodCallee<'tcx>>,
                                      pass_args: PassArgs,
                                      receiver: ExprRef<'tcx>,
                                      args: Vec<&'tcx P<hir::Expr>>)
@@ -1025,7 +1028,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
     let (temp_lifetime, was_shrunk) = cx.region_maps.temporary_scope2(expr.id);
-    let ref_kind = overloaded_operator(cx, expr, method, pass_args, receiver, args);
+    let ref_kind = overloaded_operator(cx, expr, custom_callee, pass_args, receiver, args);
     let ref_expr = Expr {
         temp_lifetime: temp_lifetime,
         temp_lifetime_was_shrunk: was_shrunk,
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 712f5f7ad39..f73ae9d42f6 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -283,7 +283,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
     match e.node {
         hir::ExprUnary(..) |
         hir::ExprBinary(..) |
-        hir::ExprIndex(..) if v.tables.method_map.contains_key(&e.id) => {
+        hir::ExprIndex(..) if v.tables.is_method_call(e) => {
             v.promotable = false;
         }
         hir::ExprBox(_) => {
@@ -380,9 +380,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
             }
         }
         hir::ExprMethodCall(..) => {
-            let method = v.tables.method_map[&e.id];
-            match v.tcx.associated_item(method.def_id).container {
-                ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty),
+            let def_id = v.tables.type_dependent_defs[&e.id].def_id();
+            match v.tcx.associated_item(def_id).container {
+                ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty),
                 ty::TraitContainer(_) => v.promotable = false
             }
         }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index d0809f0f642..b4d74cfb160 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -564,7 +564,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }
             }
             ast::ExprKind::MethodCall(..) => {
-                let method_id = self.tables.method_map[&expr.id].def_id;
+                let method_id = self.tables.type_dependent_defs[&expr.id].def_id();
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 5302ba00291..f8560550da4 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                            TupleArgumentsFlag::TupleArguments,
                                                            expected);
 
-        self.tables.borrow_mut().method_map.insert(call_expr.id, method_callee);
+        self.write_method_call(call_expr.id, method_callee);
         output_type
     }
 }
@@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
                     target: method_sig.inputs()[0]
                 });
 
-                fcx.tables.borrow_mut().method_map.insert(self.call_expr.id, method_callee);
+                fcx.write_method_call(self.call_expr.id, method_callee);
             }
             None => {
                 span_bug!(self.call_expr.span,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 71bcff84cc2..52ed6647994 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -475,7 +475,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
     {
         debug!("convert_lvalue_op_to_mutable({:?}, {:?}, {:?}, {:?})",
                op, expr, base_expr, arg_tys);
-        if !self.tables.borrow().method_map.contains_key(&expr.id) {
+        if !self.tables.borrow().is_method_call(expr) {
             debug!("convert_lvalue_op_to_mutable - builtin, nothing to do");
             return
         }
@@ -497,7 +497,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         };
         let (_, method) = self.register_infer_ok_obligations(ok);
         debug!("convert_lvalue_op_to_mutable: method={:?}", method);
-        self.tables.borrow_mut().method_map.insert(expr.id, method);
+        self.write_method_call(expr.id, method);
 
         // Convert the autoref in the base expr to mutable with the correct
         // region and mutability.
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0b0233103ef..df5023fb7a6 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1758,6 +1758,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn write_method_call(&self, node_id: ast::NodeId, method: ty::MethodCallee<'tcx>) {
+        self.tables.borrow_mut().type_dependent_defs.insert(node_id, Def::Method(method.def_id));
+        self.write_substs(node_id, method.substs);
+    }
+
     pub fn write_substs(&self, node_id: ast::NodeId, substs: &'tcx Substs<'tcx>) {
         if !substs.is_noop() {
             debug!("write_substs({}, {:?}) in fcx {}",
@@ -2238,7 +2243,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     target: method.sig.inputs()[0]
                 });
 
-                self.tables.borrow_mut().method_map.insert(expr.id, method);
+                self.write_method_call(expr.id, method);
                 (input_ty, self.make_overloaded_lvalue_return_type(method).ty)
             });
             if result.is_some() {
@@ -2777,7 +2782,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                               expr,
                                               rcvr) {
             Ok(method) => {
-                self.tables.borrow_mut().method_map.insert(expr.id, method);
+                self.write_method_call(expr.id, method);
                 Ok(method)
             }
             Err(error) => {
@@ -3453,7 +3458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 target: method.sig.inputs()[0]
                             });
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
-                            self.tables.borrow_mut().method_map.insert(expr.id, method);
+                            self.write_method_call(expr.id, method);
                         } else {
                             self.type_error_message(expr.span, |actual| {
                                 format!("type `{}` cannot be \
@@ -3918,7 +3923,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
-    // The newly resolved definition is written into `type_relative_path_defs`.
+    // The newly resolved definition is written into `type_dependent_defs`.
     fn finish_resolving_struct_path(&self,
                                     qpath: &hir::QPath,
                                     path_span: Span,
@@ -3943,7 +3948,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                                    ty, def, segment);
 
                 // Write back the new resolution.
-                self.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
+                self.tables.borrow_mut().type_dependent_defs.insert(node_id, def);
 
                 (def, ty)
             }
@@ -3951,7 +3956,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     // Resolve associated value path into a base type and associated constant or method definition.
-    // The newly resolved definition is written into `type_relative_path_defs`.
+    // The newly resolved definition is written into `type_dependent_defs`.
     pub fn resolve_ty_and_def_ufcs<'b>(&self,
                                        qpath: &'b hir::QPath,
                                        node_id: ast::NodeId,
@@ -3984,7 +3989,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         };
 
         // Write back the new resolution.
-        self.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
+        self.tables.borrow_mut().type_dependent_defs.insert(node_id, def);
         (def, Some(ty), slice::ref_slice(&**item_segment))
     }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 267b2b00978..0c820d2404a 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -421,7 +421,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     },
                     target: method.sig.inputs()[0]
                 });
-                self.tables.borrow_mut().method_map.insert(expr.id, method);
+                self.write_method_call(expr.id, method);
 
                 Ok(method.sig.output())
             }
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 2fae9d8e70e..e1451139d6e 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -520,14 +520,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
         self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span),
                                expr_ty, expr_region);
 
-        let opt_method_callee = self.tables.borrow().method_map.get(&expr.id).cloned();
-        let has_method_map = opt_method_callee.is_some();
+        let is_method_call = self.tables.borrow().is_method_call(expr);
 
         // If we are calling a method (either explicitly or via an
         // overloaded operator), check that all of the types provided as
         // arguments for its type parameters are well-formed, and all the regions
         // provided as arguments outlive the call.
-        if let Some(callee) = opt_method_callee {
+        if is_method_call {
             let origin = match expr.node {
                 hir::ExprMethodCall(..) =>
                     infer::ParameterOrigin::MethodCall,
@@ -537,7 +536,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                     infer::ParameterOrigin::OverloadedOperator
             };
 
-            self.substs_wf_in_scope(origin, &callee.substs, expr.span, expr_region);
+            let substs = self.tables.borrow().node_substs(expr.id);
+            self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
             // Arguments (sub-expressions) are checked via `constrain_call`, below.
         }
 
@@ -614,7 +614,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
             }
 
             hir::ExprCall(ref callee, ref args) => {
-                if has_method_map {
+                if is_method_call {
                     self.constrain_call(expr, Some(&callee),
                                         args.iter().map(|e| &*e), false);
                 } else {
@@ -634,7 +634,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
             }
 
             hir::ExprAssignOp(_, ref lhs, ref rhs) => {
-                if has_method_map {
+                if is_method_call {
                     self.constrain_call(expr, Some(&lhs),
                                         Some(&**rhs).into_iter(), false);
                 }
@@ -642,14 +642,14 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                 intravisit::walk_expr(self, expr);
             }
 
-            hir::ExprIndex(ref lhs, ref rhs) if has_method_map => {
+            hir::ExprIndex(ref lhs, ref rhs) if is_method_call => {
                 self.constrain_call(expr, Some(&lhs),
                                     Some(&**rhs).into_iter(), true);
 
                 intravisit::walk_expr(self, expr);
             },
 
-            hir::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
+            hir::ExprBinary(op, ref lhs, ref rhs) if is_method_call => {
                 let implicitly_ref_args = !op.node.is_by_value();
 
                 // As `expr_method_call`, but the call is via an
@@ -674,7 +674,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                 intravisit::walk_expr(self, expr);
             }
 
-            hir::ExprUnary(op, ref lhs) if has_method_map => {
+            hir::ExprUnary(op, ref lhs) if is_method_call => {
                 let implicitly_ref_args = !op.is_by_value();
 
                 // As above.
@@ -686,7 +686,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
 
             hir::ExprUnary(hir::UnDeref, ref base) => {
                 // For *a, the lifetime of a must enclose the deref
-                if self.tables.borrow().is_method_call(expr.id) {
+                if self.tables.borrow().is_method_call(expr) {
                     self.constrain_call(expr, Some(base),
                                         None::<hir::Expr>.iter(), true);
                 }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index dcdfed6cbd8..4db0475a18b 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -106,7 +106,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
 
                 if inner_ty.is_scalar() {
-                    self.fcx.tables.borrow_mut().method_map.remove(&e.id);
+                    let mut tables = self.fcx.tables.borrow_mut();
+                    tables.type_dependent_defs.remove(&e.id);
+                    tables.node_substs.remove(&e.id);
                 }
             }
             hir::ExprBinary(ref op, ref lhs, ref rhs) |
@@ -118,7 +120,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 let rhs_ty = self.fcx.resolve_type_vars_if_possible(&rhs_ty);
 
                 if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
-                    self.fcx.tables.borrow_mut().method_map.remove(&e.id);
+                    let mut tables = self.fcx.tables.borrow_mut();
+                    tables.type_dependent_defs.remove(&e.id);
+                    tables.node_substs.remove(&e.id);
 
                     // weird but true: the by-ref binops put an
                     // adjustment on the lhs but not the rhs; the
@@ -127,11 +131,11 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                     match e.node {
                         hir::ExprBinary(..) => {
                             if !op.node.is_by_value() {
-                                self.fcx.tables.borrow_mut().adjustments.remove(&lhs.id);
+                                tables.adjustments.remove(&lhs.id);
                             }
                         },
                         hir::ExprAssignOp(..) => {
-                            self.fcx.tables.borrow_mut().adjustments.remove(&lhs.id);
+                            tables.adjustments.remove(&lhs.id);
                         },
                         _ => {},
                     }
@@ -164,7 +168,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
         self.fix_scalar_builtin_expr(e);
 
         self.visit_node_id(e.span, e.id);
-        self.visit_method_map_entry(e.span, e.id);
 
         if let hir::ExprClosure(_, _, body, _) = e.node {
             let body = self.fcx.tcx.hir.body(body);
@@ -280,9 +283,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     }
 
     fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) {
-        // Export associated path extensions.
-        if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&node_id) {
-            self.tables.type_relative_path_defs.insert(node_id, def);
+        // Export associated path extensions and method resultions.
+        if let Some(def) = self.fcx.tables.borrow_mut().type_dependent_defs.remove(&node_id) {
+            self.tables.type_dependent_defs.insert(node_id, def);
         }
 
         // Resolve any borrowings for the node with id `node_id`
@@ -358,27 +361,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         }
     }
 
-    fn visit_method_map_entry(&mut self,
-                              method_span: Span,
-                              node_id: ast::NodeId) {
-        // Resolve any method map entry
-        let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&node_id) {
-            Some(method) => {
-                Some(MethodCallee {
-                    def_id: method.def_id,
-                    substs: self.resolve(&method.substs, &method_span),
-                    sig: self.resolve(&method.sig, &method_span),
-                })
-            }
-            None => None
-        };
-
-        //NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE
-        if let Some(method) = new_method {
-            self.tables.method_map.insert(node_id, method);
-        }
-    }
-
     fn visit_liberated_fn_sigs(&mut self) {
         for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
             let fn_sig = self.resolve(fn_sig, &node_id);