diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index b77f2b5b874..6735dc54053 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -309,8 +309,8 @@ fn trans_static_method_callee(bcx: block,
 }
 
 fn method_from_methods(ms: ~[@ast::method], name: ast::ident)
-    -> ast::def_id {
-  local_def(option::get(vec::find(ms, |m| m.ident == name)).id)
+    -> Option<ast::def_id> {
+    ms.find(|m| m.ident == name).map(|m| local_def(m.id))
 }
 
 fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
@@ -318,11 +318,43 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
     if impl_id.crate == ast::local_crate {
         match ccx.tcx.items.get(impl_id.node) {
           ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
-            method_from_methods(ms, name)
+            method_from_methods(ms, name).get()
           }
           ast_map::node_item(@{node:
               ast::item_class(struct_def, _), _}, _) => {
-            method_from_methods(struct_def.methods, name)
+            method_from_methods(struct_def.methods, name).get()
+          }
+          _ => fail ~"method_with_name"
+        }
+    } else {
+        csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
+    }
+}
+
+fn method_with_name_or_default(ccx: @crate_ctxt, impl_id: ast::def_id,
+                               name: ast::ident) -> ast::def_id {
+    if impl_id.crate == ast::local_crate {
+        match ccx.tcx.items.get(impl_id.node) {
+          ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
+              let did = method_from_methods(ms, name);
+              if did.is_some() {
+                  return did.get();
+              } else {
+                  // Look for a default method
+                  let pmm = ccx.tcx.provided_methods;
+                  match pmm.find(impl_id) {
+                      Some(pmis) => {
+                          for pmis.each |pmi| {
+                              if pmi.method_info.ident == name {
+                                  debug!("XXX %?", pmi.method_info.did);
+                                  return pmi.method_info.did;
+                              }
+                          }
+                          fail
+                      }
+                      None => fail
+                  }
+              }
           }
           _ => fail ~"method_with_name"
         }
@@ -333,10 +365,22 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
 
 fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id,
                          i_id: ast::def_id) -> uint {
+    debug!("mythod_ty_param_count: m_id: %?, i_id: %?", m_id, i_id);
     if m_id.crate == ast::local_crate {
-        match ccx.tcx.items.get(m_id.node) {
-          ast_map::node_method(m, _, _) => vec::len(m.tps),
-          _ => fail ~"method_ty_param_count"
+        match ccx.tcx.items.find(m_id.node) {
+            Some(ast_map::node_method(m, _, _)) => m.tps.len(),
+            None => {
+                match ccx.tcx.provided_method_sources.find(m_id) {
+                    Some(source) => {
+                        method_ty_param_count(ccx, source.method_id, source.impl_id)
+                    }
+                    None => fail
+                }
+            }
+            Some(ast_map::node_trait_method(@ast::provided(@m), _, _)) => {
+                m.tps.len()
+            }
+            e => fail fmt!("method_ty_param_count %?", e)
         }
     } else {
         csearch::get_type_param_count(ccx.sess.cstore, m_id) -
@@ -358,7 +402,8 @@ fn trans_monomorphized_callee(bcx: block,
       typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
           let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
-          let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
+          let mth_id = method_with_name_or_default(
+              bcx.ccx(), impl_did, mname);
 
           // obtain the `self` value:
           let Result {bcx, val: llself_val} =
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 58e01d42590..e3f2299b9d0 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -10,6 +10,7 @@
 
 #[warn(deprecated_pattern)];
 
+use core::dvec::DVec;
 use std::{map, smallintmap};
 use result::Result;
 use std::map::HashMap;
@@ -27,8 +28,11 @@ use middle::lint::{get_lint_level, allow};
 use syntax::ast::*;
 use syntax::print::pprust::*;
 use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
+use middle::resolve::{Impl, MethodInfo};
 
 export ProvidedMethodSource;
+export ProvidedMethodInfo;
+export ProvidedMethodsMap;
 export InstantiatedTraitRef;
 export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
 export br_hashmap;
@@ -352,6 +356,21 @@ enum AutoRefKind {
     AutoBorrowFn,
 }
 
+// Stores information about provided methods (a.k.a. default methods) in
+// implementations.
+//
+// This is a map from ID of each implementation to the method info and trait
+// method ID of each of the default methods belonging to the trait that that
+// implementation implements.
+type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
+
+// Stores the method info and definition ID of the associated trait method for
+// each instantiation of each provided method.
+struct ProvidedMethodInfo {
+    method_info: @MethodInfo,
+    trait_method_def_id: def_id
+}
+
 struct ProvidedMethodSource {
     method_id: ast::def_id,
     impl_id: ast::def_id
@@ -416,6 +435,10 @@ type ctxt =
       normalized_cache: HashMap<t, t>,
       lang_items: middle::lang_items::LanguageItems,
       legacy_boxed_traits: HashMap<node_id, ()>,
+      // A mapping from an implementation ID to the method info and trait method
+      // ID of the provided (a.k.a. default) methods in the traits that that
+      // implementation implements.
+      provided_methods: ProvidedMethodsMap,
       provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
       supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
       deriving_struct_methods: HashMap<ast::def_id, @~[DerivedFieldInfo]>,
@@ -975,6 +998,7 @@ fn mk_ctxt(s: session::Session,
       normalized_cache: new_ty_hash(),
       lang_items: move lang_items,
       legacy_boxed_traits: HashMap(),
+      provided_methods: HashMap(),
       provided_method_sources: HashMap(),
       supertraits: HashMap(),
       deriving_struct_methods: HashMap(),
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 37bc4bfae69..f1b009c40df 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -79,7 +79,7 @@ obtained the type `Foo`, we would never match this method.
 
 */
 
-use coherence::{ProvidedMethodInfo, get_base_type_def_id};
+use coherence::get_base_type_def_id;
 use middle::resolve::{Impl, MethodInfo};
 use middle::ty::*;
 use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box,
@@ -313,7 +313,7 @@ impl LookupContext {
                 }
 
                 // Look for default methods.
-                match coherence_info.provided_methods.find(*trait_did) {
+                match self.tcx().provided_methods.find(*trait_did) {
                     Some(methods) => {
                         self.push_candidates_from_provided_methods(
                             &self.extension_candidates, self_ty, *trait_did,
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index c1517d11f73..7c4bab959b5 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -19,7 +19,7 @@ use metadata::csearch::{get_impls_for_mod};
 use metadata::cstore::{CStore, iter_crate_data};
 use metadata::decoder::{dl_def, dl_field, dl_impl};
 use middle::resolve::{Impl, MethodInfo};
-use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, get};
+use middle::ty::{DerivedMethodInfo, ProvidedMethodSource, ProvidedMethodInfo, get};
 use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_class};
 use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
 use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
@@ -130,21 +130,6 @@ fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
     }
 }
 
-// Stores the method info and definition ID of the associated trait method for
-// each instantiation of each provided method.
-struct ProvidedMethodInfo {
-    method_info: @MethodInfo,
-    trait_method_def_id: def_id
-}
-
-// Stores information about provided methods (a.k.a. default methods) in
-// implementations.
-//
-// This is a map from ID of each implementation to the method info and trait
-// method ID of each of the default methods belonging to the trait that that
-// implementation implements.
-type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
-
 struct CoherenceInfo {
     // Contains implementations of methods that are inherent to a type.
     // Methods in these implementations don't need to be exported.
@@ -154,17 +139,12 @@ struct CoherenceInfo {
     // the associated trait must be imported at the call site.
     extension_methods: HashMap<def_id,@DVec<@Impl>>,
 
-    // A mapping from an implementation ID to the method info and trait method
-    // ID of the provided (a.k.a. default) methods in the traits that that
-    // implementation implements.
-    provided_methods: ProvidedMethodsMap,
 }
 
 fn CoherenceInfo() -> CoherenceInfo {
     CoherenceInfo {
         inherent_methods: HashMap(),
         extension_methods: HashMap(),
-        provided_methods: HashMap(),
     }
 }
 
@@ -350,7 +330,7 @@ impl CoherenceChecker {
                     trait_method_def_id: trait_method.def_id
                 };
 
-            let pmm = self.crate_context.coherence_info.provided_methods;
+            let pmm = self.crate_context.tcx.provided_methods;
             match pmm.find(local_def(impl_id)) {
                 Some(mis) => {
                     // If the trait already has an entry in the
@@ -765,8 +745,7 @@ impl CoherenceChecker {
                     let trait_did =
                         self.trait_ref_to_trait_def_id(*trait_ref);
 
-                    match self.crate_context
-                              .coherence_info
+                    match self.crate_context.tcx
                               .provided_methods
                               .find(local_def(item.id)) {
                         None => {
@@ -925,7 +904,7 @@ impl CoherenceChecker {
 
     fn add_default_methods_for_external_trait(trait_def_id: ast::def_id) {
         let tcx = self.crate_context.tcx;
-        let pmm = self.crate_context.coherence_info.provided_methods;
+        let pmm = tcx.provided_methods;
 
         if pmm.contains_key(trait_def_id) { return; }
 
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index f9f3ac2d45c..6af374353ab 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -88,6 +88,7 @@ export vtable_origin;
 export method_static, method_param, method_trait, method_self;
 export vtable_static, vtable_param, vtable_trait;
 export provided_methods_map;
+export coherence;
 
 #[legacy_exports]
 #[path = "check/mod.rs"]
@@ -380,7 +381,7 @@ fn check_for_main_fn(ccx: @crate_ctxt) {
 fn check_crate(tcx: ty::ctxt,
                trait_map: resolve::TraitMap,
                crate: @ast::crate)
-            -> (method_map, vtable_map) {
+    -> (method_map, vtable_map) {
 
     let ccx = @crate_ctxt_({trait_map: trait_map,
                             method_map: std::map::HashMap(),
diff --git a/src/test/run-pass/trait-default-method-bound-subst.rs b/src/test/run-pass/trait-default-method-bound-subst.rs
new file mode 100644
index 00000000000..9fbb3562a7b
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-bound-subst.rs
@@ -0,0 +1,15 @@
+// xfail-test
+
+trait A<T> {
+    fn g<U>(x: T, y: U) -> (T, U) { (move x, move y) }
+}
+
+impl int: A<int> { }
+
+fn f<T, U, V: A<T>>(i: V, j: T, k: U) -> (T, U) {
+    i.g(move j, move k)
+}
+
+fn main () {
+    assert f(0, 1, 2) == (1, 2);
+}
diff --git a/src/test/run-pass/trait-default-method-bound-subst2.rs b/src/test/run-pass/trait-default-method-bound-subst2.rs
new file mode 100644
index 00000000000..1cc35b85340
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-bound-subst2.rs
@@ -0,0 +1,15 @@
+// xfail-test
+
+trait A<T> {
+    fn g(x: T) -> T { move x }
+}
+
+impl int: A<int> { }
+
+fn f<T, V: A<T>>(i: V, j: T) -> T {
+    i.g(move j)
+}
+
+fn main () {
+    assert f(0, 2) == 2;
+}
diff --git a/src/test/run-pass/trait-default-method-bound-subst3.rs b/src/test/run-pass/trait-default-method-bound-subst3.rs
new file mode 100644
index 00000000000..dafee149a2e
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-bound-subst3.rs
@@ -0,0 +1,14 @@
+trait A {
+    fn g<T>(x: T, y: T) -> (T, T) { (move x, move y) }
+}
+
+impl int: A { }
+
+fn f<T, V: A>(i: V, j: T, k: T) -> (T, T) {
+    i.g(move j, move k)
+}
+
+fn main () {
+    assert f(0, 1, 2) == (1, 2);
+    assert f(0, 1u8, 2u8) == (1u8, 2u8);
+}
diff --git a/src/test/run-pass/trait-default-method-bound-subst4.rs b/src/test/run-pass/trait-default-method-bound-subst4.rs
new file mode 100644
index 00000000000..eeeefd041af
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-bound-subst4.rs
@@ -0,0 +1,14 @@
+trait A<T> {
+    fn g(x: uint) -> uint { move x }
+}
+
+impl<T> int: A<T> { }
+
+fn f<T, V: A<T>>(i: V, j: uint) -> uint {
+    i.g(move j)
+}
+
+fn main () {
+    assert f::<float, int>(0, 2u) == 2u;
+    assert f::<uint, int>(0, 2u) == 2u;
+}
diff --git a/src/test/run-pass/trait-default-method-bound.rs b/src/test/run-pass/trait-default-method-bound.rs
new file mode 100644
index 00000000000..3d22a3fdd66
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-bound.rs
@@ -0,0 +1,13 @@
+trait A {
+    fn g() -> int { 10 }
+}
+
+impl int: A { }
+
+fn f<T: A>(i: T) {
+    assert i.g() == 10;
+}
+
+fn main () {
+    f(0);
+}