about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/csearch.rs10
-rw-r--r--src/librustc/metadata/decoder.rs64
-rw-r--r--src/librustc/metadata/encoder.rs233
-rw-r--r--src/librustc/middle/privacy.rs32
-rw-r--r--src/librustc/middle/resolve.rs18
-rw-r--r--src/librustc/middle/trans/base.rs1
-rw-r--r--src/librustc/middle/trans/callee.rs25
-rw-r--r--src/librustc/middle/trans/common.rs3
-rw-r--r--src/librustc/middle/trans/meth.rs88
-rw-r--r--src/librustc/middle/trans/monomorphize.rs10
-rw-r--r--src/librustc/middle/trans/type_use.rs2
-rw-r--r--src/librustc/middle/ty.rs114
-rw-r--r--src/librustc/middle/typeck/check/method.rs10
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs2
-rw-r--r--src/librustc/middle/typeck/coherence.rs324
-rw-r--r--src/librustc/middle/typeck/collect.rs16
-rw-r--r--src/librustc/middle/typeck/mod.rs2
-rw-r--r--src/test/auxiliary/trait_default_method_xc_aux_2.rs17
-rw-r--r--src/test/run-pass/trait-default-method-xc-2.rs25
20 files changed, 383 insertions, 615 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index ddd07c2cb27..645188ce5a4 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -179,6 +179,8 @@ pub static tag_mod_child: uint = 0x7e;
 pub static tag_misc_info: uint = 0x7f;
 pub static tag_misc_info_crate_items: uint = 0x80;
 
+pub static tag_item_method_provided_source: uint = 0x81;
+
 pub struct LinkMeta {
     name: @str,
     vers: @str,
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index f336b0f4e4c..993649492a4 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -15,7 +15,7 @@ use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
 use metadata;
-use middle::{ty, resolve};
+use middle::ty;
 
 use std::vec;
 use reader = extra::ebml::reader;
@@ -97,10 +97,10 @@ pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl(cstore: @mut cstore::CStore, impl_def_id: ast::def_id)
-                -> resolve::Impl {
-    let cdata = cstore::get_crate_data(cstore, impl_def_id.crate);
-    decoder::get_impl(cstore.intr, cdata, impl_def_id.node)
+pub fn get_impl(tcx: ty::ctxt, impl_def_id: ast::def_id)
+                -> ty::Impl {
+    let cdata = cstore::get_crate_data(tcx.cstore, impl_def_id.crate);
+    decoder::get_impl(tcx.cstore.intr, cdata, impl_def_id.node, tcx)
 }
 
 pub fn get_method(tcx: ty::ctxt, def: ast::def_id) -> ty::Method {
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index caa170605de..a77c6c6ab52 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -20,7 +20,7 @@ use metadata::decoder;
 use metadata::tydecode::{parse_ty_data, parse_def_id,
                          parse_type_param_def_data,
                          parse_bare_fn_ty_data, parse_trait_ref_data};
-use middle::{ty, resolve};
+use middle::ty;
 
 use std::hash::HashUtil;
 use std::int;
@@ -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");
@@ -193,6 +185,12 @@ fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
     return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
 }
 
+fn get_provided_source(d: ebml::Doc, cdata: cmd) -> Option<ast::def_id> {
+    do reader::maybe_get_doc(d, tag_item_method_provided_source).map |doc| {
+        translate_def_id(cdata, reader::with_doc_data(*doc, parse_def_id))
+    }
+}
+
 fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool {
     for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
         if !f(reexport_doc) {
@@ -323,13 +321,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)),
@@ -795,34 +799,29 @@ fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
 }
 
 fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
-                     base_tps: uint) -> ~[@resolve::MethodInfo] {
+                     tcx: ty::ctxt) -> ~[@ty::Method] {
     let mut rslt = ~[];
     for reader::tagged_docs(item, tag_item_impl_method) |doc| {
         let m_did = reader::with_doc_data(doc, parse_def_id);
-        let mth_item = lookup_item(m_did.node, cdata.data);
-        let explicit_self = get_explicit_self(mth_item);
-        rslt.push(@resolve::MethodInfo {
-                    did: translate_def_id(cdata, m_did),
-                    n_tps: item_ty_param_count(mth_item) - base_tps,
-                    ident: item_name(intr, mth_item),
-                    explicit_self: explicit_self});
+        rslt.push(@get_method(intr, cdata, m_did.node, tcx));
     }
+
     rslt
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id)
-                -> resolve::Impl {
+pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id,
+               tcx: ty::ctxt)
+                -> ty::Impl {
     let data = cdata.data;
     let impl_item = lookup_item(impl_id, data);
-    let base_tps = item_ty_param_count(impl_item);
-    resolve::Impl {
+    ty::Impl {
         did: ast::def_id {
             crate: cdata.cnum,
             node: impl_id,
         },
         ident: item_name(intr, impl_item),
-        methods: item_impl_methods(intr, cdata, impl_item, base_tps),
+        methods: item_impl_methods(intr, cdata, impl_item, tcx),
     }
 }
 
@@ -842,6 +841,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);
@@ -849,6 +850,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
     let fty = doc_method_fty(method_doc, tcx, cdata);
     let vis = item_visibility(method_doc);
     let explicit_self = get_explicit_self(method_doc);
+    let provided_source = get_provided_source(method_doc, cdata);
 
     ty::Method::new(
         name,
@@ -860,7 +862,9 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
         fty,
         explicit_self,
         vis,
-        def_id
+        def_id,
+        container_id,
+        provided_source
     )
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index ab42e84e2ac..2ef00a2167f 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -15,10 +15,9 @@ use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::tyencode;
-use middle::ty::node_id_to_type;
+use middle::ty::{node_id_to_type, lookup_item_type};
 use middle::ty;
 use middle;
-use util::ppaux::ty_to_str;
 
 use std::hash::HashUtil;
 use std::hashmap::{HashMap, HashSet};
@@ -37,8 +36,6 @@ use syntax::ast_map;
 use syntax::ast_util::*;
 use syntax::attr;
 use syntax::diagnostic::span_handler;
-use syntax::opt_vec::OptVec;
-use syntax::opt_vec;
 use syntax::parse::token::special_idents;
 use syntax::{ast_util, visit};
 use syntax::parse::token;
@@ -192,13 +189,12 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
     }
 }
 
-fn encode_type_param_bounds(ebml_w: &mut writer::Encoder,
-                            ecx: &EncodeContext,
-                            params: &OptVec<TyParam>) {
-    let ty_param_defs =
-        @params.map_to_vec(|param| ecx.tcx.ty_param_defs.get_copy(&param.id));
-    encode_ty_type_param_defs(ebml_w, ecx, ty_param_defs,
+fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
+                          ecx: &EncodeContext,
+                          tpt: &ty::ty_param_bounds_and_ty) {
+    encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
                               tag_items_data_item_ty_param_bounds);
+    encode_type(ecx, ebml_w, tpt.ty);
 }
 
 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: def_id) {
@@ -321,15 +317,14 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
     let vi = ty::enum_variants(ecx.tcx,
                                ast::def_id { crate: local_crate, node: id });
     for variants.iter().advance |variant| {
+        let def_id = local_def(variant.node.id);
         index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()});
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(variant.node.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'v');
         encode_name(ecx, ebml_w, variant.node.name);
         encode_parent_item(ebml_w, local_def(id));
         encode_visibility(ebml_w, variant.node.vis);
-        encode_type(ecx, ebml_w,
-                    node_id_to_type(ecx.tcx, variant.node.id));
         match variant.node.kind {
             ast::tuple_variant_kind(ref args)
                     if args.len() > 0 && generics.ty_params.len() == 0 => {
@@ -342,7 +337,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
             encode_disr_val(ecx, ebml_w, vi[i].disr_val);
             disr_val = vi[i].disr_val;
         }
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
+        encode_bounds_and_type(ebml_w, ecx,
+                               &lookup_item_type(ecx.tcx, def_id));
         encode_path(ecx, ebml_w, path,
                     ast_map::path_name(variant.node.name));
         ebml_w.end_tag();
@@ -396,13 +392,13 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                                          ebml_w: &mut writer::Encoder,
                                          exp: &middle::resolve::Export2)
                                          -> bool {
-    match ecx.tcx.base_impls.find(&exp.def_id) {
+    match ecx.tcx.inherent_impls.find(&exp.def_id) {
         Some(implementations) => {
             for implementations.iter().advance |&base_impl| {
                 for base_impl.methods.iter().advance |&m| {
                     if m.explicit_self == ast::sty_static {
                         encode_reexported_static_method(ecx, ebml_w, exp,
-                                                        m.did, m.ident);
+                                                        m.def_id, m.ident);
                     }
                 }
             }
@@ -654,6 +650,16 @@ fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
     ebml_w.end_tag();
 }
 
+fn encode_provided_source(ebml_w: &mut writer::Encoder,
+                          source_opt: Option<def_id>) {
+    for source_opt.iter().advance |source| {
+        ebml_w.start_tag(tag_item_method_provided_source);
+        let s = def_to_str(*source);
+        ebml_w.writer.write(s.as_bytes());
+        ebml_w.end_tag();
+    }
+}
+
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
@@ -689,36 +695,6 @@ fn encode_info_for_struct(ecx: &EncodeContext,
     index
 }
 
-// This is for encoding info for ctors and dtors
-fn encode_info_for_ctor(ecx: &EncodeContext,
-                        ebml_w: &mut writer::Encoder,
-                        id: node_id,
-                        ident: ident,
-                        path: &[ast_map::path_elt],
-                        item: Option<inlined_item>,
-                        generics: &ast::Generics) {
-        ebml_w.start_tag(tag_items_data_item);
-        encode_name(ecx, ebml_w, ident);
-        encode_def_id(ebml_w, local_def(id));
-        encode_family(ebml_w, purity_fn_family(ast::impure_fn));
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        let its_ty = node_id_to_type(ecx.tcx, id);
-        debug!("fn name = %s ty = %s its node id = %d",
-               ecx.tcx.sess.str_of(ident),
-               ty_to_str(ecx.tcx, its_ty), id);
-        encode_type(ecx, ebml_w, its_ty);
-        encode_path(ecx, ebml_w, path, ast_map::path_name(ident));
-        match item {
-           Some(it) => {
-             (ecx.encode_inlined_item)(ecx, ebml_w, path, it);
-           }
-           None => {
-             encode_symbol(ecx, ebml_w, id);
-           }
-        }
-        ebml_w.end_tag();
-}
-
 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                ebml_w: &mut writer::Encoder,
                                path: &[ast_map::path_elt],
@@ -753,52 +729,47 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
     encode_method_fty(ecx, ebml_w, &method_ty.fty);
     encode_visibility(ebml_w, method_ty.vis);
     encode_explicit_self(ebml_w, method_ty.explicit_self);
+    let purity = method_ty.fty.purity;
+    match method_ty.explicit_self {
+        ast::sty_static => {
+            encode_family(ebml_w, purity_static_method_family(purity));
+        }
+        _ => encode_family(ebml_w, purity_fn_family(purity))
+    }
+    encode_provided_source(ebml_w, method_ty.provided_source);
 }
 
 fn encode_info_for_method(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
+                          m: &ty::Method,
                           impl_path: &[ast_map::path_elt],
-                          should_inline: bool,
+                          is_default_impl: bool,
                           parent_id: node_id,
-                          m: @method,
-                          owner_generics: &ast::Generics,
-                          method_generics: &ast::Generics) {
-    debug!("encode_info_for_method: %d %s %u %u", m.id,
-           ecx.tcx.sess.str_of(m.ident),
-           owner_generics.ty_params.len(),
-           method_generics.ty_params.len());
+                          ast_method_opt: Option<@method>) {
+
+    debug!("encode_info_for_method: %? %s", m.def_id,
+           ecx.tcx.sess.str_of(m.ident));
     ebml_w.start_tag(tag_items_data_item);
 
-    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_method_ty_fields(ecx, ebml_w, m);
+    encode_parent_item(ebml_w, local_def(parent_id));
 
-    match m.explicit_self.node {
-        ast::sty_static => {
-            encode_family(ebml_w, purity_static_method_family(m.purity));
-        }
-        _ => encode_family(ebml_w, purity_fn_family(m.purity))
-    }
-
-    let mut combined_ty_params = opt_vec::Empty;
-    for owner_generics.ty_params.iter().advance |x| {
-        combined_ty_params.push((*x).clone())
-    }
-    for method_generics.ty_params.iter().advance |x| {
-        combined_ty_params.push((*x).clone())
-    }
-    let len = combined_ty_params.len();
-    encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
+    // The type for methods gets encoded twice, which is unfortunate.
+    let tpt = lookup_item_type(ecx.tcx, m.def_id);
+    encode_bounds_and_type(ebml_w, ecx, &tpt);
 
-    encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
     encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
 
-    if len > 0u || should_inline {
-        (ecx.encode_inlined_item)(
-           ecx, ebml_w, impl_path,
-           ii_method(local_def(parent_id), false, m));
-    } else {
-        encode_symbol(ecx, ebml_w, m.id);
+    for ast_method_opt.iter().advance |ast_method| {
+        let num_params = tpt.generics.type_param_defs.len();
+        if num_params > 0u || is_default_impl
+            || should_inline(ast_method.attrs) {
+            (ecx.encode_inlined_item)(
+                ecx, ebml_w, impl_path,
+                ii_method(local_def(parent_id), false, *ast_method));
+        } else {
+            encode_symbol(ecx, ebml_w, m.def_id.node);
+        }
     }
 
     ebml_w.end_tag();
@@ -844,11 +815,12 @@ fn encode_info_for_item(ecx: &EncodeContext,
     debug!("encoding info for item at %s",
            ecx.tcx.sess.codemap.span_to_str(item.span));
 
+    let def_id = local_def(item.id);
     match item.node {
       item_static(_, m, _) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         if m == ast::m_mutbl {
             encode_family(ebml_w, 'b');
         } else {
@@ -864,11 +836,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
       item_fn(_, purity, _, ref generics, _) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, purity_fn_family(purity));
         let tps_len = generics.ty_params.len();
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_attributes(ebml_w, item.attrs);
@@ -892,7 +863,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
       item_foreign_mod(ref fm) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'n');
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
@@ -906,13 +877,12 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
         ebml_w.end_tag();
       }
-      item_ty(_, ref generics) => {
+      item_ty(*) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'y');
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_region_param(ecx, ebml_w, item);
@@ -922,10 +892,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         add_to_index();
 
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 't');
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         for (*enum_definition).variants.iter().advance |v| {
             encode_variant_id(ebml_w, local_def(v.node.id));
@@ -943,7 +912,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  index,
                                  generics);
       }
-      item_struct(struct_def, ref generics) => {
+      item_struct(struct_def, _) => {
         /* First, encode the fields
            These come first because we need to write them to make
            the index, and the index needs to be in the item for the
@@ -956,10 +925,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
         /* Now, make an item for the class itself */
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'S');
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
 
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
@@ -1008,14 +976,17 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                         index);
         }
       }
-      item_impl(ref generics, ref opt_trait, ref ty, ref methods) => {
+      item_impl(_, ref opt_trait, ref ty, ref ast_methods) => {
+        // We need to encode information about the default methods we
+        // have inherited, so we drive this based on the impl structure.
+        let imp = tcx.impls.get(&def_id);
+
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'i');
         encode_region_param(ecx, ebml_w, item);
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         match ty.node {
@@ -1026,15 +997,15 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             _ => {}
         }
-        for methods.iter().advance |m| {
+        for imp.methods.iter().advance |method| {
             ebml_w.start_tag(tag_item_impl_method);
-            let method_def_id = local_def(m.id);
-            let s = def_to_str(method_def_id);
+            let s = def_to_str(method.def_id);
             ebml_w.writer.write(s.as_bytes());
             ebml_w.end_tag();
         }
         for opt_trait.iter().advance |ast_trait_ref| {
-            let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
+            let trait_ref = ty::node_id_to_trait_ref(
+                tcx, ast_trait_ref.ref_id);
             encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
         }
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
@@ -1044,30 +1015,40 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let mut impl_path = vec::append(~[], path);
         impl_path.push(ast_map::path_name(item.ident));
 
-        for methods.iter().advance |m| {
-            index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
+        // Iterate down the methods, emitting them. We rely on the
+        // assumption that all of the actually implemented methods
+        // appear first in the impl structure, in the same order they do
+        // in the ast. This is a little sketchy.
+        let num_implemented_methods = ast_methods.len();
+        for imp.methods.iter().enumerate().advance |(i, m)| {
+            let ast_method = if i < num_implemented_methods {
+                Some(ast_methods[i])
+            } else { None };
+
+            index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()});
             encode_info_for_method(ecx,
                                    ebml_w,
+                                   *m,
                                    impl_path,
-                                   should_inline(m.attrs),
+                                   false,
                                    item.id,
-                                   *m,
-                                   generics,
-                                   &m.generics);
+                                   ast_method)
         }
       }
-      item_trait(ref generics, ref super_traits, ref ms) => {
+      item_trait(_, ref super_traits, ref ms) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
-        encode_def_id(ebml_w, local_def(item.id));
+        encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'I');
         encode_region_param(ecx, ebml_w, item);
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        let trait_def = ty::lookup_trait_def(tcx, local_def(item.id));
+        let trait_def = ty::lookup_trait_def(tcx, def_id);
+        encode_ty_type_param_defs(ebml_w, ecx,
+                                  trait_def.generics.type_param_defs,
+                                  tag_items_data_item_ty_param_bounds);
         encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
-        for ty::trait_method_def_ids(tcx, local_def(item.id)).iter().advance |&method_def_id| {
+        for ty::trait_method_def_ids(tcx, def_id).iter().advance |&method_def_id| {
             ebml_w.start_tag(tag_item_trait_method);
             encode_def_id(ebml_w, method_def_id);
             ebml_w.end_tag();
@@ -1084,7 +1065,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         ebml_w.end_tag();
 
         // Now output the method info for each method.
-        let r = ty::trait_method_def_ids(tcx, local_def(item.id));
+        let r = ty::trait_method_def_ids(tcx, def_id);
         for r.iter().enumerate().advance |(i, &method_def_id)| {
             assert_eq!(method_def_id.crate, ast::local_crate);
 
@@ -1096,7 +1077,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
             encode_method_ty_fields(ecx, ebml_w, method_ty);
 
-            encode_parent_item(ebml_w, local_def(item.id));
+            encode_parent_item(ebml_w, def_id);
 
             let mut trait_path = vec::append(~[], path);
             trait_path.push(ast_map::path_name(item.ident));
@@ -1109,10 +1090,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                       method_ty.fty.purity));
 
                     let tpt = ty::lookup_item_type(tcx, method_def_id);
-                    encode_ty_type_param_defs(ebml_w, ecx,
-                                              tpt.generics.type_param_defs,
-                                              tag_items_data_item_ty_param_bounds);
-                    encode_type(ecx, ebml_w, tpt.ty);
+                    encode_bounds_and_type(ebml_w, ecx, &tpt);
                 }
 
                 _ => {
@@ -1131,13 +1109,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
                     // If this is a static method, we've already encoded
                     // this.
                     if method_ty.explicit_self != sty_static {
-                        encode_type_param_bounds(ebml_w, ecx,
-                                                 &m.generics.ty_params);
+                        // XXX: I feel like there is something funny going on.
+                        let tpt = ty::lookup_item_type(tcx, method_def_id);
+                        encode_bounds_and_type(ebml_w, ecx, &tpt);
                     }
                     encode_method_sort(ebml_w, 'p');
                     (ecx.encode_inlined_item)(
                         ecx, ebml_w, path,
-                        ii_method(local_def(item.id), true, m));
+                        ii_method(def_id, true, m));
                 }
             }
 
@@ -1158,11 +1137,11 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
 
     ebml_w.start_tag(tag_items_data_item);
     match nitem.node {
-      foreign_item_fn(_, purity, ref generics) => {
+      foreign_item_fn(_, purity, _) => {
         encode_def_id(ebml_w, local_def(nitem.id));
         encode_family(ebml_w, purity_fn_family(purity));
-        encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
-        encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
+        encode_bounds_and_type(ebml_w, ecx,
+                               &lookup_item_type(ecx.tcx,local_def(nitem.id)));
         encode_name(ecx, ebml_w, nitem.ident);
         if abi.is_intrinsic() {
             (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
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/resolve.rs b/src/librustc/middle/resolve.rs
index 80078eba239..6d457b46d4f 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -55,24 +55,6 @@ pub struct binding_info {
 // Map from the name in a pattern to its binding mode.
 pub type BindingMap = HashMap<ident,binding_info>;
 
-// Implementation resolution
-//
-// FIXME #4946: This kind of duplicates information kept in
-// ty::method. Maybe it should go away.
-
-pub struct MethodInfo {
-    did: def_id,
-    n_tps: uint,
-    ident: ident,
-    explicit_self: explicit_self_
-}
-
-pub struct Impl {
-    did: def_id,
-    ident: ident,
-    methods: ~[@MethodInfo]
-}
-
 // Trait method resolution
 pub type TraitMap = HashMap<node_id,@mut ~[def_id]>;
 
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 4ca8057f388..bcf3aa6ad50 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -162,7 +162,7 @@ pub fn trans_method_callee(bcx: block,
             let self_ty = node_id_type(bcx, this.id);
             // <impl_id> is the ID of the implementation of
             // trait <trait_id> for type <self_ty>
-            let impl_id = ty::get_impl_id(tcx, trait_id, self_ty);
+            let impl_id = ty::bogus_get_impl_id_from_ty(tcx, trait_id, self_ty);
             // Get the supertrait's methods
             let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id);
             // Make sure to fail with a readable error message if
@@ -177,9 +177,7 @@ pub fn trans_method_callee(bcx: block,
             // Now that we know the impl ID, we can look up the method
             // ID from its name
             origin = typeck::method_static(
-                method_with_name_or_default(bcx.ccx(),
-                                            impl_id,
-                                            method_name));
+                method_with_name(bcx.ccx(), impl_id, method_name));
         }
         typeck::method_self(*) |
         typeck::method_static(*) | typeck::method_param(*) |
@@ -308,12 +306,10 @@ pub fn trans_static_method_callee(bcx: block,
         typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
-            let mth_id = method_with_name_or_default(bcx.ccx(),
-                                                     impl_did,
-                                                     mname);
+            let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
             let (callee_substs, callee_origins) =
                 combine_impl_and_methods_tps(
-                    bcx, mth_id, impl_did, callee_id,
+                    bcx, mth_id, callee_id,
                     *rcvr_substs, rcvr_origins);
 
             let FnData {llfn: lval} =
@@ -334,58 +330,22 @@ pub fn trans_static_method_callee(bcx: block,
     }
 }
 
-pub fn method_from_methods(ms: &[@ast::method], name: ast::ident)
-    -> Option<ast::def_id> {
-    ms.iter().find_(|m| m.ident == name).map(|m| ast_util::local_def(m.id))
-}
-
-pub fn method_with_name_or_default(ccx: &mut CrateContext,
-                                   impl_id: ast::def_id,
-                                   name: ast::ident) -> ast::def_id {
-    let imp = ccx.impl_method_cache.find_copy(&(impl_id, name));
-    match imp {
+pub fn method_with_name(ccx: &mut CrateContext,
+                        impl_id: ast::def_id,
+                        name: ast::ident) -> ast::def_id {
+    let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name));
+    match meth_id_opt {
         Some(m) => return m,
         None => {}
     }
 
-    // None of this feels like it should be the best way to do this.
-    let mut did = if impl_id.crate == ast::local_crate {
-        match ccx.tcx.items.get_copy(&impl_id.node) {
-            ast_map::node_item(@ast::item {
-                node: ast::item_impl(_, _, _, ref ms), _
-            }, _) => { method_from_methods(*ms, name) },
-            _ => fail!("method_with_name")
-        }
-    } else {
-        csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
-    };
-
-    if did.is_none() {
-        // Look for a default method
-        let pmm = ccx.tcx.provided_methods;
-        match pmm.find(&impl_id) {
-            Some(pmis) => {
-                for pmis.iter().advance |pmi| {
-                    if pmi.method_info.ident == name {
-                        debug!("pmi.method_info.did = %?",
-                               pmi.method_info.did);
-                        did = Some(pmi.method_info.did);
-                    }
-                }
-            }
-            None => {}
-        }
-    }
-
-    let imp = did.expect("could not find method while translating");
-    ccx.impl_method_cache.insert((impl_id, name), imp);
-    imp
-}
+    let imp = ccx.tcx.impls.find(&impl_id)
+        .expect("could not find impl while translating");
+    let meth = imp.methods.iter().find_(|m| m.ident == name)
+        .expect("could not find method while translating");
 
-pub fn method_ty_param_count(ccx: &CrateContext, m_id: ast::def_id,
-                             i_id: ast::def_id) -> uint {
-    debug!("method_ty_param_count: m_id: %?, i_id: %?", m_id, i_id);
-    ty::method(ccx.tcx, m_id).generics.type_param_defs.len()
+    ccx.impl_method_cache.insert((impl_id, name), meth.def_id);
+    meth.def_id
 }
 
 pub fn trans_monomorphized_callee(bcx: block,
@@ -401,8 +361,7 @@ pub fn trans_monomorphized_callee(bcx: block,
       typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
           let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
-          let mth_id = method_with_name_or_default(
-              bcx.ccx(), impl_did, mname);
+          let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
 
           // obtain the `self` value:
           let mut temp_cleanups = ~[];
@@ -413,7 +372,7 @@ pub fn trans_monomorphized_callee(bcx: block,
           // those from the impl and those from the method:
           let (callee_substs, callee_origins) =
               combine_impl_and_methods_tps(
-                  bcx, mth_id, impl_did, callee_id,
+                  bcx, mth_id, callee_id,
                   *rcvr_substs, rcvr_origins);
 
           // translate the function
@@ -452,7 +411,6 @@ pub fn trans_monomorphized_callee(bcx: block,
 
 pub fn combine_impl_and_methods_tps(bcx: block,
                                     mth_did: ast::def_id,
-                                    impl_did: ast::def_id,
                                     callee_id: ast::node_id,
                                     rcvr_substs: &[ty::t],
                                     rcvr_origins: typeck::vtable_res)
@@ -475,15 +433,16 @@ pub fn combine_impl_and_methods_tps(bcx: block,
     * mapped to. */
 
     let ccx = bcx.ccx();
-    let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
+    let method = ty::method(ccx.tcx, mth_did);
+    let n_m_tps = method.generics.type_param_defs.len();
     let node_substs = node_id_type_params(bcx, callee_id);
-    debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t)));
+    debug!("rcvr_substs=%?", rcvr_substs.repr(ccx.tcx));
     let ty_substs
         = vec::append(rcvr_substs.to_owned(),
                       node_substs.tailn(node_substs.len() - n_m_tps));
     debug!("n_m_tps=%?", n_m_tps);
-    debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t)));
-    debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t)));
+    debug!("node_substs=%?", node_substs.repr(ccx.tcx));
+    debug!("ty_substs=%?", ty_substs.repr(ccx.tcx));
 
 
     // Now, do the same work for the vtables.  The vtables might not
@@ -658,7 +617,6 @@ pub fn vtable_id(ccx: @mut CrateContext,
             monomorphize::make_mono_id(
                 ccx,
                 impl_id,
-                None,
                 &psubsts,
                 None)
         }
@@ -744,7 +702,7 @@ pub fn make_impl_vtable(bcx: block,
         } else {
             debug!("(making impl vtable) adding method to vtable: %s",
                    tcx.sess.str_of(im.ident));
-            let m_id = method_with_name_or_default(ccx, impl_id, im.ident);
+            let m_id = method_with_name(ccx, impl_id, im.ident);
 
             trans_fn_ref_with_vtables(bcx, m_id, 0,
                                       substs, Some(vtables)).llfn
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 50f331f7e7d..b63117d25bb 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -16,7 +16,6 @@ use middle::const_eval;
 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
 use middle::lang_items::OpaqueStructLangItem;
 use middle::freevars;
-use middle::resolve::{Impl, MethodInfo};
 use middle::resolve;
 use middle::ty;
 use middle::subst::Subst;
@@ -65,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 {
@@ -75,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 {
@@ -91,11 +96,19 @@ 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
         }
     }
 }
 
+pub struct Impl {
+    did: def_id,
+    ident: ident,
+    methods: ~[@Method]
+}
+
 #[deriving(Clone, Eq, IterBytes)]
 pub struct mt {
     ty: t,
@@ -214,26 +227,6 @@ pub enum AutoRef {
     AutoUnsafe(ast::mutability)
 }
 
-// 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
-// implementation implements.
-pub type ProvidedMethodsMap = @mut HashMap<def_id,@mut ~[@ProvidedMethodInfo]>;
-
-// Stores the method info and definition ID of the associated trait method for
-// each instantiation of each provided method.
-pub struct ProvidedMethodInfo {
-    method_info: @MethodInfo,
-    trait_method_def_id: def_id
-}
-
-pub struct ProvidedMethodSource {
-    method_id: ast::def_id,
-    impl_id: ast::def_id
-}
-
 pub type ctxt = @ctxt_;
 
 struct ctxt_ {
@@ -287,11 +280,8 @@ struct ctxt_ {
     adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
     normalized_cache: @mut HashMap<t, t>,
     lang_items: middle::lang_items::LanguageItems,
-    // 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: @mut HashMap<ast::def_id, ProvidedMethodSource>,
+    // A mapping of fake provided method def_ids to the default implementation
+    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
@@ -303,11 +293,19 @@ struct ctxt_ {
     // A method will be in this list if and only if it is a destructor.
     destructors: @mut HashSet<ast::def_id>,
 
-    // Maps a trait onto a mapping from self-ty to impl
-    trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,
+    // Maps a trait onto a list of impls of that trait.
+    trait_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
 
-    // Maps a base type to its impl
-    base_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
+    // Maps a def_id of a type to a list of its inherent impls.
+    // Contains implementations of methods that are inherent to a type.
+    // Methods in these implementations don't need to be exported.
+    inherent_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
+
+    // Maps a def_id of an impl to an Impl structure.
+    // Note that this contains all of the impls that we know about,
+    // including ones in other crates. It's not clear that this is the best
+    // way to do it.
+    impls: @mut HashMap<ast::def_id, @Impl>,
 
     // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     // present in this set can be warned about.
@@ -902,13 +900,13 @@ pub fn mk_ctxt(s: session::Session,
         adjustments: @mut HashMap::new(),
         normalized_cache: new_ty_hash(),
         lang_items: lang_items,
-        provided_methods: @mut HashMap::new(),
         provided_method_sources: @mut HashMap::new(),
         supertraits: @mut HashMap::new(),
         destructor_for_type: @mut HashMap::new(),
         destructors: @mut HashSet::new(),
         trait_impls: @mut HashMap::new(),
-        base_impls:  @mut HashMap::new(),
+        inherent_impls:  @mut HashMap::new(),
+        impls:  @mut HashMap::new(),
         used_unsafe: @mut HashSet::new(),
         used_mut_nodes: @mut HashSet::new(),
      }
@@ -3516,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) {
@@ -3596,20 +3599,6 @@ pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method {
 }
 
 
-pub fn add_base_impl(cx: ctxt, base_def_id: def_id, implementation: @Impl) {
-    let implementations;
-    match cx.base_impls.find(&base_def_id) {
-        None => {
-            implementations = @mut ~[];
-            cx.base_impls.insert(base_def_id, implementations);
-        }
-        Some(&existing) => {
-            implementations = existing;
-        }
-    }
-    implementations.push(implementation);
-}
-
 pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
     match cx.trait_methods_cache.find(&trait_did) {
         Some(&methods) => methods,
@@ -4375,16 +4364,25 @@ pub fn count_traits_and_supertraits(tcx: ctxt,
     return total;
 }
 
-// Given a trait and a type, returns the impl of that type
-pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
+// Given a trait and a type, returns the impl of that type.
+// This is broken, of course, by parametric impls. This used to use
+// a table specifically for this mapping, but I removed that table.
+// This is only used when calling a supertrait method from a default method,
+// and should go away once I fix how that works. -sully
+pub fn bogus_get_impl_id_from_ty(tcx: ctxt,
+                                 trait_id: def_id, self_ty: t) -> def_id {
     match tcx.trait_impls.find(&trait_id) {
-        Some(ty_to_impl) => match ty_to_impl.find(&self_ty) {
-            Some(the_impl) => the_impl.did,
-            None => // try autoderef!
-                match deref(tcx, self_ty, false) {
-                    Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty),
-                    None => tcx.sess.bug("get_impl_id: no impl of trait for \
-                                          this type")
+        Some(ty_to_impl) => {
+            for ty_to_impl.iter().advance |imp| {
+                let impl_ty = tcx.tcache.get_copy(&imp.did);
+                if impl_ty.ty == self_ty { return imp.did; }
+            }
+            // try autoderef!
+            match deref(tcx, self_ty, false) {
+                Some(some_ty) =>
+                  bogus_get_impl_id_from_ty(tcx, trait_id, some_ty.ty),
+                None => tcx.sess.bug("get_impl_id: no impl of trait for \
+                                      this type")
             }
         },
         None => tcx.sess.bug("get_impl_id: trait isn't in trait_impls")
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index d2a11953af0..4a32e8bf952 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -330,8 +330,7 @@ impl<'self> LookupContext<'self> {
         for opt_applicable_traits.iter().advance |applicable_traits| {
             for applicable_traits.iter().advance |trait_did| {
                 // Look for explicit implementations.
-                let opt_impl_infos =
-                    self.fcx.ccx.coherence_info.extension_methods.find(trait_did);
+                let opt_impl_infos = self.tcx().trait_impls.find(trait_did);
                 for opt_impl_infos.iter().advance |impl_infos| {
                     for impl_infos.iter().advance |impl_info| {
                         self.push_candidates_from_impl(
@@ -517,8 +516,7 @@ impl<'self> LookupContext<'self> {
     }
 
     pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
-        let opt_impl_infos =
-            self.fcx.ccx.coherence_info.inherent_methods.find(&did);
+        let opt_impl_infos = self.tcx().inherent_impls.find(&did);
         for opt_impl_infos.iter().advance |impl_infos| {
             for impl_infos.iter().advance |impl_info| {
                 self.push_candidates_from_impl(
@@ -529,7 +527,7 @@ impl<'self> LookupContext<'self> {
 
     pub fn push_candidates_from_impl(&self,
                                      candidates: &mut ~[Candidate],
-                                     impl_info: &resolve::Impl) {
+                                     impl_info: &ty::Impl) {
         if !self.impl_dups.insert(impl_info.did) {
             return; // already visited
         }
@@ -545,7 +543,7 @@ impl<'self> LookupContext<'self> {
             }
         };
 
-        let method = ty::method(self.tcx(), impl_info.methods[idx].did);
+        let method = ty::method(self.tcx(), impl_info.methods[idx].def_id);
 
         // determine the `self` of the impl with fresh
         // variables for each parameter:
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index d9036c72db6..6af0be48e47 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -260,7 +260,7 @@ fn lookup_vtable(vcx: &VtableContext,
 
             let mut impls_seen = HashSet::new();
 
-            match vcx.ccx.coherence_info.extension_methods.find(&trait_ref.def_id) {
+            match tcx.trait_impls.find(&trait_ref.def_id) {
                 None => {
                     // Nothing found. Continue.
                 }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 3a4154d7c50..c8225365864 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -17,10 +17,9 @@
 
 use metadata::csearch::{each_path, get_impl_trait};
 use metadata::csearch;
-use metadata::cstore::{CStore, iter_crate_data};
+use metadata::cstore::iter_crate_data;
 use metadata::decoder::{dl_def, dl_field, dl_impl};
-use middle::resolve::{Impl, MethodInfo};
-use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, 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};
@@ -31,6 +30,7 @@ use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec};
 use middle::ty::{type_is_ty_var};
 use middle::subst::Subst;
 use middle::ty;
+use middle::ty::{Impl, Method};
 use middle::typeck::CrateCtxt;
 use middle::typeck::infer::combine::Combine;
 use middle::typeck::infer::InferCtxt;
@@ -38,7 +38,7 @@ use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
 use middle::typeck::infer;
 use syntax::ast::{crate, def_id, def_struct, def_ty};
 use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct};
-use syntax::ast::{local_crate, method, trait_ref, ty_path};
+use syntax::ast::{local_crate, trait_ref, ty_path};
 use syntax::ast;
 use syntax::ast_map::node_item;
 use syntax::ast_map;
@@ -149,33 +149,6 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
     }
 }
 
-
-pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
-    @MethodInfo {
-        did: local_def(ast_method.id),
-        n_tps: ast_method.generics.ty_params.len(),
-        ident: ast_method.ident,
-        explicit_self: ast_method.explicit_self.node
-    }
-}
-
-pub struct CoherenceInfo {
-    // Contains implementations of methods that are inherent to a type.
-    // Methods in these implementations don't need to be exported.
-    inherent_methods: @mut HashMap<def_id, @mut ~[@Impl]>,
-
-    // Contains implementations of methods associated with a trait. For these,
-    // the associated trait must be imported at the call site.
-    extension_methods: @mut HashMap<def_id, @mut ~[@Impl]>,
-}
-
-pub fn CoherenceInfo() -> CoherenceInfo {
-    CoherenceInfo {
-        inherent_methods: @mut HashMap::new(),
-        extension_methods: @mut HashMap::new(),
-    }
-}
-
 pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker {
     CoherenceChecker {
         crate_context: crate_context,
@@ -267,27 +240,16 @@ impl CoherenceChecker {
             }
         }
 
-        // We only want to generate one Impl structure. When we generate one,
-        // we store it here so that we don't recreate it.
-        let mut implementation_opt = None;
+        let implementation = self.create_impl_from_item(item);
+
         for associated_traits.iter().advance |associated_trait| {
-            let trait_ref =
-                ty::node_id_to_trait_ref(
-                    self.crate_context.tcx,
-                    associated_trait.ref_id);
+            let trait_ref = ty::node_id_to_trait_ref(
+                self.crate_context.tcx, associated_trait.ref_id);
             debug!("(checking implementation) adding impl for trait '%s', item '%s'",
                    trait_ref.repr(self.crate_context.tcx),
                    self.crate_context.tcx.sess.str_of(item.ident));
 
-            self.instantiate_default_methods(local_def(item.id), trait_ref);
-
-            let implementation;
-            if implementation_opt.is_none() {
-                implementation = self.create_impl_from_item(item);
-                implementation_opt = Some(implementation);
-            }
-
-            self.add_trait_method(trait_ref.def_id, implementation_opt.get());
+            self.add_trait_impl(trait_ref.def_id, implementation);
         }
 
         // Add the implementation to the mapping from implementation to base
@@ -302,25 +264,15 @@ impl CoherenceChecker {
             Some(base_type_def_id) => {
                 // XXX: Gather up default methods?
                 if associated_traits.len() == 0 {
-                    let implementation;
-                    match implementation_opt {
-                        None => {
-                            implementation =
-                                self.create_impl_from_item(item);
-                        }
-                        Some(existing_implementation) => {
-                            implementation = existing_implementation;
-                        }
-                    }
-
-                    self.add_inherent_method(base_type_def_id,
-                                             implementation);
+                    self.add_inherent_impl(base_type_def_id, implementation);
                 }
 
                 self.base_type_def_ids.insert(local_def(item.id),
                                               base_type_def_id);
             }
         }
+
+        tcx.impls.insert(implementation.did, implementation);
     }
 
     // Creates default method IDs and performs type substitutions for an impl
@@ -328,7 +280,8 @@ impl CoherenceChecker {
     // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
     pub fn instantiate_default_methods(&self,
                                        impl_id: ast::def_id,
-                                       trait_ref: &ty::TraitRef) {
+                                       trait_ref: &ty::TraitRef,
+                                       all_methods: &mut ~[@Method]) {
         let tcx = self.crate_context.tcx;
         debug!("instantiate_default_methods(impl_id=%?, trait_ref=%s)",
                impl_id, trait_ref.repr(tcx));
@@ -350,9 +303,11 @@ 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);
 
             // construct the polytype for the method based on the method_ty
             let new_generics = ty::Generics {
@@ -374,60 +329,20 @@ 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);
-
-            let provided_method_info =
-                @ProvidedMethodInfo {
-                    method_info: @MethodInfo {
-                        did: new_did,
-                        n_tps: trait_method.generics.type_param_defs.len(),
-                        ident: trait_method.ident,
-                        explicit_self: trait_method.explicit_self
-                    },
-                    trait_method_def_id: trait_method.def_id
-                };
-
-            let pmm = self.crate_context.tcx.provided_methods;
-            match pmm.find(&impl_id) {
-                Some(&mis) => {
-                    // If the trait already has an entry in the
-                    // provided_methods_map, we just need to add this
-                    // method to that entry.
-                    debug!("(checking implementation) adding method `%s` \
-                            to entry for existing trait",
-                            self.crate_context.tcx.sess.str_of(
-                                provided_method_info.method_info.ident));
-                    mis.push(provided_method_info);
-                }
-                None => {
-                    // If the trait doesn't have an entry yet, create one.
-                    debug!("(checking implementation) creating new entry \
-                            for method `%s`",
-                            self.crate_context.tcx.sess.str_of(
-                                provided_method_info.method_info.ident));
-                    pmm.insert(impl_id,
-                               @mut ~[provided_method_info]);
-                }
-            }
+            self.crate_context.tcx.provided_method_sources
+                .insert(new_did, trait_method.def_id);
         }
     }
 
-    pub fn add_inherent_method(&self,
-                               base_def_id: def_id,
-                               implementation: @Impl) {
+    pub fn add_inherent_impl(&self,
+                             base_def_id: def_id,
+                             implementation: @Impl) {
+        let tcx = self.crate_context.tcx;
         let implementation_list;
-        match self.crate_context.coherence_info.inherent_methods
-                  .find(&base_def_id) {
+        match tcx.inherent_impls.find(&base_def_id) {
             None => {
                 implementation_list = @mut ~[];
-                self.crate_context.coherence_info.inherent_methods
-                    .insert(base_def_id, implementation_list);
+                tcx.inherent_impls.insert(base_def_id, implementation_list);
             }
             Some(&existing_implementation_list) => {
                 implementation_list = existing_implementation_list;
@@ -435,18 +350,17 @@ impl CoherenceChecker {
         }
 
         implementation_list.push(implementation);
-
-        ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation);
     }
 
-    pub fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) {
+    pub fn add_trait_impl(&self,
+                          base_def_id: def_id,
+                          implementation: @Impl) {
+        let tcx = self.crate_context.tcx;
         let implementation_list;
-        match self.crate_context.coherence_info.extension_methods
-                  .find(&trait_id) {
+        match tcx.trait_impls.find(&base_def_id) {
             None => {
                 implementation_list = @mut ~[];
-                self.crate_context.coherence_info.extension_methods
-                    .insert(trait_id, implementation_list);
+                tcx.trait_impls.insert(base_def_id, implementation_list);
             }
             Some(&existing_implementation_list) => {
                 implementation_list = existing_implementation_list;
@@ -457,8 +371,7 @@ impl CoherenceChecker {
     }
 
     pub fn check_implementation_coherence(&self) {
-        let coherence_info = &self.crate_context.coherence_info;
-        for coherence_info.extension_methods.each_key |&trait_id| {
+        for self.crate_context.tcx.trait_impls.each_key |&trait_id| {
             self.check_implementation_coherence_of(trait_id);
         }
     }
@@ -472,8 +385,6 @@ impl CoherenceChecker {
 
             // "We have an impl of trait <trait_def_id> for type <polytype_a>,
             // and that impl is <implementation_a>"
-            self.add_impl_for_trait(trait_def_id, polytype_a.ty,
-                                    implementation_a);
             do self.iter_impls_of_trait(trait_def_id) |b| {
                 let implementation_b = b;
 
@@ -494,32 +405,8 @@ impl CoherenceChecker {
         }
     }
 
-    // Adds an impl of trait trait_t for self type self_t; that impl
-    // is the_impl
-    pub fn add_impl_for_trait(&self,
-                              trait_t: def_id,
-                              self_t: t,
-                              the_impl: @Impl) {
-        debug!("Adding impl %? of %? for %s",
-               the_impl.did, trait_t,
-               ty_to_str(self.crate_context.tcx, self_t));
-        match self.crate_context.tcx.trait_impls.find(&trait_t) {
-            None => {
-                let m = @mut HashMap::new();
-                m.insert(self_t, the_impl);
-                self.crate_context.tcx.trait_impls.insert(trait_t, m);
-            }
-            Some(&m) => {
-                m.insert(self_t, the_impl);
-            }
-        }
-    }
-
     pub fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) {
-        let coherence_info = &self.crate_context.coherence_info;
-        let extension_methods = &*coherence_info.extension_methods;
-
-        match extension_methods.find(&trait_def_id) {
+        match self.crate_context.tcx.trait_impls.find(&trait_def_id) {
             Some(impls) => {
                 for impls.iter().advance |&im| {
                     f(im);
@@ -653,13 +540,11 @@ impl CoherenceChecker {
 
     // This check doesn't really have anything to do with coherence. It's
     // here for historical reasons
-    pub fn please_check_that_trait_methods_are_implemented(&self,
-                                                           all_methods:
-                                                           &mut
-                                                           ~[@MethodInfo],
-                                                           trait_did: def_id,
-                                                           trait_ref_span:
-                                                           span) {
+    pub fn check_trait_methods_are_implemented(
+        &self,
+        all_methods: &mut ~[@Method],
+        trait_did: def_id,
+        trait_ref_span: span) {
 
         let tcx = self.crate_context.tcx;
 
@@ -668,12 +553,6 @@ impl CoherenceChecker {
         for uint::range(0, all_methods.len()) |i| {
             provided_names.insert(all_methods[i].ident);
         }
-        // Default methods
-        let r = ty::provided_trait_methods(tcx, trait_did);
-        for r.iter().advance |method| {
-            debug!("inserting provided method %s", method.ident.repr(tcx));
-            provided_names.insert(method.ident);
-        }
 
         let r = ty::trait_methods(tcx, trait_did);
         for r.iter().advance |method| {
@@ -726,70 +605,33 @@ impl CoherenceChecker {
         }
     }
 
-    fn add_provided_methods_to_impl(
-        &self,
-        all_methods: &mut ~[@MethodInfo],
-        trait_did: &ast::def_id,
-        impl_id: &ast::def_id) {
-
-
-        match self.crate_context.tcx
-            .provided_methods
-            .find(impl_id) {
-                None => {
-                    debug!("(creating impl) trait with node_id `%d` \
-                            has no provided methods", trait_did.node);
-                    /* fall through */
-                }
-                Some(&all_provided_methods) => {
-                    debug!("(creating impl) trait with node_id `%d` \
-                            has provided methods", trait_did.node);
-                    // Add all provided methods.
-                    for all_provided_methods.iter().advance |provided_method| {
-                        debug!(
-                            "(creating impl) adding provided method \
-                             `%s` to impl",
-                            provided_method.method_info
-                            .ident.repr(self.crate_context.tcx));
-                        all_methods.push(provided_method.method_info);
-                    }
-                }
-            }
-
-
-    }
-
     // Converts an implementation in the AST to an Impl structure.
     pub fn create_impl_from_item(&self, item: @item) -> @Impl {
+        let tcx = self.crate_context.tcx;
         match item.node {
             item_impl(_, ref trait_refs, _, ref ast_methods) => {
                 let mut methods = ~[];
                 for ast_methods.iter().advance |ast_method| {
-                    methods.push(method_to_MethodInfo(*ast_method));
+                    methods.push(ty::method(tcx, local_def(ast_method.id)));
                 }
 
-                // Check that we have implementations of every trait method
                 for trait_refs.iter().advance |trait_ref| {
-                    let trait_did =
-                        self.trait_ref_to_trait_def_id(trait_ref);
-                    self.please_check_that_trait_methods_are_implemented(
+                    let ty_trait_ref = ty::node_id_to_trait_ref(
+                        self.crate_context.tcx,
+                        trait_ref.ref_id);
+                    let trait_did = ty_trait_ref.def_id;
+
+                    self.instantiate_default_methods(local_def(item.id),
+                                                     ty_trait_ref,
+                                                     &mut methods);
+
+                    // Check that we have implementations of every trait method
+                    self.check_trait_methods_are_implemented(
                         &mut methods,
                         trait_did,
                         trait_ref.path.span);
                 }
 
-                // For each trait that the impl implements, see which
-                // methods are provided.  For each of those methods,
-                // if a method of that name is not inherent to the
-                // impl, use the provided definition in the trait.
-                for trait_refs.iter().advance |trait_ref| {
-                    let trait_did = self.trait_ref_to_trait_def_id(trait_ref);
-                    self.add_provided_methods_to_impl(
-                        &mut methods,
-                        &trait_did,
-                        &local_def(item.id));
-                }
-
                 return @Impl {
                     did: local_def(item.id),
                     ident: item.ident,
@@ -820,12 +662,12 @@ impl CoherenceChecker {
 
     pub fn add_external_impl(&self,
                              impls_seen: &mut HashSet<def_id>,
-                             crate_store: @mut CStore,
                              impl_def_id: def_id) {
-        let implementation = csearch::get_impl(crate_store, impl_def_id);
+        let tcx = self.crate_context.tcx;
+        let implementation = @csearch::get_impl(tcx, impl_def_id);
 
         debug!("coherence: adding impl from external crate: %s",
-               ty::item_path_str(self.crate_context.tcx, implementation.did));
+               ty::item_path_str(tcx, implementation.did));
 
         // Make sure we don't visit the same implementation multiple times.
         if !impls_seen.insert(implementation.did) {
@@ -834,9 +676,8 @@ impl CoherenceChecker {
         }
         // Good. Continue.
 
-        let self_type = lookup_item_type(self.crate_context.tcx,
-                                         implementation.did);
-        let associated_traits = get_impl_trait(self.crate_context.tcx,
+        let self_type = lookup_item_type(tcx, implementation.did);
+        let associated_traits = get_impl_trait(tcx,
                                                implementation.did);
 
         // Do a sanity check to make sure that inherent methods have base
@@ -846,35 +687,26 @@ impl CoherenceChecker {
                                        dummy_sp(),
                                        self_type.ty) {
                 None => {
-                    let session = self.crate_context.tcx.sess;
-                    session.bug(fmt!("no base type for external impl with no \
+                    tcx.sess.bug(fmt!("no base type for external impl with no \
                                       trait: %s (type %s)!",
-                                     session.str_of(implementation.ident),
-                                     ty_to_str(self.crate_context.tcx,
-                                               self_type.ty)));
+                                     tcx.sess.str_of(implementation.ident),
+                                     ty_to_str(tcx, self_type.ty)));
                 }
                 Some(_) => {} // Nothing to do.
             }
         }
 
         // Record all the trait methods.
-        let mut implementation = @implementation;
         for associated_traits.iter().advance |trait_ref| {
-            self.instantiate_default_methods(implementation.did,
-                                             *trait_ref);
-
-            // XXX(sully): We could probably avoid this copy if there are no
-            // default methods.
-            let mut methods = implementation.methods.clone();
-            self.add_provided_methods_to_impl(&mut methods,
-                                              &trait_ref.def_id,
-                                              &implementation.did);
-            implementation = @Impl {
-                methods: methods,
-                ..*implementation
-            };
+              self.add_trait_impl(trait_ref.def_id, implementation);
+        }
 
-            self.add_trait_method(trait_ref.def_id, implementation);
+        // For any methods that use a default implementation, add them to
+        // the map. This is a bit unfortunate.
+        for implementation.methods.iter().advance |method| {
+            for method.provided_source.iter().advance |source| {
+                tcx.provided_method_sources.insert(method.def_id, *source);
+            }
         }
 
         // Add the implementation to the mapping from implementation to base
@@ -887,14 +719,16 @@ impl CoherenceChecker {
                 // inherent methods apply to `impl Type` but not
                 // `impl Trait for Type`:
                 if associated_traits.is_none() {
-                    self.add_inherent_method(base_type_def_id,
-                                             implementation);
+                    self.add_inherent_impl(base_type_def_id,
+                                           implementation);
                 }
 
                 self.base_type_def_ids.insert(implementation.did,
                                               base_type_def_id);
             }
         }
+
+        tcx.impls.insert(implementation.did, implementation);
     }
 
     // Adds implementations and traits from external crates to the coherence
@@ -907,9 +741,7 @@ impl CoherenceChecker {
             for each_path(crate_store, crate_number) |_, def_like, _| {
                 match def_like {
                     dl_impl(def_id) => {
-                        self.add_external_impl(&mut impls_seen,
-                                               crate_store,
-                                               def_id)
+                        self.add_external_impl(&mut impls_seen, def_id)
                     }
                     dl_def(_) | dl_field => loop,   // Skip this.
                 }
@@ -922,12 +754,11 @@ impl CoherenceChecker {
     //
 
     pub fn populate_destructor_table(&self) {
-        let coherence_info = &self.crate_context.coherence_info;
         let tcx = self.crate_context.tcx;
         let drop_trait = match tcx.lang_items.drop_trait() {
             Some(id) => id, None => { return }
         };
-        let impls_opt = coherence_info.extension_methods.find(&drop_trait);
+        let impls_opt = tcx.trait_impls.find(&drop_trait);
 
         let impls;
         match impls_opt {
@@ -940,7 +771,7 @@ impl CoherenceChecker {
                 // We'll error out later. For now, just don't ICE.
                 loop;
             }
-            let method_def_id = impl_info.methods[0].did;
+            let method_def_id = impl_info.methods[0].def_id;
 
             let self_type = self.get_self_type_for_implementation(*impl_info);
             match ty::get(self_type.ty).sty {
@@ -1024,7 +855,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(
@@ -1044,7 +876,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);
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 5f68f439eba..bfbebd0a52e 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -192,7 +192,6 @@ pub struct CrateCtxt {
     trait_map: resolve::TraitMap,
     method_map: method_map,
     vtable_map: vtable_map,
-    coherence_info: coherence::CoherenceInfo,
     tcx: ty::ctxt
 }
 
@@ -415,7 +414,6 @@ pub fn check_crate(tcx: ty::ctxt,
         trait_map: trait_map,
         method_map: @mut HashMap::new(),
         vtable_map: @mut HashMap::new(),
-        coherence_info: coherence::CoherenceInfo(),
         tcx: tcx
     };
 
diff --git a/src/test/auxiliary/trait_default_method_xc_aux_2.rs b/src/test/auxiliary/trait_default_method_xc_aux_2.rs
new file mode 100644
index 00000000000..2d4f539f82b
--- /dev/null
+++ b/src/test/auxiliary/trait_default_method_xc_aux_2.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_default_method_xc_aux.rs
+
+extern mod aux(name = "trait_default_method_xc_aux");
+use aux::A;
+
+pub struct a_struct { x: int }
+
+impl A for a_struct {
+    fn f(&self) -> int { 10 }
+}
+
+// This function will need to get inlined, and badness may result.
+pub fn welp<A>(x: A) -> A {
+    let a = a_struct { x: 0 };
+    a.g();
+    x
+}
diff --git a/src/test/run-pass/trait-default-method-xc-2.rs b/src/test/run-pass/trait-default-method-xc-2.rs
new file mode 100644
index 00000000000..1dad5d23b88
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-xc-2.rs
@@ -0,0 +1,25 @@
+// xfail-fast
+// aux-build:trait_default_method_xc_aux.rs
+// aux-build:trait_default_method_xc_aux_2.rs
+
+
+extern mod aux(name = "trait_default_method_xc_aux");
+extern mod aux2(name = "trait_default_method_xc_aux_2");
+use aux::A;
+use aux2::{a_struct, welp};
+
+
+fn main () {
+
+    let a = a_struct { x: 0 };
+    let b = a_struct { x: 1 };
+
+    assert_eq!(0i.g(), 10);
+    assert_eq!(a.g(), 10);
+    assert_eq!(a.h(), 11);
+    assert_eq!(b.g(), 10);
+    assert_eq!(b.h(), 11);
+    assert_eq!(A::lurr(&a, &b), 21);
+
+    welp(&0);
+}