about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-10-12 17:00:08 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-10-12 17:46:43 -0700
commitcb55e246ba517a14eaabb82cba3294ab4ad23c0a (patch)
treee2c9dd4e2183de97b01c81c08b71d0b46a471e1a /src/rustc
parent57b4d10ff652d3beddae64782c882a07822bac3c (diff)
Use the Nth impl when translating a static method call, instead
of the 0th.  0th is only correct when there are no bound tps
on the trait.

Fixes #3741.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/decoder.rs64
-rw-r--r--src/rustc/metadata/encoder.rs1
-rw-r--r--src/rustc/middle/astencode.rs4
-rw-r--r--src/rustc/middle/resolve.rs1
-rw-r--r--src/rustc/middle/trans/callee.rs5
-rw-r--r--src/rustc/middle/trans/expr.rs7
-rw-r--r--src/rustc/middle/trans/meth.rs43
-rw-r--r--src/rustc/middle/typeck/check.rs4
8 files changed, 90 insertions, 39 deletions
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 4c647d41880..38838120a10 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -178,6 +178,12 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
     None
 }
 
+fn item_reqd_and_translated_parent_item(cnum: ast::crate_num,
+                                        d: ebml::Doc) -> ast::def_id {
+    let trait_did = item_parent_item(d).expect(~"item without parent");
+    {crate: cnum, node: trait_did.node}
+}
+
 fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
     let tagdoc = ebml::get_doc(d, tag_def_id);
     return translate_def_id(cdata, ebml::with_doc_data(tagdoc,
@@ -297,35 +303,39 @@ fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
 }
 
 fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
-        -> def_like {
+    -> def_like
+{
     let fam = item_family(item);
     match fam {
-      Const     => dl_def(ast::def_const(did)),
-      Class     => dl_def(ast::def_class(did, true)),
-      Struct    => dl_def(ast::def_class(did, false)),
-      UnsafeFn  => dl_def(ast::def_fn(did, ast::unsafe_fn)),
-      Fn        => dl_def(ast::def_fn(did, ast::impure_fn)),
-      PureFn    => dl_def(ast::def_fn(did, ast::pure_fn)),
-      ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
-      UnsafeStaticMethod => dl_def(ast::def_static_method(did,
-                                                          ast::unsafe_fn)),
-      StaticMethod => dl_def(ast::def_static_method(did, ast::impure_fn)),
-      PureStaticMethod => dl_def(ast::def_static_method(did, ast::pure_fn)),
-      Type | ForeignType => dl_def(ast::def_ty(did)),
-      Mod => dl_def(ast::def_mod(did)),
-      ForeignMod => dl_def(ast::def_foreign_mod(did)),
-      Variant => {
-          match item_parent_item(item) {
-              Some(t) => {
-                let tid = {crate: cnum, node: t.node};
-                dl_def(ast::def_variant(tid, did))
-              }
-              None => fail ~"item_to_def_like: enum item has no parent"
-          }
-      }
-      Trait | Enum => dl_def(ast::def_ty(did)),
-      Impl => dl_impl(did),
-      PublicField | PrivateField | InheritedField => dl_field,
+        Const     => dl_def(ast::def_const(did)),
+        Class     => dl_def(ast::def_class(did, true)),
+        Struct    => dl_def(ast::def_class(did, false)),
+        UnsafeFn  => dl_def(ast::def_fn(did, ast::unsafe_fn)),
+        Fn        => dl_def(ast::def_fn(did, ast::impure_fn)),
+        PureFn    => dl_def(ast::def_fn(did, ast::pure_fn)),
+        ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)),
+        UnsafeStaticMethod => {
+            let trait_did = item_reqd_and_translated_parent_item(cnum, item);
+            dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn))
+        }
+        StaticMethod => {
+            let trait_did = item_reqd_and_translated_parent_item(cnum, item);
+            dl_def(ast::def_static_method(did, trait_did, ast::impure_fn))
+        }
+        PureStaticMethod => {
+            let trait_did = item_reqd_and_translated_parent_item(cnum, item);
+            dl_def(ast::def_static_method(did, trait_did, ast::pure_fn))
+        }
+        Type | ForeignType => dl_def(ast::def_ty(did)),
+        Mod => dl_def(ast::def_mod(did)),
+        ForeignMod => dl_def(ast::def_foreign_mod(did)),
+        Variant => {
+            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)),
+        Impl => dl_impl(did),
+        PublicField | PrivateField | InheritedField => dl_field,
     }
 }
 
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index f188d8ee5d8..63a7ce1ac74 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -794,6 +794,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer,
 
             ebml_w.start_tag(tag_items_data_item);
             encode_def_id(ebml_w, local_def(ty_m.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));
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index 103f1eecf87..15b20c41b67 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -345,8 +345,8 @@ impl ast::def: tr {
     fn tr(xcx: extended_decode_ctxt) -> ast::def {
         match self {
           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_static_method(did, did2, p) => {
+            ast::def_static_method(did.tr(xcx), did2.tr(xcx), p)
           }
           ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) }
           ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs
index 18880fe917b..314dea1b576 100644
--- a/src/rustc/middle/resolve.rs
+++ b/src/rustc/middle/resolve.rs
@@ -1126,6 +1126,7 @@ impl Resolver {
                             self.add_child(ident, new_parent, ~[ValueNS],
                                            ty_m.span);
                         let def = def_static_method(local_def(ty_m.id),
+                                                    local_def(item.id),
                                                     ty_m.purity);
                         (*method_name_bindings).define_value
                             (Public, def, ty_m.span);
diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs
index c851c5bc725..aa998fb7b92 100644
--- a/src/rustc/middle/trans/callee.rs
+++ b/src/rustc/middle/trans/callee.rs
@@ -78,8 +78,9 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee {
             ast::def_fn(did, _) => {
                 fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
             }
-            ast::def_static_method(did, _) => {
-                fn_callee(bcx, meth::trans_static_method_callee(bcx, did,
+            ast::def_static_method(impl_did, trait_did, _) => {
+                fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did,
+                                                                trait_did,
                                                                 ref_expr.id))
             }
             ast::def_variant(tid, vid) => {
diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs
index 4e50f7a848e..c841d9bd913 100644
--- a/src/rustc/middle/trans/expr.rs
+++ b/src/rustc/middle/trans/expr.rs
@@ -641,10 +641,11 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
             let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id);
             return fn_data_to_datum(bcx, did, fn_data, lldest);
         }
-        ast::def_static_method(did, _) => {
-            let fn_data = meth::trans_static_method_callee(bcx, did,
+        ast::def_static_method(impl_did, trait_did, _) => {
+            let fn_data = meth::trans_static_method_callee(bcx, impl_did,
+                                                           trait_did,
                                                            ref_expr.id);
-            return fn_data_to_datum(bcx, did, fn_data, lldest);
+            return fn_data_to_datum(bcx, impl_did, fn_data, lldest);
         }
         ast::def_variant(tid, vid) => {
             if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u {
diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs
index d8a2fda4d14..96cf7fabd1f 100644
--- a/src/rustc/middle/trans/meth.rs
+++ b/src/rustc/middle/trans/meth.rs
@@ -162,11 +162,50 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
 
 fn trans_static_method_callee(bcx: block,
                               method_id: ast::def_id,
+                              trait_id: ast::def_id,
                               callee_id: ast::node_id) -> FnData
 {
     let _icx = bcx.insn_ctxt("impl::trans_static_method_callee");
     let ccx = bcx.ccx();
 
+    debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \
+            callee_id=%?)",
+           method_id,
+           ty::item_path_str(bcx.tcx(), trait_id),
+           callee_id);
+    let _indenter = indenter();
+
+    // When we translate a static fn defined in a trait like:
+    //
+    //   trait<T1...Tn> Trait {
+    //       static fn foo<M1...Mn>(...) {...}
+    //   }
+    //
+    // this winds up being translated as something like:
+    //
+    //   fn foo<T1...Tn,self: Trait<T1...Tn>,M1...Mn>(...) {...}
+    //
+    // So when we see a call to this function foo, we have to figure
+    // out which impl the `Trait<T1...Tn>` bound on the type `self` was
+    // bound to.  Due to the fact that we use a flattened list of
+    // impls, one per bound, this means we have to total up the bounds
+    // found on the type parametesr T1...Tn to find the index of the
+    // one we are interested in.
+    let bound_index = {
+        let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id);
+        let mut index = 0;
+        for trait_polyty.bounds.each |param_bounds| {
+            for param_bounds.each |param_bound| {
+                match *param_bound {
+                    ty::bound_trait(_) => { index += 1; }
+                    ty::bound_copy | ty::bound_owned |
+                    ty::bound_send | ty::bound_const => {}
+                }
+            }
+        }
+        index
+    };
+
     let mname = if method_id.crate == ast::local_crate {
         match bcx.tcx().items.get(method_id.node) {
             ast_map::node_trait_method(trait_method, _, _) => {
@@ -187,9 +226,7 @@ fn trans_static_method_callee(bcx: block,
     let vtbls = resolve_vtables_in_fn_ctxt(
         bcx.fcx, ccx.maps.vtable_map.get(callee_id));
 
-    // FIXME(#3446) -- I am pretty sure index 0 is not the right one,
-    // if the static method is implemented on a generic type. (NDM)
-    match vtbls[0] {
+    match vtbls[bound_index] {
         typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
 
             let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index c1ab29758f2..bf0ca36dddf 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -2403,13 +2403,13 @@ 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_static_method(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_static_method(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);