about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-08 19:02:22 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-15 09:31:34 +0100
commit8f84d4c8b6305c960cf51c35a5ea38697d7fa530 (patch)
tree0f0e84976e0ba84a8feb360961427fc83ccdf47b /src/rustc
parent83c9f585342d6974c5f1847f18ab2b6322b1ea42 (diff)
downloadrust-8f84d4c8b6305c960cf51c35a5ea38697d7fa530.tar.gz
rust-8f84d4c8b6305c960cf51c35a5ea38697d7fa530.zip
Remove a large part of the tydesc-passing code
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/metadata/encoder.rs5
-rw-r--r--src/rustc/middle/trans/base.rs241
-rw-r--r--src/rustc/middle/trans/closure.rs119
-rw-r--r--src/rustc/middle/trans/common.rs11
-rw-r--r--src/rustc/middle/trans/impl.rs12
-rw-r--r--src/rustc/middle/trans/native.rs5
-rw-r--r--src/rustc/middle/trans/shape.rs2
-rw-r--r--src/rustc/middle/trans/tvec.rs2
-rw-r--r--src/rustc/middle/trans/type_of.rs22
9 files changed, 112 insertions, 307 deletions
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 56e7ab47f60..5c6eb30bbeb 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -429,7 +429,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_family(ebml_w, 'f');
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, fn_ty);
-        encode_symbol(ecx, ebml_w, ctor_id);
+        if tps.len() == 0u {
+            encode_symbol(ecx, ebml_w, ctor_id);
+        }
         encode_path(ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
       }
@@ -447,7 +449,6 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         }
         alt ifce {
           some(t) {
-            encode_symbol(ecx, ebml_w, item.id);
             let i_ty = alt check t.node {
               ty_path(_, id) { ty::node_id_to_type(tcx, id) }
             };
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 2cf565a9f97..2babf26b3b7 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -270,7 +270,7 @@ fn dynastack_alloca(cx: block, t: TypeRef, n: ValueRef, ty: ty::t) ->
                    C_uint(bcx.ccx(), llsize_of_real(bcx.ccx(), t)),
                    n);
 
-    let lltydesc = get_tydesc_simple(cx, ty, false).val;
+    let lltydesc = get_tydesc_simple(cx, ty).val;
 
     let llresult = Call(dy_cx, dynastack_alloc, [llsz, lltydesc]);
     ret PointerCast(dy_cx, llresult, T_ptr(t));
@@ -450,7 +450,7 @@ fn trans_malloc_boxed_raw(bcx: block, t: ty::t,
     let llty = type_of(ccx, box_ptr);
 
     // Get the tydesc for the body:
-    let {bcx, val: lltydesc} = get_tydesc(bcx, t, true, static_ti);
+    let {bcx, val: lltydesc} = get_tydesc(bcx, t, static_ti);
     lazily_emit_all_tydesc_glue(ccx, static_ti);
 
     // Allocate space:
@@ -470,37 +470,6 @@ fn trans_malloc_boxed(bcx: block, t: ty::t) ->
 
 // Type descriptor and type glue stuff
 
-// Given a type and a field index into its corresponding type descriptor,
-// returns an LLVM ValueRef of that field from the tydesc, generating the
-// tydesc if necessary.
-fn field_of_tydesc(cx: block, t: ty::t, escapes: bool, field: int) ->
-   result {
-    let tydesc = get_tydesc_simple(cx, t, escapes);
-    ret rslt(tydesc.bcx,
-             GEPi(tydesc.bcx, tydesc.val, [0, field]));
-}
-
-// Given a type containing ty params, build a vector containing a ValueRef for
-// each of the ty params it uses (from the current frame) and a vector of the
-// indices of the ty params present in the type. This is used solely for
-// constructing derived tydescs.
-fn linearize_ty_params(cx: block, t: ty::t) ->
-   {params: [uint], descs: [ValueRef]} {
-    let param_vals = [], param_defs = [];
-    ty::walk_ty(cx.tcx(), t) {|t|
-        alt ty::get(t).struct {
-          ty::ty_param(pid, _) {
-            if !vec::any(param_defs, {|d| d == pid}) {
-                param_vals += [cx.fcx.lltyparams[pid].desc];
-                param_defs += [pid];
-            }
-          }
-          _ { }
-        }
-    }
-    ret {params: param_defs, descs: param_vals};
-}
-
 fn trans_stack_local_derived_tydesc(cx: block, llsz: ValueRef,
                                     llalign: ValueRef, llroottydesc: ValueRef,
                                     llfirstparam: ValueRef, n_params: uint)
@@ -527,93 +496,16 @@ fn trans_stack_local_derived_tydesc(cx: block, llsz: ValueRef,
     ret llmyroottydesc;
 }
 
-fn get_derived_tydesc(cx: block, t: ty::t, escapes: bool,
-                      &static_ti: option<@tydesc_info>) -> result {
-    alt cx.fcx.derived_tydescs.find(t) {
-      some(info) {
-        // If the tydesc escapes in this context, the cached derived
-        // tydesc also has to be one that was marked as escaping.
-        if !(escapes && !info.escapes) {
-            ret rslt(cx, info.lltydesc);
-        }
-      }
-      none {/* fall through */ }
-    }
-
-    cx.ccx().stats.n_derived_tydescs += 1u;
-    let bcx = raw_block(cx.fcx, cx.fcx.llderivedtydescs);
-    let tys = linearize_ty_params(bcx, t);
-    let root_ti = get_static_tydesc(bcx.ccx(), t, tys.params);
-    static_ti = some(root_ti);
-    lazily_emit_all_tydesc_glue(cx.ccx(), static_ti);
-    let root = root_ti.tydesc;
-    let sz = size_of(bcx, t);
-    bcx = sz.bcx;
-    let align = align_of(bcx, t);
-    bcx = align.bcx;
-
-    // Store the captured type descriptors in an alloca if the caller isn't
-    // promising to do so itself.
-    let n_params = ty::count_ty_params(bcx.tcx(), t);
-
-    assert n_params == tys.params.len();
-    assert n_params == tys.descs.len();
-
-    let llparamtydescs =
-        alloca(bcx, T_array(T_ptr(bcx.ccx().tydesc_type), n_params + 1u));
-    let i = 0;
-
-    // If the type descriptor escapes, we need to add in the root as
-    // the first parameter, because upcall_get_type_desc() expects it.
-    if escapes {
-        Store(bcx, root, GEPi(bcx, llparamtydescs, [0, 0]));
-        i += 1;
-    }
-
-    for td: ValueRef in tys.descs {
-        Store(bcx, td, GEPi(bcx, llparamtydescs, [0, i]));
-        i += 1;
-    }
-
-    let llfirstparam =
-        PointerCast(bcx, llparamtydescs,
-                    T_ptr(T_ptr(bcx.ccx().tydesc_type)));
-
-    let v;
-    if escapes {
-        let ccx = bcx.ccx();
-        let td_val =
-            Call(bcx, ccx.upcalls.get_type_desc,
-                 [C_null(T_ptr(T_nil())), sz.val,
-                  align.val, C_uint(ccx, 1u + n_params), llfirstparam,
-                  C_uint(ccx, 0u)]);
-        v = td_val;
-    } else {
-        v = trans_stack_local_derived_tydesc(bcx, sz.val, align.val, root,
-                                             llfirstparam, n_params);
-    }
-    bcx.fcx.derived_tydescs.insert(t, {lltydesc: v, escapes: escapes});
-    ret rslt(cx, v);
-}
-
-fn get_tydesc_simple(bcx: block, t: ty::t, escapes: bool) -> result {
+fn get_tydesc_simple(bcx: block, t: ty::t) -> result {
     let ti = none;
-    get_tydesc(bcx, t, escapes, ti)
+    get_tydesc(bcx, t, ti)
 }
 
-fn get_tydesc(cx: block, t: ty::t, escapes: bool,
+fn get_tydesc(cx: block, t: ty::t,
               &static_ti: option<@tydesc_info>) -> result {
 
-    // Is the supplied type a type param? If so, return the passed-in tydesc.
-    alt ty::type_param(t) {
-      some(id) { ret rslt(cx, cx.fcx.lltyparams[id].desc); }
-      none {/* fall through */ }
-    }
-
-    // Does it contain a type param? If so, generate a derived tydesc.
-    if ty::type_has_params(t) {
-        ret get_derived_tydesc(cx, t, escapes, static_ti);
-    }
+    // FIXME[mono]
+    assert !ty::type_has_params(t);
     // Otherwise, generate a tydesc if necessary, and return it.
     let info = get_static_tydesc(cx.ccx(), t, []);
     static_ti = some(info);
@@ -980,7 +872,7 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
         let dtor_addr = common::get_res_dtor(ccx, did, inner_t);
         let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
         for tp in tps {
-            let td = get_tydesc_simple(bcx, tp, false);
+            let td = get_tydesc_simple(bcx, tp);
             args += [td.val];
             bcx = td.bcx;
         }
@@ -1244,13 +1136,6 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
     lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti);
 }
 
-fn lazily_emit_all_generic_info_tydesc_glues(ccx: @crate_ctxt,
-                                             gi: generic_info) {
-    for ti: option<@tydesc_info> in gi.static_tis {
-        lazily_emit_all_tydesc_glue(ccx, ti);
-    }
-}
-
 fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: int,
                            static_ti: option<@tydesc_info>) {
     alt static_ti {
@@ -1349,7 +1234,7 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
 fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: int) ->
    block {
     let ti: option<@tydesc_info> = none::<@tydesc_info>;
-    let {bcx: bcx, val: td} = get_tydesc(cx, t, false, ti);
+    let {bcx: bcx, val: td} = get_tydesc(cx, t, ti);
     call_tydesc_glue_full(bcx, v, td, field, ti);
     ret bcx;
 }
@@ -1370,7 +1255,7 @@ fn call_cmp_glue(cx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
 
     let llrawlhsptr = BitCast(bcx, lllhs, T_ptr(T_i8()));
     let llrawrhsptr = BitCast(bcx, llrhs, T_ptr(T_i8()));
-    r = get_tydesc_simple(bcx, t, false);
+    r = get_tydesc_simple(bcx, t);
     let lltydesc = r.val;
     bcx = r.bcx;
     let lltydescs =
@@ -2047,18 +1932,6 @@ fn trans_loop(cx:block, body: ast::blk) -> block {
     ret next_cx;
 }
 
-type generic_info = {item_type: ty::t,
-                     static_tis: [option<@tydesc_info>],
-                     tydescs: [ValueRef],
-                     param_bounds: @[ty::param_bounds],
-                     origins: option<typeck::vtable_res>};
-
-enum generic_callee {
-    generic_full(generic_info),
-    generic_mono(ty::t),
-    generic_none,
-}
-
 enum lval_kind {
     temporary, //< Temporary value passed by value if of immediate type
     owned,     //< Non-temporary value passed by pointer
@@ -2075,7 +1948,7 @@ type lval_maybe_callee = {bcx: block,
                           val: ValueRef,
                           kind: lval_kind,
                           env: callee_env,
-                          generic: generic_callee};
+                          tds: option<[ValueRef]>};
 
 fn null_env_ptr(bcx: block) -> ValueRef {
     C_null(T_opaque_box_ptr(bcx.ccx()))
@@ -2094,8 +1967,7 @@ fn lval_temp(bcx: block, val: ValueRef) -> lval_result {
 
 fn lval_no_env(bcx: block, val: ValueRef, kind: lval_kind)
     -> lval_maybe_callee {
-    ret {bcx: bcx, val: val, kind: kind, env: is_closure,
-         generic: generic_none};
+    ret {bcx: bcx, val: val, kind: kind, env: is_closure, tds: none};
 }
 
 fn trans_external_path(cx: block, did: ast::def_id,
@@ -2108,7 +1980,7 @@ fn trans_external_path(cx: block, did: ast::def_id,
 
 fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
                   vtables: option<typeck::vtable_res>)
-    -> option<{llfn: ValueRef, fty: ty::t}> {
+    -> option<ValueRef> {
     let substs = vec::map(substs, {|t|
         alt ty::get(t).struct {
           ty::ty_box(mt) { ty::mk_opaque_box(ccx.tcx) }
@@ -2126,7 +1998,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
 
     let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
     let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
-    let llfty = type_of_fn_from_ty(ccx, mono_ty, []);
+    let llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
 
     let map_node = ccx.tcx.items.get(fn_id.node);
     // Get the path so that we can create a symbol
@@ -2146,7 +2018,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
     let pt = *pt + [path_name(ccx.names(name))];
     let s = mangle_exported_name(ccx, pt, mono_ty);
     let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
-    ccx.monomorphized.insert(hash_id, {llfn: lldecl, fty: mono_ty});
+    ccx.monomorphized.insert(hash_id, lldecl);
 
     let psubsts = some({tys: substs, vtables: vtables, bounds: tpt.bounds});
     alt check map_node {
@@ -2182,10 +2054,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
         }
       }
     }
-    some({llfn: lldecl, fty: mono_ty})
+    some(lldecl)
 }
 
-// FIXME[mono] Only actually translate things that are not generic
 fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
     -> ast::def_id {
     alt ccx.external.find(fn_id) {
@@ -2266,10 +2137,12 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
           }
         };
         alt mono {
-          some({llfn, fty}) {
-            ret {bcx: bcx, val: llfn,
+          some(llfn) {
+            let cast = PointerCast(bcx, llfn, T_ptr(type_of_fn_from_ty(
+                ccx, node_id_type(bcx, id), 0u)));
+            ret {bcx: bcx, val: cast,
                  kind: owned, env: null_env,
-                 generic: generic_mono(fty)};
+                 tds: none};
           }
           none {}
         }
@@ -2295,23 +2168,22 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
         }
     }
 
-    let gen = generic_none, bcx = bcx;
+    let tds = none, bcx = bcx;
+    // FIXME[mono] ensure this is a native function
     if tys.len() > 0u {
-        let tydescs = [], tis = [];
+        val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
+            ccx, node_id_type(bcx, id), tys.len())));
+        let tydescs = [];
         for t in tys {
             let ti = none;
-            let td = get_tydesc(bcx, t, true, ti);
-            tis += [ti];
+            let td = get_tydesc(bcx, t, ti);
+            lazily_emit_all_tydesc_glue(ccx, ti);
             bcx = td.bcx;
             tydescs += [td.val];
         }
-        gen = generic_full({item_type: tpt.ty,
-                            static_tis: tis,
-                            tydescs: tydescs,
-                            param_bounds: tpt.bounds,
-                            origins: ccx.maps.vtable_map.find(id)});
+        tds = some(tydescs);
     }
-    ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
+    ret {bcx: bcx, val: val, kind: owned, env: null_env, tds: tds};
 }
 
 fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
@@ -2564,7 +2436,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
 }
 
 fn lval_maybe_callee_to_lval(c: lval_maybe_callee, ty: ty::t) -> lval_result {
-    let must_bind = alt c.generic { generic_full(_) { true } _ { false } } ||
+    let must_bind = option::is_some(c.tds) ||
         alt c.env { self_env(_, _) { true } _ { false } };
     if must_bind {
         let n_args = ty::ty_fn_args(ty).len();
@@ -2761,7 +2633,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
 //  - new_fn_ctxt
 //  - trans_args
 fn trans_args(cx: block, llenv: ValueRef,
-              gen: generic_callee, es: [@ast::expr], fn_ty: ty::t,
+              tds: option<[ValueRef]>, es: [@ast::expr], fn_ty: ty::t,
               dest: dest)
    -> {bcx: block,
        args: [ValueRef],
@@ -2770,54 +2642,40 @@ fn trans_args(cx: block, llenv: ValueRef,
     let temp_cleanups = [];
     let args = ty::ty_fn_args(fn_ty);
     let llargs: [ValueRef] = [];
-    let lltydescs: [ValueRef] = [];
 
     let ccx = cx.ccx();
     let bcx = cx;
 
-    let retty = ty::ty_fn_ret(fn_ty), full_retty = retty;
-    alt gen {
-      generic_full(g) { fail; }
-      generic_mono(t) {
-        args = ty::ty_fn_args(t);
-        retty = ty::ty_fn_ret(t);
-      }
-      _ { }
-    }
+    let retty = ty::ty_fn_ret(fn_ty);
     // Arg 0: Output pointer.
     let llretslot = alt dest {
       ignore {
         if ty::type_is_nil(retty) {
             llvm::LLVMGetUndef(T_ptr(T_nil()))
         } else {
-            let {bcx: cx, val} = alloc_ty(bcx, full_retty);
+            let {bcx: cx, val} = alloc_ty(bcx, retty);
             bcx = cx;
             val
         }
       }
       save_in(dst) { dst }
       by_val(_) {
-          let {bcx: cx, val} = alloc_ty(bcx, full_retty);
+          let {bcx: cx, val} = alloc_ty(bcx, retty);
           bcx = cx;
           val
       }
     };
 
-    if retty != full_retty || ty::type_has_params(retty) {
-        // It's possible that the callee has some generic-ness somewhere in
-        // its return value -- say a method signature within an obj or a fn
-        // type deep in a structure -- which the caller has a concrete view
-        // of. If so, cast the caller's view of the restlot to the callee's
-        // view, for the sake of making a type-compatible call.
-        let llretty = T_ptr(type_of(ccx, retty));
-        llargs += [PointerCast(cx, llretslot, llretty)];
-    } else { llargs += [llretslot]; }
+    llargs += [llretslot];
 
     // Arg 1: Env (closure-bindings / self value)
     llargs += [llenv];
 
     // Args >2: ty_params ...
-    llargs += lltydescs;
+    alt tds {
+      some(tds) { llargs += tds; }
+      none {}
+    }
 
     // ... then explicit args.
 
@@ -2883,7 +2741,7 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
 
         let ret_ty = node_id_type(bcx, id);
         let args_res =
-            trans_args(bcx, llenv, f_res.generic, args, fn_expr_ty, dest);
+            trans_args(bcx, llenv, f_res.tds, args, fn_expr_ty, dest);
         bcx = args_res.bcx;
         let llargs = args_res.args;
         let llretslot = args_res.retslot;
@@ -3418,7 +3276,7 @@ fn trans_log(lvl: @ast::expr, bcx: block, e: @ast::expr) -> block {
         with_scope(bcx, "log") {|bcx|
             let {bcx, val, _} = trans_temp_expr(bcx, e);
             let e_ty = expr_ty(bcx, e);
-            let {bcx, val: tydesc} = get_tydesc_simple(bcx, e_ty, false);
+            let {bcx, val: tydesc} = get_tydesc_simple(bcx, e_ty);
             // Call the polymorphic log function.
             let {bcx, val} = spill_if_immediate(bcx, val, e_ty);
             let val = PointerCast(bcx, val, T_ptr(T_i8()));
@@ -4376,6 +4234,15 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
             let llfndecl = get_item_val(ccx, item.id);
             trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
                      llfndecl, no_self, none, item.id, none);
+        } else {
+            for stmt in body.node.stmts {
+                alt stmt.node {
+                  ast::stmt_decl(@{node: ast::decl_item(i), _}, _) {
+                    trans_item(ccx, *i);
+                  }
+                  _ {}
+                }
+            }
         }
       }
       ast::item_impl(tps, _, _, ms) {
@@ -4400,8 +4267,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
             let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
             let i = 0;
             for variant: ast::variant in variants {
-                let llfn = get_item_val(ccx, variant.node.id);
                 if variant.node.args.len() > 0u {
+                    let llfn = get_item_val(ccx, variant.node.id);
                     trans_enum_variant(ccx, item.id, variant,
                                        vi[i].disr_val, degen,
                                        none, llfn);
@@ -4535,7 +4402,7 @@ fn param_bounds(ccx: @crate_ctxt, tps: [ast::ty_param])
 fn register_fn_full(ccx: @crate_ctxt, sp: span, path: path, flav: str,
                     bnds: [ty::param_bounds], node_id: ast::node_id,
                     node_type: ty::t) -> ValueRef {
-    let llfty = type_of_fn_from_ty(ccx, node_type, bnds);
+    let llfty = type_of_fn_from_ty(ccx, node_type, bnds.len());
     register_fn_fuller(ccx, sp, path, flav, node_id, node_type,
                        lib::llvm::CCallConv, llfty)
 }
@@ -4582,7 +4449,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
             {mode: ast::expl(ast::by_val),
              ty: ty::mk_vec(ccx.tcx, {ty: unit_ty, mutbl: ast::m_imm})};
         let nt = ty::mk_nil(ccx.tcx);
-        let llfty = type_of_fn(ccx, [vecarg_ty], nt, []);
+        let llfty = type_of_fn(ccx, [vecarg_ty], nt, 0u);
         let llfdecl = decl_fn(ccx.llmod, "_rust_main",
                               lib::llvm::CCallConv, llfty);
 
diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs
index 2f5f6da87c2..eae89f4304c 100644
--- a/src/rustc/middle/trans/closure.rs
+++ b/src/rustc/middle/trans/closure.rs
@@ -131,21 +131,15 @@ fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
 // Given a closure ty, emits a corresponding tuple ty
 fn mk_closure_tys(tcx: ty::ctxt,
                   ck: ty::closure_kind,
-                  ty_params: [fn_ty_param],
+                  ty_params: option<[ValueRef]>,
                   bound_values: [environment_value])
     -> (ty::t, [ty::t]) {
     let bound_tys = [];
 
-    let tydesc_ty = mk_tydesc_ty(tcx, ck);
-
     // Compute the closed over tydescs
-    let param_ptrs = [];
-    for tp in ty_params {
-        param_ptrs += [tydesc_ty];
-        option::may(tp.vtables) {|vtables|
-            for vtable in vtables { param_ptrs += [tydesc_ty]; }
-        }
-    }
+    let n_param_ptrs = alt ty_params {
+      some(tds) { tds.len() } none { 0u }
+    };
 
     // Compute the closed over data
     for bv in bound_values {
@@ -158,7 +152,8 @@ fn mk_closure_tys(tcx: ty::ctxt,
     }
     let bound_data_ty = ty::mk_tup(tcx, bound_tys);
 
-    let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, param_ptrs),
+    let typtrs = vec::from_elem(n_param_ptrs, mk_tydesc_ty(tcx, ck));
+    let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, typtrs),
                                     bound_data_ty]);
     #debug["cdata_ty=%s", ty_to_str(tcx, cdata_ty)];
     ret (cdata_ty, bound_tys);
@@ -186,7 +181,7 @@ fn allocate_cbox(bcx: block,
                          &ti: option<@tydesc_info>) -> block {
         let ccx = bcx.ccx();
         let bound_tydesc = GEPi(bcx, box, [0, abi::box_field_tydesc]);
-        let {bcx, val: td} = base::get_tydesc(bcx, cdata_ty, true, ti);
+        let {bcx, val: td} = base::get_tydesc(bcx, cdata_ty, ti);
         let td = Call(bcx, ccx.upcalls.create_shared_type_desc, [td]);
         Store(bcx, td, bound_tydesc);
         bcx
@@ -243,7 +238,7 @@ fn cast_if_we_can(bcx: block, llbox: ValueRef, t: ty::t) -> ValueRef {
 // heap allocated closure that copies the upvars into environment.
 // Otherwise, it is stack allocated and copies pointers to the upvars.
 fn store_environment(
-    bcx: block, lltyparams: [fn_ty_param],
+    bcx: block, lltyparams: option<[ValueRef]>,
     bound_values: [environment_value],
     ck: ty::closure_kind)
     -> closure_result {
@@ -284,18 +279,11 @@ fn store_environment(
     let {bcx:bcx, val:ty_params_slot} =
         GEP_tup_like(bcx, cbox_ty, llbox,
                      [0, abi::box_field_body, abi::closure_body_ty_params]);
-    let off = 0;
-    for tp in lltyparams {
-        let cloned_td = maybe_clone_tydesc(bcx, ck, tp.desc);
-        Store(bcx, cloned_td, GEPi(bcx, ty_params_slot, [0, off]));
-        off += 1;
-        option::may(tp.vtables, {|vtables|
-            for vtable in vtables {
-                let cast = PointerCast(bcx, vtable, val_ty(cloned_td));
-                Store(bcx, cast, GEPi(bcx, ty_params_slot, [0, off]));
-                off += 1;
-            }
-        });
+    option::may(lltyparams) {|tds|
+        vec::iteri(tds) {|i, td|
+            let cloned_td = maybe_clone_tydesc(bcx, ck, td);
+            Store(bcx, cloned_td, GEPi(bcx, ty_params_slot, [0, i as int]));
+        }
     }
 
     // Copy expr values into boxed bindings.
@@ -389,14 +377,13 @@ fn build_closure(bcx0: block,
           }
         }
     }
-    ret store_environment(bcx, copy bcx.fcx.lltyparams, env_vals, ck);
+    ret store_environment(bcx, none, env_vals, ck);
 }
 
 // Given an enclosing block context, a new function context, a closure type,
 // and a list of upvars, generate code to load and populate the environment
 // with the upvars and type descriptors.
-fn load_environment(enclosing_cx: block,
-                    fcx: fn_ctxt,
+fn load_environment(fcx: fn_ctxt,
                     cdata_ty: ty::t,
                     cap_vars: [capture::capture_var],
                     ck: ty::closure_kind) {
@@ -405,27 +392,6 @@ fn load_environment(enclosing_cx: block,
     // Load a pointer to the closure data, skipping over the box header:
     let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
 
-    // Populate the type parameters from the environment. We need to
-    // do this first because the tydescs are needed to index into
-    // the bindings if they are dynamically sized.
-    let {bcx, val: lltydescs} = GEP_tup_like(bcx, cdata_ty, llcdata,
-                                            [0, abi::closure_body_ty_params]);
-    let off = 0;
-    for tp in copy enclosing_cx.fcx.lltyparams {
-        let tydesc = Load(bcx, GEPi(bcx, lltydescs, [0, off]));
-        off += 1;
-        let vtables = option::map(tp.vtables, {|vtables|
-            let rslt = [];
-            for vtable in vtables {
-                let vtable = Load(bcx, GEPi(bcx, lltydescs, [0, off]));
-                rslt += [PointerCast(bcx, vtable, T_ptr(T_vtable()))];
-                off += 1;
-            }
-            rslt
-        });
-        fcx.lltyparams += [{desc: tydesc, vtables: vtables}];
-    }
-
     // Populate the upvars from the environment.
     let i = 0u;
     vec::iter(cap_vars) { |cap_var|
@@ -460,7 +426,7 @@ fn trans_expr_fn(bcx: block,
     if dest == ignore { ret bcx; }
     let ccx = bcx.ccx(), bcx = bcx;
     let fty = node_id_type(bcx, id);
-    let llfnty = type_of_fn_from_ty(ccx, fty, []);
+    let llfnty = type_of_fn_from_ty(ccx, fty, 0u);
     let sub_path = bcx.fcx.path + [path_name("anon")];
     let s = mangle_internal_name_by_path(ccx, sub_path);
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
@@ -472,7 +438,7 @@ fn trans_expr_fn(bcx: block,
         let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id);
         trans_closure(ccx, sub_path, decl, body, llfn, no_self,
                       bcx.fcx.param_substs, id, none, {|fcx|
-            load_environment(bcx, fcx, cdata_ty, cap_vars, ck);
+            load_environment(fcx, cdata_ty, cap_vars, ck);
         });
         llbox
     };
@@ -513,13 +479,7 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
         ret bcx;
     }
 
-    // Figure out which tydescs we need to pass, if any.
-    let (outgoing_fty_real, lltydescs, param_bounds) = alt f_res.generic {
-      generic_full(ginfo) { fail; }
-      _ { (outgoing_fty, [], @[]) }
-    };
-
-    if bound.len() == 0u && lltydescs.len() == 0u &&
+    if bound.len() == 0u && option::is_none(f_res.tds) &&
        (f_res.env == null_env || f_res.env == is_closure) {
         // Trivial 'binding': just return the closure
         let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
@@ -545,14 +505,15 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
 
     // Actually construct the closure
     let {llbox, cdata_ty, bcx} = store_environment(
-        bcx, vec::map(lltydescs, {|d| {desc: d, vtables: none}}),
+        bcx, f_res.tds,
         env_vals + vec::map(bound, {|x| env_expr(x, expr_ty(bcx, x))}),
         ty::ck_box);
 
     // Make thunk
     let llthunk = trans_bind_thunk(
-        cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty_real, args,
-        cdata_ty, *param_bounds, target_info);
+        cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty, args,
+        cdata_ty, target_info,
+        alt f_res.tds { some(x) { x.len() } _ { 0u } });
 
     // Fill the function pair
     fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
@@ -704,16 +665,15 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
                     outgoing_fty: ty::t,
                     args: [option<@ast::expr>],
                     cdata_ty: ty::t,
-                    param_bounds: [ty::param_bounds],
-                    target_info: target_info)
+                    target_info: target_info,
+                    n_tps: uint)
     -> {val: ValueRef, ty: TypeRef} {
     let tcx = ccx.tcx;
     #debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
-            cdata_ty=%s,param_bounds=%?]",
+            cdata_ty=%s]",
            ty_to_str(tcx, incoming_fty),
            ty_to_str(tcx, outgoing_fty),
-           ty_to_str(tcx, cdata_ty),
-           param_bounds];
+           ty_to_str(tcx, cdata_ty)];
 
     // Here we're not necessarily constructing a thunk in the sense of
     // "function with no arguments".  The result of compiling 'bind f(foo,
@@ -813,28 +773,11 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
     let {bcx: l_bcx, val: param_record} =
         GEP_tup_like(l_bcx, cdata_ty, llcdata,
                      [0, abi::closure_body_ty_params]);
-    let off = 0;
-    for param in param_bounds {
-        let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, off])),
-            vtables = none;
+    let i = 0u;
+    while i < n_tps {
+        let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, i as int]));
         llargs += [dsc];
-        off += 1;
-        for bound in *param {
-            alt bound {
-              ty::bound_iface(_) {
-                let vtable = Load(l_bcx, GEPi(l_bcx, param_record, [0, off]));
-                vtable = PointerCast(l_bcx, vtable, T_ptr(T_vtable()));
-                llargs += [vtable];
-                off += 1;
-                vtables = some(alt vtables {
-                  none { [vtable] }
-                  some(ds) { ds + [vtable] }
-                });
-              }
-              _ {}
-            }
-        }
-        fcx.lltyparams += [{desc: dsc, vtables: vtables}];
+        fcx.lltyparams += [{desc: dsc, vtables: none}];
     }
 
     let a: uint = first_tp_arg; // retptr, env come first
@@ -895,7 +838,7 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
     // in the closure does not know how many type descriptors the function
     // needs to take.
     let lltargetty =
-        type_of_fn_from_ty(ccx, outgoing_fty, param_bounds);
+        type_of_fn_from_ty(ccx, outgoing_fty, 0u);
     lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
     Call(bcx, lltargetfn, llargs);
     build_return(bcx);
diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 7dce92d94d7..6c7b1aa916f 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -93,7 +93,7 @@ type crate_ctxt = {
      // Track mapping of external ids to local items imported for inlining
      external: hashmap<ast::def_id, option<ast::node_id>>,
      // Cache instances of monomorphized functions
-     monomorphized: hashmap<mono_id, {llfn: ValueRef, fty: ty::t}>,
+     monomorphized: hashmap<mono_id, ValueRef>,
      // Cache generated vtables
      vtables: hashmap<mono_id, ValueRef>,
      module_data: hashmap<str, ValueRef>,
@@ -180,6 +180,7 @@ type fn_ctxt = @{
     llupvars: hashmap<ast::node_id, ValueRef>,
 
     // A vector of incoming type descriptors and their associated vtables.
+    // Currently only used by glue functions
     mutable lltyparams: [fn_ty_param],
 
     // Derived tydescs are tydescs created at runtime, for types that
@@ -307,7 +308,7 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
     let nil_res = ty::mk_nil(ccx.tcx);
     let fn_mode = ast::expl(ast::by_ref);
     let f_t = type_of::type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
-                                  nil_res, *param_bounds);
+                                  nil_res, (*param_bounds).len());
     ret base::get_extern_const(ccx.externs, ccx.llmod,
                                 csearch::get_symbol(ccx.sess.cstore,
                                                     did), f_t);
@@ -542,9 +543,9 @@ fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
 fn T_empty_struct() -> TypeRef { ret T_struct([]); }
 
 // A vtable is, in reality, a vtable pointer followed by zero or more pointers
-// to tydescs and other vtables that it closes over. But the types and number
-// of those are rarely known to the code that needs to manipulate them, so
-// they are described by this opaque type.
+// to tydescs and other vtables that it closes over. But the types and number of
+// those are rarely known to the code that needs to manipulate them, so they
+// are described by this opaque type.
 fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
 
 fn T_task(targ_cfg: @session::config) -> TypeRef {
diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs
index a48f4147ba3..85ba984bed9 100644
--- a/src/rustc/middle/trans/impl.rs
+++ b/src/rustc/middle/trans/impl.rs
@@ -76,7 +76,7 @@ fn trans_static_callee(bcx: block, callee_id: ast::node_id,
 
 fn wrapper_fn_ty(ccx: @crate_ctxt, vtable_ty: TypeRef, fty: ty::t,
                  tps: @[ty::param_bounds]) -> {ty: ty::t, llty: TypeRef} {
-    let bare_fn_ty = type_of_fn_from_ty(ccx, fty, *tps);
+    let bare_fn_ty = type_of_fn_from_ty(ccx, fty, (*tps).len());
     let {inputs, output} = llfn_arg_tys(bare_fn_ty);
     {ty: fty, llty: T_fn([vtable_ty] + inputs, output)}
 }
@@ -86,13 +86,11 @@ fn trans_vtable_callee(bcx: block, env: callee_env, vtable: ValueRef,
     -> lval_maybe_callee {
     let bcx = bcx, ccx = bcx.ccx();
     let fty = node_id_type(bcx, callee_id);
-    let llfty = type_of::type_of_fn_from_ty(ccx, fty, []);
+    let llfty = type_of::type_of_fn_from_ty(ccx, fty, 0u);
     let vtable = PointerCast(bcx, vtable,
                              T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
     let mptr = Load(bcx, GEPi(bcx, vtable, [0, n_method as int]));
-    {bcx: bcx, val: mptr, kind: owned,
-     env: env,
-     generic: generic_none}
+    {bcx: bcx, val: mptr, kind: owned, env: env, tds: none}
 }
 
 fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
@@ -243,10 +241,10 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: [ty::t],
         let fty = ty::substitute_type_params(tcx, substs,
                                              ty::mk_fn(tcx, im.fty));
         if (*im.tps).len() > 0u || ty::type_has_vars(fty) {
-            C_null(type_of_fn_from_ty(ccx, fty, []))
+            C_null(type_of_fn_from_ty(ccx, fty, 0u))
         } else {
             let m_id = method_with_name(ccx, impl_id, im.ident);
-            option::get(monomorphic_fn(ccx, m_id, substs, some(vtables))).llfn
+            option::get(monomorphic_fn(ccx, m_id, substs, some(vtables)))
         }
     }))
 }
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index 3a681644f51..7aa059fb17e 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -269,7 +269,7 @@ fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
         let t = ty::node_id_to_type(ccx.tcx, id);
         let ps = link::mangle_internal_name_by_path(
             ccx, path + [ast_map::path_name("__rust_abi")]);
-        let llty = type_of_fn_from_ty(ccx, t, []);
+        let llty = type_of_fn_from_ty(ccx, t, 0u);
         let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
         trans_fn(ccx, path, decl, body, llfndecl, no_self, none, id,
                  none);
@@ -383,8 +383,7 @@ fn decl_native_fn(ccx: @crate_ctxt, i: @ast::native_item,
           ast::native_abi_rust_intrinsic {
             // For intrinsics: link the function directly to the intrinsic
             // function itself.
-            let fn_type = type_of_fn_from_ty(
-                ccx, node_type, param_bounds(ccx, tps));
+            let fn_type = type_of_fn_from_ty(ccx, node_type, tps.len());
             let ri_name = "rust_intrinsic_" + native::link_name(i);
             ccx.item_symbols.insert(i.id, ri_name);
             get_extern_fn(ccx.externs, ccx.llmod, ri_name,
diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs
index 0502fc9abb1..cf774e19acf 100644
--- a/src/rustc/middle/trans/shape.rs
+++ b/src/rustc/middle/trans/shape.rs
@@ -701,7 +701,7 @@ fn dynamic_metrics(cx: block, t: ty::t) -> metrics {
 
     alt ty::get(t).struct {
       ty::ty_param(p, _) {
-        let {bcx, val: tydesc} = base::get_tydesc_simple(cx, t, false);
+        let {bcx, val: tydesc} = base::get_tydesc_simple(cx, t);
         let szptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_size]);
         let aptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_align]);
         {bcx: bcx, sz: Load(bcx, szptr), align: Load(bcx, aptr)}
diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs
index aeaf65db7f4..e7034adb47d 100644
--- a/src/rustc/middle/trans/tvec.rs
+++ b/src/rustc/middle/trans/tvec.rs
@@ -202,7 +202,7 @@ fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t,
     let ccx = bcx.ccx();
     let elt_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
     let ti = none;
-    let {bcx: bcx, val: td} = get_tydesc(bcx, elt_ty, false, ti);
+    let {bcx: bcx, val: td} = get_tydesc(bcx, elt_ty, ti);
     base::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, ti);
     let opaque_v = PointerCast(bcx, vptrptr,
                                T_ptr(T_ptr(ccx.opaque_vec_type)));
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index 417147fee95..a7991563abb 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -19,7 +19,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
 }
 
 fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
-              output: ty::t, params: [ty::param_bounds]) -> TypeRef {
+              output: ty::t, n_ty_params: uint) -> TypeRef {
     let atys: [TypeRef] = [];
 
     // Arg 0: Output pointer.
@@ -29,14 +29,10 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
     atys += [T_opaque_box_ptr(cx)];
 
     // Args >2: ty params, if not acquired via capture...
-    for bounds in params {
+    let i = 0u;
+    while i < n_ty_params {
         atys += [T_ptr(cx.tydesc_type)];
-        for bound in *bounds {
-            alt bound {
-              ty::bound_iface(_) { atys += [T_ptr(T_vtable())]; }
-              _ {}
-            }
-        }
+        i += 1u;
     }
     // ... then explicit args.
     atys += type_of_explicit_args(cx, inputs);
@@ -44,9 +40,9 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
 }
 
 // Given a function type and a count of ty params, construct an llvm type
-fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t,
-                      param_bounds: [ty::param_bounds]) -> TypeRef {
-    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), param_bounds)
+fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t, n_ty_params: uint)
+    -> TypeRef {
+    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), n_ty_params)
 }
 
 fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
@@ -93,7 +89,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
         T_struct(tys)
       }
       ty::ty_fn(_) {
-        T_fn_pair(cx, type_of_fn_from_ty(cx, t, []))
+        T_fn_pair(cx, type_of_fn_from_ty(cx, t, 0u))
       }
       ty::ty_iface(_, _) { T_opaque_iface(cx) }
       ty::ty_res(_, sub, tps) {
@@ -155,7 +151,7 @@ fn type_of_ty_param_bounds_and_ty
     let t = tpt.ty;
     alt ty::get(t).struct {
       ty::ty_fn(_) {
-        ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
+        ret type_of_fn_from_ty(ccx, t, (*tpt.bounds).len());
       }
       _ {
         // fall through