Correctly "detuple" arguments when creating trait object shims for a trait method with rust-call ABI.

This commit is contained in:
Niko Matsakis 2015-01-05 13:53:39 -05:00 committed by Jorge Aparicio
parent f97b124a44
commit c98814b124
5 changed files with 85 additions and 2 deletions

View file

@ -100,7 +100,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
-> Callee<'blk, 'tcx> {
let DatumBlock { mut bcx, datum, .. } = expr::trans(bcx, expr);
let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr);
match datum.ty.sty {
ty::ty_bare_fn(..) => {
let llval = datum.to_llscalarish(bcx);

View file

@ -599,8 +599,27 @@ pub fn trans_object_shim<'a, 'tcx>(
bcx.val_to_string(llobject));
// the remaining arguments will be, well, whatever they are
let input_tys =
match fty.abi {
RustCall => {
// unpack the tuple to extract the input type arguments:
match fty.sig.0.inputs[1].sty {
ty::ty_tup(ref tys) => tys.as_slice(),
_ => {
bcx.sess().bug(
format!("rust-call expects a tuple not {}",
fty.sig.0.inputs[1].repr(tcx)).as_slice());
}
}
}
_ => {
// skip the self parameter:
fty.sig.0.inputs.slice_from(1)
}
};
let llargs: Vec<_> =
fty.sig.0.inputs[1..].iter()
input_tys.iter()
.enumerate()
.map(|(i, _)| {
let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
@ -609,6 +628,7 @@ pub fn trans_object_shim<'a, 'tcx>(
llarg
})
.collect();
assert!(!fcx.needs_ret_allocas);
let dest =

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Tests calls to closure arguments where the closure takes 1 argument.
// This is a bit tricky due to rust-call ABI.
fn foo(f: &mut FnMut(int) -> int) -> int {
f(22)
}
fn main() {
let z = foo(&mut |x| x *100);
assert_eq!(z, 2200);
}

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Tests calls to closure arguments where the closure takes 2 arguments.
// This is a bit tricky due to rust-call ABI.
fn foo(f: &mut FnMut(int, int) -> int) -> int {
f(1, 2)
}
fn main() {
let z = foo(&mut |x, y| x * 10 + y);
assert_eq!(z, 12);
}

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Tests calls to closure arguments where the closure takes 0 arguments.
// This is a bit tricky due to rust-call ABI.
fn foo(f: &mut FnMut()) -> int {
f()
}
fn main() {
let z = foo(|| 22);
assert_eq!(z, 22);
}