Skip to content

Commit

Permalink
Fix bug.
Browse files Browse the repository at this point in the history
  • Loading branch information
schungx committed Jun 27, 2023
1 parent 541844e commit 2474c1f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Rhai Release Notes
==================

Version 1.16.0
==============

Bug fixes
---------

* Fixes a panic when using `this` as the first parameter in a namespace-qualified function call.


Version 1.15.1
==============

Expand Down
28 changes: 20 additions & 8 deletions src/func/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,15 +1289,17 @@ impl Engine {

// Call with blank scope
#[cfg(not(feature = "no_closure"))]
let this_ptr_not_shared = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
let has_non_shared_this_ptr = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
#[cfg(feature = "no_closure")]
let this_ptr_not_shared = true;
let has_non_shared_this_ptr = this_ptr.is_some();

// If the first argument is a variable, and there are no curried arguments,
// convert to method-call style in order to leverage potential &mut first argument
// and avoid cloning the value.
match first_arg {
Some(_first_expr @ Expr::ThisPtr(pos)) if curry.is_empty() && this_ptr_not_shared => {
Some(_first_expr @ Expr::ThisPtr(pos))
if curry.is_empty() && has_non_shared_this_ptr =>
{
// Turn it into a method call only if the object is not shared
self.track_operation(global, *pos)?;

Expand Down Expand Up @@ -1381,21 +1383,30 @@ impl Engine {
let mut first_arg_value = None;

#[cfg(not(feature = "no_closure"))]
let this_ptr_not_shared = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
let has_non_shared_this_ptr = this_ptr.as_ref().map_or(false, |v| !v.is_shared());
#[cfg(feature = "no_closure")]
let this_ptr_not_shared = true;
let has_non_shared_this_ptr = this_ptr.is_some();

// See if the first argument is a variable.
// If so, convert to method-call style in order to leverage potential
// &mut first argument and avoid cloning the value.
match args_expr.get(0) {
Some(_first_expr @ Expr::ThisPtr(pos)) if this_ptr_not_shared => {
Some(_first_expr @ Expr::ThisPtr(pos)) if has_non_shared_this_ptr => {
self.track_operation(global, *pos)?;

#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), _first_expr)?;

// Turn it into a method call only if the object is not shared
// The first value is a placeholder (for later if it needs to be cloned)
arg_values.push(Dynamic::UNIT);

for expr in args_expr.iter().skip(1) {
let (value, ..) =
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
arg_values.push(value.flatten());
}

// func(x, ...) -> x.func(...)
let (first, rest) = arg_values.split_first_mut().unwrap();
first_arg_value = Some(first);
args.push(this_ptr.unwrap());
Expand All @@ -1407,7 +1418,7 @@ impl Engine {
#[cfg(feature = "debugging")]
self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?;

// func(x, ...) -> x.func(...)
// The first value is a placeholder (for later if it needs to be cloned)
arg_values.push(Dynamic::UNIT);

for expr in args_expr.iter().skip(1) {
Expand All @@ -1423,6 +1434,7 @@ impl Engine {
args.extend(arg_values.iter_mut());
} else {
// Turn it into a method call only if the object is not shared and not a simple value
// func(x, ...) -> x.func(...)
let (first, rest) = arg_values.split_first_mut().unwrap();
first_arg_value = Some(first);
let obj_ref = target.take_ref().expect("ref");
Expand Down

0 comments on commit 2474c1f

Please sign in to comment.