From babc0b5466cd6006f9d80ec733586ae9ca91a074 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 20 Dec 2022 16:52:55 +0800 Subject: [PATCH] Remove Dynamic::NULL, use .as_deref_mut() for this_ptr. --- src/api/call_fn.rs | 14 ++--- src/api/eval.rs | 3 +- src/api/run.rs | 3 +- src/eval/chaining.rs | 86 ++++++++++++++++++------------ src/eval/debugger.rs | 8 +-- src/eval/eval_context.rs | 29 ++++------ src/eval/expr.rs | 47 ++++++++++------- src/eval/stmt.rs | 82 +++++++++++++++++------------ src/func/call.rs | 111 +++++++++++++++++---------------------- src/func/script.rs | 13 +++-- src/optimizer.rs | 35 ++++++------ src/parser.rs | 3 +- src/serde/de.rs | 2 - src/serde/serialize.rs | 2 - src/types/dynamic.rs | 35 ------------ src/types/fn_ptr.rs | 17 +++--- 16 files changed, 235 insertions(+), 255 deletions(-) diff --git a/src/api/call_fn.rs b/src/api/call_fn.rs index 680b7a7e..28f0a405 100644 --- a/src/api/call_fn.rs +++ b/src/api/call_fn.rs @@ -219,17 +219,11 @@ impl Engine { let orig_lib_len = global.lib.len(); - let mut orig_tag = None; - - if let Some(value) = options.tag { - orig_tag = Some(mem::replace(&mut global.tag, value)); - } + let orig_tag = options.tag.map(|v| mem::replace(&mut global.tag, v)); + let mut this_ptr = options.this_ptr; global.lib.push(ast.shared_lib().clone()); - let mut no_this_ptr = Dynamic::NULL; - let this_ptr = options.this_ptr.unwrap_or(&mut no_this_ptr); - #[cfg(not(feature = "no_module"))] let orig_embedded_module_resolver = std::mem::replace( &mut global.embedded_module_resolver, @@ -264,7 +258,7 @@ impl Engine { global, caches, scope, - this_ptr, + this_ptr.as_deref_mut(), None, fn_def, args, @@ -279,7 +273,7 @@ impl Engine { if self.is_debugger_registered() { global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate; let node = &crate::ast::Stmt::Noop(Position::NONE); - self.run_debugger(global, caches, scope, this_ptr, node)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), node)?; } #[cfg(not(feature = "no_module"))] diff --git a/src/api/eval.rs b/src/api/eval.rs index 7955d1c0..d08915c4 100644 --- a/src/api/eval.rs +++ b/src/api/eval.rs @@ -250,9 +250,8 @@ impl Engine { #[cfg(feature = "debugging")] if self.is_debugger_registered() { global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate; - let mut this_ptr = Dynamic::NULL; let node = &crate::ast::Stmt::Noop(Position::NONE); - self.run_debugger(global, caches, scope, &mut this_ptr, node)?; + self.run_debugger(global, caches, scope, None, node)?; } Ok(r) }) diff --git a/src/api/run.rs b/src/api/run.rs index 4ed9caf5..e0f0b49c 100644 --- a/src/api/run.rs +++ b/src/api/run.rs @@ -131,9 +131,8 @@ impl Engine { #[cfg(feature = "debugging")] if self.is_debugger_registered() { global.debugger_mut().status = crate::eval::DebuggerStatus::Terminate; - let mut this_ptr = crate::Dynamic::NULL; let node = &crate::ast::Stmt::Noop(crate::Position::NONE); - self.run_debugger(global, caches, scope, &mut this_ptr, node)?; + self.run_debugger(global, caches, scope, None, node)?; } Ok(()) }) diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index 82b6551a..c69ba77b 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -340,7 +340,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, expr: &Expr, new_val: Option<(Dynamic, &OpAssignment)>, ) -> RhaiResult { @@ -379,7 +379,13 @@ impl Engine { } // All other patterns - evaluate the arguments chain _ => self.eval_dot_index_chain_arguments( - global, caches, scope, this_ptr, expr, rhs, idx_values, + global, + caches, + scope, + this_ptr.as_deref_mut(), + expr, + rhs, + idx_values, )?, } @@ -387,22 +393,13 @@ impl Engine { // id.??? or id[???] Expr::Variable(.., var_pos) => { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, lhs)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), lhs)?; self.track_operation(global, *var_pos)?; let target = &mut self.search_namespace(global, caches, scope, this_ptr, lhs)?; - let mut this_ptr = Dynamic::NULL; self.eval_dot_index_chain_raw( - global, - caches, - &mut this_ptr, - lhs, - expr, - target, - rhs, - idx_values, - new_val, + global, caches, None, lhs, expr, target, rhs, idx_values, new_val, ) } // {expr}.??? = ??? or {expr}[???] = ??? @@ -410,7 +407,7 @@ impl Engine { // {expr}.??? or {expr}[???] lhs_expr => { let value = self - .eval_expr(global, caches, scope, this_ptr, lhs_expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs_expr)? .flatten(); let obj_ptr = &mut value.into(); @@ -428,7 +425,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, parent: &Expr, expr: &Expr, idx_values: &mut FnArgsVec, @@ -440,12 +437,10 @@ impl Engine { match expr { #[cfg(not(feature = "no_object"))] Expr::MethodCall(x, ..) if chain_type == ChainType::Dotting && !x.is_qualified() => { - for arg_expr in &x.args { - idx_values.push( - self.get_arg_value(global, caches, scope, this_ptr, arg_expr)? - .0 - .flatten(), - ); + for expr in &x.args { + let arg_value = + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?; + idx_values.push(arg_value.0.flatten()); } } #[cfg(not(feature = "no_object"))] @@ -474,12 +469,15 @@ impl Engine { Expr::MethodCall(x, ..) if chain_type == ChainType::Dotting && !x.is_qualified() => { - for arg_expr in &x.args { - _arg_values.push( - self.get_arg_value(global, caches, scope, this_ptr, arg_expr)? - .0 - .flatten(), - ); + for expr in &x.args { + let arg_value = self.get_arg_value( + global, + caches, + scope, + this_ptr.as_deref_mut(), + expr, + )?; + _arg_values.push(arg_value.0.flatten()); } } #[cfg(not(feature = "no_object"))] @@ -493,7 +491,7 @@ impl Engine { #[cfg(not(feature = "no_index"))] _ if chain_type == ChainType::Indexing => { _arg_values.push( - self.eval_expr(global, caches, scope, this_ptr, lhs)? + self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs)? .flatten(), ); } @@ -530,7 +528,7 @@ impl Engine { &self, global: &mut GlobalRuntimeState, caches: &mut Caches, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, root: &Expr, parent: &Expr, target: &mut Target, @@ -560,7 +558,7 @@ impl Engine { if !parent.options().contains(ASTFlags::BREAK) => { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, parent)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), parent)?; let idx_val = &mut idx_values.pop().unwrap(); let mut idx_val_for_setter = idx_val.clone(); @@ -843,7 +841,13 @@ impl Engine { let val_target = &mut match x.lhs { Expr::Property(ref p, pos) => { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, _node)?; + self.run_debugger( + global, + caches, + scope, + this_ptr.as_deref_mut(), + _node, + )?; let index = &mut p.2.clone().into(); self.get_indexed_mut( @@ -854,7 +858,11 @@ impl Engine { Expr::MethodCall(ref x, pos) if !x.is_qualified() => { #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset( - global, caches, scope, this_ptr, _node, + global, + caches, + scope, + this_ptr.as_deref_mut(), + _node, )?; #[cfg(feature = "debugging")] auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset)); @@ -896,7 +904,13 @@ impl Engine { // xxx.prop[expr] | xxx.prop.expr Expr::Property(ref p, pos) => { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, _node)?; + self.run_debugger( + global, + caches, + scope, + this_ptr.as_deref_mut(), + _node, + )?; let ((getter, hash_get), (setter, hash_set), name) = &**p; let args = &mut [target.as_mut()]; @@ -972,7 +986,11 @@ impl Engine { let val = { #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset( - global, caches, scope, this_ptr, _node, + global, + caches, + scope, + this_ptr.as_deref_mut(), + _node, )?; #[cfg(feature = "debugging")] auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset)); diff --git a/src/eval/debugger.rs b/src/eval/debugger.rs index f1ffb39a..e852e46e 100644 --- a/src/eval/debugger.rs +++ b/src/eval/debugger.rs @@ -410,7 +410,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + this_ptr: Option<&mut Dynamic>, node: impl Into>, ) -> RhaiResultOf<()> { if self.is_debugger_registered() { @@ -435,7 +435,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + this_ptr: Option<&mut Dynamic>, node: impl Into>, ) -> RhaiResultOf> { if self.is_debugger_registered() { @@ -456,7 +456,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + this_ptr: Option<&mut Dynamic>, node: impl Into>, ) -> RhaiResultOf> { let node = node.into(); @@ -502,7 +502,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + this_ptr: Option<&mut Dynamic>, node: ASTNode<'a>, event: DebuggerEvent, ) -> Result, Box> { diff --git a/src/eval/eval_context.rs b/src/eval/eval_context.rs index d0ee3b10..66c4539f 100644 --- a/src/eval/eval_context.rs +++ b/src/eval/eval_context.rs @@ -17,7 +17,7 @@ pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't> { /// The current [`Scope`]. scope: &'s mut Scope<'ps>, /// The current bound `this` pointer, if any. - this_ptr: &'t mut Dynamic, + this_ptr: Option<&'t mut Dynamic>, } impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> { @@ -29,7 +29,7 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> { global: &'g mut GlobalRuntimeState, caches: &'c mut Caches, scope: &'s mut Scope<'ps>, - this_ptr: &'t mut Dynamic, + this_ptr: Option<&'t mut Dynamic>, ) -> Self { Self { engine, @@ -118,24 +118,16 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> { &self.global.lib } /// The current bound `this` pointer, if any. - #[inline] + #[inline(always)] #[must_use] pub fn this_ptr(&self) -> Option<&Dynamic> { - if self.this_ptr.is_null() { - None - } else { - Some(self.this_ptr) - } + self.this_ptr.as_deref() } /// Mutable reference to the current bound `this` pointer, if any. - #[inline] + #[inline(always)] #[must_use] pub fn this_ptr_mut(&mut self) -> Option<&mut Dynamic> { - if self.this_ptr.is_null() { - None - } else { - Some(self.this_ptr) - } + self.this_ptr.as_deref_mut() } /// The current nesting level of function calls. #[inline(always)] @@ -177,19 +169,20 @@ impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> { rewind_scope: bool, ) -> crate::RhaiResult { let expr: &crate::ast::Expr = expr; + let this_ptr = self.this_ptr.as_deref_mut(); match expr { - crate::ast::Expr::Stmt(statements) => self.engine.eval_stmt_block( + crate::ast::Expr::Stmt(stmts) => self.engine.eval_stmt_block( self.global, self.caches, self.scope, - self.this_ptr, - statements, + this_ptr, + stmts, rewind_scope, ), _ => self .engine - .eval_expr(self.global, self.caches, self.scope, self.this_ptr, expr), + .eval_expr(self.global, self.caches, self.scope, this_ptr, expr), } } } diff --git a/src/eval/expr.rs b/src/eval/expr.rs index d6981151..a87d91e0 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -53,7 +53,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &'s mut Scope, - this_ptr: &'s mut Dynamic, + this_ptr: Option<&'s mut Dynamic>, expr: &Expr, ) -> RhaiResultOf> { match expr { @@ -132,7 +132,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &'s mut Scope, - this_ptr: &'s mut Dynamic, + this_ptr: Option<&'s mut Dynamic>, expr: &Expr, ) -> RhaiResultOf> { // Make sure that the pointer indirection is taken only when absolutely necessary. @@ -142,10 +142,10 @@ impl Engine { Expr::Variable(v, None, ..) if v.0.is_none() && v.1.is_empty() && v.3 == KEYWORD_THIS => { - return if this_ptr.is_null() { - Err(ERR::ErrorUnboundThis(expr.position()).into()) - } else { + return if let Some(this_ptr) = this_ptr { Ok(this_ptr.into()) + } else { + Err(ERR::ErrorUnboundThis(expr.position()).into()) }; } @@ -223,7 +223,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, expr: &Expr, ) -> RhaiResult { // Coded this way for better branch prediction. @@ -233,7 +233,8 @@ impl Engine { // binary operators are also function calls. if let Expr::FnCall(x, pos) = expr { #[cfg(feature = "debugging")] - let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; + let reset = + self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), expr)?; #[cfg(feature = "debugging")] auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset)); @@ -247,16 +248,14 @@ impl Engine { // will cost more than the mis-predicted `match` branch. if let Expr::Variable(x, index, var_pos) = expr { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, expr)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), expr)?; self.track_operation(global, expr.position())?; return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS { - if this_ptr.is_null() { - ERR::ErrorUnboundThis(*var_pos).into() - } else { - Ok(this_ptr.clone()) - } + this_ptr + .ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into()) + .cloned() } else { self.search_namespace(global, caches, scope, this_ptr, expr) .map(Target::take_or_clone) @@ -264,7 +263,8 @@ impl Engine { } #[cfg(feature = "debugging")] - let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, expr)?; + let reset = + self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), expr)?; #[cfg(feature = "debugging")] auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset)); @@ -291,7 +291,7 @@ impl Engine { x.iter() .try_for_each(|expr| { let item = self - .eval_expr(global, caches, scope, this_ptr, expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .flatten(); op_info.pos = expr.start_position(); @@ -312,7 +312,13 @@ impl Engine { crate::Array::with_capacity(x.len()), |mut array, item_expr| { let value = self - .eval_expr(global, caches, scope, this_ptr, item_expr)? + .eval_expr( + global, + caches, + scope, + this_ptr.as_deref_mut(), + item_expr, + )? .flatten(); #[cfg(not(feature = "unchecked"))] @@ -344,7 +350,7 @@ impl Engine { x.0.iter() .try_fold(x.1.clone(), |mut map, (key, value_expr)| { let value = self - .eval_expr(global, caches, scope, this_ptr, value_expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), value_expr)? .flatten(); #[cfg(not(feature = "unchecked"))] @@ -367,7 +373,7 @@ impl Engine { } Expr::And(x, ..) => Ok((self - .eval_expr(global, caches, scope, this_ptr, &x.lhs)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)? .as_bool() .map_err(|typ| self.make_type_mismatch_err::(typ, x.lhs.position()))? && self @@ -377,7 +383,7 @@ impl Engine { .into()), Expr::Or(x, ..) => Ok((self - .eval_expr(global, caches, scope, this_ptr, &x.lhs)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)? .as_bool() .map_err(|typ| self.make_type_mismatch_err::(typ, x.lhs.position()))? || self @@ -387,7 +393,8 @@ impl Engine { .into()), Expr::Coalesce(x, ..) => { - let value = self.eval_expr(global, caches, scope, this_ptr, &x.lhs)?; + let value = + self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), &x.lhs)?; if value.is_unit() { self.eval_expr(global, caches, scope, this_ptr, &x.rhs) diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 9fef726f..7ef26bf4 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -32,7 +32,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, statements: &[Stmt], restore_orig_state: bool, ) -> RhaiResult { @@ -71,6 +71,8 @@ impl Engine { // Run the statements statements.iter().try_fold(Dynamic::UNIT, |_, stmt| { + let this_ptr = this_ptr.as_deref_mut(); + #[cfg(not(feature = "no_module"))] let imports_len = global.num_imports(); @@ -198,12 +200,13 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, stmt: &Stmt, rewind_scope: bool, ) -> RhaiResult { #[cfg(feature = "debugging")] - let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr, stmt)?; + let reset = + self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), stmt)?; #[cfg(feature = "debugging")] auto_restore!(global if Some(reset) => move |g| g.debugger_mut().reset_status(reset)); @@ -227,7 +230,7 @@ impl Engine { if let Expr::Variable(x, ..) = lhs { let rhs_val = self - .eval_expr(global, caches, scope, this_ptr, rhs)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), rhs)? .flatten(); let mut target = self.search_namespace(global, caches, scope, this_ptr, lhs)?; @@ -259,7 +262,7 @@ impl Engine { #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] { let rhs_val = self - .eval_expr(global, caches, scope, this_ptr, rhs)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), rhs)? .flatten() .intern_string(self); @@ -310,7 +313,7 @@ impl Engine { let (expr, if_block, else_block) = &**x; let guard_val = self - .eval_expr(global, caches, scope, this_ptr, expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .as_bool() .map_err(|typ| self.make_type_mismatch_err::(typ, expr.position()))?; @@ -337,7 +340,7 @@ impl Engine { let mut result = None; - let value = self.eval_expr(global, caches, scope, this_ptr, expr)?; + let value = self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)?; if value.is_hashable() { let hasher = &mut get_hasher(); @@ -354,7 +357,7 @@ impl Engine { let cond_result = match block.condition { Expr::BoolConstant(b, ..) => b, ref c => self - .eval_expr(global, caches, scope, this_ptr, c)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), c)? .as_bool() .map_err(|typ| { self.make_type_mismatch_err::(typ, c.position()) @@ -376,7 +379,7 @@ impl Engine { let cond_result = match block.condition { Expr::BoolConstant(b, ..) => b, ref c => self - .eval_expr(global, caches, scope, this_ptr, c)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), c)? .as_bool() .map_err(|typ| { self.make_type_mismatch_err::(typ, c.position()) @@ -409,14 +412,15 @@ impl Engine { } loop { - if let Err(err) = - self.eval_stmt_block(global, caches, scope, this_ptr, body, true) - { - match *err { + let this_ptr = this_ptr.as_deref_mut(); + + match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) { + Ok(..) => (), + Err(err) => match *err { ERR::LoopBreak(false, ..) => (), ERR::LoopBreak(true, value, ..) => break Ok(value), _ => break Err(err), - } + }, } } } @@ -427,7 +431,7 @@ impl Engine { loop { let condition = self - .eval_expr(global, caches, scope, this_ptr, expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .as_bool() .map_err(|typ| self.make_type_mismatch_err::(typ, expr.position()))?; @@ -439,14 +443,15 @@ impl Engine { continue; } - if let Err(err) = - self.eval_stmt_block(global, caches, scope, this_ptr, body, true) - { - match *err { + let this_ptr = this_ptr.as_deref_mut(); + + match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) { + Ok(..) => (), + Err(err) => match *err { ERR::LoopBreak(false, ..) => (), ERR::LoopBreak(true, value, ..) => break Ok(value), _ => break Err(err), - } + }, } } } @@ -458,19 +463,20 @@ impl Engine { loop { if !body.is_empty() { - if let Err(err) = - self.eval_stmt_block(global, caches, scope, this_ptr, body, true) - { - match *err { + let this_ptr = this_ptr.as_deref_mut(); + + match self.eval_stmt_block(global, caches, scope, this_ptr, body, true) { + Ok(..) => (), + Err(err) => match *err { ERR::LoopBreak(false, ..) => continue, ERR::LoopBreak(true, value, ..) => break Ok(value), _ => break Err(err), - } + }, } } let condition = self - .eval_expr(global, caches, scope, this_ptr, expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .as_bool() .map_err(|typ| self.make_type_mismatch_err::(typ, expr.position()))?; @@ -485,7 +491,7 @@ impl Engine { let (var_name, counter, expr, statements) = &**x; let iter_obj = self - .eval_expr(global, caches, scope, this_ptr, expr)? + .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), expr)? .flatten(); let iter_type = iter_obj.type_id(); @@ -566,6 +572,8 @@ impl Engine { continue; } + let this_ptr = this_ptr.as_deref_mut(); + match self.eval_stmt_block(global, caches, scope, this_ptr, statements, true) { Ok(_) => (), Err(err) => match *err { @@ -603,7 +611,14 @@ impl Engine { catch_block, } = &**x; - match self.eval_stmt_block(global, caches, scope, this_ptr, try_block, true) { + match self.eval_stmt_block( + global, + caches, + scope, + this_ptr.as_deref_mut(), + try_block, + true, + ) { r @ Ok(_) => r, Err(err) if err.is_pseudo_error() => Err(err), Err(err) if !err.is_catchable() => Err(err), @@ -650,6 +665,8 @@ impl Engine { scope.push(catch_var.name.clone(), err_value); } + let this_ptr = this_ptr.as_deref_mut(); + self.eval_stmt_block(global, caches, scope, this_ptr, catch_block, true) .map(|_| Dynamic::UNIT) .map_err(|result_err| match *result_err { @@ -707,7 +724,8 @@ impl Engine { nesting_level: global.scope_level, will_shadow, }; - let context = EvalContext::new(self, global, caches, scope, this_ptr); + let context = + EvalContext::new(self, global, caches, scope, this_ptr.as_deref_mut()); if !filter(true, info, context)? { return Err(ERR::ErrorForbiddenVariable(var_name.to_string(), *pos).into()); @@ -866,7 +884,7 @@ impl Engine { /// Evaluate a list of statements with no `this` pointer. /// This is commonly used to evaluate a list of statements in an [`AST`][crate::AST] or a script function body. - #[inline] + #[inline(always)] pub(crate) fn eval_global_statements( &self, global: &mut GlobalRuntimeState, @@ -874,9 +892,7 @@ impl Engine { scope: &mut Scope, statements: &[Stmt], ) -> RhaiResult { - let mut this_ptr = Dynamic::NULL; - - self.eval_stmt_block(global, caches, scope, &mut this_ptr, statements, false) + self.eval_stmt_block(global, caches, scope, None, statements, false) .or_else(|err| match *err { ERR::Return(out, ..) => Ok(out), ERR::LoopBreak(..) => { diff --git a/src/func/call.rs b/src/func/call.rs index f64e7dfa..3724e2d6 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -438,7 +438,6 @@ impl Engine { }; if trigger { let scope = &mut Scope::new(); - let mut this_ptr = Dynamic::NULL; let node = crate::ast::Stmt::Noop(pos); let node = (&node).into(); let event = match _result { @@ -446,10 +445,9 @@ impl Engine { Err(ref err) => DebuggerEvent::FunctionExitWithError(err), }; - if let Err(err) = - self.run_debugger_raw(global, caches, scope, &mut this_ptr, node, event) - { - _result = Err(err); + match self.run_debugger_raw(global, caches, scope, None, node, event) { + Ok(..) => (), + Err(err) => _result = Err(err), } } @@ -676,7 +674,15 @@ impl Engine { let (first_arg, rest_args) = _args.split_first_mut().unwrap(); self.call_script_fn( - global, caches, scope, first_arg, environ, f, rest_args, true, pos, + global, + caches, + scope, + Some(first_arg), + environ, + f, + rest_args, + true, + pos, ) } else { // Normal call of script function @@ -691,19 +697,7 @@ impl Engine { auto_restore!(args = (_args) if swap => move |a| backup.restore_first_arg(a)); - let mut this_ptr = Dynamic::NULL; - - self.call_script_fn( - global, - caches, - scope, - &mut this_ptr, - environ, - f, - args, - true, - pos, - ) + self.call_script_fn(global, caches, scope, None, environ, f, args, true, pos) } .map(|r| (r, false)); } @@ -724,7 +718,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + this_ptr: Option<&mut Dynamic>, arg_expr: &Expr, ) -> RhaiResultOf<(Dynamic, Position)> { // Literal values @@ -782,14 +776,12 @@ impl Engine { #[cfg(not(feature = "no_function"))] if let Some(fn_def) = fn_ptr.fn_def() { if fn_def.params.len() == args.len() { - let mut this_ptr = Dynamic::NULL; - return self .call_script_fn( global, caches, &mut Scope::new(), - &mut this_ptr, + None, fn_ptr.encapsulated_environ(), fn_def, args, @@ -876,7 +868,7 @@ impl Engine { global, caches, &mut Scope::new(), - target, + Some(target), _environ.as_deref(), &fn_def, args, @@ -1018,7 +1010,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, fn_name: &str, op_token: Token, first_arg: Option<&Expr>, @@ -1042,7 +1034,7 @@ impl Engine { KEYWORD_FN_PTR_CALL if total_args >= 1 => { let arg = first_arg.unwrap(); let (arg_value, arg_pos) = - self.get_arg_value(global, caches, scope, this_ptr, arg)?; + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), arg)?; if !arg_value.is_fnptr() { let typ = self.map_type_name(arg_value.type_name()); @@ -1074,23 +1066,17 @@ impl Engine { .into_iter() .map(Ok) .chain(a_expr.iter().map(|expr| -> Result<_, RhaiError> { + let this_ptr = this_ptr.as_deref_mut(); self.get_arg_value(global, caches, scope, this_ptr, expr) .map(|(v, ..)| v) })) .collect::>>()?; let args = &mut arg_values.iter_mut().collect::>(); - let mut this_ptr = Dynamic::NULL; + let scope = &mut Scope::new(); + let environ = _environ.as_deref(); return self.call_script_fn( - global, - caches, - &mut Scope::new(), - &mut this_ptr, - _environ.as_deref(), - &fn_def, - args, - true, - pos, + global, caches, scope, None, environ, &fn_def, args, true, pos, ); } } @@ -1134,7 +1120,7 @@ impl Engine { KEYWORD_FN_PTR_CURRY if total_args > 1 => { let first = first_arg.unwrap(); let (arg_value, arg_pos) = - self.get_arg_value(global, caches, scope, this_ptr, first)?; + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), first)?; if !arg_value.is_fnptr() { let typ = self.map_type_name(arg_value.type_name()); @@ -1145,7 +1131,8 @@ impl Engine { // Append the new curried arguments to the existing list. a_expr.iter().try_for_each(|expr| -> Result<_, RhaiError> { - let (value, ..) = self.get_arg_value(global, caches, scope, this_ptr, expr)?; + let (value, ..) = + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?; fn_ptr.add_curry(value); Ok(()) })?; @@ -1157,7 +1144,8 @@ impl Engine { #[cfg(not(feature = "no_closure"))] crate::engine::KEYWORD_IS_SHARED if total_args == 1 => { let arg = first_arg.unwrap(); - let (arg_value, ..) = self.get_arg_value(global, caches, scope, this_ptr, arg)?; + let (arg_value, ..) = + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), arg)?; return Ok(arg_value.is_shared().into()); } @@ -1166,7 +1154,7 @@ impl Engine { crate::engine::KEYWORD_IS_DEF_FN if total_args == 2 => { let first = first_arg.unwrap(); let (arg_value, arg_pos) = - self.get_arg_value(global, caches, scope, this_ptr, first)?; + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), first)?; let fn_name = arg_value .into_immutable_string() @@ -1258,7 +1246,7 @@ impl Engine { .copied() .chain(a_expr.iter()) .try_for_each(|expr| { - self.get_arg_value(global, caches, scope, this_ptr, expr) + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) .map(|(value, ..)| arg_values.push(value.flatten())) })?; args.extend(curry.iter_mut()); @@ -1286,11 +1274,11 @@ impl Engine { let first_expr = first_arg.unwrap(); #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, first_expr)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), first_expr)?; // func(x, ...) -> x.func(...) a_expr.iter().try_for_each(|expr| { - self.get_arg_value(global, caches, scope, this_ptr, expr) + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) .map(|(value, ..)| arg_values.push(value.flatten())) })?; @@ -1317,7 +1305,7 @@ impl Engine { .into_iter() .chain(a_expr.iter()) .try_for_each(|expr| { - self.get_arg_value(global, caches, scope, this_ptr, expr) + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) .map(|(value, ..)| arg_values.push(value.flatten())) })?; args.extend(curry.iter_mut()); @@ -1339,7 +1327,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, namespace: &crate::ast::Namespace, fn_name: &str, args_expr: &[Expr], @@ -1358,13 +1346,19 @@ impl Engine { // and avoid cloning the value if !args_expr.is_empty() && args_expr[0].is_variable_access(true) { #[cfg(feature = "debugging")] - self.run_debugger(global, caches, scope, this_ptr, &args_expr[0])?; + self.run_debugger( + global, + caches, + scope, + this_ptr.as_deref_mut(), + &args_expr[0], + )?; // func(x, ...) -> x.func(...) arg_values.push(Dynamic::UNIT); args_expr.iter().skip(1).try_for_each(|expr| { - self.get_arg_value(global, caches, scope, this_ptr, expr) + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) .map(|(value, ..)| arg_values.push(value.flatten())) })?; @@ -1393,7 +1387,7 @@ impl Engine { } else { // func(..., ...) or func(mod::x, ...) args_expr.iter().try_for_each(|expr| { - self.get_arg_value(global, caches, scope, this_ptr, expr) + self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr) .map(|(value, ..)| arg_values.push(value.flatten())) })?; args.extend(arg_values.iter_mut()); @@ -1466,25 +1460,14 @@ impl Engine { #[cfg(not(feature = "no_function"))] Some(func) if func.is_script() => { let f = func.get_script_fn_def().expect("script-defined function"); - let environ = func.get_encapsulated_environ(); + let environ = func.get_encapsulated_environ(); let scope = &mut Scope::new(); - let mut this_ptr = Dynamic::NULL; let orig_source = mem::replace(&mut global.source, module.id_raw().cloned()); auto_restore!(global => move |g| g.source = orig_source); - self.call_script_fn( - global, - caches, - scope, - &mut this_ptr, - environ, - f, - args, - true, - pos, - ) + self.call_script_fn(global, caches, scope, None, environ, f, args, true, pos) } Some(f) if f.is_plugin_fn() => { @@ -1581,7 +1564,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, expr: &FnCallExpr, pos: Position, ) -> RhaiResult { @@ -1601,7 +1584,7 @@ impl Engine { // Short-circuit native unary operator call if under Fast Operators mode if op_token == Token::Bang && self.fast_operators() && args.len() == 1 { let mut value = self - .get_arg_value(global, caches, scope, this_ptr, &args[0])? + .get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])? .0 .flatten(); @@ -1617,7 +1600,7 @@ impl Engine { // Short-circuit native binary operator call if under Fast Operators mode if op_token != NO_TOKEN && self.fast_operators() && args.len() == 2 { let mut lhs = self - .get_arg_value(global, caches, scope, this_ptr, &args[0])? + .get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), &args[0])? .0 .flatten(); diff --git a/src/func/script.rs b/src/func/script.rs index 03482ffc..06be7d54 100644 --- a/src/func/script.rs +++ b/src/func/script.rs @@ -28,7 +28,7 @@ impl Engine { global: &mut GlobalRuntimeState, caches: &mut Caches, scope: &mut Scope, - this_ptr: &mut Dynamic, + mut this_ptr: Option<&mut Dynamic>, _environ: Option<&EncapsulatedEnviron>, fn_def: &ScriptFnDef, args: &mut FnCallArgs, @@ -108,12 +108,19 @@ impl Engine { #[cfg(feature = "debugging")] if self.is_debugger_registered() { let node = crate::ast::Stmt::Noop(fn_def.body.position()); - self.run_debugger(global, caches, scope, this_ptr, &node)?; + self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), &node)?; } // Evaluate the function let mut _result: RhaiResult = self - .eval_stmt_block(global, caches, scope, this_ptr, &fn_def.body, rewind_scope) + .eval_stmt_block( + global, + caches, + scope, + this_ptr.as_deref_mut(), + &fn_def.body, + rewind_scope, + ) .or_else(|err| match *err { // Convert return statement to return value ERR::Return(x, ..) => Ok(x), diff --git a/src/optimizer.rs b/src/optimizer.rs index 6c7cc76f..6bf6f280 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -54,7 +54,7 @@ struct OptimizerState<'a> { /// Has the [`AST`] been changed during this pass? changed: bool, /// Collection of constants to use for eager function evaluations. - variables: StaticVec<(Identifier, AccessMode, Dynamic)>, + variables: StaticVec<(Identifier, AccessMode, Option)>, /// Activate constants propagation? propagate_constants: bool, /// An [`Engine`] instance for eager function evaluation. @@ -115,7 +115,12 @@ impl<'a> OptimizerState<'a> { } /// Add a new variable to the list. #[inline(always)] - pub fn push_var(&mut self, name: impl Into, access: AccessMode, value: Dynamic) { + pub fn push_var( + &mut self, + name: impl Into, + access: AccessMode, + value: Option, + ) { self.variables.push((name.into(), access, value)); } /// Look up a constant from the list. @@ -129,8 +134,7 @@ impl<'a> OptimizerState<'a> { if n == name { return match access { AccessMode::ReadWrite => None, - AccessMode::ReadOnly if value.is_null() => None, - AccessMode::ReadOnly => Some(value), + AccessMode::ReadOnly => value.as_ref(), }; } } @@ -144,7 +148,7 @@ impl<'a> OptimizerState<'a> { fn_name: &str, op_token: Token, arg_values: &mut [Dynamic], - ) -> Dynamic { + ) -> Option { self.engine .exec_native_fn_call( &mut self.global, @@ -156,7 +160,8 @@ impl<'a> OptimizerState<'a> { false, Position::NONE, ) - .map_or(Dynamic::NULL, |(v, ..)| v) + .ok() + .map(|(v, ..)| v) } } @@ -234,13 +239,13 @@ fn optimize_stmt_block( state.push_var( x.0.as_str(), AccessMode::ReadOnly, - x.1.get_literal_value().unwrap_or(Dynamic::NULL), + x.1.get_literal_value(), ); } } else { // Add variables into the state optimize_expr(&mut x.1, state, false); - state.push_var(x.0.as_str(), AccessMode::ReadWrite, Dynamic::NULL); + state.push_var(x.0.as_str(), AccessMode::ReadWrite, None); } } // Optimize the statement @@ -1190,15 +1195,15 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) { let arg_values = &mut x.args.iter().map(Expr::get_literal_value).collect::>>().unwrap(); let result = match x.name.as_str() { - KEYWORD_TYPE_OF if arg_values.len() == 1 => state.engine.map_type_name(arg_values[0].type_name()).into(), + KEYWORD_TYPE_OF if arg_values.len() == 1 => Some(state.engine.map_type_name(arg_values[0].type_name()).into()), #[cfg(not(feature = "no_closure"))] - crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Dynamic::FALSE, + crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Some(Dynamic::FALSE), _ => state.call_fn_with_constant_arguments(&x.name, x.op_token.clone(), arg_values) }; - if !result.is_null() { + if let Some(r) = result { state.set_dirty(); - *expr = Expr::from_dynamic(result, *pos); + *expr = Expr::from_dynamic(r, *pos); return; } } @@ -1303,15 +1308,15 @@ impl Engine { // Add constants from global modules for (name, value) in self.global_modules.iter().rev().flat_map(|m| m.iter_var()) { - state.push_var(name, AccessMode::ReadOnly, value.clone()); + state.push_var(name, AccessMode::ReadOnly, Some(value.clone())); } // Add constants and variables from the scope for (name, constant, value) in scope.iter() { if constant { - state.push_var(name, AccessMode::ReadOnly, value); + state.push_var(name, AccessMode::ReadOnly, Some(value)); } else { - state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL); + state.push_var(name, AccessMode::ReadWrite, None); } } diff --git a/src/parser.rs b/src/parser.rs index 8dceca1b..469c1ff5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2890,8 +2890,7 @@ impl Engine { will_shadow, }; let caches = &mut Caches::new(); - let mut this_ptr = Dynamic::NULL; - let context = EvalContext::new(self, global, caches, stack, &mut this_ptr); + let context = EvalContext::new(self, global, caches, stack, None); match filter(false, info, context) { Ok(true) => (), diff --git a/src/serde/de.rs b/src/serde/de.rs index 2cf9ec3f..30a1de6f 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -125,8 +125,6 @@ impl<'de> Deserializer<'de> for DynamicDeserializer<'de> { fn deserialize_any>(self, visitor: V) -> RhaiResultOf { match self.0 .0 { - Union::Null => unreachable!(), - Union::Unit(..) => self.deserialize_unit(visitor), Union::Bool(..) => self.deserialize_bool(visitor), Union::Str(..) => self.deserialize_str(visitor), diff --git a/src/serde/serialize.rs b/src/serde/serialize.rs index 4cebe930..34595826 100644 --- a/src/serde/serialize.rs +++ b/src/serde/serialize.rs @@ -15,8 +15,6 @@ use crate::types::dynamic::Variant; impl Serialize for Dynamic { fn serialize(&self, ser: S) -> Result { match self.0 { - Union::Null => unreachable!(), - Union::Unit(..) => ser.serialize_unit(), Union::Bool(x, ..) => ser.serialize_bool(x), Union::Str(ref s, ..) => ser.serialize_str(s.as_str()), diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index 47423128..57cd0440 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -57,9 +57,6 @@ pub struct Dynamic(pub(crate) Union); /// Most variants are boxed to reduce the size. #[must_use] pub enum Union { - /// An error value which should not exist. - Null, - /// The Unit value - (). Unit((), Tag, AccessMode), /// A boolean value. @@ -187,8 +184,6 @@ impl Dynamic { #[must_use] pub const fn tag(&self) -> Tag { match self.0 { - Union::Null => unreachable!(), - Union::Unit(_, tag, _) | Union::Bool(_, tag, _) | Union::Str(_, tag, _) @@ -214,8 +209,6 @@ impl Dynamic { /// Attach arbitrary data to this [`Dynamic`]. pub fn set_tag(&mut self, value: Tag) -> &mut Self { match self.0 { - Union::Null => unreachable!(), - Union::Unit(_, ref mut tag, _) | Union::Bool(_, ref mut tag, _) | Union::Str(_, ref mut tag, _) @@ -239,12 +232,6 @@ impl Dynamic { } self } - /// Is this [`Dynamic`] null? - #[inline(always)] - #[must_use] - pub(crate) const fn is_null(&self) -> bool { - matches!(self.0, Union::Null) - } /// Does this [`Dynamic`] hold a variant data type instead of one of the supported system /// primitive types? #[inline(always)] @@ -334,8 +321,6 @@ impl Dynamic { #[must_use] pub fn type_id(&self) -> TypeId { match self.0 { - Union::Null => unreachable!(), - Union::Unit(..) => TypeId::of::<()>(), Union::Bool(..) => TypeId::of::(), Union::Str(..) => TypeId::of::(), @@ -370,8 +355,6 @@ impl Dynamic { #[must_use] pub fn type_name(&self) -> &'static str { match self.0 { - Union::Null => unreachable!(), - Union::Unit(..) => "()", Union::Bool(..) => "bool", Union::Str(..) => "string", @@ -416,8 +399,6 @@ impl Hash for Dynamic { mem::discriminant(&self.0).hash(state); match self.0 { - Union::Null => unreachable!(), - Union::Unit(..) => (), Union::Bool(ref b, ..) => b.hash(state), Union::Str(ref s, ..) => s.hash(state), @@ -449,8 +430,6 @@ impl Hash for Dynamic { impl fmt::Display for Dynamic { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { - Union::Null => unreachable!(), - Union::Unit(..) => Ok(()), Union::Bool(ref v, ..) => fmt::Display::fmt(v, f), Union::Str(ref v, ..) => fmt::Display::fmt(v, f), @@ -544,8 +523,6 @@ impl fmt::Debug for Dynamic { #[inline(never)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { - Union::Null => unreachable!(), - Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f), Union::Bool(ref v, ..) => fmt::Debug::fmt(v, f), Union::Str(ref v, ..) => fmt::Debug::fmt(v, f), @@ -657,8 +634,6 @@ impl Clone for Dynamic { /// The cloned copy is marked read-write even if the original is read-only. fn clone(&self) -> Self { match self.0 { - Union::Null => unreachable!(), - Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)), Union::Bool(v, tag, ..) => Self(Union::Bool(v, tag, ReadWrite)), Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)), @@ -705,9 +680,6 @@ use std::f32::consts as FloatConstants; use std::f64::consts as FloatConstants; impl Dynamic { - /// A [`Dynamic`] containing a `null`. - pub(crate) const NULL: Self = Self(Union::Null); - /// A [`Dynamic`] containing a `()`. pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite)); /// A [`Dynamic`] containing a `true`. @@ -921,8 +893,6 @@ impl Dynamic { #[must_use] pub(crate) const fn access_mode(&self) -> AccessMode { match self.0 { - Union::Null => unreachable!(), - Union::Unit(.., access) | Union::Bool(.., access) | Union::Str(.., access) @@ -948,8 +918,6 @@ impl Dynamic { /// Set the [`AccessMode`] for this [`Dynamic`]. pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self { match self.0 { - Union::Null => unreachable!(), - Union::Unit(.., ref mut access) | Union::Bool(.., ref mut access) | Union::Str(.., ref mut access) @@ -1138,7 +1106,6 @@ impl Dynamic { let _access = self.access_mode(); match self.0 { - Union::Null => unreachable!(), Union::Shared(..) => self, _ => Self(Union::Shared( crate::Locked::new(self).into(), @@ -1584,7 +1551,6 @@ impl Dynamic { } match self.0 { - Union::Null => unreachable!(), Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::(), #[cfg(not(feature = "no_closure"))] Union::Shared(..) => None, @@ -1683,7 +1649,6 @@ impl Dynamic { } match self.0 { - Union::Null => unreachable!(), Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::(), #[cfg(not(feature = "no_closure"))] Union::Shared(..) => None, diff --git a/src/types/fn_ptr.rs b/src/types/fn_ptr.rs index 5aa6e4eb..c307c912 100644 --- a/src/types/fn_ptr.rs +++ b/src/types/fn_ptr.rs @@ -298,19 +298,19 @@ impl FnPtr { // Linked to scripted function? #[cfg(not(feature = "no_function"))] - if let Some(fn_def) = self.fn_def() { + if let Some(ref fn_def) = self.fn_def { if fn_def.params.len() == args.len() { let global = &mut context.global_runtime_state().clone(); global.level += 1; let caches = &mut crate::eval::Caches::new(); - let mut null_ptr = Dynamic::NULL; + let mut this_ptr = this_ptr; return context.engine().call_script_fn( global, caches, &mut crate::Scope::new(), - this_ptr.unwrap_or(&mut null_ptr), + this_ptr.as_deref_mut(), self.encapsulated_environ(), &fn_def, args, @@ -348,8 +348,8 @@ impl FnPtr { #[cfg(not(feature = "no_function"))] #[inline(always)] #[must_use] - pub(crate) fn fn_def(&self) -> Option<&Shared> { - self.fn_def.as_ref() + pub(crate) fn fn_def(&self) -> Option<&crate::ast::ScriptFnDef> { + self.fn_def.as_deref() } /// Set a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef]. #[cfg(not(feature = "no_function"))] @@ -410,12 +410,11 @@ impl FnPtr { extras: [Dynamic; E], ) -> RhaiResult { #[cfg(not(feature = "no_function"))] - { - let arity = self.fn_def().map(|f| f.params.len()).unwrap_or(0); - + if let Some(arity) = self.fn_def().map(|f| f.params.len()) { if arity == N { return self.call_raw(&ctx, None, items); - } else if arity == N + E { + } + if arity == N + E { let mut items2 = FnArgsVec::with_capacity(items.len() + extras.len()); items2.extend(IntoIterator::into_iter(items)); items2.extend(IntoIterator::into_iter(extras));