about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-20 07:28:36 -0700
committerbors <bors@rust-lang.org>2013-07-20 07:28:36 -0700
commit3a1db2d1e631feede472396fced1806dfd3cf677 (patch)
tree22cdb1e335e8b20c45ebdb994e43260cdb0bec1d /src
parentec53efa64dcd449c78381b680a7184d9876d4f29 (diff)
parent002bfd796648547839d0f3740308995b4a926f50 (diff)
downloadrust-3a1db2d1e631feede472396fced1806dfd3cf677.tar.gz
rust-3a1db2d1e631feede472396fced1806dfd3cf677.zip
auto merge of #7886 : msullivan/rust/default-methods, r=pcwalton
This does a bunch of cleanup on the data structures for the trait system. (Unfortunately it doesn't remove `provided_method_sources`. Maybe later.)

It also changes how cross crate methods are handled, so that information about them is exported in metadata, instead of having the methods regenerated by every crate that imports an impl.

r? @nikomatsakis, maybe?
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);
+}