about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2013-06-26 17:20:53 -0700
committerMichael Sullivan <sully@msully.net>2013-06-28 16:12:08 -0700
commit649b26f7c64a573b2d1ee03a0b866dd351510338 (patch)
tree132d46f96442dea7b5c3f833693aa46edc70d075
parent57ee34c2bf66a26527959b0a1dc2b7e23638e67b (diff)
downloadrust-649b26f7c64a573b2d1ee03a0b866dd351510338.tar.gz
rust-649b26f7c64a573b2d1ee03a0b866dd351510338.zip
Rework vtable_res to not be flattened. It is now a list of the resolutions for each param.
-rw-r--r--src/librustc/middle/astencode.rs10
-rw-r--r--src/librustc/middle/trans/callee.rs26
-rw-r--r--src/librustc/middle/trans/common.rs11
-rw-r--r--src/librustc/middle/trans/meth.rs85
-rw-r--r--src/librustc/middle/trans/monomorphize.rs12
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs7
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs12
-rw-r--r--src/librustc/middle/typeck/mod.rs3
8 files changed, 76 insertions, 90 deletions
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index c1d553b0454..16e3bd34cdd 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -599,8 +599,10 @@ fn encode_vtable_res(ecx: &e::EncodeContext,
     // ty::t doesn't work, and there is no way (atm) to have
     // hand-written encoding routines combine with auto-generated
     // ones.  perhaps we should fix this.
-    do ebml_w.emit_from_vec(*dr) |ebml_w, vtable_origin| {
-        encode_vtable_origin(ecx, ebml_w, vtable_origin)
+    do ebml_w.emit_from_vec(*dr) |ebml_w, param_tables| {
+        do ebml_w.emit_from_vec(**param_tables) |ebml_w, vtable_origin| {
+            encode_vtable_origin(ecx, ebml_w, vtable_origin)
+        }
     }
 }
 
@@ -653,7 +655,9 @@ trait vtable_decoder_helpers {
 impl vtable_decoder_helpers for reader::Decoder {
     fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
                       -> typeck::vtable_res {
-        @self.read_to_vec(|this| this.read_vtable_origin(xcx))
+        @self.read_to_vec(|this|
+           @this.read_to_vec(|this|
+               this.read_vtable_origin(xcx)))
     }
 
     fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index dc18c6b17ee..7032b559f76 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -17,6 +17,7 @@
 // closure.
 
 use core::prelude::*;
+use core::vec;
 
 use back::abi;
 use driver::session;
@@ -274,9 +275,7 @@ pub fn trans_fn_ref_with_vtables(
             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()
+                    @call_vtables.initn(param_defs.len()).to_owned()
                 }
             };
 
@@ -305,6 +304,27 @@ pub fn trans_fn_ref_with_vtables(
         }
     };
 
+    // XXX: this is *completely* bad and wrong. I feel bad.  Handling
+    // of vtables is currently bogus for default methods, and changing
+    // to an unflattented representation of vtables causes this to
+    // show up in cases that it did not previously. We need to make
+    // the vtables list be the same length as the substs.  There is
+    // nothing right about this. I really need to emphasize just how
+    // wrong it is: it is completely wrong.
+    // XXX: bad.
+    // This will be fixed in the next commit.
+    let vtables = do vtables.map |vtbls| {
+        if vtbls.len() < substs.tps.len() {
+            @(vec::from_elem(substs.tps.len() - vtbls.len(), @~[]) +
+              **vtbls)
+        } else if vtbls.len() > substs.tps.len() {
+            @vtbls.tailn(vtbls.len() - substs.tps.len()).to_owned()
+        } else {
+            *vtbls
+        }
+    };
+
+
     // Check whether this fn has an inlined copy and, if so, redirect
     // def_id to the local id of the inlined copy.
     let def_id = {
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index b9e1ba7a8d9..b3051006238 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -1035,7 +1035,8 @@ pub fn node_vtables(bcx: block, id: ast::node_id)
 
 pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
     -> typeck::vtable_res {
-    @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
+    @vec::map(*vts, |ds|
+      @vec::map(**ds, |d|  resolve_vtable_in_fn_ctxt(fcx, copy *d)))
 }
 
 // Apply the typaram substitutions in the fn_ctxt to a vtable. This should
@@ -1090,13 +1091,7 @@ pub fn find_vtable(tcx: ty::ctxt, ps: &param_substs,
     debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)",
            n_param, n_bound, ps.repr(tcx));
 
-    // Vtables are stored in a flat array, finding the right one is
-    // somewhat awkward
-    let first_n_type_param_defs = ps.type_param_defs.slice(0, n_param);
-    let vtables_to_skip =
-        ty::count_traits_and_supertraits(tcx, first_n_type_param_defs);
-    let vtable_off = vtables_to_skip + n_bound;
-    /*bad*/ copy ps.vtables.get()[vtable_off]
+    /*bad*/ copy ps.vtables.get()[n_param][n_bound]
 }
 
 pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 5087fcca788..11ae094b799 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -292,15 +292,9 @@ pub fn trans_static_method_callee(bcx: block,
     //
     // 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_def = ty::lookup_trait_def(bcx.tcx(), trait_id);
-        ty::count_traits_and_supertraits(
-            bcx.tcx(), *trait_def.generics.type_param_defs)
-    };
+    // bound to.
+    let bound_index = ty::lookup_trait_def(bcx.tcx(), trait_id).
+        generics.type_param_defs.len();
 
     let mname = if method_id.crate == ast::local_crate {
         match bcx.tcx().items.get_copy(&method_id.node) {
@@ -322,17 +316,17 @@ pub fn trans_static_method_callee(bcx: block,
     let vtbls = resolve_vtables_in_fn_ctxt(
         bcx.fcx, ccx.maps.vtable_map.get_copy(&callee_id));
 
-    match vtbls[bound_index] {
+    match vtbls[bound_index][0] {
         typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
             let mth_id = method_with_name_or_default(bcx.ccx(),
                                                      impl_did,
                                                      mname);
-            let callee_substs = combine_impl_and_methods_tps(
-                bcx, mth_id, impl_did, callee_id, *rcvr_substs);
-            let callee_origins = combine_impl_and_methods_origins(
-                bcx, mth_id, impl_did, callee_id, rcvr_origins);
+            let (callee_substs, callee_origins) =
+                combine_impl_and_methods_tps(
+                    bcx, mth_id, impl_did, callee_id,
+                    *rcvr_substs, rcvr_origins);
 
             let FnData {llfn: lval} =
                 trans_fn_ref_with_vtables(bcx,
@@ -428,10 +422,10 @@ pub fn trans_monomorphized_callee(bcx: block,
 
           // create a concatenated set of substitutions which includes
           // those from the impl and those from the method:
-          let callee_substs = combine_impl_and_methods_tps(
-              bcx, mth_id, impl_did, callee_id, *rcvr_substs);
-          let callee_origins = combine_impl_and_methods_origins(
-              bcx, mth_id, impl_did, callee_id, rcvr_origins);
+          let (callee_substs, callee_origins) =
+              combine_impl_and_methods_tps(
+                  bcx, mth_id, impl_did, callee_id,
+                  *rcvr_substs, rcvr_origins);
 
           // translate the function
           let callee = trans_fn_ref_with_vtables(bcx,
@@ -471,8 +465,9 @@ pub fn combine_impl_and_methods_tps(bcx: block,
                                     mth_did: ast::def_id,
                                     impl_did: ast::def_id,
                                     callee_id: ast::node_id,
-                                    rcvr_substs: &[ty::t])
-                                    -> ~[ty::t] {
+                                    rcvr_substs: &[ty::t],
+                                    rcvr_origins: typeck::vtable_res)
+                                    -> (~[ty::t], typeck::vtable_res) {
     /*!
     *
     * Creates a concatenated set of substitutions which includes
@@ -501,52 +496,18 @@ pub fn combine_impl_and_methods_tps(bcx: block,
     debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t)));
     debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t)));
 
-    return ty_substs;
-}
-
-pub fn combine_impl_and_methods_origins(bcx: block,
-                                        mth_did: ast::def_id,
-                                        impl_did: ast::def_id,
-                                        callee_id: ast::node_id,
-                                        rcvr_origins: typeck::vtable_res)
-                                     -> typeck::vtable_res {
-    /*!
-     *
-     * Similar to `combine_impl_and_methods_tps`, but for vtables.
-     * This is much messier because of the flattened layout we are
-     * currently using (for some reason that I fail to understand).
-     * The proper fix is described in #3446.
-     */
-
 
-    // Find the bounds for the method, which are the tail of the
-    // bounds found in the item type, as the item type combines the
-    // rcvr + method bounds.
-    let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
-    let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
-    let ty::ty_param_bounds_and_ty {
-        generics: r_m_generics,
-        _
-    } = ty::lookup_item_type(tcx, mth_did);
-    let n_r_m_tps = r_m_generics.type_param_defs.len(); // rcvr + method tps
-    let m_type_param_defs =
-        r_m_generics.type_param_defs.slice(n_r_m_tps - n_m_tps, n_r_m_tps);
-
-    // Flatten out to find the number of vtables the method expects.
-    let m_vtables = ty::count_traits_and_supertraits(tcx, m_type_param_defs);
-
-    // Find the vtables we computed at type check time and monomorphize them
+    // Now, do the same work for the vtables.  The vtables might not
+    // exist, in which case we need to make them.
     let r_m_origins = match node_vtables(bcx, callee_id) {
         Some(vt) => vt,
-        None => @~[]
+        None => @vec::from_elem(node_substs.len(), @~[])
     };
+    let vtables
+        = @vec::append(rcvr_origins.to_owned(),
+                       r_m_origins.tailn(r_m_origins.len() - n_m_tps));
 
-    // Extract those that belong to method:
-    let m_origins = r_m_origins.tailn(r_m_origins.len() - m_vtables);
-
-    // Combine rcvr + method to find the final result:
-    @vec::append(/*bad*/copy *rcvr_origins, m_origins)
+    return (ty_substs, vtables);
 }
 
 
@@ -845,7 +806,7 @@ pub fn trans_trait_cast(bcx: block,
     bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
 
     // Store the vtable into the pair or triple.
-    let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0];
+    let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0][0];
     let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig);
     let vtable = get_vtable(bcx, v_ty, orig);
     Store(bcx, vtable, PointerCast(bcx,
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 06dec1995d9..3011f0c5d84 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -340,14 +340,10 @@ pub fn make_mono_id(ccx: @mut CrateContext,
                     param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
     let precise_param_ids = match vtables {
       Some(vts) => {
-        let item_ty = ty::lookup_item_type(ccx.tcx, item);
-        let mut i = 0;
-        vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
-            let mut v = ~[];
-            for type_param_def.bounds.trait_bounds.iter().advance |_bound| {
-                v.push(meth::vtable_id(ccx, &vts[i]));
-                i += 1;
-            }
+        debug!("make_mono_id vtables=%s substs=%s",
+               vts.repr(ccx.tcx), substs.repr(ccx.tcx));
+        vec::map_zip(*vts, substs, |vtable, subst| {
+            let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
             (*subst, if !v.is_empty() { Some(@v) } else { None })
         })
       }
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 03348d5a1dc..0bf20f9fbcb 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -90,6 +90,7 @@ fn lookup_vtables(vcx: &VtableContext,
     let mut i = 0u;
     for substs.tps.iter().advance |ty| {
         // ty is the value supplied for the type parameter A...
+        let mut param_result = ~[];
 
         for ty::each_bound_trait_and_supertraits(
             tcx, type_param_defs[i].bounds) |trait_ref|
@@ -106,7 +107,7 @@ fn lookup_vtables(vcx: &VtableContext,
             debug!("after subst: %s", trait_ref.repr(tcx));
 
             match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) {
-                Some(vtable) => result.push(vtable),
+                Some(vtable) => param_result.push(vtable),
                 None => {
                     vcx.tcx().sess.span_fatal(
                         location_info.span,
@@ -117,6 +118,7 @@ fn lookup_vtables(vcx: &VtableContext,
                 }
             }
         }
+        result.push(@param_result);
         i += 1u;
     }
     debug!("lookup_vtables result(\
@@ -600,7 +602,8 @@ pub fn early_resolve_expr(ex: @ast::expr,
                                   // vtable (that is: "ex has vtable
                                   // <vtable>")
                                   if !is_early {
-                                      insert_vtables(fcx, ex.id, @~[vtable]);
+                                      insert_vtables(fcx, ex.id,
+                                                     @~[@~[vtable]]);
                                   }
                               }
                               None => {
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 73710978ad4..e2efdc51fca 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -20,7 +20,8 @@ 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, vtable_self};
+use middle::typeck::{vtable_res, vtable_origin};
+use middle::typeck::{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;
@@ -84,7 +85,7 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
     match fcx.inh.vtable_map.find(&id) {
         None => {}
         Some(origins) => {
-            let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
+            let r_origins = resolve_origins(fcx, sp, *origins);
             let vtable_map = fcx.ccx.vtable_map;
             vtable_map.insert(id, r_origins);
             debug!("writeback::resolve_vtable_map_entry(id=%d, vtables=%?)",
@@ -92,13 +93,18 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
         }
     }
 
+    fn resolve_origins(fcx: @mut FnCtxt, sp: span,
+                       vtbls: vtable_res) -> vtable_res {
+        @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o)))
+    }
+
     fn resolve_origin(fcx: @mut FnCtxt,
                       sp: span,
                       origin: &vtable_origin) -> vtable_origin {
         match origin {
             &vtable_static(def_id, ref tys, origins) => {
                 let r_tys = resolve_type_vars_in_types(fcx, sp, *tys);
-                let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
+                let r_origins = resolve_origins(fcx, sp, origins);
                 vtable_static(def_id, r_tys, r_origins)
             }
             &vtable_param(n, b) => {
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 3511844bb9f..98f7af4bfd4 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -135,8 +135,9 @@ pub struct method_map_entry {
 // of the method to be invoked
 pub type method_map = @mut HashMap<ast::node_id, method_map_entry>;
 
+pub type vtable_param_res = @~[vtable_origin];
 // Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res = @~[vtable_origin];
+pub type vtable_res = @~[vtable_param_res];
 
 pub enum vtable_origin {
     /*