about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2013-06-20 09:29:24 -0700
committerMichael Sullivan <sully@msully.net>2013-06-28 16:12:08 -0700
commit817f98085f2332b604f0a2da5127f29c8fabc41f (patch)
treebc9b643a90a6df5d1b13a217605dec1ff3ea19cf
parenta9e51f5f701d8104be0adfb50f5d409f8bf233ff (diff)
downloadrust-817f98085f2332b604f0a2da5127f29c8fabc41f.tar.gz
rust-817f98085f2332b604f0a2da5127f29c8fabc41f.zip
Make calling methods parameterized on the trait work from default methods.
This is done by adding a new notion of "vtable_self".
We do not yet properly handle super traits.

Closes #7183.
-rw-r--r--src/librustc/middle/astencode.rs18
-rw-r--r--src/librustc/middle/trans/base.rs1
-rw-r--r--src/librustc/middle/trans/callee.rs31
-rw-r--r--src/librustc/middle/trans/common.rs22
-rw-r--r--src/librustc/middle/trans/meth.rs41
-rw-r--r--src/librustc/middle/trans/monomorphize.rs5
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs15
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs5
-rw-r--r--src/librustc/middle/typeck/mod.rs10
9 files changed, 117 insertions, 31 deletions
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 70e94844319..c1d553b0454 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -632,6 +632,13 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
                 }
             }
           }
+          typeck::vtable_self(def_id) => {
+            do ebml_w.emit_enum_variant("vtable_self", 2u, 1u) |ebml_w| {
+                do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
+                    ebml_w.emit_def_id(def_id)
+                }
+            }
+          }
         }
     }
 }
@@ -652,7 +659,9 @@ impl vtable_decoder_helpers for reader::Decoder {
     fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
         -> typeck::vtable_origin {
         do self.read_enum("vtable_origin") |this| {
-            do this.read_enum_variant(["vtable_static", "vtable_param"])
+            do this.read_enum_variant(["vtable_static",
+                                       "vtable_param",
+                                       "vtable_self"])
                     |this, i| {
                 match i {
                   0 => {
@@ -678,6 +687,13 @@ impl vtable_decoder_helpers for reader::Decoder {
                         }
                     )
                   }
+                  2 => {
+                    typeck::vtable_self(
+                        do this.read_enum_variant_arg(0u) |this| {
+                            this.read_def_id(xcx)
+                        }
+                    )
+                  }
                   // hard to avoid - user input
                   _ => fail!("bad enum variant")
                 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index df7f73a5243..8e8270320c6 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -461,6 +461,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
                                                     &tsubsts,
                                                     None,
                                                     None,
+                                                    None,
                                                     None);
 
         val
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 27f1c4d039d..dc18c6b17ee 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -245,8 +245,9 @@ pub fn trans_fn_ref_with_vtables(
     // We need to do a bunch of special handling for default methods.
     // We need to modify the def_id and our substs in order to monomorphize
     // the function.
-    let (def_id, opt_impl_did, substs) = match tcx.provided_method_sources.find(&def_id) {
-        None => (def_id, None, substs),
+    let (def_id, opt_impl_did, substs, self_vtable) =
+        match tcx.provided_method_sources.find(&def_id) {
+        None => (def_id, None, substs, None),
         Some(source) => {
             // There are two relevant substitutions when compiling
             // default methods. First, there is the substitution for
@@ -266,6 +267,26 @@ pub fn trans_fn_ref_with_vtables(
                          default methods");
             let method = ty::method(tcx, source.method_id);
 
+            // Get all of the type params for the receiver
+            let param_defs = method.generics.type_param_defs;
+            let receiver_substs =
+                type_params.initn(param_defs.len()).to_owned();
+            let receiver_vtables = match vtables {
+                None => @~[],
+                Some(call_vtables) => {
+                    let num_method_vtables =
+                        ty::count_traits_and_supertraits(tcx, *param_defs);
+                    @call_vtables.initn(num_method_vtables).to_owned()
+                }
+            };
+
+            let self_vtable =
+                typeck::vtable_static(source.impl_id, receiver_substs,
+                                      receiver_vtables);
+
+            // XXX: I think that if the *trait* has vtables on it,
+            // it is all over
+
             // Compute the first substitution
             let first_subst = make_substs_for_receiver_types(
                 tcx, source.impl_id, trait_ref, method);
@@ -279,7 +300,8 @@ pub fn trans_fn_ref_with_vtables(
                    first_subst.repr(tcx), new_substs.repr(tcx));
 
 
-            (source.method_id, Some(source.impl_id), new_substs)
+            (source.method_id, Some(source.impl_id),
+             new_substs, Some(self_vtable))
         }
     };
 
@@ -326,7 +348,8 @@ pub fn trans_fn_ref_with_vtables(
 
         let (val, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs,
-                                         vtables, opt_impl_did, Some(ref_id));
+                                         vtables, self_vtable,
+                                         opt_impl_did, Some(ref_id));
         let mut val = val;
         if must_cast && ref_id != 0 {
             // Monotype of the REFERENCE to the function (type params
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index a7ffa8e13b0..b9e1ba7a8d9 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -132,7 +132,8 @@ pub struct param_substs {
     tys: ~[ty::t],
     vtables: Option<typeck::vtable_res>,
     type_param_defs: @~[ty::TypeParameterDef],
-    self_ty: Option<ty::t>
+    self_ty: Option<ty::t>,
+    self_vtable: Option<typeck::vtable_origin>
 }
 
 impl param_substs {
@@ -981,7 +982,11 @@ pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
         Some(substs) => {
             ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
         }
-        _ => { assert!(!ty::type_has_params(t)); t }
+        _ => {
+            assert!(!ty::type_has_params(t));
+            assert!(!ty::type_has_self(t));
+            t
+        }
     }
 }
 
@@ -1063,6 +1068,19 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
                 }
             }
         }
+        typeck::vtable_self(_trait_id) => {
+            match fcx.param_substs {
+                Some(@param_substs
+                     {self_vtable: Some(ref self_vtable), _}) => {
+                    copy *self_vtable
+                }
+                _ => {
+                    tcx.sess.bug(fmt!(
+                        "resolve_vtable_in_fn_ctxt: asked to lookup but \
+                         no self_vtable in the fn_ctxt!"))
+                }
+            }
+        }
     }
 }
 
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index fc0c9c06c45..5087fcca788 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -139,7 +139,6 @@ pub fn trans_self_arg(bcx: block,
 
     // Compute the type of self.
     let self_ty = monomorphize_type(bcx, mentry.self_ty);
-
     let result = trans_arg_expr(bcx,
                                 self_ty,
                                 mentry.self_mode,
@@ -174,21 +173,6 @@ pub fn trans_method_callee(bcx: block,
     // Replace method_self with method_static here.
     let mut origin = mentry.origin;
     match origin {
-        typeck::method_self(trait_id, method_index) => {
-            // Get the ID of the impl we're inside.
-            let impl_def_id = bcx.fcx.impl_id.get();
-
-            debug!("impl_def_id is %?", impl_def_id);
-
-            // Get the ID of the method we're calling.
-            let method_name =
-                ty::trait_method(tcx, trait_id, method_index).ident;
-            let method_id =
-                method_with_name_or_default(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, this.id);
@@ -213,6 +197,7 @@ pub fn trans_method_callee(bcx: block,
                                             impl_id,
                                             method_name));
         }
+        typeck::method_self(*) |
         typeck::method_static(*) | typeck::method_param(*) |
         typeck::method_trait(*) => {}
     }
@@ -250,6 +235,21 @@ pub fn trans_method_callee(bcx: block,
                 None => fail!("trans_method_callee: missing param_substs")
             }
         }
+
+        typeck::method_self(trait_id, method_index) => {
+            match bcx.fcx.param_substs {
+                Some(@param_substs
+                     {self_vtable: Some(ref vtbl), _}) => {
+                    trans_monomorphized_callee(bcx, callee_id, this, mentry,
+                                               trait_id, method_index,
+                                               copy *vtbl)
+                }
+                _ => {
+                    fail!("trans_method_callee: missing self_vtable")
+                }
+            }
+        }
+
         typeck::method_trait(_, off, store) => {
             trans_trait_callee(bcx,
                                callee_id,
@@ -258,9 +258,9 @@ pub fn trans_method_callee(bcx: block,
                                store,
                                mentry.explicit_self)
         }
-        typeck::method_self(*) | typeck::method_super(*) => {
-            fail!("method_self or method_super should have been handled \
-                above")
+            typeck::method_super(*) => {
+            fail!("method_super should have been handled \
+                   above")
         }
     }
 }
@@ -460,6 +460,9 @@ pub fn trans_monomorphized_callee(bcx: block,
       typeck::vtable_param(*) => {
           fail!("vtable_param left in monomorphized function's vtable substs");
       }
+      typeck::vtable_self(*) => {
+          fail!("vtable_self left in monomorphized function's vtable substs");
+      }
     };
 
 }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 586dfd7e98a..06dec1995d9 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -43,6 +43,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
                       fn_id: ast::def_id,
                       real_substs: &ty::substs,
                       vtables: Option<typeck::vtable_res>,
+                      self_vtable: Option<typeck::vtable_origin>,
                       impl_did_opt: Option<ast::def_id>,
                       ref_id: Option<ast::node_id>)
     -> (ValueRef, bool)
@@ -165,6 +166,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     let mut pt = /* bad */copy (*pt);
     pt.push(elt);
     let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty);
+    debug!("monomorphize_fn mangled to %s", s);
 
     let mk_lldecl = || {
         let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty);
@@ -176,7 +178,8 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
         tys: substs,
         vtables: vtables,
         type_param_defs: tpt.generics.type_param_defs,
-        self_ty: real_substs.self_ty
+        self_ty: real_substs.self_ty,
+        self_vtable: self_vtable
     });
 
     let lldecl = match map_node {
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index bd78e9cc5fb..a886e06139e 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -17,8 +17,8 @@ use middle::typeck::check::{structurally_resolved_type};
 use middle::typeck::infer::fixup_err_to_str;
 use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
 use middle::typeck::infer;
-use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res};
-use middle::typeck::vtable_static;
+use middle::typeck::{CrateCtxt, vtable_origin, vtable_res};
+use middle::typeck::{vtable_static, vtable_param, vtable_self};
 use middle::subst::Subst;
 use util::common::indenter;
 use util::ppaux::tys_to_str;
@@ -237,6 +237,17 @@ fn lookup_vtable(vcx: &VtableContext,
             }
         }
 
+        ty::ty_self(trait_id) => {
+            debug!("trying to find %? vtable for type %?",
+                   trait_ref.def_id, trait_id);
+
+            if trait_id == trait_ref.def_id {
+                let vtable = vtable_self(trait_id);
+                debug!("found self vtable: %?", vtable);
+                return Some(vtable);
+            }
+        }
+
         _ => {
             let mut found = ~[];
 
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index dd9d68beb1f..73710978ad4 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -20,7 +20,7 @@ use middle::typeck::check::{FnCtxt, SelfInfo};
 use middle::typeck::infer::{force_all, resolve_all, resolve_region};
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
-use middle::typeck::{vtable_origin, vtable_static, vtable_param};
+use middle::typeck::{vtable_origin, vtable_static, vtable_param, vtable_self};
 use middle::typeck::method_map_entry;
 use middle::typeck::write_substs_to_tcx;
 use middle::typeck::write_ty_to_tcx;
@@ -104,6 +104,9 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
             &vtable_param(n, b) => {
                 vtable_param(n, b)
             }
+            &vtable_self(def_id) => {
+                vtable_self(def_id)
+            }
         }
     }
 }
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index d834998d4ee..3511844bb9f 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -154,7 +154,12 @@ pub enum vtable_origin {
       The first uint is the param number (identifying T in the example),
       and the second is the bound number (identifying baz)
      */
-    vtable_param(uint, uint)
+    vtable_param(uint, uint),
+
+    /*
+     Dynamic vtable, comes from self.
+    */
+    vtable_self(ast::def_id)
 }
 
 impl Repr for vtable_origin {
@@ -171,6 +176,9 @@ impl Repr for vtable_origin {
             vtable_param(x, y) => {
                 fmt!("vtable_param(%?, %?)", x, y)
             }
+            vtable_self(def_id) => {
+                fmt!("vtable_self(%?)", def_id)
+            }
         }
     }
 }