fix turning function items into closure trait objects
This commit is contained in:
parent
9f7ca351e0
commit
0377990dc6
@ -6,7 +6,7 @@
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
use rustc::ty::{self, Ty, TyCtxt, BareFnTy};
|
||||
use syntax::codemap::{DUMMY_SP, Span};
|
||||
use syntax::{ast, attr};
|
||||
use syntax::{ast, attr, abi};
|
||||
|
||||
use error::{EvalError, EvalResult};
|
||||
use eval_context::{EvalContext, IntegerExt, StackPopCleanup, monomorphize_field_ty, is_inhabited};
|
||||
@ -313,6 +313,10 @@ fn eval_fn_call(
|
||||
)?;
|
||||
|
||||
let arg_locals = self.frame().mir.args_iter();
|
||||
// FIXME: impl ExactSizeIterator and use args_locals.len()
|
||||
// FIXME: last-use-in-cap-clause works by chance, insert some arguments and it will fail
|
||||
// we currently write the first argument (unit) to the return field (unit)
|
||||
//assert_eq!(self.frame().mir.args_iter().count(), args.len());
|
||||
for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
|
||||
let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
|
||||
self.write_value(arg_val, dest, arg_ty)?;
|
||||
@ -624,18 +628,31 @@ fn trait_method(
|
||||
|
||||
traits::VtableObject(ref data) => {
|
||||
let idx = self.tcx.get_vtable_index_of_object_method(data, def_id) as u64;
|
||||
if let Some(&mut(ref mut first_arg, ref mut first_ty)) = args.get_mut(0) {
|
||||
let (self_ptr, vtable) = first_arg.expect_ptr_vtable_pair(&self.memory)?;
|
||||
*first_arg = Value::ByVal(PrimVal::Ptr(self_ptr));
|
||||
let idx = idx + 3;
|
||||
let offset = idx * self.memory.pointer_size();
|
||||
let fn_ptr = self.memory.read_ptr(vtable.offset(offset))?;
|
||||
let (def_id, substs, _abi, sig) = self.memory.get_fn(fn_ptr.alloc_id)?;
|
||||
*first_ty = sig.inputs()[0];
|
||||
Ok((def_id, substs, Vec::new()))
|
||||
} else {
|
||||
Err(EvalError::VtableForArgumentlessMethod)
|
||||
if args.is_empty() {
|
||||
return Err(EvalError::VtableForArgumentlessMethod);
|
||||
}
|
||||
let (self_ptr, vtable) = args[0].0.expect_ptr_vtable_pair(&self.memory)?;
|
||||
let idx = idx + 3;
|
||||
let offset = idx * self.memory.pointer_size();
|
||||
let fn_ptr = self.memory.read_ptr(vtable.offset(offset))?;
|
||||
let (def_id, substs, abi, sig) = self.memory.get_fn(fn_ptr.alloc_id)?;
|
||||
trace!("args: {:#?}", args);
|
||||
trace!("sig: {:#?}", sig);
|
||||
if abi != abi::Abi::RustCall && args.len() == 2 {
|
||||
if let ty::TyTuple(wrapped_args) = args[1].1.sty {
|
||||
assert_eq!(sig.inputs(), &wrapped_args[..]);
|
||||
// a function item turned into a closure trait object
|
||||
// the first arg is just there to give use the vtable
|
||||
args.remove(0);
|
||||
self.unpack_fn_args(args)?;
|
||||
return Ok((def_id, substs, Vec::new()));
|
||||
}
|
||||
}
|
||||
args[0] = (
|
||||
Value::ByVal(PrimVal::Ptr(self_ptr)),
|
||||
sig.inputs()[0],
|
||||
);
|
||||
Ok((def_id, substs, Vec::new()))
|
||||
},
|
||||
vtable => bug!("resolved vtable bad vtable {:?} in trans", vtable),
|
||||
}
|
||||
|
6
tests/run-pass/fn_item_as_closure_trait_object.rs
Normal file
6
tests/run-pass/fn_item_as_closure_trait_object.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn foo() {}
|
||||
|
||||
fn main() {
|
||||
let f: &Fn() = &foo;
|
||||
f();
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
fn foo(i: i32) {
|
||||
assert_eq!(i, 42);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f: &Fn(i32) = &foo;
|
||||
f(42);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fn foo(i: i32, j: i32) {
|
||||
assert_eq!(i, 42);
|
||||
assert_eq!(j, 55);
|
||||
}
|
||||
|
||||
fn bar(i: i32, j: i32, k: f32) {
|
||||
assert_eq!(i, 42);
|
||||
assert_eq!(j, 55);
|
||||
assert_eq!(k, 3.14159)
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let f: &Fn(i32, i32) = &foo;
|
||||
f(42, 55);
|
||||
let f: &Fn(i32, i32, f32) = &bar;
|
||||
f(42, 55, 3.14159);
|
||||
}
|
Loading…
Reference in New Issue
Block a user