diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 7d515fe62b5..6604ef5df34 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -174,14 +174,6 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
     None
 }
 
-fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) ->
-        Option<ast::def_id> {
-    let trait_did_opt = item_parent_item(d);
-    do trait_did_opt.map |trait_did| {
-        ast::def_id { crate: cnum, node: trait_did.node }
-    }
-}
-
 fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
                                         d: ebml::Doc) -> ast::def_id {
     let trait_did = item_parent_item(d).expect("item without parent");
@@ -323,13 +315,19 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
         UnsafeFn  => dl_def(ast::def_fn(did, ast::unsafe_fn)),
         Fn        => dl_def(ast::def_fn(did, ast::impure_fn)),
         ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
-        UnsafeStaticMethod => {
-            let trait_did_opt = translated_parent_item_opt(cnum, item);
-            dl_def(ast::def_static_method(did, trait_did_opt, ast::unsafe_fn))
-        }
-        StaticMethod => {
-            let trait_did_opt = translated_parent_item_opt(cnum, item);
-            dl_def(ast::def_static_method(did, trait_did_opt, ast::impure_fn))
+        StaticMethod | UnsafeStaticMethod => {
+            let purity = if fam == UnsafeStaticMethod { ast::unsafe_fn } else
+                { ast::impure_fn };
+            // def_static_method carries an optional field of its enclosing
+            // *trait*, but not an inclosing Impl (if this is an inherent
+            // static method). So we need to detect whether this is in
+            // a trait or not, which we do through the mildly hacky
+            // way of checking whether there is a trait_method_sort.
+            let trait_did_opt = if reader::maybe_get_doc(
+                  item, tag_item_trait_method_sort).is_some() {
+                Some(item_reqd_and_translated_parent_item(cnum, item))
+            } else { None };
+            dl_def(ast::def_static_method(did, trait_did_opt, purity))
         }
         Type | ForeignType => dl_def(ast::def_ty(did)),
         Mod => dl_def(ast::def_mod(did)),
@@ -837,6 +835,8 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
 {
     let method_doc = lookup_item(id, cdata.data);
     let def_id = item_def_id(method_doc, cdata);
+    let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
+                                                            method_doc);
     let name = item_name(intr, method_doc);
     let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
                                              tag_item_method_tps);
@@ -855,7 +855,9 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
         fty,
         explicit_self,
         vis,
-        def_id
+        def_id,
+        container_id,
+        None
     )
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 722f8ff9580..aa4f5d0267c 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -772,6 +772,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
     let method_def_id = local_def(m.id);
     let method_ty = ty::method(ecx.tcx, method_def_id);
     encode_method_ty_fields(ecx, ebml_w, method_ty);
+    encode_parent_item(ebml_w, local_def(parent_id));
 
     match m.explicit_self.node {
         ast::sty_static => {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 036c0751483..c602a143253 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -106,29 +106,6 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
         }
     };
 
-    // Returns the ID of the container (impl or trait) that a crate-local
-    // method belongs to.
-    let local_method_container_id:
-            @fn(span: span, method_id: node_id) -> def_id =
-            |span, method_id| {
-        match tcx.items.find(&method_id) {
-            Some(&node_method(_, impl_id, _)) => impl_id,
-            Some(&node_trait_method(_, trait_id, _)) => trait_id,
-            Some(_) => {
-                tcx.sess.span_bug(span,
-                                  fmt!("method was a %s?!",
-                                       ast_map::node_id_to_str(
-                                            tcx.items,
-                                            method_id,
-                                           token::get_ident_interner())));
-            }
-            None => {
-                tcx.sess.span_bug(span, "method not found in \
-                                         AST map?!");
-            }
-        }
-    };
-
     // Returns true if a crate-local method is private and false otherwise.
     let method_is_private: @fn(span: span, method_id: node_id) -> bool =
             |span, method_id| {
@@ -248,15 +225,12 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
         // If the method is a default method, we need to use the def_id of
         // the default implementation.
         // Having to do this this is really unfortunate.
-        let method_id = match tcx.provided_method_sources.find(&method_id) {
-            None => method_id,
-            Some(source) => source.method_id
-        };
+        let method_id = ty::method(tcx, method_id).provided_source
+            .get_or_default(method_id);
 
         if method_id.crate == local_crate {
             let is_private = method_is_private(span, method_id.node);
-            let container_id = local_method_container_id(span,
-                                                         method_id.node);
+            let container_id = ty::method(tcx, method_id).container_id;
             if is_private &&
                     (container_id.crate != local_crate ||
                      !privileged_items.iter().any(|x| x == &(container_id.node))) {
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 588b0b5c75f..6741637ae9a 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -524,7 +524,6 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
                                                     &tsubsts,
                                                     None,
                                                     None,
-                                                    None,
                                                     None);
 
         val
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 0885c5086e8..f03a2a62e0c 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -296,10 +296,10 @@ pub fn trans_fn_ref_with_vtables(
     // We need to do a bunch of special handling for default methods.
     // We need to modify the def_id and our substs in order to monomorphize
     // the function.
-    let (def_id, opt_impl_did, substs, self_vtable, vtables) =
-        match tcx.provided_method_sources.find(&def_id) {
-        None => (def_id, None, substs, None, vtables),
-        Some(source) => {
+    let (is_default, def_id, substs, self_vtable, vtables) =
+        match ty::provided_source(tcx, def_id) {
+        None => (false, def_id, substs, None, vtables),
+        Some(source_id) => {
             // There are two relevant substitutions when compiling
             // default methods. First, there is the substitution for
             // the type parameters of the impl we are using and the
@@ -313,10 +313,11 @@ pub fn trans_fn_ref_with_vtables(
             // So, what we need to do is find this substitution and
             // compose it with the one we already have.
 
-            let trait_ref = ty::impl_trait_ref(tcx, source.impl_id)
+            let impl_id = ty::method(tcx, def_id).container_id;
+            let method = ty::method(tcx, source_id);
+            let trait_ref = ty::impl_trait_ref(tcx, impl_id)
                 .expect("could not find trait_ref for impl with \
                          default methods");
-            let method = ty::method(tcx, source.method_id);
 
             // Get all of the type params for the receiver
             let param_defs = method.generics.type_param_defs;
@@ -330,18 +331,18 @@ pub fn trans_fn_ref_with_vtables(
             };
 
             let self_vtable =
-                typeck::vtable_static(source.impl_id, receiver_substs,
+                typeck::vtable_static(impl_id, receiver_substs,
                                       receiver_vtables);
             // Compute the first substitution
             let first_subst = make_substs_for_receiver_types(
-                tcx, source.impl_id, trait_ref, method);
+                tcx, impl_id, trait_ref, method);
 
             // And compose them
             let new_substs = first_subst.subst(tcx, &substs);
 
 
             let vtables =
-                resolve_default_method_vtables(bcx, source.impl_id,
+                resolve_default_method_vtables(bcx, impl_id,
                                                method, &new_substs, vtables);
 
             debug!("trans_fn_with_vtables - default method: \
@@ -352,7 +353,7 @@ pub fn trans_fn_ref_with_vtables(
                    first_subst.repr(tcx), new_substs.repr(tcx),
                    self_vtable.repr(tcx), vtables.repr(tcx));
 
-            (source.method_id, Some(source.impl_id),
+            (true, source_id,
              new_substs, Some(self_vtable), Some(vtables))
         }
     };
@@ -372,7 +373,7 @@ pub fn trans_fn_ref_with_vtables(
     // intrinsic that is inlined from a different crate, we want to reemit the
     // intrinsic instead of trying to call it in the other crate.
     let must_monomorphise;
-    if type_params.len() > 0 || opt_impl_did.is_some() {
+    if type_params.len() > 0 || is_default {
         must_monomorphise = true;
     } else if def_id.crate == ast::local_crate {
         let map_node = session::expect(
@@ -400,7 +401,7 @@ pub fn trans_fn_ref_with_vtables(
         let (val, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs,
                                          vtables, self_vtable,
-                                         opt_impl_did, Some(ref_id));
+                                         Some(ref_id));
         let mut val = val;
         if must_cast && ref_id != 0 {
             // Monotype of the REFERENCE to the function (type params
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 29cc8d81973..d90614ebc02 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -938,8 +938,7 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
 #[deriving(Eq,IterBytes)]
 pub struct mono_id_ {
     def: ast::def_id,
-    params: ~[mono_param_id],
-    impl_did_opt: Option<ast::def_id>
+    params: ~[mono_param_id]
 }
 
 pub type mono_id = @mono_id_;
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 03dbe0869fb..bcf3aa6ad50 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -617,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext,
             monomorphize::make_mono_id(
                 ccx,
                 impl_id,
-                None,
                 &psubsts,
                 None)
         }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 3e5f7267972..789532abc61 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -42,7 +42,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
                       real_substs: &ty::substs,
                       vtables: Option<typeck::vtable_res>,
                       self_vtable: Option<typeck::vtable_origin>,
-                      impl_did_opt: Option<ast::def_id>,
                       ref_id: Option<ast::node_id>)
     -> (ValueRef, bool)
 {
@@ -51,13 +50,11 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
             real_substs=%s, \
             vtables=%s, \
             self_vtable=%s, \
-            impl_did_opt=%s, \
             ref_id=%?)",
            fn_id.repr(ccx.tcx),
            real_substs.repr(ccx.tcx),
            vtables.repr(ccx.tcx),
            self_vtable.repr(ccx.tcx),
-           impl_did_opt.repr(ccx.tcx),
            ref_id);
 
     assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
@@ -83,9 +80,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len());
 
 
-    let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
-                               &*psubsts,
-                               Some(param_uses));
+    let hash_id = make_mono_id(ccx, fn_id, &*psubsts, Some(param_uses));
     if hash_id.params.iter().any(
                 |p| match *p { mono_precise(_, _) => false, _ => true }) {
         must_cast = true;
@@ -367,7 +362,6 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
 
 pub fn make_mono_id(ccx: @mut CrateContext,
                     item: ast::def_id,
-                    impl_did_opt: Option<ast::def_id>,
                     substs: &param_substs,
                     param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
     // FIXME (possibly #5801): Need a lot of type hints to get
@@ -442,5 +436,5 @@ pub fn make_mono_id(ccx: @mut CrateContext,
           }).collect()
       }
     };
-    @mono_id_ {def: item, params: param_ids, impl_did_opt: impl_did_opt}
+    @mono_id_ {def: item, params: param_ids}
 }
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 2c63079ad8f..53c290ec029 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -90,7 +90,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
     // used.  This is imprecise, but simple. Getting it right is
     // tricky because the substs on the call and the substs on the
     // default method differ, because of substs on the trait/impl.
-    let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc);
+    let is_default = ty::provided_source(ccx.tcx, fn_id_loc).is_some();
     // We also mark all of the params as used if it is an extern thing
     // that we haven't been able to inline yet.
     if is_default || fn_id_loc.crate != local_crate {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 6f3c3d9037e..b63117d25bb 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -64,7 +64,11 @@ pub struct Method {
     fty: BareFnTy,
     explicit_self: ast::explicit_self_,
     vis: ast::visibility,
-    def_id: ast::def_id
+    def_id: ast::def_id,
+    container_id: ast::def_id,
+
+    // If this method is provided, we need to know where it came from
+    provided_source: Option<ast::def_id>
 }
 
 impl Method {
@@ -74,7 +78,9 @@ impl Method {
                fty: BareFnTy,
                explicit_self: ast::explicit_self_,
                vis: ast::visibility,
-               def_id: ast::def_id)
+               def_id: ast::def_id,
+               container_id: ast::def_id,
+               provided_source: Option<ast::def_id>)
                -> Method {
         // Check the invariants.
         if explicit_self == ast::sty_static {
@@ -90,7 +96,9 @@ impl Method {
             fty: fty,
             explicit_self: explicit_self,
             vis: vis,
-            def_id: def_id
+            def_id: def_id,
+            container_id: container_id,
+            provided_source: provided_source
         }
     }
 }
@@ -219,11 +227,6 @@ pub enum AutoRef {
     AutoUnsafe(ast::mutability)
 }
 
-pub struct ProvidedMethodSource {
-    method_id: ast::def_id,
-    impl_id: ast::def_id
-}
-
 pub type ctxt = @ctxt_;
 
 struct ctxt_ {
@@ -278,7 +281,7 @@ struct ctxt_ {
     normalized_cache: @mut HashMap<t, t>,
     lang_items: middle::lang_items::LanguageItems,
     // A mapping of fake provided method def_ids to the default implementation
-    provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
+    provided_method_sources: @mut HashMap<ast::def_id, ast::def_id>,
     supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
 
     // A mapping from the def ID of an enum or struct type to the def ID
@@ -3511,6 +3514,11 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
     }
 }
 
+pub fn provided_source(cx: ctxt, id: ast::def_id)
+    -> Option<ast::def_id> {
+    cx.provided_method_sources.find(&id).map(|x| **x)
+}
+
 pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@Method] {
     if is_local(id) {
         match cx.items.find(&id.node) {
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 2bdb2f2932a..51b206428e3 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -19,7 +19,7 @@ use metadata::csearch::{each_path, get_impl_trait};
 use metadata::csearch;
 use metadata::cstore::iter_crate_data;
 use metadata::decoder::{dl_def, dl_field, dl_impl};
-use middle::ty::{ProvidedMethodSource, get};
+use middle::ty::get;
 use middle::ty::{lookup_item_type, subst};
 use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
 use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
@@ -303,7 +303,8 @@ impl CoherenceChecker {
                     impl_id,
                     trait_ref,
                     new_did,
-                    *trait_method);
+                    *trait_method,
+                    Some(trait_method.def_id));
 
             debug!("new_method_ty=%s", new_method_ty.repr(tcx));
             all_methods.push(new_method_ty);
@@ -328,13 +329,8 @@ impl CoherenceChecker {
 
             // Pair the new synthesized ID up with the
             // ID of the method.
-            let source = ProvidedMethodSource {
-                method_id: trait_method.def_id,
-                impl_id: impl_id
-            };
-
-            self.crate_context.tcx.provided_method_sources.insert(new_did,
-                                                                  source);
+            self.crate_context.tcx.provided_method_sources
+                .insert(new_did, trait_method.def_id);
         }
     }
 
@@ -864,7 +860,8 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
                                      impl_id: ast::def_id,
                                      trait_ref: &ty::TraitRef,
                                      new_def_id: ast::def_id,
-                                     method: &ty::Method)
+                                     method: &ty::Method,
+                                     provided_source: Option<ast::def_id>)
                                      -> ty::Method {
 
     let combined_substs = make_substs_for_receiver_types(
@@ -884,7 +881,9 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
 
         method.explicit_self,
         method.vis,
-        new_def_id
+        new_def_id,
+        impl_id,
+        provided_source
     )
 }
 
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 791774999c2..1941317ede5 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -376,7 +376,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
             m_explicit_self.node,
             // assume public, because this is only invoked on trait methods
             ast::public,
-            local_def(*m_id)
+            local_def(*m_id),
+            local_def(trait_id),
+            None
         )
     }
 }
@@ -720,6 +722,7 @@ pub struct ConvertedMethod {
 }
 
 pub fn convert_methods(ccx: &CrateCtxt,
+                       container_id: ast::node_id,
                        ms: &[@ast::method],
                        untransformed_rcvr_ty: ty::t,
                        rcvr_ty_generics: &ty::Generics,
@@ -734,7 +737,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
             ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
                         num_rcvr_ty_params);
         let mty =
-            @ty_of_method(ccx, *m, rcvr_ty_generics.region_param,
+            @ty_of_method(ccx, container_id, *m, rcvr_ty_generics.region_param,
                           untransformed_rcvr_ty,
                           rcvr_ast_generics, rcvr_visibility,
                           &m.generics);
@@ -760,6 +763,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
     }).collect();
 
     fn ty_of_method(ccx: &CrateCtxt,
+                    container_id: ast::node_id,
                     m: &ast::method,
                     rp: Option<ty::region_variance>,
                     untransformed_rcvr_ty: ty::t,
@@ -790,7 +794,9 @@ pub fn convert_methods(ccx: &CrateCtxt,
             fty,
             m.explicit_self.node,
             method_vis,
-            local_def(m.id)
+            local_def(m.id),
+            local_def(container_id),
+            None
         )
     }
 }
@@ -849,7 +855,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
             it.vis
         };
 
-        let cms = convert_methods(ccx, *ms, selfty,
+        let cms = convert_methods(ccx, it.id, *ms, selfty,
                                   &i_ty_generics, generics,
                                   parent_visibility);
         for opt_trait_ref.iter().advance |t| {
@@ -867,7 +873,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
           let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
           let (ty_generics, _) = mk_item_substs(ccx, generics, rp,
                                                 Some(untransformed_rcvr_ty));
-          let _ = convert_methods(ccx, provided_methods,
+          let _ = convert_methods(ccx, it.id, provided_methods,
                                   untransformed_rcvr_ty,
                                   &ty_generics, generics,
                                   it.vis);