diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index db62e6bedf082..94947b95cd38f 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -581,41 +581,48 @@ impl tr for moves::CaptureVar {
 // Encoding and decoding of MethodCallee
 
 trait read_method_callee_helper {
-    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee;
+    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee);
 }
 
 fn encode_method_callee(ecx: &e::EncodeContext,
                         ebml_w: &mut writer::Encoder,
+                        autoderef: u32,
                         method: &MethodCallee) {
-    ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
-        ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
+    ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
+        ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
+            autoderef.encode(ebml_w);
+        });
+        ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
             method.origin.encode(ebml_w);
         });
-        ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
+        ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
             ebml_w.emit_ty(ecx, method.ty);
         });
-        ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
+        ebml_w.emit_struct_field("substs", 3u, |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| {
+    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
+        self.read_struct("MethodCallee", 4, |this| {
+            let autoderef = this.read_struct_field("autoderef", 0, |this| {
+                Decodable::decode(this)
+            });
+            (autoderef, MethodCallee {
+                origin: this.read_struct_field("origin", 1, |this| {
                     let method_origin: MethodOrigin =
                         Decodable::decode(this);
                     method_origin.tr(xcx)
                 }),
-                ty: this.read_struct_field("ty", 1, |this| {
+                ty: this.read_struct_field("ty", 2, |this| {
                     this.read_ty(xcx)
                 }),
-                substs: this.read_struct_field("substs", 2, |this| {
+                substs: this.read_struct_field("substs", 3, |this| {
                     this.read_substs(xcx)
                 })
-            }
+            })
         })
     }
 }
@@ -647,6 +654,20 @@ impl tr for MethodOrigin {
 // ______________________________________________________________________
 // Encoding and decoding vtable_res
 
+fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
+                              ebml_w: &mut writer::Encoder,
+                              autoderef: u32,
+                              dr: typeck::vtable_res) {
+    ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
+        ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
+            autoderef.encode(ebml_w);
+        });
+        ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
+            encode_vtable_res(ecx, ebml_w, dr);
+        });
+    })
+}
+
 pub fn encode_vtable_res(ecx: &e::EncodeContext,
                      ebml_w: &mut writer::Encoder,
                      dr: typeck::vtable_res) {
@@ -701,6 +722,10 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
 }
 
 pub trait vtable_decoder_helpers {
+    fn read_vtable_res_with_key(&mut self,
+                                tcx: &ty::ctxt,
+                                cdata: @cstore::crate_metadata)
+                                -> (u32, typeck::vtable_res);
     fn read_vtable_res(&mut self,
                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_res;
@@ -713,6 +738,20 @@ pub trait vtable_decoder_helpers {
 }
 
 impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
+    fn read_vtable_res_with_key(&mut self,
+                                tcx: &ty::ctxt,
+                                cdata: @cstore::crate_metadata)
+                                -> (u32, typeck::vtable_res) {
+        self.read_struct("VtableWithKey", 2, |this| {
+            let autoderef = this.read_struct_field("autoderef", 0, |this| {
+                Decodable::decode(this)
+            });
+            (autoderef, this.read_struct_field("vtable_res", 1, |this| {
+                this.read_vtable_res(tcx, cdata)
+            }))
+        })
+    }
+
     fn read_vtable_res(&mut self,
                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_res {
@@ -1018,21 +1057,48 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         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)
+                encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
             })
         })
     }
 
-    for &dr in maps.vtable_map.borrow().find(&id).iter() {
+    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                encode_vtable_res(ecx, ebml_w, *dr);
+                encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
             })
         })
     }
 
     for adj in tcx.adjustments.borrow().find(&id).iter() {
+        match ***adj {
+            ty::AutoDerefRef(adj) => {
+                for autoderef in range(0, adj.autoderefs) {
+                    let method_call = MethodCall::autoderef(id, autoderef as u32);
+                    for &method in maps.method_map.borrow().find(&method_call).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_call.autoderef, method)
+                            })
+                        })
+                    }
+
+                    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
+                        ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
+                            ebml_w.id(id);
+                            ebml_w.tag(c::tag_table_val, |ebml_w| {
+                                encode_vtable_res_with_key(ecx, ebml_w,
+                                                           method_call.autoderef, *dr);
+                            })
+                        })
+                    }
+                }
+            }
+            _ => {}
+        }
+
         ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1336,15 +1402,22 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
                     }
                     c::tag_table_method_map => {
-                        let method = val_dsr.read_method_callee(xcx);
-                        let method_call = MethodCall::expr(id);
+                        let (autoderef, method) = val_dsr.read_method_callee(xcx);
+                        let method_call = MethodCall {
+                            expr_id: id,
+                            autoderef: autoderef
+                        };
                         dcx.maps.method_map.borrow_mut().insert(method_call, method);
                     }
                     c::tag_table_vtable_map => {
-                        let vtable_res =
-                            val_dsr.read_vtable_res(xcx.dcx.tcx,
-                                                    xcx.dcx.cdata);
-                        dcx.maps.vtable_map.borrow_mut().insert(id, vtable_res);
+                        let (autoderef, vtable_res) =
+                            val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
+                                                             xcx.dcx.cdata);
+                        let vtable_key = MethodCall {
+                            expr_id: id,
+                            autoderef: autoderef
+                        };
+                        dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
                     }
                     c::tag_table_adjustments => {
                         let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index e1b3419877756..8d7cff98f42be 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -129,7 +129,7 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt,
         let maps = astencode::Maps {
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(NodeMap::new()),
+            vtable_map: @RefCell::new(FnvHashMap::new()),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, enum_def,
@@ -170,7 +170,7 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
         let maps = astencode::Maps {
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(NodeMap::new()),
+            vtable_map: @RefCell::new(FnvHashMap::new()),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, def_id,
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 5ab94240357be..92b97cdfc9f02 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -170,16 +170,11 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
     let _icx = push_ctxt("trans_fn_ref");
 
     let type_params = node_id_type_params(bcx, node);
-    let vtables = match node {
-        ExprId(id) => node_vtables(bcx, id),
-        MethodCall(ref method_call) => {
-            if method_call.autoderef == 0 {
-                node_vtables(bcx, method_call.expr_id)
-            } else {
-                None
-            }
-        }
+    let vtable_key = match node {
+        ExprId(id) => MethodCall::expr(id),
+        MethodCall(method_call) => method_call
     };
+    let vtables = node_vtables(bcx, vtable_key);
     debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
            def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
            vtables.repr(bcx.tcx()));
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index b5b68a521a87f..9787e9228bf91 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -829,7 +829,7 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
     }
 }
 
-pub fn node_vtables(bcx: &Block, id: ast::NodeId)
+pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
                  -> Option<typeck::vtable_res> {
     let vtable_map = bcx.ccx().maps.vtable_map.borrow();
     let raw_vtables = vtable_map.find(&id);
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index c5e4fa49f64be..4701f38c09a8b 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -208,7 +208,8 @@ pub fn trans_static_method_callee(bcx: &Block,
     debug!("trans_static_method_callee: method_id={:?}, expr_id={:?}, \
             name={}", method_id, expr_id, token::get_name(mname));
 
-    let vtbls = ccx.maps.vtable_map.borrow().get_copy(&expr_id);
+    let vtable_key = MethodCall::expr(expr_id);
+    let vtbls = ccx.maps.vtable_map.borrow().get_copy(&vtable_key);
     let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
 
     match vtbls.get(bound_index).get(0) {
@@ -327,16 +328,11 @@ 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 vtables = match node {
-        ExprId(id) => node_vtables(bcx, id),
-        MethodCall(method_call) => {
-            if method_call.autoderef == 0 {
-                node_vtables(bcx, method_call.expr_id)
-            } else {
-                None
-            }
-        }
+    let vtable_key = match node {
+        ExprId(id) => MethodCall::expr(id),
+        MethodCall(method_call) => method_call
     };
+    let vtables = node_vtables(bcx, vtable_key);
     let r_m_origins = match vtables {
         Some(vt) => vt,
         None => @Vec::from_elem(node_substs.len(), @Vec::new())
@@ -597,10 +593,8 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
     bcx = datum.store_to(bcx, llboxdest);
 
     // Store the vtable into the second half of pair.
-    // This is structured a bit funny because of dynamic borrow failures.
-    let res = *ccx.maps.vtable_map.borrow().get(&id);
-    let res = resolve_vtables_in_fn_ctxt(bcx.fcx, res);
-    let origins = *res.get(0);
+    let res = *ccx.maps.vtable_map.borrow().get(&MethodCall::expr(id));
+    let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0);
     let vtable = get_vtable(bcx, v_ty, origins);
     let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
     let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index d4fd8d4392731..2410390b5e74d 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -267,7 +267,7 @@ impl<'a> Inherited<'a> {
             node_type_substs: RefCell::new(NodeMap::new()),
             adjustments: RefCell::new(NodeMap::new()),
             method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(NodeMap::new()),
+            vtable_map: @RefCell::new(FnvHashMap::new()),
             upvar_borrow_map: RefCell::new(HashMap::new()),
         }
     }
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 29f481f9c04df..15de3bf2b5f8e 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -516,10 +516,10 @@ fn connect_trait_tps(vcx: &VtableContext,
     relate_trait_refs(vcx, span, impl_trait_ref, trait_ref);
 }
 
-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().insert(expr_id, vtables);
+fn insert_vtables(fcx: &FnCtxt, vtable_key: MethodCall, vtables: vtable_res) {
+    debug!("insert_vtables(vtable_key={}, vtables={:?})",
+           vtable_key, vtables.repr(fcx.tcx()));
+    fcx.inh.vtable_map.borrow_mut().insert(vtable_key, vtables);
 }
 
 pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
@@ -591,7 +591,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                                      is_early);
 
                       if !is_early {
-                          insert_vtables(fcx, ex.id, @vec!(vtables));
+                          insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables));
                       }
 
                       // Now, if this is &trait, we need to link the
@@ -648,7 +648,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                            item_ty.generics.type_param_defs(),
                                            substs, is_early);
                 if !is_early {
-                    insert_vtables(fcx, ex.id, vtbls);
+                    insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
                 }
             }
             true
@@ -673,7 +673,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                            type_param_defs.as_slice(),
                                            &substs, is_early);
                 if !is_early {
-                    insert_vtables(fcx, ex.id, vtbls);
+                    insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
                 }
             }
           }
@@ -692,6 +692,30 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     match fcx.inh.adjustments.borrow().find(&ex.id) {
         Some(adjustment) => {
             match **adjustment {
+                AutoDerefRef(adj) => {
+                    for autoderef in range(0, adj.autoderefs) {
+                        let method_call = MethodCall::autoderef(ex.id, autoderef as u32);
+                        match fcx.inh.method_map.borrow().find(&method_call) {
+                            Some(method) => {
+                                debug!("vtable resolution on parameter bounds for autoderef {}",
+                                       ex.repr(fcx.tcx()));
+                                let type_param_defs =
+                                    ty::method_call_type_param_defs(cx.tcx, method.origin);
+                                if has_trait_bounds(type_param_defs.deref().as_slice()) {
+                                    let vcx = fcx.vtable_context();
+                                    let vtbls = lookup_vtables(&vcx, ex.span,
+                                                               type_param_defs.deref()
+                                                               .as_slice(),
+                                                               &method.substs, is_early);
+                                    if !is_early {
+                                        insert_vtables(fcx, method_call, vtbls);
+                                    }
+                                }
+                            }
+                            None => {}
+                        }
+                    }
+                }
                 AutoObject(ref sigil,
                            ref region,
                            m,
@@ -713,7 +737,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                                                b);
                     resolve_object_cast(ex, object_ty);
                 }
-                AutoAddEnv(..) | AutoDerefRef(..) => {}
+                AutoAddEnv(..) => {}
             }
         }
         None => {}
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 688baa18c95d1..31d74a1e938aa 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -21,8 +21,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region};
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
 use middle::typeck::{MethodCall, MethodCallee};
-use middle::typeck::{vtable_res, vtable_origin};
-use middle::typeck::{vtable_static, vtable_param};
+use middle::typeck::{vtable_res, vtable_static, vtable_param};
 use middle::typeck::write_substs_to_tcx;
 use middle::typeck::write_ty_to_tcx;
 use util::ppaux;
@@ -100,38 +99,34 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
     }
 }
 
-fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, id: ast::NodeId) {
+fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
     // Resolve any vtable map entry
-    match fcx.inh.vtable_map.borrow().find_copy(&id) {
+    match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) {
         Some(origins) => {
             let r_origins = resolve_origins(fcx, sp, origins);
-            fcx.ccx.vtable_map.borrow_mut().insert(id, r_origins);
-            debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
-                    id, r_origins.repr(fcx.tcx()));
+            fcx.ccx.vtable_map.borrow_mut().insert(vtable_key, r_origins);
+            debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
+                    vtable_key, r_origins.repr(fcx.tcx()));
         }
         None => {}
     }
 
     fn resolve_origins(fcx: &FnCtxt, sp: Span,
                        vtbls: vtable_res) -> vtable_res {
-        @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o)))
-    }
-
-    fn resolve_origin(fcx: &FnCtxt,
-                      sp: Span,
-                      origin: &vtable_origin) -> vtable_origin {
-        match origin {
-            &vtable_static(def_id, ref tys, origins) => {
-                let r_tys = resolve_type_vars_in_types(fcx,
-                                                       sp,
-                                                       tys.as_slice());
-                let r_origins = resolve_origins(fcx, sp, origins);
-                vtable_static(def_id, r_tys, r_origins)
-            }
-            &vtable_param(n, b) => {
-                vtable_param(n, b)
+        @vtbls.map(|os| @os.map(|origin| {
+            match origin {
+                &vtable_static(def_id, ref tys, origins) => {
+                    let r_tys = resolve_type_vars_in_types(fcx,
+                                                           sp,
+                                                           tys.as_slice());
+                    let r_origins = resolve_origins(fcx, sp, origins);
+                    vtable_static(def_id, r_tys, r_origins)
+                }
+                &vtable_param(n, b) => {
+                    vtable_param(n, b)
+                }
             }
-        }
+        }))
     }
 }
 
@@ -183,6 +178,7 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                     for autoderef in range(0, adj.autoderefs) {
                         let method_call = MethodCall::autoderef(id, autoderef as u32);
                         resolve_method_map_entry(wbcx, sp, method_call);
+                        resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
                     }
 
                     let fixup_region = |r| {
@@ -273,7 +269,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
 
     resolve_type_vars_for_node(wbcx, e.span, e.id);
     resolve_method_map_entry(wbcx, e.span, MethodCall::expr(e.id));
-    resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
+    resolve_vtable_map_entry(wbcx.fcx, e.span, MethodCall::expr(e.id));
 
     match e.node {
         ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 22881b26f63e6..b33819ff7f464 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -68,7 +68,7 @@ use middle::ty;
 use util::common::time;
 use util::ppaux::Repr;
 use util::ppaux;
-use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
+use util::nodemap::{DefIdMap, FnvHashMap};
 
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -148,7 +148,7 @@ pub struct MethodCallee {
     substs: ty::substs
 }
 
-#[deriving(Clone, Eq, Hash)]
+#[deriving(Clone, Eq, Hash, Show)]
 pub struct MethodCall {
     expr_id: ast::NodeId,
     autoderef: u32
@@ -216,7 +216,7 @@ impl Repr for vtable_origin {
     }
 }
 
-pub type vtable_map = @RefCell<NodeMap<vtable_res>>;
+pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>;
 
 
 // Information about the vtable resolutions for a trait impl.
@@ -461,7 +461,7 @@ pub fn check_crate(tcx: &ty::ctxt,
     let ccx = CrateCtxt {
         trait_map: trait_map,
         method_map: @RefCell::new(FnvHashMap::new()),
-        vtable_map: @RefCell::new(NodeMap::new()),
+        vtable_map: @RefCell::new(FnvHashMap::new()),
         tcx: tcx
     };
 
diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs
new file mode 100644
index 0000000000000..65a404d1ff362
--- /dev/null
+++ b/src/test/auxiliary/overloaded_autoderef_xc.rs
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Deref;
+
+struct DerefWithHelper<H, T> {
+    helper: H
+}
+
+trait Helper<T> {
+    fn helper_borrow<'a>(&'a self) -> &'a T;
+}
+
+impl<T> Helper<T> for Option<T> {
+    fn helper_borrow<'a>(&'a self) -> &'a T {
+        self.as_ref().unwrap()
+    }
+}
+
+impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
+    fn deref<'a>(&'a self) -> &'a T {
+        self.helper.helper_borrow()
+    }
+}
+
+// Test cross-crate autoderef + vtable.
+pub fn check<T: Eq>(x: T, y: T) -> bool {
+    let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
+    d.eq(&y)
+}
diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs
new file mode 100644
index 0000000000000..15b5cca9cf83e
--- /dev/null
+++ b/src/test/run-pass/overloaded-autoderef-vtable.rs
@@ -0,0 +1,42 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Deref;
+
+struct DerefWithHelper<H, T> {
+    helper: H
+}
+
+trait Helper<T> {
+    fn helper_borrow<'a>(&'a self) -> &'a T;
+}
+
+impl<T> Helper<T> for Option<T> {
+    fn helper_borrow<'a>(&'a self) -> &'a T {
+        self.as_ref().unwrap()
+    }
+}
+
+impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
+    fn deref<'a>(&'a self) -> &'a T {
+        self.helper.helper_borrow()
+    }
+}
+
+struct Foo {x: int}
+
+impl Foo {
+    fn foo(&self) -> int {self.x}
+}
+
+pub fn main() {
+    let x: DerefWithHelper<Option<Foo>, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) };
+    assert!(x.foo() == 5);
+}
diff --git a/src/test/run-pass/overloaded-autoderef-xcrate.rs b/src/test/run-pass/overloaded-autoderef-xcrate.rs
new file mode 100644
index 0000000000000..fc969093d23a9
--- /dev/null
+++ b/src/test/run-pass/overloaded-autoderef-xcrate.rs
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-fast
+// aux-build:overloaded_autoderef_xc.rs
+
+extern crate overloaded_autoderef_xc;
+
+fn main() {
+    assert!(overloaded_autoderef_xc::check(5, 5));
+}