Avoid copying arguments in packages.
This commit is contained in:
parent
e966f5d49e
commit
34327f6e54
@ -502,6 +502,12 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Universal method for calling functions either registered with the `Engine` or written in Rhai.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
|
||||
pub(crate) fn call_fn_raw(
|
||||
&self,
|
||||
scope: Option<&mut Scope>,
|
||||
@ -596,6 +602,12 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Call a script-defined function.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
|
||||
pub(crate) fn call_fn_from_lib(
|
||||
&self,
|
||||
scope: Option<&mut Scope>,
|
||||
@ -678,6 +690,12 @@ impl Engine {
|
||||
}
|
||||
|
||||
// Perform an actual function call, taking care of special functions
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||
/// **DO NOT** reuse the argument values unless for the first `&mut` argument - all others are silently replaced by `()`!
|
||||
fn exec_fn_call(
|
||||
&self,
|
||||
fn_lib: &FunctionsLib,
|
||||
@ -1105,17 +1123,20 @@ impl Engine {
|
||||
rhs: &Expr,
|
||||
level: usize,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut lhs_value = self.eval_expr(scope, state, fn_lib, lhs, level)?;
|
||||
let lhs_value = self.eval_expr(scope, state, fn_lib, lhs, level)?;
|
||||
let rhs_value = self.eval_expr(scope, state, fn_lib, rhs, level)?;
|
||||
|
||||
match rhs_value {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Dynamic(Union::Array(mut rhs_value)) => {
|
||||
Dynamic(Union::Array(rhs_value)) => {
|
||||
let def_value = false.into();
|
||||
|
||||
// Call the '==' operator to compare each value
|
||||
for value in rhs_value.iter_mut() {
|
||||
let args = &mut [&mut lhs_value, value];
|
||||
// Call the `==` operator to compare each value
|
||||
for value in rhs_value.iter() {
|
||||
// WARNING - Always clone the values here because they'll be consumed by the function call.
|
||||
// Do not pass the `&mut` straight through because the `==` implementation
|
||||
// very likely takes parameters passed by value!
|
||||
let args = &mut [&mut lhs_value.clone(), &mut value.clone()];
|
||||
let def_value = Some(&def_value);
|
||||
let pos = rhs.position();
|
||||
|
||||
|
@ -9,6 +9,7 @@ use crate::token::Position;
|
||||
use crate::stdlib::{
|
||||
any::TypeId,
|
||||
boxed::Box,
|
||||
mem,
|
||||
string::{String, ToString},
|
||||
};
|
||||
|
||||
@ -170,9 +171,9 @@ pub fn reg_unary<T: Variant + Clone, R>(
|
||||
check_num_args(fn_name, 1, args, pos)?;
|
||||
|
||||
let mut drain = args.iter_mut();
|
||||
let x: &mut T = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let x = mem::take(*drain.next().unwrap()).cast::<T>();
|
||||
|
||||
let r = func(x.clone());
|
||||
let r = func(x);
|
||||
map_result(r, pos)
|
||||
});
|
||||
|
||||
@ -286,10 +287,10 @@ pub fn reg_binary<A: Variant + Clone, B: Variant + Clone, R>(
|
||||
check_num_args(fn_name, 2, args, pos)?;
|
||||
|
||||
let mut drain = args.iter_mut();
|
||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||
|
||||
let r = func(x.clone(), y.clone());
|
||||
let r = func(x, y);
|
||||
map_result(r, pos)
|
||||
});
|
||||
|
||||
@ -351,9 +352,9 @@ pub fn reg_binary_mut<A: Variant + Clone, B: Variant + Clone, R>(
|
||||
|
||||
let mut drain = args.iter_mut();
|
||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||
|
||||
let r = func(x, y.clone());
|
||||
let r = func(x, y);
|
||||
map_result(r, pos)
|
||||
});
|
||||
|
||||
@ -390,11 +391,11 @@ pub fn reg_trinary<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, R
|
||||
check_num_args(fn_name, 3, args, pos)?;
|
||||
|
||||
let mut drain = args.iter_mut();
|
||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||
let z = mem::take(*drain.next().unwrap()).cast::<C>();
|
||||
|
||||
let r = func(x.clone(), y.clone(), z.clone());
|
||||
let r = func(x, y, z);
|
||||
map_result(r, pos)
|
||||
});
|
||||
|
||||
@ -432,10 +433,10 @@ pub fn reg_trinary_mut<A: Variant + Clone, B: Variant + Clone, C: Variant + Clon
|
||||
|
||||
let mut drain = args.iter_mut();
|
||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
||||
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||
let z = mem::take(*drain.next().unwrap()).cast::<C>();
|
||||
|
||||
let r = func(x, y.clone(), z.clone());
|
||||
let r = func(x, y, z);
|
||||
map_result(r, pos)
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user