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.
|
/// 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(
|
pub(crate) fn call_fn_raw(
|
||||||
&self,
|
&self,
|
||||||
scope: Option<&mut Scope>,
|
scope: Option<&mut Scope>,
|
||||||
@ -596,6 +602,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Call a script-defined function.
|
/// 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(
|
pub(crate) fn call_fn_from_lib(
|
||||||
&self,
|
&self,
|
||||||
scope: Option<&mut Scope>,
|
scope: Option<&mut Scope>,
|
||||||
@ -678,6 +690,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform an actual function call, taking care of special functions
|
// 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(
|
fn exec_fn_call(
|
||||||
&self,
|
&self,
|
||||||
fn_lib: &FunctionsLib,
|
fn_lib: &FunctionsLib,
|
||||||
@ -1105,17 +1123,20 @@ impl Engine {
|
|||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> 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)?;
|
let rhs_value = self.eval_expr(scope, state, fn_lib, rhs, level)?;
|
||||||
|
|
||||||
match rhs_value {
|
match rhs_value {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Dynamic(Union::Array(mut rhs_value)) => {
|
Dynamic(Union::Array(rhs_value)) => {
|
||||||
let def_value = false.into();
|
let def_value = false.into();
|
||||||
|
|
||||||
// Call the '==' operator to compare each value
|
// Call the `==` operator to compare each value
|
||||||
for value in rhs_value.iter_mut() {
|
for value in rhs_value.iter() {
|
||||||
let args = &mut [&mut lhs_value, value];
|
// 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 def_value = Some(&def_value);
|
||||||
let pos = rhs.position();
|
let pos = rhs.position();
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ use crate::token::Position;
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
|
mem,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -170,9 +171,9 @@ pub fn reg_unary<T: Variant + Clone, R>(
|
|||||||
check_num_args(fn_name, 1, args, pos)?;
|
check_num_args(fn_name, 1, args, pos)?;
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
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)
|
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)?;
|
check_num_args(fn_name, 2, args, pos)?;
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
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)
|
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 mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
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)
|
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)?;
|
check_num_args(fn_name, 3, args, pos)?;
|
||||||
|
|
||||||
let mut drain = args.iter_mut();
|
let mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
let x = mem::take(*drain.next().unwrap()).cast::<A>();
|
||||||
let y: &mut B = drain.next().unwrap().downcast_mut().unwrap();
|
let y = mem::take(*drain.next().unwrap()).cast::<B>();
|
||||||
let z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
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)
|
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 mut drain = args.iter_mut();
|
||||||
let x: &mut A = drain.next().unwrap().downcast_mut().unwrap();
|
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 z: &mut C = drain.next().unwrap().downcast_mut().unwrap();
|
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)
|
map_result(r, pos)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user