diff options
| author | Michael Sullivan <sully@msully.net> | 2013-06-26 17:20:53 -0700 |
|---|---|---|
| committer | Michael Sullivan <sully@msully.net> | 2013-06-28 16:12:08 -0700 |
| commit | 649b26f7c64a573b2d1ee03a0b866dd351510338 (patch) | |
| tree | 132d46f96442dea7b5c3f833693aa46edc70d075 | |
| parent | 57ee34c2bf66a26527959b0a1dc2b7e23638e67b (diff) | |
| download | rust-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.rs | 10 | ||||
| -rw-r--r-- | src/librustc/middle/trans/callee.rs | 26 | ||||
| -rw-r--r-- | src/librustc/middle/trans/common.rs | 11 | ||||
| -rw-r--r-- | src/librustc/middle/trans/meth.rs | 85 | ||||
| -rw-r--r-- | src/librustc/middle/trans/monomorphize.rs | 12 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/vtable.rs | 7 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/writeback.rs | 12 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/mod.rs | 3 |
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: ¶m_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 { /* |
