about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/common.rs4
-rw-r--r--src/librustc/metadata/csearch.rs29
-rw-r--r--src/librustc/metadata/decoder.rs102
-rw-r--r--src/librustc/metadata/encoder.rs175
-rw-r--r--src/librustc/metadata/tydecode.rs6
-rw-r--r--src/librustc/metadata/tyencode.rs2
-rw-r--r--src/librustc/middle/astencode.rs1
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/moves.rs2
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/middle/resolve.rs71
-rw-r--r--src/librustc/middle/trans/callee.rs2
-rw-r--r--src/librustc/middle/trans/meth.rs26
-rw-r--r--src/librustc/middle/trans/reflect.rs2
-rw-r--r--src/librustc/middle/ty.rs115
-rw-r--r--src/librustc/middle/typeck/astconv.rs10
-rw-r--r--src/librustc/middle/typeck/check/mod.rs16
-rw-r--r--src/librustc/middle/typeck/coherence.rs6
-rw-r--r--src/librustc/middle/typeck/collect.rs153
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/libsyntax/ast.rs1
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/test/compile-fail/extern-no-call.rs2
-rw-r--r--src/test/compile-fail/issue-3563.rs2
24 files changed, 414 insertions, 323 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 920631a55b4..d3b06009d72 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -102,6 +102,7 @@ pub static tag_item_dtor: uint = 0x49u;
 pub static tag_item_trait_method_self_ty: uint = 0x4b;
 pub static tag_item_trait_method_self_ty_region: uint = 0x4c;
 
+
 // Reexports are found within module tags. Each reexport contains def_ids
 // and names.
 pub static tag_items_data_item_reexport: uint = 0x4d;
@@ -159,6 +160,9 @@ pub static tag_items_data_item_visibility: uint = 0x78;
 pub static tag_link_args: uint = 0x79;
 pub static tag_link_args_arg: uint = 0x7a;
 
+pub static tag_item_method_tps: uint = 0x7b;
+pub static tag_item_method_fty: uint = 0x7c;
+
 pub struct LinkMeta {
     name: @str,
     vers: @str,
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 16b896f11d6..8e7ecdec638 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -111,12 +111,24 @@ pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id,
     }
 }
 
-pub fn get_trait_methods(tcx: ty::ctxt,
-                         def: ast::def_id)
-                      -> @~[ty::method] {
-    let cstore = tcx.cstore;
+pub fn get_method(tcx: ty::ctxt,
+                  def: ast::def_id) -> ty::method
+{
+    let cdata = cstore::get_crate_data(tcx.cstore, def.crate);
+    decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx)
+}
+
+pub fn get_method_name_and_self_ty(cstore: @mut cstore::CStore,
+                                   def: ast::def_id) -> (ast::ident, ast::self_ty_)
+{
+    let cdata = cstore::get_crate_data(cstore, def.crate);
+    decoder::get_method_name_and_self_ty(cstore.intr, cdata, def.node)
+}
+
+pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore,
+                                def: ast::def_id) -> ~[ast::def_id] {
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx)
+    decoder::get_trait_method_def_ids(cdata, def.node)
 }
 
 pub fn get_provided_trait_methods(tcx: ty::ctxt,
@@ -133,13 +145,6 @@ pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] {
     decoder::get_supertraits(cdata, def.node, tcx)
 }
 
-pub fn get_method_names_if_trait(cstore: @mut cstore::CStore,
-                                 def: ast::def_id)
-                              -> Option<~[(ast::ident, ast::self_ty_)]> {
-    let cdata = cstore::get_crate_data(cstore, def.crate);
-    return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
-}
-
 pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::def_id)
                           -> Option<ast::ident> {
     let cdata = cstore::get_crate_data(cstore, def.crate);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index dcea22b09d6..800df628bc2 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -19,7 +19,8 @@ use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
 use metadata::csearch;
 use metadata::cstore;
 use metadata::decoder;
-use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
+use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
+                         parse_bare_fn_ty_data};
 use middle::{ty, resolve};
 
 use core::hash::HashUtil;
@@ -229,6 +230,12 @@ fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
                   |_, did| translate_def_id(cdata, did))
 }
 
+fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy {
+    let tp = reader::get_doc(doc, tag_item_method_fty);
+    parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
+                          |_, did| translate_def_id(cdata, did))
+}
+
 pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
                  tcx: ty::ctxt, cdata: cmd) -> ty::t {
     let t = doc_type(item, tcx, cdata);
@@ -247,10 +254,11 @@ fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
     results
 }
 
-fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
+fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
+                        tag: uint)
     -> @~[ty::param_bounds] {
     let mut bounds = ~[];
-    for reader::tagged_docs(item, tag_items_data_item_ty_param_bounds) |p| {
+    for reader::tagged_docs(item, tag) |p| {
         let bd = parse_bounds_data(p.data, p.start, cdata.cnum, tcx,
                                    |_, did| translate_def_id(cdata, did));
         bounds.push(bd);
@@ -338,7 +346,8 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
             let enum_did = item_reqd_and_translated_parent_item(cnum, item);
             dl_def(ast::def_variant(enum_did, did))
         }
-        Trait | Enum => dl_def(ast::def_ty(did)),
+        Trait => dl_def(ast::def_trait(did)),
+        Enum => dl_def(ast::def_ty(did)),
         Impl => dl_impl(did),
         PublicField | PrivateField | InheritedField => dl_field,
     }
@@ -359,7 +368,7 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     let t = item_type(ast::def_id { crate: cdata.cnum, node: id }, item, tcx,
                       cdata);
     let tp_bounds = if family_has_type_params(item_family(item)) {
-        item_ty_param_bounds(item, tcx, cdata)
+        item_ty_param_bounds(item, tcx, cdata, tag_items_data_item_ty_param_bounds)
     } else { @~[] };
     let rp = item_ty_region_param(item);
     ty::ty_param_bounds_and_ty {
@@ -690,36 +699,46 @@ pub fn get_impls_for_mod(intr: @ident_interner,
     @result
 }
 
-/* Works for both classes and traits */
-pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
-                         tcx: ty::ctxt) -> @~[ty::method] {
+pub fn get_method_name_and_self_ty(
+    intr: @ident_interner,
+    cdata: cmd,
+    id: ast::node_id) -> (ast::ident, ast::self_ty_)
+{
+    let method_doc = lookup_item(id, cdata.data);
+    let name = item_name(intr, method_doc);
+    let self_ty = get_self_ty(method_doc);
+    (name, self_ty)
+}
+
+pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
+                  tcx: ty::ctxt) -> ty::method
+{
+    let method_doc = lookup_item(id, cdata.data);
+    let bounds = item_ty_param_bounds(method_doc, tcx, cdata,
+                                      tag_item_method_tps);
+    let name = item_name(intr, method_doc);
+    let def_id = item_def_id(method_doc, cdata);
+    let fty = doc_method_fty(method_doc, tcx, cdata);
+    let self_ty = get_self_ty(method_doc);
+    ty::method {
+        ident: name,
+        tps: bounds,
+        fty: fty,
+        self_ty: self_ty,
+        vis: ast::public,
+        def_id: def_id
+    }
+}
+
+pub fn get_trait_method_def_ids(cdata: cmd,
+                                id: ast::node_id) -> ~[ast::def_id] {
     let data = cdata.data;
     let item = lookup_item(id, data);
     let mut result = ~[];
     for reader::tagged_docs(item, tag_item_trait_method) |mth| {
-        let bounds = item_ty_param_bounds(mth, tcx, cdata);
-        let name = item_name(intr, mth);
-        let ty = doc_type(mth, tcx, cdata);
-        let def_id = item_def_id(mth, cdata);
-        let fty = match ty::get(ty).sty {
-            ty::ty_bare_fn(ref f) => copy *f,
-            _ => {
-                tcx.diag.handler().bug(
-                    ~"get_trait_methods: id has non-function type");
-            }
-        };
-        let self_ty = get_self_ty(mth);
-        result.push(ty::method {
-            ident: name,
-            tps: bounds,
-            fty: fty,
-            self_ty: self_ty,
-            vis: ast::public,
-            def_id: def_id
-        });
+        result.push(item_def_id(mth, cdata));
     }
-    debug!("get_trait_methods: }");
-    @result
+    result
 }
 
 pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
@@ -734,7 +753,8 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
 
         let did = item_def_id(mth, cdata);
 
-        let bounds = item_ty_param_bounds(mth, tcx, cdata);
+        let bounds = item_ty_param_bounds(mth, tcx, cdata,
+                                          tag_items_data_item_ty_param_bounds);
         let name = item_name(intr, mth);
         let ty = doc_type(mth, tcx, cdata);
 
@@ -777,26 +797,6 @@ pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     return results;
 }
 
-// If the item in question is a trait, returns its set of methods and
-// their self types. Otherwise, returns none. This overlaps in an
-// annoying way with get_trait_methods.
-pub fn get_method_names_if_trait(intr: @ident_interner, cdata: cmd,
-                                 node_id: ast::node_id)
-                              -> Option<~[(ast::ident, ast::self_ty_)]> {
-
-    let item = lookup_item(node_id, cdata.data);
-    if item_family(item) != Trait {
-        return None;
-    }
-
-    let mut resulting_methods = ~[];
-    for reader::tagged_docs(item, tag_item_trait_method) |method| {
-        resulting_methods.push(
-            (item_name(intr, method), get_self_ty(method)));
-    }
-    return Some(resulting_methods);
-}
-
 pub fn get_type_name_if_impl(intr: @ident_interner,
                              cdata: cmd,
                              node_id: ast::node_id) -> Option<ast::ident> {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 6000e559554..61501d83083 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -170,8 +170,10 @@ fn encode_family(ebml_w: writer::Encoder, c: char) {
 
 pub fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) }
 
-fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
-                               params: @~[ty::param_bounds]) {
+fn encode_ty_type_param_bounds(ebml_w: writer::Encoder,
+                               ecx: @EncodeContext,
+                               params: @~[ty::param_bounds],
+                               tag: uint) {
     let ty_str_ctxt = @tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
@@ -179,7 +181,7 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
         reachable: |a| reachable(ecx, a),
         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
     for params.each |param| {
-        ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
+        ebml_w.start_tag(tag);
         tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param);
         ebml_w.end_tag();
     }
@@ -190,7 +192,8 @@ fn encode_type_param_bounds(ebml_w: writer::Encoder,
                             params: &OptVec<TyParam>) {
     let ty_param_bounds =
         @params.map_to_vec(|param| *ecx.tcx.ty_param_bounds.get(&param.id));
-    encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds);
+    encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds,
+                                tag_items_data_item_ty_param_bounds);
 }
 
 
@@ -227,6 +230,23 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) {
     ebml_w.end_tag();
 }
 
+fn encode_method_fty(ecx: @EncodeContext,
+                     ebml_w: writer::Encoder,
+                     typ: &ty::BareFnTy)
+{
+    ebml_w.start_tag(tag_item_method_fty);
+
+    let ty_str_ctxt = @tyencode::ctxt {
+        diag: ecx.diag,
+        ds: def_to_str,
+        tcx: ecx.tcx,
+        reachable: |a| reachable(ecx, a),
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+    tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
+
+    ebml_w.end_tag();
+}
+
 fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) {
     ebml_w.start_tag(tag_items_data_item_symbol);
     match ecx.item_symbols.find(&id) {
@@ -868,8 +888,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
         }
       }
       item_trait(ref generics, ref traits, ref ms) => {
-        let mut provided_methods = ~[];
-
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
@@ -879,96 +897,89 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
-        let mut i = 0u;
-        for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
-            match (*ms)[i] {
-              required(ref ty_m) => {
-                ebml_w.start_tag(tag_item_trait_method);
-                encode_def_id(ebml_w, local_def((*ty_m).id));
-                encode_name(ecx, ebml_w, mty.ident);
-                encode_type_param_bounds(ebml_w, ecx,
-                                         &ty_m.generics.ty_params);
-                encode_type(ecx, ebml_w,
-                            ty::mk_bare_fn(tcx, copy mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
-                encode_self_type(ebml_w, mty.self_ty);
-                encode_method_sort(ebml_w, 'r');
-                encode_visibility(ebml_w, ast::public);
-                ebml_w.end_tag();
-              }
-              provided(m) => {
-                provided_methods.push(m);
-
-                ebml_w.start_tag(tag_item_trait_method);
-                encode_def_id(ebml_w, local_def(m.id));
-                encode_name(ecx, ebml_w, mty.ident);
-                encode_type_param_bounds(ebml_w, ecx,
-                                         &m.generics.ty_params);
-                encode_type(ecx, ebml_w,
-                            ty::mk_bare_fn(tcx, copy mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
-                encode_self_type(ebml_w, mty.self_ty);
-                encode_method_sort(ebml_w, 'p');
-                encode_visibility(ebml_w, m.vis);
-                ebml_w.end_tag();
-              }
-            }
-            i += 1;
+        for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
+            ebml_w.start_tag(tag_item_trait_method);
+            encode_def_id(ebml_w, method_def_id);
+            ebml_w.end_tag();
         }
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         for traits.each |associated_trait| {
-           encode_trait_ref(ebml_w, ecx, *associated_trait)
+            encode_trait_ref(ebml_w, ecx, *associated_trait);
         }
-
         ebml_w.end_tag();
 
-        // Now, output all of the static methods as items.  Note that for the
-        // method info, we output static methods with type signatures as
-        // written. Here, we output the *real* type signatures. I feel like
-        // maybe we should only ever handle the real type signatures.
-        for ms.each |m| {
-            let ty_m = ast_util::trait_method_to_ty_method(m);
-            if ty_m.self_ty.node != ast::sty_static { loop; }
+        // Now output the method info for each method.
+        //
+        // Note: for the moment, the data structures here are *slightly*
+        // different from those expected by `encode_info_for_method()`,
+        // but I do plan to refactor this later in this patch to avoid the
+        // duplication.
+        for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
+            assert!(method_def_id.crate == ast::local_crate);
 
-            index.push(entry { val: ty_m.id, pos: ebml_w.writer.tell() });
+            let method_ty: @ty::method = ty::method(tcx, method_def_id);
+
+            index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
 
             ebml_w.start_tag(tag_items_data_item);
-            encode_def_id(ebml_w, local_def(ty_m.id));
+
+            encode_def_id(ebml_w, method_def_id);
             encode_parent_item(ebml_w, local_def(item.id));
-            encode_name(ecx, ebml_w, ty_m.ident);
-            encode_family(ebml_w,
-                          purity_static_method_family(ty_m.purity));
-            let polyty = ecx.tcx.tcache.get(&local_def(ty_m.id));
-            encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
-            encode_type(ecx, ebml_w, polyty.ty);
-            let mut m_path = vec::append(~[], path); // :-(
-            m_path += [ast_map::path_name(item.ident)];
-            encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident));
-
-            // For now, use the item visibility until trait methods can have
-            // real visibility in the AST.
-            encode_visibility(ebml_w, item.vis);
+            encode_name(ecx, ebml_w, method_ty.ident);
+
+            match method_ty.self_ty {
+                sty_static => {
+                    encode_family(ebml_w,
+                                  purity_static_method_family(
+                                      method_ty.fty.purity));
+
+                    let tpt = ty::lookup_item_type(tcx, method_def_id);
+                    encode_ty_type_param_bounds(ebml_w, ecx, tpt.bounds,
+                                                tag_items_data_item_ty_param_bounds);
+                    encode_type(ecx, ebml_w, tpt.ty);
+                }
 
-            ebml_w.end_tag();
-        }
+                _ => {
+                    encode_family(ebml_w,
+                                  purity_fn_family(
+                                      method_ty.fty.purity));
+                }
+            }
 
-        // Finally, output all the provided methods as items.
-        for provided_methods.each |m| {
-            index.push(entry { val: m.id, pos: ebml_w.writer.tell() });
+            encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
+                                        tag_item_method_tps);
+            encode_method_fty(ecx, ebml_w, &method_ty.fty);
+            encode_visibility(ebml_w, method_ty.vis);
+            encode_self_type(ebml_w, method_ty.self_ty);
+            let mut trait_path = vec::append(~[], path);
+            trait_path.push(ast_map::path_name(item.ident));
+            encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
+
+            match ms[i] {
+                required(_) => {
+                    encode_method_sort(ebml_w, 'r');
+                }
 
-            // We do not concatenate the generics of the owning impl and that
-            // of provided methods.  I am not sure why this is. -ndm
-            let owner_generics = ast_util::empty_generics();
+                provided(m) => {
+                    // This is obviously a bogus assert but I don't think this
+                    // ever worked before anyhow...near as I can tell, before
+                    // we would emit two items.
+                    if method_ty.self_ty == sty_static {
+                        tcx.sess.span_unimpl(
+                            item.span,
+                            fmt!("Method %s is both provided and static",
+                                 *tcx.sess.intr().get(method_ty.ident)));
+                    }
+                    encode_type_param_bounds(ebml_w, ecx,
+                                             &m.generics.ty_params);
+                    encode_method_sort(ebml_w, 'p');
+                    (ecx.encode_inlined_item)(
+                        ecx, ebml_w, path,
+                        ii_method(local_def(item.id), m));
+                }
+            }
 
-            encode_info_for_method(ecx,
-                                   ebml_w,
-                                   /*bad*/copy path,
-                                   true,
-                                   item.id,
-                                   *m,
-                                   item.vis,
-                                   &owner_generics,
-                                   &m.generics);
+            ebml_w.end_tag();
         }
       }
       item_mac(*) => fail!(~"item macros unimplemented")
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 111bc307ed3..2982ed26877 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -119,6 +119,12 @@ pub fn parse_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
     parse_ty(st, conv)
 }
 
+pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
+                             conv: conv_did) -> ty::BareFnTy {
+    let st = parse_state_from_data(data, crate_num, pos, tcx);
+    parse_bare_fn_ty(st, conv)
+}
+
 pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
                       conv: conv_did) -> ty::arg {
     let st = parse_state_from_data(data, crate_num, pos, tcx);
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 251ba9b35cb..419219d411d 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -384,7 +384,7 @@ fn enc_onceness(w: @io::Writer, o: Onceness) {
     }
 }
 
-fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
+pub fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
     enc_purity(w, ft.purity);
     enc_abi_set(w, ft.abis);
     enc_fn_sig(w, cx, &ft.sig);
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index b6b6730620e..6fc74c9a713 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -417,6 +417,7 @@ impl tr for ast::def {
           ast::def_variant(e_did, v_did) => {
             ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
           }
+          ast::def_trait(did) => ast::def_trait(did.tr(xcx)),
           ast::def_ty(did) => ast::def_ty(did.tr(xcx)),
           ast::def_prim_ty(p) => ast::def_prim_ty(p),
           ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index b7ec6208d56..6473cb8e8e0 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -462,7 +462,7 @@ pub impl mem_categorization_ctxt {
           ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) |
           ast::def_foreign_mod(_) | ast::def_const(_) |
           ast::def_use(_) | ast::def_variant(*) |
-          ast::def_ty(_) | ast::def_prim_ty(_) |
+          ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) |
           ast::def_ty_param(*) | ast::def_struct(*) |
           ast::def_typaram_binder(*) | ast::def_region(_) |
           ast::def_label(_) | ast::def_self_ty(*) => {
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 7740485e82c..ed7ca441b98 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -211,7 +211,7 @@ use core::prelude::*;
 use middle::pat_util::{pat_bindings};
 use middle::freevars;
 use middle::ty;
-use middle::typeck::method_map;
+use middle::typeck::{method_map, method_map_entry};
 use util::ppaux;
 use util::common::indenter;
 
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 75eb8ef1a85..1c60c37ed12 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -690,7 +690,9 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
     match ty.node {
       ast::ty_path(path, id) => {
         match cx.def_map.find(&id) {
-          Some(&ast::def_ty(did)) | Some(&ast::def_struct(did)) => {
+          Some(&ast::def_ty(did)) |
+          Some(&ast::def_trait(did)) |
+          Some(&ast::def_struct(did)) => {
             if did.crate == ast::local_crate {
                 if cx.region_is_relevant(path.rp) {
                     cx.add_dep(did.node);
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 08542301e23..7232e99bf22 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -12,7 +12,8 @@ use core::prelude::*;
 
 use driver::session;
 use driver::session::Session;
-use metadata::csearch::{each_path, get_method_names_if_trait};
+use metadata::csearch::{each_path, get_trait_method_def_ids};
+use metadata::csearch::get_method_name_and_self_ty;
 use metadata::csearch::get_static_methods_if_impl;
 use metadata::csearch::get_type_name_if_impl;
 use metadata::cstore::find_extern_mod_stmt_cnum;
@@ -31,7 +32,7 @@ use syntax::ast::{crate, decl_item, def, def_arg, def_binding};
 use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
 use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
 use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty};
-use syntax::ast::{def_ty_param, def_typaram_binder};
+use syntax::ast::{def_ty_param, def_typaram_binder, def_trait};
 use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
 use syntax::ast::{expr_binary, expr_break, expr_field};
 use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
@@ -1341,7 +1342,7 @@ pub impl Resolver {
                 let def_id = local_def(item.id);
                 self.trait_info.insert(def_id, method_names);
 
-                name_bindings.define_type(privacy, def_ty(def_id), sp);
+                name_bindings.define_type(privacy, def_trait(def_id), sp);
                 visit_item(item, new_parent, visitor);
             }
 
@@ -1611,36 +1612,40 @@ pub impl Resolver {
                     crate) building value %s", final_ident);
             child_name_bindings.define_value(Public, def, dummy_sp());
           }
-          def_ty(def_id) => {
-            debug!("(building reduced graph for external \
-                    crate) building type %s", final_ident);
-
-            // If this is a trait, add all the method names
-            // to the trait info.
-
-            match get_method_names_if_trait(self.session.cstore, def_id) {
-              None => {
-                // Nothing to do.
-              }
-              Some(method_names) => {
-                let mut interned_method_names = HashSet::new();
-                for method_names.each |method_data| {
-                    let (method_name, self_ty) = *method_data;
-                    debug!("(building reduced graph for \
-                            external crate) ... adding \
-                            trait method '%s'",
-                           *self.session.str_of(method_name));
-
-                    // Add it to the trait info if not static.
-                    if self_ty != sty_static {
-                        interned_method_names.insert(method_name);
-                    }
-                }
-                self.trait_info.insert(def_id, interned_method_names);
+          def_trait(def_id) => {
+              debug!("(building reduced graph for external \
+                      crate) building type %s", final_ident);
+
+              // If this is a trait, add all the method names
+              // to the trait info.
+
+              let method_def_ids = get_trait_method_def_ids(self.session.cstore,
+                                                            def_id);
+              let mut interned_method_names = HashSet::new();
+              for method_def_ids.each |&method_def_id| {
+                  let (method_name, self_ty) =
+                      get_method_name_and_self_ty(self.session.cstore,
+                                                  method_def_id);
+
+                  debug!("(building reduced graph for \
+                          external crate) ... adding \
+                          trait method '%s'",
+                         *self.session.str_of(method_name));
+
+                  // Add it to the trait info if not static.
+                  if self_ty != sty_static {
+                      interned_method_names.insert(method_name);
+                  }
               }
-            }
+              self.trait_info.insert(def_id, interned_method_names);
 
-            child_name_bindings.define_type(Public, def, dummy_sp());
+              child_name_bindings.define_type(Public, def, dummy_sp());
+          }
+          def_ty(_) => {
+              debug!("(building reduced graph for external \
+                      crate) building type %s", final_ident);
+
+              child_name_bindings.define_type(Public, def, dummy_sp());
           }
           def_struct(def_id) => {
             debug!("(building reduced graph for external \
@@ -4952,7 +4957,7 @@ pub impl Resolver {
                 match child_name_bindings.def_for_namespace(TypeNS) {
                     Some(def) => {
                         match def {
-                            def_ty(trait_def_id) => {
+                            def_trait(trait_def_id) => {
                                 self.add_trait_info_if_containing_method(
                                     &mut found_traits, trait_def_id, name);
                             }
@@ -4979,7 +4984,7 @@ pub impl Resolver {
                         match target.bindings.def_for_namespace(TypeNS) {
                             Some(def) => {
                                 match def {
-                                    def_ty(trait_def_id) => {
+                                    def_trait(trait_def_id) => {
                                         let added = self.
                                         add_trait_info_if_containing_method(
                                             &mut found_traits,
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index ec67c68f93c..b8b0bddcf05 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -148,7 +148,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
             ast::def_self(*) => {
                 datum_callee(bcx, ref_expr)
             }
-            ast::def_mod(*) | ast::def_foreign_mod(*) |
+            ast::def_mod(*) | ast::def_foreign_mod(*) | ast::def_trait(*) |
             ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
             ast::def_use(*) | ast::def_typaram_binder(*) |
             ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ed9000e7418..accdb655750 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -174,6 +174,7 @@ pub fn trans_method_callee(bcx: block,
                            mentry: typeck::method_map_entry)
                         -> Callee {
     let _icx = bcx.insn_ctxt("impl::trans_method_callee");
+    let tcx = bcx.tcx();
 
     debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)",
            callee_id, bcx.expr_to_str(self), mentry);
@@ -189,33 +190,33 @@ pub fn trans_method_callee(bcx: block,
 
             // Get the ID of the method we're calling.
             let method_name =
-                ty::trait_methods(bcx.tcx(), trait_id)[method_index].ident;
-            let method_id = method_with_name(bcx.ccx(), impl_def_id,
-                                             method_name);
+                ty::trait_method(tcx, trait_id, method_index).ident;
+            let method_id =
+                method_with_name(bcx.ccx(), impl_def_id, method_name);
             origin = typeck::method_static(method_id);
         }
         typeck::method_super(trait_id, method_index) => {
             // <self_ty> is the self type for this method call
             let self_ty = node_id_type(bcx, self.id);
-            let tcx = bcx.tcx();
             // <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);
             // Get the supertrait's methods
-            let supertrait_methods = ty::trait_methods(tcx, trait_id);
+            let supertrait_method_def_ids = ty::trait_method_def_ids(tcx, trait_id);
             // Make sure to fail with a readable error message if
             // there's some internal error here
-            if !(method_index < supertrait_methods.len()) {
+            if !(method_index < supertrait_method_def_ids.len()) {
                 tcx.sess.bug(~"trans_method_callee: supertrait method \
                                index is out of bounds");
             }
             // Get the method name using the method index in the origin
-            let method_name = supertrait_methods[method_index].ident;
+            let method_name =
+                ty::method(tcx, supertrait_method_def_ids[method_index]).ident;
             // Now that we know the impl ID, we can look up the method
             // ID from its name
             origin = typeck::method_static(method_with_name(bcx.ccx(),
-                                              impl_id,
-                                              method_name));
+                                                            impl_id,
+                                                            method_name));
         }
         typeck::method_static(*) | typeck::method_param(*) |
         typeck::method_trait(*) => {}
@@ -448,7 +449,7 @@ pub fn trans_monomorphized_callee(bcx: block,
     return match vtbl {
       typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
-          let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
+          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);
 
@@ -791,10 +792,11 @@ pub fn make_impl_vtable(ccx: @CrateContext,
         || ~"make_impl_vtable: non-trait-type implemented");
 
     let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
-    make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
+    make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
+        let im = ty::method(tcx, *method_def_id);
         let fty = ty::subst_tps(tcx, substs, None,
                                 ty::mk_bare_fn(tcx, copy im.fty));
-        if (*im.tps).len() > 0u || ty::type_has_self(fty) {
+        if im.tps.len() > 0u || ty::type_has_self(fty) {
             debug!("(making impl vtable) method has self or type params: %s",
                    *tcx.sess.str_of(im.ident));
             C_null(T_ptr(T_nil()))
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index a9869f15875..224981d6e75 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -31,7 +31,7 @@ use syntax::ast;
 
 pub struct Reflector {
     visitor_val: ValueRef,
-    visitor_methods: @~[ty::method],
+    visitor_methods: @~[@ty::method],
     final_bcx: block,
     tydesc_ty: TypeRef,
     bcx: block
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 19ffb4edc84..fcdd5a650af 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -255,6 +255,15 @@ struct ctxt_ {
     // other items.
     node_type_substs: @mut HashMap<node_id, ~[t]>,
 
+    // Maps from a method to the method "descriptor"
+    methods: @mut HashMap<def_id, @method>,
+
+    // Maps from a trait def-id to a list of the def-ids of its methods
+    trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
+
+    // A cache for the trait_methods() routine
+    trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
+
     items: ast_map::map,
     intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
     freevars: freevars::freevar_map,
@@ -266,7 +275,6 @@ struct ctxt_ {
     tc_cache: @mut HashMap<uint, TypeContents>,
     ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
     enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
-    trait_method_cache: @mut HashMap<def_id, @~[method]>,
     ty_param_bounds: @mut HashMap<ast::node_id, param_bounds>,
     inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
     adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
@@ -831,7 +839,9 @@ pub fn mk_ctxt(s: session::Session,
         tc_cache: @mut HashMap::new(),
         ast_ty_to_ty_cache: @mut HashMap::new(),
         enum_var_cache: @mut HashMap::new(),
-        trait_method_cache: @mut HashMap::new(),
+        methods: @mut HashMap::new(),
+        trait_method_def_ids: @mut HashMap::new(),
+        trait_methods_cache: @mut HashMap::new(),
         ty_param_bounds: @mut HashMap::new(),
         inferred_modes: @mut HashMap::new(),
         adjustments: @mut HashMap::new(),
@@ -3028,7 +3038,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
             let trt_bounds =
                 ty::lookup_item_type(tcx, trt_id).bounds;
             @(vec::append(/*bad*/copy *trt_bounds,
-                          *ty::trait_methods(tcx, trt_id)[n_mth].tps))
+                          *ty::trait_method(tcx, trt_id, n_mth).tps))
           }
         }
     }
@@ -3213,10 +3223,8 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
         fields.map(|f| tcx.sess.str_of(f.ident))));
 }
 
-pub fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
-    let mut i = 0u;
-    for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
-    return None;
+pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
+    vec::position(meths, |m| m.ident == id)
 }
 
 /// Returns a vector containing the indices of all type parameters that appear
@@ -3537,10 +3545,6 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
     }
 }
 
-pub fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
-    cx.trait_method_cache.insert(ast_util::local_def(id), ms);
-}
-
 pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
     if is_local(id) {
         match cx.items.find(&id.node) {
@@ -3594,25 +3598,66 @@ pub fn trait_supertraits(cx: ctxt,
     return @result;
 }
 
-pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
-    match cx.trait_method_cache.find(&id) {
-      // Local traits are supposed to have been added explicitly.
-      Some(&ms) => ms,
-      _ => {
-        // If the lookup in trait_method_cache fails, assume that the trait
-        // method we're trying to look up is in a different crate, and look
-        // for it there.
-        assert!(id.crate != ast::local_crate);
-        let result = csearch::get_trait_methods(cx, id);
-
-        // Store the trait method in the local trait_method_cache so that
-        // future lookups succeed.
-        cx.trait_method_cache.insert(id, result);
-        result
-      }
+fn lookup_locally_or_in_crate_store<V:Copy>(
+    descr: &str,
+    def_id: ast::def_id,
+    map: &mut HashMap<ast::def_id, V>,
+    load_external: &fn() -> V) -> V
+{
+    /*!
+     *
+     * Helper for looking things up in the various maps
+     * that are populated during typeck::collect (e.g.,
+     * `cx.methods`, `cx.tcache`, etc).  All of these share
+     * the pattern that if the id is local, it should have
+     * been loaded into the map by the `typeck::collect` phase.
+     * If the def-id is external, then we have to go consult
+     * the crate loading code (and cache the result for the future).
+     */
+
+    match map.find(&def_id) {
+        Some(&v) => { return v; }
+        None => { }
+    }
+
+    if def_id.crate == ast::local_crate {
+        fail!(fmt!("No def'n found for %? in tcx.%s",
+                   def_id, descr));
+    }
+    let v = load_external();
+    map.insert(def_id, v);
+    return v;
+}
+
+pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
+    let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
+    ty::method(cx, method_def_id)
+}
+
+pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
+    match cx.trait_methods_cache.find(&trait_did) {
+        Some(&methods) => methods,
+        None => {
+            let def_ids = ty::trait_method_def_ids(cx, trait_did);
+            let methods = @def_ids.map(|d| ty::method(cx, *d));
+            cx.trait_methods_cache.insert(trait_did, methods);
+            methods
+        }
     }
 }
 
+pub fn method(cx: ctxt, id: ast::def_id) -> @method {
+    lookup_locally_or_in_crate_store(
+        "methods", id, cx.methods,
+        || @csearch::get_method(cx, id))
+}
+
+pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
+    lookup_locally_or_in_crate_store(
+        "methods", id, cx.trait_method_def_ids,
+        || @csearch::get_trait_method_def_ids(cx.cstore, id))
+}
+
 /*
   Could this return a list of (def_id, substs) pairs?
  */
@@ -3916,19 +3961,9 @@ pub fn enum_variant_with_id(cx: ctxt,
 pub fn lookup_item_type(cx: ctxt,
                         did: ast::def_id)
                      -> ty_param_bounds_and_ty {
-    match cx.tcache.find(&did) {
-      Some(&tpt) => {
-        // The item is in this crate. The caller should have added it to the
-        // type cache already
-        return tpt;
-      }
-      None => {
-        assert!(did.crate != ast::local_crate);
-        let tyt = csearch::get_type(cx, did);
-        cx.tcache.insert(did, tyt);
-        return tyt;
-      }
-    }
+    lookup_locally_or_in_crate_store(
+        "tcache", did, cx.tcache,
+        || csearch::get_type(cx, did))
 }
 
 // Look up a field ID, whether or not it's local
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 4b4cb857252..c54e76b9c05 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -243,7 +243,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
                         return ty::mk_estr(tcx, vst);
                     }
-                    Some(&ast::def_ty(type_def_id)) => {
+                    Some(&ast::def_trait(type_def_id)) => {
                         let result = ast_path_to_substs_and_ty(
                             self, rscope,
                             type_def_id, path);
@@ -271,7 +271,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
                                                     trait_store);
 
                             }
-                            _ => {}
+                            _ => {
+                                tcx.sess.span_bug(
+                                    a_seq_ty.ty.span,
+                                    fmt!("def_trait but not ty_trait"));
+                            }
                         }
                     }
                     _ => {}
@@ -372,7 +376,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
           Some(&d) => d
         };
         match a_def {
-          ast::def_ty(did) | ast::def_struct(did) => {
+          ast::def_trait(did) | ast::def_ty(did) | ast::def_struct(did) => {
             ast_path_to_ty(self, rscope, did, path).ty
           }
           ast::def_prim_ty(nty) => {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 32009495772..c8b274e4569 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -2126,11 +2126,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
       ast::expr_vstore(ev, vst) => {
         let typ = match ev.node {
           ast::expr_lit(@codemap::spanned { node: ast::lit_str(s), _ }) => {
-            let tt = ast_expr_vstore_to_vstore(fcx, ev, s.len(), vst);
+            let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
             ty::mk_estr(tcx, tt)
           }
           ast::expr_vec(ref args, mutbl) => {
-            let tt = ast_expr_vstore_to_vstore(fcx, ev, args.len(), vst);
+            let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
             let mutability;
             let mut any_error = false;
             let mut any_bot = false;
@@ -2164,7 +2164,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
           ast::expr_repeat(element, count_expr, mutbl) => {
             let count = ty::eval_repeat_count(tcx, count_expr);
             check_expr_with_hint(fcx, count_expr, ty::mk_uint(tcx));
-            let tt = ast_expr_vstore_to_vstore(fcx, ev, count, vst);
+            let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
             let mutability = match vst {
                 ast::expr_vstore_mut_box | ast::expr_vstore_mut_slice => {
                     ast::m_mutbl
@@ -3173,7 +3173,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
       ast::def_upvar(_, inner, _, _) => {
         return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
       }
-      ast::def_ty(_) | ast::def_prim_ty(_) | ast::def_ty_param(*)=> {
+      ast::def_trait(_) |
+      ast::def_ty(_) |
+      ast::def_prim_ty(_) |
+      ast::def_ty_param(*)=> {
         fcx.ccx.tcx.sess.span_bug(sp, ~"expected value but found type");
       }
       ast::def_mod(*) | ast::def_foreign_mod(*) => {
@@ -3211,6 +3214,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
     let ty_param_count = vec::len(*tpt.bounds);
     let ty_substs_len = vec::len(pth.types);
 
+    debug!("ty_param_count=%? ty_substs_len=%?",
+           ty_param_count,
+           ty_substs_len);
+
     // determine the region bound, using the value given by the user
     // (if any) and otherwise using a fresh region variable
     let self_r = match pth.rp {
@@ -3306,7 +3313,6 @@ pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: span, typ: ty::t) -> bool {
 
 pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt,
                                  e: @ast::expr,
-                                 _n: uint,
                                  v: ast::expr_vstore)
                               -> ty::vstore {
     match v {
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 466cb8ed54f..ab99aa20d64 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -38,7 +38,7 @@ use middle::typeck::infer::combine::Combine;
 use middle::typeck::infer::InferCtxt;
 use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
 use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
-use syntax::ast::{crate, def_id, def_mod, def_ty};
+use syntax::ast::{crate, def_id, def_mod, def_ty, def_trait};
 use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
 use syntax::ast;
 use syntax::ast_map::node_item;
@@ -507,7 +507,7 @@ pub impl CoherenceChecker {
             provided_method_idents.insert(*ident);
         }
 
-        for ty::trait_methods(tcx, trait_did).each |method| {
+        for ty::trait_methods(tcx, trait_did).each |&method| {
             if provided_method_idents.contains(&method.ident) {
                 if !f(method) {
                     break;
@@ -947,7 +947,7 @@ pub impl CoherenceChecker {
                                                   crate_store,
                                                   def_id);
                     }
-                    dl_def(def_ty(def_id)) => {
+                    dl_def(def_trait(def_id)) => {
                         let tcx = self.crate_context.tcx;
                         let polytype = csearch::get_type(tcx, def_id);
                         match ty::get(polytype.ty).sty {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index f1d743e79e5..d89d1c407d7 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -53,7 +53,6 @@ use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::{local_def, split_trait_methods};
-use syntax::ast_util::{trait_method_to_ty_method};
 use syntax::ast_util;
 use syntax::codemap::span;
 use syntax::codemap;
@@ -221,19 +220,61 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
 }
 
 pub fn ensure_trait_methods(ccx: &CrateCtxt,
-                            id: ast::node_id,
-                            trait_ty: ty::t) {
-    fn store_methods<T>(ccx: &CrateCtxt,
-                        id: ast::node_id,
-                        stuff: &[T],
-                        f: &fn(v: &T) -> ty::method) {
-        ty::store_trait_methods(ccx.tcx, id, @stuff.map(f));
+                            trait_id: ast::node_id,
+                            trait_ty: ty::t)
+{
+    let tcx = ccx.tcx;
+    let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x);
+    match *tcx.items.get(&trait_id) {
+        ast_map::node_item(@ast::item {
+            node: ast::item_trait(ref generics, _, ref ms),
+            _
+        }, _) => {
+            let trait_bounds = ty_param_bounds(ccx, generics);
+
+            // For each method, construct a suitable ty::method and
+            // store it into the `tcx.methods` table:
+            for ms.each |m| {
+                let ty_method = @match m {
+                    &ast::required(ref m) => {
+                        ty_method_of_trait_method(ccx, region_paramd, generics,
+                                                  &m.id, &m.ident, &m.self_ty,
+                                                  &m.generics, &m.purity, &m.decl)
+                    }
+
+                    &ast::provided(ref m) => {
+                        ty_method_of_trait_method(ccx, region_paramd, generics,
+                                                  &m.id, &m.ident, &m.self_ty,
+                                                  &m.generics, &m.purity, &m.decl)
+                    }
+                };
+
+                if ty_method.self_ty == ast::sty_static {
+                    make_static_method_ty(ccx, region_paramd,
+                                          ty_method, trait_ty,
+                                          trait_bounds);
+                }
+
+                tcx.methods.insert(ty_method.def_id, ty_method);
+            }
+
+            // Add an entry mapping
+            let method_def_ids = @ms.map(|m| {
+                match m {
+                    &ast::required(ref ty_method) => local_def(ty_method.id),
+                    &ast::provided(ref method) => local_def(method.id)
+                }
+            });
+
+            let trait_def_id = local_def(trait_id);
+            tcx.trait_method_def_ids.insert(trait_def_id, method_def_ids);
+        }
+        _ => { /* Ignore things that aren't traits */ }
     }
 
     fn make_static_method_ty(ccx: &CrateCtxt,
-                             am: &ast::ty_method,
                              rp: Option<ty::region_variance>,
-                             m: ty::method,
+                             m: &ty::method,
                              // Take this as an argument b/c we may check
                              // the impl before the trait.
                              trait_ty: ty::t,
@@ -267,7 +308,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                            ty::mk_bare_fn(ccx.tcx, copy m.fty));
         let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
                        + *m.tps);
-        ccx.tcx.tcache.insert(local_def(am.id),
+        ccx.tcx.tcache.insert(m.def_id,
                               ty_param_bounds_and_ty {
                                 bounds: bounds,
                                 region_param: rp,
@@ -275,40 +316,31 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
     }
 
 
-    let tcx = ccx.tcx;
-    let region_paramd = tcx.region_paramd_items.find(&id).map_consume(|x| *x);
-    match *tcx.items.get(&id) {
-      ast_map::node_item(@ast::item {
-                node: ast::item_trait(ref generics, _, ref ms),
-                _
-            }, _) => {
-        store_methods::<ast::trait_method>(ccx, id, *ms, |m| {
-            let def_id;
-            match *m {
-                ast::required(ref ty_method) => {
-                    def_id = local_def((*ty_method).id)
-                }
-                ast::provided(method) => def_id = local_def(method.id)
-            }
-
-            let trait_bounds = ty_param_bounds(ccx, generics);
-            let ty_m = trait_method_to_ty_method(m);
-            let method_ty = ty_of_ty_method(
-                ccx,
-                &ty_m,
-                region_paramd,
-                def_id,
-                generics
-            );
-            if ty_m.self_ty.node == ast::sty_static {
-                make_static_method_ty(ccx, &ty_m, region_paramd,
-                                      method_ty, trait_ty,
-                                      trait_bounds);
-            }
-            method_ty
-        });
-      }
-      _ => { /* Ignore things that aren't traits */ }
+    fn ty_method_of_trait_method(self: &CrateCtxt,
+                                 trait_rp: Option<ty::region_variance>,
+                                 trait_generics: &ast::Generics,
+                                 m_id: &ast::node_id,
+                                 m_ident: &ast::ident,
+                                 m_self_ty: &ast::self_ty,
+                                 m_generics: &ast::Generics,
+                                 m_purity: &ast::purity,
+                                 m_decl: &ast::fn_decl) -> ty::method
+    {
+        let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics);
+        ty::method {
+            ident: *m_ident,
+            tps: ty_param_bounds(self, m_generics),
+            fty: astconv::ty_of_bare_fn(self,
+                                        &rscope,
+                                        *m_purity,
+                                        AbiSet::Rust(),
+                                        &m_generics.lifetimes,
+                                        m_decl),
+            // assume public, because this is only invoked on trait methods
+            self_ty: m_self_ty.node,
+            vis: ast::public,
+            def_id: local_def(*m_id)
+        }
     }
 }
 
@@ -501,8 +533,8 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
                                    rp: Option<ty::region_variance>,
                                    selfty: ty::t,
                                    a_trait_ty: @ast::trait_ref,
-                                   impl_ms: &[ConvertedMethod]) {
-
+                                   impl_ms: &[ConvertedMethod])
+{
     let tcx = ccx.tcx;
     let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
 
@@ -530,7 +562,7 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
     let trait_ms = ty::trait_methods(tcx, did);
     for impl_ms.each |impl_m| {
         match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
-            Some(ref trait_m) => {
+            Some(trait_m) => {
                 let num_impl_tps = generics.ty_params.len();
                 compare_impl_method(
                     ccx.tcx, num_impl_tps, impl_m, trait_m,
@@ -786,29 +818,6 @@ pub fn ty_of_method(ccx: &CrateCtxt,
     }
 }
 
-pub fn ty_of_ty_method(self: &CrateCtxt,
-                       m: &ast::ty_method,
-                       rp: Option<ty::region_variance>,
-                       id: ast::def_id,
-                       generics: &ast::Generics)
-                    -> ty::method {
-    let rscope = MethodRscope::new(m.self_ty.node, rp, generics);
-    ty::method {
-        ident: m.ident,
-        tps: ty_param_bounds(self, &m.generics),
-        fty: astconv::ty_of_bare_fn(self,
-                                    &rscope,
-                                    m.purity,
-                                    AbiSet::Rust(),
-                                    &m.generics.lifetimes,
-                                    &m.decl),
-        // assume public, because this is only invoked on trait methods
-        self_ty: m.self_ty.node,
-        vis: ast::public,
-        def_id: id
-    }
-}
-
 /*
   Instantiates the path for the given trait reference, assuming that
   it's bound to a valid trait type. Returns the def_id for the defining
@@ -828,7 +837,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
     let rscope = type_rscope(rp);
 
     match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
-      ast::def_ty(t_id) => {
+      ast::def_trait(t_id) => {
         let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path);
 
         write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index afbf3f485d0..238ecf7acea 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -443,7 +443,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
                    str::from_bytes(~[('a' as u8) + (id as u8)]))
           }
       }
-      ty_self(*) => ~"self",
+      ty_self(*) => ~"Self",
       ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
         let path = ty::item_path(cx, did);
         let base = ast_map::path_to_str(path, cx.sess.intr());
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 2e7ae4c537a..31dc476cbe4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -194,6 +194,7 @@ pub enum def {
     def_local(node_id, bool /* is_mutbl */),
     def_variant(def_id /* enum */, def_id /* variant */),
     def_ty(def_id),
+    def_trait(def_id),
     def_prim_ty(prim_ty),
     def_ty_param(def_id, uint),
     def_binding(node_id, binding_mode),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 208ed1e35fe..c7227fa1768 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -61,7 +61,7 @@ pub fn def_id_of_def(d: def) -> def_id {
       def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
       def_foreign_mod(id) | def_const(id) |
       def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
-      def_use(id) | def_struct(id) => {
+      def_use(id) | def_struct(id) | def_trait(id) => {
         id
       }
       def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
diff --git a/src/test/compile-fail/extern-no-call.rs b/src/test/compile-fail/extern-no-call.rs
index 8c6deb34816..58649f3209b 100644
--- a/src/test/compile-fail/extern-no-call.rs
+++ b/src/test/compile-fail/extern-no-call.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:expected function or foreign function but found `*u8`
+// error-pattern:expected function but found `*u8`
 extern fn f() {
 }
 
diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs
index 0388f0fd290..d56cb0d51d2 100644
--- a/src/test/compile-fail/issue-3563.rs
+++ b/src/test/compile-fail/issue-3563.rs
@@ -10,7 +10,7 @@
 
 trait A {
   fn a(&self) {
-      || self.b() //~ ERROR type `&'self self` does not implement any method in scope named `b`
+      || self.b() //~ ERROR type `&'self Self` does not implement any method in scope named `b`
   }
 }
 fn main() {}