about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-09 17:44:55 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-11 11:11:45 +0100
commit0145b15f0cd61389599eb1cb77c028f7f4a8229a (patch)
tree2b2a71143eabcd7cac4b184ca8039854bf7bc984
parentef895b96320a9d5c64090bad1c8a147b0431eef1 (diff)
downloadrust-0145b15f0cd61389599eb1cb77c028f7f4a8229a.tar.gz
rust-0145b15f0cd61389599eb1cb77c028f7f4a8229a.zip
Pass type with params intact as item_type for method callees
This prevents trans_args from optimizing out nil return types. The
method might be generic, in which case it *will* write to a nil retptr.
-rw-r--r--src/comp/middle/trans.rs9
-rw-r--r--src/comp/middle/trans_impl.rs4
2 files changed, 6 insertions, 7 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 2c5c45ed570..7fb21547589 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1313,7 +1313,7 @@ fn make_take_glue(cx: @block_ctxt, v: ValueRef, t: ty::t) {
     let tcx = bcx_tcx(cx);
     // NB: v is an *alias* of type t here, not a direct value.
     bcx = alt ty::struct(tcx, t) {
-      ty::ty_box(_) {
+      ty::ty_box(_) | ty::ty_iface(_, _) {
         incr_refcnt_of_boxed(bcx, Load(bcx, v))
       }
       ty::ty_uniq(_) {
@@ -3078,7 +3078,7 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
     ret store_in_dest(e_res.bcx, newval, dest);
 }
 
-fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
+fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
                   &to_zero: [{v: ValueRef, t: ty::t}],
                   &to_revoke: [{v: ValueRef, t: ty::t}], e: @ast::expr) ->
    result {
@@ -3092,8 +3092,8 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
         // For values of type _|_, we generate an
         // "undef" value, as such a value should never
         // be inspected. It's important for the value
-        // to have type lldestty0 (the callee's expected type).
-        val = llvm::LLVMGetUndef(lldestty0);
+        // to have type lldestty (the callee's expected type).
+        val = llvm::LLVMGetUndef(lldestty);
     } else if arg.mode == ast::by_ref || arg.mode == ast::by_val {
         let copied = false, imm = ty::type_is_immediate(ccx.tcx, e_ty);
         if arg.mode == ast::by_ref && lv.kind != owned && imm {
@@ -3134,7 +3134,6 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
     }
 
     if !is_bot && ty::type_contains_params(ccx.tcx, arg.ty) {
-        let lldestty = lldestty0;
         val = PointerCast(bcx, val, lldestty);
     }
 
diff --git a/src/comp/middle/trans_impl.rs b/src/comp/middle/trans_impl.rs
index 6b550a76c86..bb17553b2f0 100644
--- a/src/comp/middle/trans_impl.rs
+++ b/src/comp/middle/trans_impl.rs
@@ -73,7 +73,7 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
                        n_method: uint) -> lval_maybe_callee {
     let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx;
     let method = ty::iface_methods(tcx, iface_id)[n_method];
-    let fty = ty::expr_ty(tcx, fld_expr);
+    let fty = ty::mk_fn(tcx, method.fty);
     let bare_fn_ty = type_of_fn_from_ty(ccx, ast_util::dummy_sp(),
                                         fty, *method.tps);
     let {inputs: bare_inputs, output} = llfn_arg_tys(bare_fn_ty);
@@ -82,7 +82,7 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
                              T_ptr(T_array(T_ptr(fn_ty), n_method + 1u)));
     let mptr = Load(bcx, GEPi(bcx, vtable, [0, n_method as int]));
     let generic = none;
-    if vec::len(*method.tps) > 0u {
+    if vec::len(*method.tps) > 0u || ty::type_contains_params(tcx, fty) {
         let tydescs = [], tis = [];
         let tptys = ty::node_id_to_type_params(tcx, fld_expr.id);
         for t in vec::tail_n(tptys, vec::len(tptys) - vec::len(*method.tps)) {