about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2012-08-02 16:01:38 -0700
committerMichael Sullivan <sully@msully.net>2012-08-07 17:18:14 -0700
commit7f7f47620eaeaab8e4993e568d2f5c23e1cb6416 (patch)
tree3e93c8b6772ae3d87b090766661e429215b2cbad /src/rustc
parenta695e074f23e1c5353947c1d0e0c2b418750b80d (diff)
downloadrust-7f7f47620eaeaab8e4993e568d2f5c23e1cb6416.tar.gz
rust-7f7f47620eaeaab8e4993e568d2f5c23e1cb6416.zip
Implement static typeclass methods. Closes #3132.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/csearch.rs2
-rw-r--r--src/rustc/metadata/decoder.rs29
-rw-r--r--src/rustc/metadata/encoder.rs77
-rw-r--r--src/rustc/middle/astencode.rs17
-rw-r--r--src/rustc/middle/borrowck/categorization.rs2
-rw-r--r--src/rustc/middle/resolve3.rs321
-rw-r--r--src/rustc/middle/trans/base.rs3
-rw-r--r--src/rustc/middle/trans/impl.rs64
-rw-r--r--src/rustc/middle/trans/type_use.rs6
-rw-r--r--src/rustc/middle/typeck/check.rs8
-rw-r--r--src/rustc/middle/typeck/check/method.rs7
-rw-r--r--src/rustc/middle/typeck/collect.rs73
12 files changed, 396 insertions, 213 deletions
diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs
index 627d7a326d0..203b527b21f 100644
--- a/src/rustc/metadata/csearch.rs
+++ b/src/rustc/metadata/csearch.rs
@@ -144,7 +144,7 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] {
 }
 
 fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
-                          -> option<@dvec<@~str>> {
+    -> option<@dvec<(@~str, ast::self_ty_)>> {
 
     let cdata = cstore::get_crate_data(cstore, def.crate);
     return decoder::get_method_names_if_trait(cdata, def.node);
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 2fae50785af..fdb4be4c6e0 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -282,7 +282,10 @@ fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num)
       'u' => dl_def(ast::def_fn(did, ast::unsafe_fn)),
       'f' => dl_def(ast::def_fn(did, ast::impure_fn)),
       'p' => dl_def(ast::def_fn(did, ast::pure_fn)),
-      'F' => dl_def(ast::def_fn(did, ast::extern_fn)),
+      'e' => dl_def(ast::def_fn(did, ast::extern_fn)),
+      'U' => dl_def(ast::def_static_method(did, ast::unsafe_fn)),
+      'F' => dl_def(ast::def_static_method(did, ast::impure_fn)),
+      'P' => dl_def(ast::def_static_method(did, ast::pure_fn)),
       'y' => dl_def(ast::def_ty(did)),
       't' => dl_def(ast::def_ty(did)),
       'm' => dl_def(ast::def_mod(did)),
@@ -592,6 +595,7 @@ fn get_self_ty(item: ebml::doc) -> ast::self_ty_ {
 
     let self_ty_kind = string[0];
     match self_ty_kind as char {
+        's' => { return ast::sty_static; }
         'r' => { return ast::sty_by_ref; }
         'v' => { return ast::sty_value; }
         '@' => { return ast::sty_box(get_mutability(string[1])); }
@@ -693,21 +697,23 @@ fn get_trait_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     @result
 }
 
-// If the item in question is a trait, returns its set of methods. Otherwise,
-// returns none.
+// 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.
 fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id)
-                          -> option<@dvec<@~str>> {
+                          -> option<@dvec<(@~str, ast::self_ty_)>> {
 
     let item = lookup_item(node_id, cdata.data);
     if item_family(item) != 'I' {
         return none;
     }
 
-    let resulting_method_names = @dvec();
+    let resulting_methods = @dvec();
     for ebml::tagged_docs(item, tag_item_trait_method) |method| {
-        (*resulting_method_names).push(item_name(method));
+        resulting_methods.push(
+            (item_name(method), get_self_ty(method)));
     }
-    return some(resulting_method_names);
+    return some(resulting_methods);
 }
 
 fn get_item_attrs(cdata: cmd,
@@ -757,7 +763,7 @@ fn get_class_fields(cdata: cmd, id: ast::node_id) -> ~[ty::field_ty] {
 
 fn family_has_type_params(fam_ch: char) -> bool {
     match check fam_ch {
-      'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' => false,
+      'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' | 'e' => false,
       'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
           | 'a' | 'S'
           => true
@@ -791,9 +797,10 @@ fn item_family_to_str(fam: char) -> ~str {
       'f' => return ~"fn",
       'u' => return ~"unsafe fn",
       'p' => return ~"pure fn",
-      'F' => return ~"foreign fn",
-      'U' => return ~"unsafe foreign fn",
-      'P' => return ~"pure foreign fn",
+      'F' => return ~"static method",
+      'U' => return ~"unsafe static method",
+      'P' => return ~"pure static method",
+      'e' => return ~"foreign fn",
       'y' => return ~"type",
       'T' => return ~"foreign type",
       't' => return ~"type",
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 545d3821f02..4c535f8af09 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -122,6 +122,21 @@ fn encode_enum_variant_paths(ebml_w: ebml::writer, variants: ~[variant],
     }
 }
 
+fn encode_trait_static_method_paths(ebml_w: ebml::writer,
+                                    methods: ~[trait_method],
+                                    path: ~[ident],
+                                    &index: ~[entry<~str>]) {
+    for methods.each |method| {
+        let ty_m = trait_method_to_ty_method(method);
+        if ty_m.self_ty.node != sty_static { again; }
+        add_to_index(ebml_w, path, index, ty_m.ident);
+        do ebml_w.wr_tag(tag_paths_data_item) {
+            encode_name(ebml_w, ty_m.ident);
+            encode_def_id(ebml_w, local_def(ty_m.id));
+        }
+    }
+}
+
 fn add_to_index(ebml_w: ebml::writer, path: &[ident], &index: ~[entry<~str>],
                 name: ident) {
     let mut full_path = ~[];
@@ -214,10 +229,11 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
               }
               encode_enum_variant_paths(ebml_w, variants, path, index);
           }
-          item_trait(*) => {
+          item_trait(_, _, methods) => {
             do ebml_w.wr_tag(tag_paths_data_item) {
-                  encode_name_and_def_id(ebml_w, it.ident, it.id);
-              }
+                encode_name_and_def_id(ebml_w, it.ident, it.id);
+            }
+            encode_trait_static_method_paths(ebml_w, methods, path, index);
           }
           item_impl(*) => {}
           item_mac(*) => fail ~"item macros unimplemented"
@@ -286,8 +302,8 @@ fn encode_family(ebml_w: ebml::writer, c: char) {
 
 fn def_to_str(did: def_id) -> ~str { fmt!{"%d:%d", did.crate, did.node} }
 
-fn encode_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
-                            params: ~[ty_param]) {
+fn encode_ty_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
+                               params: @~[ty::param_bounds]) {
     let ty_str_ctxt = @{diag: ecx.diag,
                         ds: def_to_str,
                         tcx: ecx.tcx,
@@ -295,12 +311,19 @@ fn encode_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
                         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
     for params.each |param| {
         ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
-        let bs = ecx.tcx.ty_param_bounds.get(param.id);
-        tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, bs);
+        tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, param);
         ebml_w.end_tag();
     }
 }
 
+fn encode_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
+                            params: ~[ty_param]) {
+    let ty_param_bounds =
+        @params.map(|param| ecx.tcx.ty_param_bounds.get(param.id));
+    encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds);
+}
+
+
 fn encode_variant_id(ebml_w: ebml::writer, vid: def_id) {
     ebml_w.start_tag(tag_items_data_item_variant);
     ebml_w.writer.write(str::bytes(def_to_str(vid)));
@@ -472,6 +495,7 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) {
     // Encode the base self type.
     let ch;
     match self_type {
+        sty_static =>       { ch = 's' as u8; }
         sty_by_ref =>       { ch = 'r' as u8; }
         sty_value =>        { ch = 'v' as u8; }
         sty_region(_, _) => { ch = '&' as u8; }
@@ -482,7 +506,7 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) {
 
     // Encode mutability.
     match self_type {
-        sty_by_ref | sty_value => { /* No-op. */ }
+        sty_static | sty_by_ref | sty_value => { /* No-op. */ }
         sty_region(_, m_imm) | sty_box(m_imm) | sty_uniq(m_imm) => {
             ebml_w.writer.write(&[ 'i' as u8 ]);
         }
@@ -499,7 +523,7 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) {
         sty_region(region, _) => {
             encode_region(ebml_w, *region);
         }
-        sty_by_ref | sty_value | sty_box(*) | sty_uniq(*) => {
+        sty_static | sty_by_ref | sty_value | sty_box(*) | sty_uniq(*) => {
             // Nothing to do.
         }
     }
@@ -608,7 +632,15 @@ fn purity_fn_family(p: purity) -> char {
       unsafe_fn => 'u',
       pure_fn => 'p',
       impure_fn => 'f',
-      extern_fn => 'F'
+      extern_fn => 'e'
+    }
+}
+fn purity_static_method_family(p: purity) -> char {
+    match p {
+      unsafe_fn => 'U',
+      pure_fn => 'P',
+      impure_fn => 'F',
+      extern_fn => 'E'
     }
 }
 
@@ -853,6 +885,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             match ms[i] {
               required(ty_m) => {
                 ebml_w.start_tag(tag_item_trait_method);
+                encode_def_id(ebml_w, local_def(ty_m.id));
                 encode_name(ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
                 encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
@@ -873,6 +906,30 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
            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 vec::each(ms) |m| {
+            let ty_m = ast_util::trait_method_to_ty_method(m);
+            if ty_m.self_ty.node != ast::sty_static { again; }
+
+            vec::push(*index, {val: ty_m.id, pos: ebml_w.writer.tell()});
+
+            ebml_w.start_tag(tag_items_data_item);
+            encode_def_id(ebml_w, local_def(ty_m.id));
+            encode_name(ebml_w, ty_m.ident);
+            encode_family(ebml_w,
+                          purity_static_method_family(ty_m.decl.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);
+            encode_path(ebml_w, path, ast_map::path_name(ty_m.ident));
+            ebml_w.end_tag();
+        }
+
+
       }
       item_mac(*) => fail ~"item macros unimplemented"
     }
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index b1b54816998..cf0b586e51e 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -353,13 +353,16 @@ fn decode_def(xcx: extended_decode_ctxt, doc: ebml::doc) -> ast::def {
 impl of tr for ast::def {
     fn tr(xcx: extended_decode_ctxt) -> ast::def {
         match self {
-          ast::def_fn(did, p) => ast::def_fn(did.tr(xcx), p),
-          ast::def_self(nid) => ast::def_self(xcx.tr_id(nid)),
-          ast::def_mod(did) => ast::def_mod(did.tr(xcx)),
-          ast::def_foreign_mod(did) => ast::def_foreign_mod(did.tr(xcx)),
-          ast::def_const(did) => ast::def_const(did.tr(xcx)),
-          ast::def_arg(nid, m) => ast::def_arg(xcx.tr_id(nid), m),
-          ast::def_local(nid, b) => ast::def_local(xcx.tr_id(nid), b),
+          ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) }
+          ast::def_static_method(did, p) => {
+            ast::def_static_method(did.tr(xcx), p)
+          }
+          ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) }
+          ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
+          ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) }
+          ast::def_const(did) => { ast::def_const(did.tr(xcx)) }
+          ast::def_arg(nid, m) => { ast::def_arg(xcx.tr_id(nid), m) }
+          ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) }
           ast::def_variant(e_did, v_did) => {
             ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
           }
diff --git a/src/rustc/middle/borrowck/categorization.rs b/src/rustc/middle/borrowck/categorization.rs
index 2d76607e8fa..41204f117a5 100644
--- a/src/rustc/middle/borrowck/categorization.rs
+++ b/src/rustc/middle/borrowck/categorization.rs
@@ -191,7 +191,7 @@ impl public_methods for borrowck_ctxt {
                expr_ty: ty::t,
                def: ast::def) -> cmt {
         match def {
-          ast::def_fn(*) | ast::def_mod(_) |
+          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(_) |
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index a2bd1280021..7efd7442380 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -16,7 +16,7 @@ import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
 import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
 import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod};
 import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
-import syntax::ast::{def_typaram_binder};
+import syntax::ast::{def_typaram_binder, def_static_method};
 import syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
 import syntax::ast::{expr_binary, expr_cast, expr_field, expr_fn};
 import syntax::ast::{expr_fn_block, expr_index, expr_path};
@@ -30,17 +30,18 @@ import syntax::ast::{instance_var, item, item_class, item_const, item_enum};
 import syntax::ast::{item_fn, item_mac, item_foreign_mod, item_impl};
 import syntax::ast::{item_mod, item_trait, item_ty, le, local, local_crate};
 import syntax::ast::{lt, method, mul, ne, neg, node_id, pat, pat_enum};
-import syntax::ast::{pat_ident, pat_struct, path, prim_ty, pat_box, pat_uniq};
-import syntax::ast::{pat_lit, pat_range, pat_rec, pat_tup, pat_wild};
+import syntax::ast::{pat_ident, path, prim_ty, pat_box, pat_uniq, pat_lit};
+import syntax::ast::{pat_range, pat_rec, pat_struct, pat_tup, pat_wild};
 import syntax::ast::{provided, required, rem, self_ty_, shl, stmt_decl};
-import syntax::ast::{subtract, ty, ty_bool, ty_char, ty_f, ty_f32, ty_f64};
-import syntax::ast::{ty_float, ty_i, ty_i16, ty_i32, ty_i64, ty_i8, ty_int};
-import syntax::ast::{ty_param, ty_path, ty_str, ty_u, ty_u16, ty_u32, ty_u64};
-import syntax::ast::{ty_u8, ty_uint, variant, view_item, view_item_export};
+import syntax::ast::{sty_static, subtract, ty};
+import syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
+import syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param};
+import syntax::ast::{ty_path, ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8};
+import syntax::ast::{ty_uint, variant, view_item, view_item_export};
 import syntax::ast::{view_item_import, view_item_use, view_path_glob};
 import syntax::ast::{view_path_list, view_path_simple};
 import syntax::ast_util::{def_id_of_def, dummy_sp, local_def, new_def_hash};
-import syntax::ast_util::{walk_pat, path_to_ident};
+import syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
 import syntax::attr::{attr_metas, contains_name};
 import syntax::print::pprust::{pat_to_str, path_to_str};
 import syntax::codemap::span;
@@ -1079,18 +1080,25 @@ class Resolver {
                 // Add the names of all the methods to the trait info.
                 let method_names = @atom_hashmap();
                 for methods.each |method| {
-                    let atom;
-                    match method {
-                        required(required_method) => {
-                            atom = (*self.atom_table).intern
-                                (required_method.ident);
-                        }
-                        provided(provided_method) => {
-                            atom = (*self.atom_table).intern
-                                (provided_method.ident);
-                        }
+                    let ty_m = trait_method_to_ty_method(method);
+
+                    let atom = (*self.atom_table).intern(ty_m.ident);
+                    // Add it to the trait info if not static,
+                    // add it as a name in the enclosing module otherwise.
+                    match ty_m.self_ty.node {
+                      sty_static => {
+                        // which parent to use??
+                        let (method_name_bindings, _) =
+                            self.add_child(atom, new_parent, ~[ValueNS],
+                                           ty_m.span);
+                        let def = def_static_method(local_def(ty_m.id),
+                                                    ty_m.decl.purity);
+                        (*method_name_bindings).define_value(def, ty_m.span);
+                      }
+                      _ => {
+                        (*method_names).insert(atom, ());
+                      }
                     }
-                    (*method_names).insert(atom, ());
                 }
 
                 let def_id = local_def(item.id);
@@ -1338,6 +1346,124 @@ class Resolver {
         visit_block(block, new_parent, visitor);
     }
 
+    fn handle_external_def(def: def, modules: hashmap<def_id, @Module>,
+                           child_name_bindings: @NameBindings,
+                           final_ident: ~str,
+                           atom: Atom, new_parent: ReducedGraphParent) {
+        match def {
+          def_mod(def_id) | def_foreign_mod(def_id) => {
+            match copy child_name_bindings.module_def {
+              NoModuleDef => {
+                debug!("(building reduced graph for \
+                        external crate) building module \
+                        %s", final_ident);
+                let parent_link = self.get_parent_link(new_parent, atom);
+
+                match modules.find(def_id) {
+                  none => {
+                    child_name_bindings.define_module(parent_link,
+                                                      some(def_id),
+                                                      dummy_sp());
+                    modules.insert(def_id,
+                                   child_name_bindings.get_module());
+                  }
+                  some(existing_module) => {
+                    // Create an import resolution to
+                    // avoid creating cycles in the
+                    // module graph.
+
+                    let resolution = @ImportResolution(dummy_sp());
+                    resolution.outstanding_references = 0;
+
+                    match existing_module.parent_link {
+                      NoParentLink |
+                      BlockParentLink(*) => {
+                        fail ~"can't happen";
+                      }
+                      ModuleParentLink(parent_module, atom) => {
+
+                        let name_bindings = parent_module.children.get(atom);
+
+                        resolution.module_target =
+                            some(Target(parent_module, name_bindings));
+                      }
+                    }
+
+                    debug!("(building reduced graph for external crate) \
+                            ... creating import resolution");
+
+                    new_parent.import_resolutions.insert(atom, resolution);
+                  }
+                }
+              }
+              ModuleDef(module_) => {
+                debug!("(building reduced graph for \
+                        external crate) already created \
+                        module");
+                module_.def_id = some(def_id);
+                modules.insert(def_id, module_);
+              }
+            }
+          }
+          def_fn(def_id, _) | def_static_method(def_id, _) |
+          def_const(def_id) | def_variant(_, def_id) => {
+            debug!("(building reduced graph for external \
+                    crate) building value %s", final_ident);
+            (*child_name_bindings).define_value(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 interned_method_names = @atom_hashmap();
+                for method_names.each |method_data| {
+                    let (method_name, self_ty) = method_data;
+                    debug!("(building reduced graph for \
+                            external crate) ... adding \
+                            trait method '%?'", method_name);
+
+                    let m_atom = self.atom_table.intern(method_name);
+
+                    // Add it to the trait info if not static.
+                    if self_ty != sty_static {
+                        interned_method_names.insert(m_atom, ());
+                    }
+                }
+                self.trait_info.insert(def_id, interned_method_names);
+              }
+            }
+
+            child_name_bindings.define_type(def, dummy_sp());
+          }
+          def_class(def_id, has_constructor) => {
+            debug!("(building reduced graph for external \
+                    crate) building type %s (value? %d)",
+                   final_ident,
+                   if has_constructor { 1 } else { 0 });
+            child_name_bindings.define_type(def, dummy_sp());
+
+            if has_constructor {
+                child_name_bindings.define_value(def, dummy_sp());
+            }
+          }
+          def_self(*) | def_arg(*) | def_local(*) |
+          def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
+          def_use(*) | def_upvar(*) | def_region(*) |
+          def_typaram_binder(*) => {
+            fail fmt!("didn't expect `%?`", def);
+          }
+        }
+    }
+
     /**
      * Builds the reduced graph rooted at the 'use' directive for an external
      * crate.
@@ -1395,145 +1521,9 @@ class Resolver {
 
             match path_entry.def_like {
                 dl_def(def) => {
-                    match def {
-                        def_mod(def_id) | def_foreign_mod(def_id) => {
-                            match copy child_name_bindings.module_def {
-                                NoModuleDef => {
-                                    debug!{"(building reduced graph for \
-                                            external crate) building module \
-                                            %s", final_ident};
-                                    let parent_link =
-                                        self.get_parent_link(new_parent,
-                                                             atom);
-
-                                    match modules.find(def_id) {
-                                        none => {
-                                            (*child_name_bindings).
-                                                define_module(parent_link,
-                                                              some(def_id),
-                                                             dummy_sp());
-                                            modules.insert(def_id,
-                                                (*child_name_bindings).
-                                                    get_module());
-                                        }
-                                        some(existing_module) => {
-                                            // Create an import resolution to
-                                            // avoid creating cycles in the
-                                            // module graph.
-
-                                            let resolution =
-                                                @ImportResolution(dummy_sp());
-                                            resolution.
-                                                outstanding_references = 0;
-
-                                            match existing_module
-                                                .parent_link {
-
-                                                NoParentLink |
-                                                BlockParentLink(*) => {
-                                                    fail ~"can't happen";
-                                                }
-                                                ModuleParentLink
-                                                        (parent_module,
-                                                         atom) => {
-
-                                                    let name_bindings =
-                                                        parent_module.
-                                                            children.get
-                                                                (atom);
-
-                                                    resolution.module_target =
-                                                        some(Target
-                                                            (parent_module,
-                                                             name_bindings));
-                                                }
-                                            }
-
-                                            debug!{"(building reduced graph \
-                                                     for external crate) \
-                                                     ... creating import \
-                                                     resolution"};
-
-                                            new_parent.import_resolutions.
-                                                insert(atom, resolution);
-                                        }
-                                    }
-                                }
-                                ModuleDef(module_) => {
-                                    debug!{"(building reduced graph for \
-                                            external crate) already created \
-                                            module"};
-                                    module_.def_id = some(def_id);
-                                    modules.insert(def_id, module_);
-                                }
-                            }
-                        }
-                        def_fn(def_id, _) | def_const(def_id) |
-                        def_variant(_, def_id) => {
-                            debug!{"(building reduced graph for external \
-                                    crate) building value %s", final_ident};
-                            // Might want a better span
-                            (*child_name_bindings).define_value(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 interned_method_names =
-                                        @atom_hashmap();
-                                    for method_names.each |method_name| {
-                                        debug!{"(building reduced graph for \
-                                                 external crate) ... adding \
-                                                 trait method '%?'",
-                                               method_name};
-                                        let atom =
-                                            (*self.atom_table).intern
-                                                (method_name);
-                                        (*interned_method_names).insert(atom,
-                                                                        ());
-                                    }
-                                    self.trait_info.insert
-                                        (def_id, interned_method_names);
-                                }
-                            }
-
-                            // Might want a better span
-                            (*child_name_bindings).define_type(def,
-                                                               dummy_sp());
-                        }
-                        def_class(def_id, has_constructor) => {
-                            debug!{"(building reduced graph for external \
-                                    crate) building type %s (value? %d)",
-                                    final_ident,
-                                    if has_constructor { 1 } else { 0 }};
-                            // Might want a better span
-                            (*child_name_bindings).define_type(def,
-                                                               dummy_sp());
-
-                            // Might want a better span
-                            if has_constructor {
-                                (*child_name_bindings).define_value(def,
-                                                              dummy_sp());
-                            }
-                        }
-                        def_self(*) | def_arg(*) | def_local(*) |
-                        def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
-                        def_use(*) | def_upvar(*) | def_region(*) |
-                          def_typaram_binder(*) => {
-                            fail fmt!{"didn't expect `%?`", def};
-                        }
-                    }
+                    self.handle_external_def(def, modules,
+                                             child_name_bindings,
+                                             final_ident, atom, new_parent);
                 }
                 dl_impl(_) => {
                     // Because of the infelicitous way the metadata is
@@ -3589,11 +3579,17 @@ class Resolver {
                               method.id,
                               outer_type_parameter_count,
                               rib_kind);
+        // we only have self ty if it is a non static method
+        let self_binding = match method.self_ty.node {
+          sty_static => { NoSelfBinding }
+          _ => { HasSelfBinding(method.self_id) }
+        };
+
         self.resolve_function(rib_kind,
                               some(@method.decl),
                               type_parameters,
                               method.body,
-                              HasSelfBinding(method.self_id),
+                              self_binding,
                               NoCaptureClause,
                               visitor);
     }
@@ -3647,7 +3643,11 @@ class Resolver {
             for methods.each |method| {
                 // We also need a new scope for the method-specific
                 // type parameters.
-
+                self.resolve_method(MethodRibKind(id, Provided(method.id)),
+                                    method,
+                                    outer_type_parameter_count,
+                                    visitor);
+/*
                 let borrowed_type_parameters = &method.tps;
                 self.resolve_function(MethodRibKind(id, Provided(method.id)),
                                       some(@method.decl),
@@ -3660,6 +3660,7 @@ class Resolver {
                                       HasSelfBinding(method.self_id),
                                       NoCaptureClause,
                                       visitor);
+*/
             }
 
             // Restore the original trait references.
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 36397250f1a..11643f8a5ee 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -2454,6 +2454,9 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id)-> lval_maybe_callee {
       ast::def_fn(did, _) => {
         return lval_static_fn(cx, did, id);
       }
+      ast::def_static_method(did, _) => {
+        return impl::trans_static_method_callee(cx, did, id);
+      }
       ast::def_variant(tid, vid) => {
         if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u {
             // N-ary variant.
diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs
index 7bac09e3706..5d821dbd86d 100644
--- a/src/rustc/middle/trans/impl.rs
+++ b/src/rustc/middle/trans/impl.rs
@@ -26,10 +26,15 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
     for vec::each(methods) |m| {
         if m.tps.len() == 0u {
             let llfn = get_item_val(ccx, m.id);
+            let self_arg = match m.self_ty.node {
+              ast::sty_static => { no_self }
+              _ => { impl_self(ty::node_id_to_type(ccx.tcx, m.self_id)) }
+            };
+
             trans_fn(ccx,
                      vec::append_one(sub_path, path_name(m.ident)),
                      m.decl, m.body,
-                     llfn, impl_self(ty::node_id_to_type(ccx.tcx, m.self_id)),
+                     llfn, self_arg,
                      none, m.id);
         }
     }
@@ -65,8 +70,9 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
                             param_num:p, bound_num:b}) => {
         match check bcx.fcx.param_substs {
           some(substs) => {
+            let vtbl = find_vtable_in_fn_ctxt(substs, p, b);
             trans_monomorphized_callee(bcx, callee_id, self, mentry.derefs,
-                                       iid, off, p, b, substs)
+                                       iid, off, vtbl)
           }
         }
       }
@@ -81,6 +87,54 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
     }
 }
 
+fn trans_static_method_callee(bcx: block, method_id: ast::def_id,
+                              callee_id: ast::node_id) -> lval_maybe_callee {
+    let _icx = bcx.insn_ctxt(~"impl::trans_static_method_callee");
+    let ccx = bcx.ccx();
+
+    let mname = if method_id.crate == ast::local_crate {
+        match check bcx.tcx().items.get(method_id.node) {
+          ast_map::node_trait_method(trait_method, _, _) => {
+            ast_util::trait_method_to_ty_method(*trait_method).ident
+          }
+        }
+    } else {
+        let path = csearch::get_item_path(bcx.tcx(), method_id);
+        match path[path.len()-1] {
+          path_name(s) => { s }
+          path_mod(_) => { fail ~"path doesn't have a name?" }
+        }
+    };
+    debug!("trans_static_method_callee: method_id=%?, callee_id=%?, \
+            name=%s", method_id, callee_id, *mname);
+
+    let vtbls = resolve_vtables_in_fn_ctxt(
+        bcx.fcx, ccx.maps.vtable_map.get(callee_id));
+
+    match vtbls[0] { // is index 0 always the one we want?
+      typeck::vtable_static(impl_did, impl_substs, sub_origins) => {
+
+        let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
+        let n_m_tps = method_ty_param_count(ccx, mth_id, impl_did);
+        let node_substs = node_id_type_params(bcx, callee_id);
+        let ty_substs
+            = vec::append(impl_substs,
+                          vec::tailn(node_substs,
+                                     node_substs.len() - n_m_tps));
+
+        let lval = lval_static_fn_inner(bcx, mth_id, callee_id, ty_substs,
+                                        some(sub_origins));
+        {env: null_env,
+         val: PointerCast(bcx, lval.val, T_ptr(type_of_fn_from_ty(
+             ccx, node_id_type(bcx, callee_id))))
+         with lval}
+      }
+      _ => {
+        fail ~"vtable_param left in monomorphized function's vtable substs";
+      }
+    }
+}
+
 fn method_from_methods(ms: ~[@ast::method], name: ast::ident)
     -> ast::def_id {
   local_def(option::get(vec::find(ms, |m| m.ident == name)).id)
@@ -119,10 +173,10 @@ fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id,
 fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id,
                               base: @ast::expr, derefs: uint,
                               trait_id: ast::def_id, n_method: uint,
-                              n_param: uint, n_bound: uint,
-                              substs: param_substs) -> lval_maybe_callee {
+                              vtbl: typeck::vtable_origin)
+    -> lval_maybe_callee {
     let _icx = bcx.insn_ctxt(~"impl::trans_monomorphized_callee");
-    match find_vtable_in_fn_ctxt(substs, n_param, n_bound) {
+    match vtbl {
       typeck::vtable_static(impl_did, impl_substs, sub_origins) => {
         let ccx = bcx.ccx();
         let mname = ty::trait_methods(ccx.tcx, trait_id)[n_method].ident;
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index a48e594818f..fda5902e594 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -69,6 +69,12 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
       ast_map::node_method(@{body, _}, _, _) => {
         handle_body(cx, body);
       }
+      ast_map::node_trait_method(*) => {
+        // This will be a static trait method. For now, we just assume
+        // it fully depends on all of the type information. (Doing
+        // otherwise would require finding the actual implementation).
+        for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr|use_tydesc;}
+      }
       ast_map::node_variant(_, _, _) => {
         for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
       }
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index d5165e26a2b..cb723bca83d 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -2179,14 +2179,16 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
         };
       }
 
-      ast::def_fn(id, ast::unsafe_fn) => {
+      ast::def_fn(id, ast::unsafe_fn) |
+      ast::def_static_method(id, ast::unsafe_fn) => {
         // Unsafe functions can only be touched in an unsafe context
         fcx.require_unsafe(sp, ~"access to unsafe function");
         return ty::lookup_item_type(fcx.ccx.tcx, id);
       }
 
-      ast::def_fn(id, _) | ast::def_const(id) |
-      ast::def_variant(_, id) | ast::def_class(id, _) => {
+      ast::def_fn(id, _) | ast::def_static_method(id, _) |
+      ast::def_const(id) | ast::def_variant(_, id) |
+      ast::def_class(id, _) => {
         return ty::lookup_item_type(fcx.ccx.tcx, id);
       }
       ast::def_binding(nid, _) => {
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index 905f1f10137..2f2da5b65bc 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -4,7 +4,8 @@ import coherence::get_base_type_def_id;
 import middle::resolve3::{Impl, MethodInfo};
 import middle::ty::{mk_box, mk_rptr, mk_uniq};
 import middle::typeck::infer::methods; // next_ty_vars
-import syntax::ast::{def_id, sty_box, sty_by_ref, sty_region, sty_uniq};
+import syntax::ast::{def_id,
+                     sty_static, sty_box, sty_by_ref, sty_region, sty_uniq};
 import syntax::ast::{sty_value};
 import syntax::ast_map;
 import syntax::ast_map::node_id_to_str;
@@ -25,6 +26,10 @@ fn transform_self_type_for_method(fcx: @fn_ctxt,
                                   method_info: MethodInfo)
                                -> ty::t {
     match method_info.self_type {
+      sty_static => {
+        fcx.tcx().sess.bug(~"calling transform_self_type_for_method on \
+                             static method");
+      }
       sty_by_ref | sty_value => {
         impl_ty
       }
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 2abc201d132..eb2f31d1c16 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -21,6 +21,7 @@ are represented as `ty_param()` instances.
 */
 
 import astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty};
+import ast_util::trait_method_to_ty_method;
 import rscope::*;
 
 fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
@@ -147,19 +148,54 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
         ty::store_trait_methods(ccx.tcx, id, @vec::map(stuff, f));
     }
 
+    fn make_static_method_ty(ccx: @crate_ctxt, id: ast::node_id,
+                             am: ast::ty_method,
+                             rp: bool, m: ty::method,
+                             trait_bounds: @~[ty::param_bounds]) {
+        // We need to create a typaram that replaces self. This param goes
+        // *in between* the typarams from the trait and those from the
+        // method (since its bound can depend on the trait? or
+        // something like that).
+
+        // build up a subst that shifts all of the parameters over
+        // by one and substitute in a new type param for self
+
+        let dummy_defid = {crate: 0, node: 0};
+
+        let non_shifted_trait_tps = do vec::from_fn(trait_bounds.len()) |i| {
+            ty::mk_param(ccx.tcx, i, dummy_defid)
+        };
+        let self_param = ty::mk_param(ccx.tcx, trait_bounds.len(),
+                                      dummy_defid);
+        let shifted_method_tps = do vec::from_fn(m.tps.len()) |i| {
+            ty::mk_param(ccx.tcx, i + 1, dummy_defid)
+        };
+
+        let substs = { self_r: none, self_ty: some(self_param),
+                       tps: non_shifted_trait_tps + shifted_method_tps };
+
+        let ty = ty::subst(ccx.tcx, substs, ty::mk_fn(ccx.tcx, m.fty));
+        let trait_ty = ty::node_id_to_type(ccx.tcx, id);
+        let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
+                       + *m.tps);
+        ccx.tcx.tcache.insert(local_def(am.id),
+                              {bounds: bounds, rp: rp, ty: ty});
+    }
+
+
     let tcx = ccx.tcx;
     let rp = tcx.region_paramd_items.contains_key(id);
     match check tcx.items.get(id) {
-      ast_map::node_item(@{node: ast::item_trait(_, _, ms), _}, _) => {
+      ast_map::node_item(@{node: ast::item_trait(params, _, ms), _}, _) => {
         store_methods::<ast::trait_method>(ccx, id, ms, |m| {
-            match m {
-              required(ty_m) => {
-                ty_of_ty_method(ccx, ty_m, rp)
-              }
-              provided(m) => {
-                ty_of_method(ccx, m, rp)
-              }
+            let trait_bounds = ty_param_bounds(ccx, params);
+            let ty_m = trait_method_to_ty_method(m);
+            let method_ty = ty_of_ty_method(ccx, ty_m, rp);
+            if ty_m.self_ty.node == ast::sty_static {
+                make_static_method_ty(ccx, id, ty_m, rp,
+                                      method_ty, trait_bounds);
             }
+            method_ty
         });
       }
       ast_map::node_item(@{node: ast::item_class(struct_def, _), _}, _) => {
@@ -190,6 +226,21 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
                        trait_m: ty::method, trait_substs: ty::substs,
                        self_ty: ty::t) {
 
+    if impl_m.purity != trait_m.purity {
+        tcx.sess.span_err(
+            sp, fmt!{"method `%s`'s purity does \
+                          not match the trait method's \
+                          purity", *impl_m.ident});
+    }
+
+    // is this check right?
+    if impl_m.self_ty != trait_m.self_ty {
+        tcx.sess.span_err(
+            sp, fmt!{"method `%s`'s self type does \
+                          not match the trait method's \
+                          self type", *impl_m.ident});
+    }
+
     if impl_m.tps != trait_m.tps {
         tcx.sess.span_err(sp, ~"method `" + *trait_m.ident +
                           ~"` has an incompatible set of type parameters");
@@ -259,12 +310,6 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
     for vec::each(*ty::trait_methods(tcx, did)) |trait_m| {
         match vec::find(impl_ms, |impl_m| trait_m.ident == impl_m.mty.ident) {
           some({mty: impl_m, id, span}) => {
-            if impl_m.purity != trait_m.purity {
-                ccx.tcx.sess.span_err(
-                    span, fmt!{"method `%s`'s purity does \
-                                not match the trait method's \
-                                purity", *impl_m.ident});
-            }
             compare_impl_method(
                 ccx.tcx, span, impl_m, vec::len(tps),
                 trait_m, tpt.substs, selfty);