Add Dynamic::NULL to simplify this pointer binding.
This commit is contained in:
parent
6053aa1641
commit
8f128f37f0
@ -250,7 +250,9 @@ impl Engine {
|
|||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let statements = ast.statements();
|
let statements = ast.statements();
|
||||||
let lib = &[AsRef::<SharedModule>::as_ref(ast).clone()];
|
let lib = &[AsRef::<SharedModule>::as_ref(ast).clone()];
|
||||||
let mut this_ptr = this_ptr;
|
|
||||||
|
let mut no_this_ptr = Dynamic::NULL;
|
||||||
|
let mut this_ptr = this_ptr.unwrap_or(&mut no_this_ptr);
|
||||||
|
|
||||||
let orig_scope_len = scope.len();
|
let orig_scope_len = scope.len();
|
||||||
|
|
||||||
|
@ -198,8 +198,10 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
||||||
];
|
];
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
let node = &crate::ast::Stmt::Noop(Position::NONE);
|
let node = &crate::ast::Stmt::Noop(Position::NONE);
|
||||||
self.run_debugger(global, caches, lib, 0, scope, &mut None, node)?;
|
|
||||||
|
self.run_debugger(global, caches, lib, 0, scope, &mut this, node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let typ = self.map_type_name(result.type_name());
|
let typ = self.map_type_name(result.type_name());
|
||||||
|
@ -141,8 +141,9 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
|
||||||
];
|
];
|
||||||
|
let mut this = crate::Dynamic::NULL;
|
||||||
let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
|
let node = &crate::ast::Stmt::Noop(crate::Position::NONE);
|
||||||
self.run_debugger(global, caches, lib, 0, scope, &mut None, node)?;
|
self.run_debugger(global, caches, lib, 0, scope, &mut this, node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -45,7 +45,7 @@ impl Engine {
|
|||||||
caches: &mut Caches,
|
caches: &mut Caches,
|
||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
target: &mut Target,
|
target: &mut Target,
|
||||||
root: (&str, Position),
|
root: (&str, Position),
|
||||||
_parent: &Expr,
|
_parent: &Expr,
|
||||||
@ -573,7 +573,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
new_val: &mut Option<(Dynamic, &OpAssignment)>,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
@ -630,9 +630,10 @@ impl Engine {
|
|||||||
|
|
||||||
let obj_ptr = &mut target;
|
let obj_ptr = &mut target;
|
||||||
let root = (x.3.as_str(), *var_pos);
|
let root = (x.3.as_str(), *var_pos);
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
self.eval_dot_index_chain_helper(
|
self.eval_dot_index_chain_helper(
|
||||||
global, caches, lib, level, &mut None, obj_ptr, root, expr, options, rhs,
|
global, caches, lib, level, &mut this, obj_ptr, root, expr, options, rhs,
|
||||||
idx_values, chain_type, new_val,
|
idx_values, chain_type, new_val,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -664,7 +665,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
parent_options: ASTFlags,
|
parent_options: ASTFlags,
|
||||||
parent_chain_type: ChainType,
|
parent_chain_type: ChainType,
|
||||||
|
@ -416,7 +416,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
node: impl Into<ASTNode<'a>>,
|
node: impl Into<ASTNode<'a>>,
|
||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
if self.debugger.is_some() {
|
if self.debugger.is_some() {
|
||||||
@ -443,7 +443,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
node: impl Into<ASTNode<'a>>,
|
node: impl Into<ASTNode<'a>>,
|
||||||
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
||||||
if self.debugger.is_some() {
|
if self.debugger.is_some() {
|
||||||
@ -466,7 +466,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
node: impl Into<ASTNode<'a>>,
|
node: impl Into<ASTNode<'a>>,
|
||||||
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
) -> RhaiResultOf<Option<DebuggerStatus>> {
|
||||||
let node = node.into();
|
let node = node.into();
|
||||||
@ -513,7 +513,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
node: ASTNode<'a>,
|
node: ASTNode<'a>,
|
||||||
event: DebuggerEvent,
|
event: DebuggerEvent,
|
||||||
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
|
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {
|
||||||
|
@ -8,7 +8,7 @@ use std::prelude::v1::*;
|
|||||||
/// Context of a script evaluation process.
|
/// Context of a script evaluation process.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
|
||||||
/// The current [`Engine`].
|
/// The current [`Engine`].
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
/// The current [`Scope`].
|
/// The current [`Scope`].
|
||||||
@ -20,12 +20,12 @@ pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
|||||||
/// The current stack of imported [modules][Module].
|
/// The current stack of imported [modules][Module].
|
||||||
lib: &'a [SharedModule],
|
lib: &'a [SharedModule],
|
||||||
/// The current bound `this` pointer, if any.
|
/// The current bound `this` pointer, if any.
|
||||||
this_ptr: &'t mut Option<&'pt mut Dynamic>,
|
this_ptr: &'t mut Dynamic,
|
||||||
/// The current nesting level of function calls.
|
/// The current nesting level of function calls.
|
||||||
level: usize,
|
level: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
impl<'a, 's, 'ps, 'g, 'c, 't> EvalContext<'a, 's, 'ps, 'g, 'c, 't> {
|
||||||
/// Create a new [`EvalContext`].
|
/// Create a new [`EvalContext`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -36,7 +36,7 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
|||||||
lib: &'a [SharedModule],
|
lib: &'a [SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &'s mut Scope<'ps>,
|
scope: &'s mut Scope<'ps>,
|
||||||
this_ptr: &'t mut Option<&'pt mut Dynamic>,
|
this_ptr: &'t mut Dynamic,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine,
|
engine,
|
||||||
@ -104,8 +104,8 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
|||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn global_runtime_state_mut(&mut self) -> &mut &'g mut GlobalRuntimeState {
|
pub fn global_runtime_state_mut(&mut self) -> &mut GlobalRuntimeState {
|
||||||
&mut self.global
|
self.global
|
||||||
}
|
}
|
||||||
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -121,16 +121,24 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
|
|||||||
self.lib
|
self.lib
|
||||||
}
|
}
|
||||||
/// The current bound `this` pointer, if any.
|
/// The current bound `this` pointer, if any.
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn this_ptr(&self) -> Option<&Dynamic> {
|
pub fn this_ptr(&self) -> Option<&Dynamic> {
|
||||||
self.this_ptr.as_ref().map(|v| &**v)
|
if self.this_ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.this_ptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Mutable reference to the current bound `this` pointer, if any.
|
/// Mutable reference to the current bound `this` pointer, if any.
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
|
pub fn this_ptr_mut(&mut self) -> Option<&mut Dynamic> {
|
||||||
self.this_ptr
|
if self.this_ptr.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.this_ptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// The current nesting level of function calls.
|
/// The current nesting level of function calls.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -54,7 +54,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &'s mut Scope,
|
scope: &'s mut Scope,
|
||||||
this_ptr: &'s mut Option<&mut Dynamic>,
|
this_ptr: &'s mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
) -> RhaiResultOf<(Target<'s>, Position)> {
|
) -> RhaiResultOf<(Target<'s>, Position)> {
|
||||||
match expr {
|
match expr {
|
||||||
@ -140,7 +140,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &'s mut Scope,
|
scope: &'s mut Scope,
|
||||||
this_ptr: &'s mut Option<&mut Dynamic>,
|
this_ptr: &'s mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
) -> RhaiResultOf<(Target<'s>, Position)> {
|
) -> RhaiResultOf<(Target<'s>, Position)> {
|
||||||
// Make sure that the pointer indirection is taken only when absolutely necessary.
|
// Make sure that the pointer indirection is taken only when absolutely necessary.
|
||||||
@ -148,10 +148,11 @@ impl Engine {
|
|||||||
let (index, var_pos) = match expr {
|
let (index, var_pos) = match expr {
|
||||||
// Check if the variable is `this`
|
// Check if the variable is `this`
|
||||||
Expr::Variable(v, None, pos) if v.0.is_none() && v.3 == KEYWORD_THIS => {
|
Expr::Variable(v, None, pos) if v.0.is_none() && v.3 == KEYWORD_THIS => {
|
||||||
return this_ptr.as_mut().map_or_else(
|
return if this_ptr.is_null() {
|
||||||
|| Err(ERR::ErrorUnboundThis(*pos).into()),
|
Err(ERR::ErrorUnboundThis(*pos).into())
|
||||||
|val| Ok(((*val).into(), *pos)),
|
} else {
|
||||||
)
|
Ok((this_ptr.into(), *pos))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
_ if global.always_search_scope => (0, expr.start_position()),
|
_ if global.always_search_scope => (0, expr.start_position()),
|
||||||
Expr::Variable(.., Some(i), pos) => (i.get() as usize, *pos),
|
Expr::Variable(.., Some(i), pos) => (i.get() as usize, *pos),
|
||||||
@ -224,7 +225,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
// Coded this way for better branch prediction.
|
// Coded this way for better branch prediction.
|
||||||
@ -256,10 +257,11 @@ impl Engine {
|
|||||||
self.track_operation(global, expr.position())?;
|
self.track_operation(global, expr.position())?;
|
||||||
|
|
||||||
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
||||||
this_ptr
|
if this_ptr.is_null() {
|
||||||
.as_deref()
|
ERR::ErrorUnboundThis(*var_pos).into()
|
||||||
.cloned()
|
} else {
|
||||||
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
|
Ok(this_ptr.clone())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.search_namespace(global, caches, lib, level, scope, this_ptr, expr)
|
self.search_namespace(global, caches, lib, level, scope, this_ptr, expr)
|
||||||
.map(|(val, ..)| val.take_or_clone())
|
.map(|(val, ..)| val.take_or_clone())
|
||||||
|
@ -29,7 +29,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
statements: &[Stmt],
|
statements: &[Stmt],
|
||||||
restore_orig_state: bool,
|
restore_orig_state: bool,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
@ -203,7 +203,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
rewind_scope: bool,
|
rewind_scope: bool,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
@ -912,8 +912,10 @@ impl Engine {
|
|||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
statements: &[Stmt],
|
statements: &[Stmt],
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
self.eval_stmt_block(
|
self.eval_stmt_block(
|
||||||
global, caches, lib, level, scope, &mut None, statements, false,
|
global, caches, lib, level, scope, &mut this, statements, false,
|
||||||
)
|
)
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
ERR::Return(out, ..) => Ok(out),
|
ERR::Return(out, ..) => Ok(out),
|
||||||
|
@ -11,8 +11,8 @@ use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
|
|||||||
use crate::tokenizer::{is_valid_function_name, Token};
|
use crate::tokenizer::{is_valid_function_name, Token};
|
||||||
use crate::types::RestoreOnDrop;
|
use crate::types::RestoreOnDrop;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString, SharedModule,
|
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString,
|
||||||
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, ERR,
|
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, SharedModule, ERR,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::hash_map::Entry;
|
||||||
@ -407,6 +407,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
if trigger {
|
if trigger {
|
||||||
let scope = &mut &mut Scope::new();
|
let scope = &mut &mut Scope::new();
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
let node = crate::ast::Stmt::Noop(pos);
|
let node = crate::ast::Stmt::Noop(pos);
|
||||||
let node = (&node).into();
|
let node = (&node).into();
|
||||||
let event = match _result {
|
let event = match _result {
|
||||||
@ -415,7 +416,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = self
|
if let Err(err) = self
|
||||||
.run_debugger_raw(global, caches, lib, level, scope, &mut None, node, event)
|
.run_debugger_raw(global, caches, lib, level, scope, &mut this, node, event)
|
||||||
{
|
{
|
||||||
_result = Err(err);
|
_result = Err(err);
|
||||||
}
|
}
|
||||||
@ -646,16 +647,7 @@ impl Engine {
|
|||||||
let (first_arg, rest_args) = args.split_first_mut().unwrap();
|
let (first_arg, rest_args) = args.split_first_mut().unwrap();
|
||||||
|
|
||||||
self.call_script_fn(
|
self.call_script_fn(
|
||||||
global,
|
global, caches, lib, level, scope, first_arg, func, rest_args, true, pos,
|
||||||
caches,
|
|
||||||
lib,
|
|
||||||
level,
|
|
||||||
scope,
|
|
||||||
&mut Some(*first_arg),
|
|
||||||
func,
|
|
||||||
rest_args,
|
|
||||||
true,
|
|
||||||
pos,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Normal call of script function
|
// Normal call of script function
|
||||||
@ -672,8 +664,10 @@ impl Engine {
|
|||||||
backup.restore_first_arg(a)
|
backup.restore_first_arg(a)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
self.call_script_fn(
|
self.call_script_fn(
|
||||||
global, caches, lib, level, scope, &mut None, func, args, true, pos,
|
global, caches, lib, level, scope, &mut this, func, args, true, pos,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.map(|r| (r, false));
|
.map(|r| (r, false));
|
||||||
@ -697,7 +691,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
arg_expr: &Expr,
|
arg_expr: &Expr,
|
||||||
) -> RhaiResultOf<(Dynamic, Position)> {
|
) -> RhaiResultOf<(Dynamic, Position)> {
|
||||||
// Literal values
|
// Literal values
|
||||||
@ -956,7 +950,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
op_token: Option<&Token>,
|
op_token: Option<&Token>,
|
||||||
first_arg: Option<&Expr>,
|
first_arg: Option<&Expr>,
|
||||||
@ -1247,7 +1241,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
namespace: &crate::ast::Namespace,
|
namespace: &crate::ast::Namespace,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
args_expr: &[Expr],
|
args_expr: &[Expr],
|
||||||
@ -1376,12 +1370,13 @@ impl Engine {
|
|||||||
Some(f) if f.is_script() => {
|
Some(f) if f.is_script() => {
|
||||||
let fn_def = f.get_script_fn_def().expect("script-defined function");
|
let fn_def = f.get_script_fn_def().expect("script-defined function");
|
||||||
let new_scope = &mut Scope::new();
|
let new_scope = &mut Scope::new();
|
||||||
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source);
|
let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source);
|
||||||
|
|
||||||
self.call_script_fn(
|
self.call_script_fn(
|
||||||
global, caches, lib, level, new_scope, &mut None, fn_def, &mut args, true, pos,
|
global, caches, lib, level, new_scope, &mut this, fn_def, &mut args, true, pos,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1474,7 +1469,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
expr: &FnCallExpr,
|
expr: &FnCallExpr,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
|
@ -29,7 +29,7 @@ impl Engine {
|
|||||||
lib: &[SharedModule],
|
lib: &[SharedModule],
|
||||||
level: usize,
|
level: usize,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Dynamic,
|
||||||
fn_def: &ScriptFnDef,
|
fn_def: &ScriptFnDef,
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
rewind_scope: bool,
|
rewind_scope: bool,
|
||||||
|
@ -50,7 +50,7 @@ struct OptimizerState<'a> {
|
|||||||
/// Has the [`AST`] been changed during this pass?
|
/// Has the [`AST`] been changed during this pass?
|
||||||
changed: bool,
|
changed: bool,
|
||||||
/// Collection of constants to use for eager function evaluations.
|
/// Collection of constants to use for eager function evaluations.
|
||||||
variables: StaticVec<(Identifier, AccessMode, Option<Dynamic>)>,
|
variables: StaticVec<(Identifier, AccessMode, Dynamic)>,
|
||||||
/// Activate constants propagation?
|
/// Activate constants propagation?
|
||||||
propagate_constants: bool,
|
propagate_constants: bool,
|
||||||
/// An [`Engine`] instance for eager function evaluation.
|
/// An [`Engine`] instance for eager function evaluation.
|
||||||
@ -108,12 +108,7 @@ impl<'a> OptimizerState<'a> {
|
|||||||
}
|
}
|
||||||
/// Add a new variable to the list.
|
/// Add a new variable to the list.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_var(
|
pub fn push_var(&mut self, name: impl Into<Identifier>, access: AccessMode, value: Dynamic) {
|
||||||
&mut self,
|
|
||||||
name: impl Into<Identifier>,
|
|
||||||
access: AccessMode,
|
|
||||||
value: Option<Dynamic>,
|
|
||||||
) {
|
|
||||||
self.variables.push((name.into(), access, value));
|
self.variables.push((name.into(), access, value));
|
||||||
}
|
}
|
||||||
/// Look up a constant from the list.
|
/// Look up a constant from the list.
|
||||||
@ -127,7 +122,8 @@ impl<'a> OptimizerState<'a> {
|
|||||||
if n == name {
|
if n == name {
|
||||||
return match access {
|
return match access {
|
||||||
AccessMode::ReadWrite => None,
|
AccessMode::ReadWrite => None,
|
||||||
AccessMode::ReadOnly => value.as_ref(),
|
AccessMode::ReadOnly if value.is_null() => None,
|
||||||
|
AccessMode::ReadOnly => Some(value),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +137,7 @@ impl<'a> OptimizerState<'a> {
|
|||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
op_token: Option<&Token>,
|
op_token: Option<&Token>,
|
||||||
arg_values: &mut [Dynamic],
|
arg_values: &mut [Dynamic],
|
||||||
) -> Option<Dynamic> {
|
) -> Dynamic {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
let lib = self.lib;
|
let lib = self.lib;
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
@ -160,8 +156,7 @@ impl<'a> OptimizerState<'a> {
|
|||||||
false,
|
false,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
)
|
)
|
||||||
.ok()
|
.map_or(Dynamic::NULL, |(v, ..)| v)
|
||||||
.map(|(v, ..)| v)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,13 +266,13 @@ fn optimize_stmt_block(
|
|||||||
state.push_var(
|
state.push_var(
|
||||||
x.0.as_str(),
|
x.0.as_str(),
|
||||||
AccessMode::ReadOnly,
|
AccessMode::ReadOnly,
|
||||||
x.1.get_literal_value(),
|
x.1.get_literal_value().unwrap_or(Dynamic::NULL),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add variables into the state
|
// Add variables into the state
|
||||||
optimize_expr(&mut x.1, state, false);
|
optimize_expr(&mut x.1, state, false);
|
||||||
state.push_var(x.0.as_str(), AccessMode::ReadWrite, None);
|
state.push_var(x.0.as_str(), AccessMode::ReadWrite, Dynamic::NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Optimize the statement
|
// Optimize the statement
|
||||||
@ -1197,13 +1192,13 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
|||||||
let arg_values = &mut x.args.iter().map(Expr::get_literal_value).collect::<Option<StaticVec<_>>>().unwrap();
|
let arg_values = &mut x.args.iter().map(Expr::get_literal_value).collect::<Option<StaticVec<_>>>().unwrap();
|
||||||
|
|
||||||
let result = match x.name.as_str() {
|
let result = match x.name.as_str() {
|
||||||
KEYWORD_TYPE_OF if arg_values.len() == 1 => Some(state.engine.map_type_name(arg_values[0].type_name()).into()),
|
KEYWORD_TYPE_OF if arg_values.len() == 1 => state.engine.map_type_name(arg_values[0].type_name()).into(),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Some(Dynamic::FALSE),
|
crate::engine::KEYWORD_IS_SHARED if arg_values.len() == 1 => Dynamic::FALSE,
|
||||||
_ => state.call_fn_with_constant_arguments(&x.name, x.op_token.as_ref(), arg_values)
|
_ => state.call_fn_with_constant_arguments(&x.name, x.op_token.as_ref(), arg_values)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(result) = result {
|
if !result.is_null() {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*expr = Expr::from_dynamic(result, *pos);
|
*expr = Expr::from_dynamic(result, *pos);
|
||||||
return;
|
return;
|
||||||
@ -1289,15 +1284,15 @@ fn optimize_top_level(
|
|||||||
.rev()
|
.rev()
|
||||||
.flat_map(|m| m.iter_var())
|
.flat_map(|m| m.iter_var())
|
||||||
{
|
{
|
||||||
state.push_var(name, AccessMode::ReadOnly, Some(value.clone()));
|
state.push_var(name, AccessMode::ReadOnly, value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add constants and variables from the scope
|
// Add constants and variables from the scope
|
||||||
for (name, constant, value) in scope.iter() {
|
for (name, constant, value) in scope.iter() {
|
||||||
if constant {
|
if constant {
|
||||||
state.push_var(name, AccessMode::ReadOnly, Some(value));
|
state.push_var(name, AccessMode::ReadOnly, value);
|
||||||
} else {
|
} else {
|
||||||
state.push_var(name, AccessMode::ReadWrite, None);
|
state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2907,7 +2907,7 @@ impl Engine {
|
|||||||
will_shadow,
|
will_shadow,
|
||||||
};
|
};
|
||||||
let caches = &mut Caches::new();
|
let caches = &mut Caches::new();
|
||||||
let this_ptr = &mut None;
|
let mut this = Dynamic::NULL;
|
||||||
|
|
||||||
let context = EvalContext::new(
|
let context = EvalContext::new(
|
||||||
self,
|
self,
|
||||||
@ -2916,7 +2916,7 @@ impl Engine {
|
|||||||
&[],
|
&[],
|
||||||
level,
|
level,
|
||||||
&mut state.stack,
|
&mut state.stack,
|
||||||
this_ptr,
|
&mut this,
|
||||||
);
|
);
|
||||||
|
|
||||||
match filter(false, info, context) {
|
match filter(false, info, context) {
|
||||||
|
@ -125,6 +125,8 @@ impl<'de> Deserializer<'de> for DynamicDeserializer<'de> {
|
|||||||
|
|
||||||
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> RhaiResultOf<V::Value> {
|
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> RhaiResultOf<V::Value> {
|
||||||
match self.0 .0 {
|
match self.0 .0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => self.deserialize_unit(visitor),
|
Union::Unit(..) => self.deserialize_unit(visitor),
|
||||||
Union::Bool(..) => self.deserialize_bool(visitor),
|
Union::Bool(..) => self.deserialize_bool(visitor),
|
||||||
Union::Str(..) => self.deserialize_str(visitor),
|
Union::Str(..) => self.deserialize_str(visitor),
|
||||||
|
@ -15,6 +15,8 @@ use crate::types::dynamic::Variant;
|
|||||||
impl Serialize for Dynamic {
|
impl Serialize for Dynamic {
|
||||||
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => ser.serialize_unit(),
|
Union::Unit(..) => ser.serialize_unit(),
|
||||||
Union::Bool(x, ..) => ser.serialize_bool(x),
|
Union::Bool(x, ..) => ser.serialize_bool(x),
|
||||||
Union::Str(ref s, ..) => ser.serialize_str(s.as_str()),
|
Union::Str(ref s, ..) => ser.serialize_str(s.as_str()),
|
||||||
|
@ -55,6 +55,9 @@ pub struct Dynamic(pub(crate) Union);
|
|||||||
///
|
///
|
||||||
/// Most variants are boxed to reduce the size.
|
/// Most variants are boxed to reduce the size.
|
||||||
pub enum Union {
|
pub enum Union {
|
||||||
|
/// An error value which should not exist.
|
||||||
|
Null,
|
||||||
|
|
||||||
/// The Unit value - ().
|
/// The Unit value - ().
|
||||||
Unit((), Tag, AccessMode),
|
Unit((), Tag, AccessMode),
|
||||||
/// A boolean value.
|
/// A boolean value.
|
||||||
@ -178,6 +181,8 @@ impl Dynamic {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn tag(&self) -> Tag {
|
pub const fn tag(&self) -> Tag {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(_, tag, _)
|
Union::Unit(_, tag, _)
|
||||||
| Union::Bool(_, tag, _)
|
| Union::Bool(_, tag, _)
|
||||||
| Union::Str(_, tag, _)
|
| Union::Str(_, tag, _)
|
||||||
@ -203,6 +208,8 @@ impl Dynamic {
|
|||||||
/// Attach arbitrary data to this [`Dynamic`].
|
/// Attach arbitrary data to this [`Dynamic`].
|
||||||
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
|
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(_, ref mut tag, _)
|
Union::Unit(_, ref mut tag, _)
|
||||||
| Union::Bool(_, ref mut tag, _)
|
| Union::Bool(_, ref mut tag, _)
|
||||||
| Union::Str(_, ref mut tag, _)
|
| Union::Str(_, ref mut tag, _)
|
||||||
@ -226,6 +233,12 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
self
|
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
|
/// Does this [`Dynamic`] hold a variant data type instead of one of the supported system
|
||||||
/// primitive types?
|
/// primitive types?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -307,6 +320,8 @@ impl Dynamic {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn type_id(&self) -> TypeId {
|
pub fn type_id(&self) -> TypeId {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => TypeId::of::<()>(),
|
Union::Unit(..) => TypeId::of::<()>(),
|
||||||
Union::Bool(..) => TypeId::of::<bool>(),
|
Union::Bool(..) => TypeId::of::<bool>(),
|
||||||
Union::Str(..) => TypeId::of::<ImmutableString>(),
|
Union::Str(..) => TypeId::of::<ImmutableString>(),
|
||||||
@ -341,6 +356,8 @@ impl Dynamic {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn type_name(&self) -> &'static str {
|
pub fn type_name(&self) -> &'static str {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => "()",
|
Union::Unit(..) => "()",
|
||||||
Union::Bool(..) => "bool",
|
Union::Bool(..) => "bool",
|
||||||
Union::Str(..) => "string",
|
Union::Str(..) => "string",
|
||||||
@ -385,6 +402,8 @@ impl Hash for Dynamic {
|
|||||||
mem::discriminant(&self.0).hash(state);
|
mem::discriminant(&self.0).hash(state);
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => (),
|
Union::Unit(..) => (),
|
||||||
Union::Bool(ref b, ..) => b.hash(state),
|
Union::Bool(ref b, ..) => b.hash(state),
|
||||||
Union::Str(ref s, ..) => s.hash(state),
|
Union::Str(ref s, ..) => s.hash(state),
|
||||||
@ -416,6 +435,8 @@ impl Hash for Dynamic {
|
|||||||
impl fmt::Display for Dynamic {
|
impl fmt::Display for Dynamic {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(..) => Ok(()),
|
Union::Unit(..) => Ok(()),
|
||||||
Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
|
Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
|
||||||
Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
|
Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
|
||||||
@ -509,6 +530,8 @@ impl fmt::Debug for Dynamic {
|
|||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
|
Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
|
||||||
Union::Bool(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),
|
Union::Str(ref v, ..) => fmt::Debug::fmt(v, f),
|
||||||
@ -619,6 +642,8 @@ impl Clone for Dynamic {
|
|||||||
/// The cloned copy is marked read-write even if the original is read-only.
|
/// The cloned copy is marked read-write even if the original is read-only.
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
|
Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
|
||||||
Union::Bool(v, tag, ..) => Self(Union::Bool(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)),
|
Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)),
|
||||||
@ -666,6 +691,9 @@ use std::f32::consts as FloatConstants;
|
|||||||
use std::f64::consts as FloatConstants;
|
use std::f64::consts as FloatConstants;
|
||||||
|
|
||||||
impl Dynamic {
|
impl Dynamic {
|
||||||
|
/// A [`Dynamic`] containing a `null`.
|
||||||
|
pub(crate) const NULL: Self = Self(Union::Null);
|
||||||
|
|
||||||
/// A [`Dynamic`] containing a `()`.
|
/// A [`Dynamic`] containing a `()`.
|
||||||
pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
|
pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
|
||||||
/// A [`Dynamic`] containing a `true`.
|
/// A [`Dynamic`] containing a `true`.
|
||||||
@ -888,6 +916,8 @@ impl Dynamic {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) const fn access_mode(&self) -> AccessMode {
|
pub(crate) const fn access_mode(&self) -> AccessMode {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(.., access)
|
Union::Unit(.., access)
|
||||||
| Union::Bool(.., access)
|
| Union::Bool(.., access)
|
||||||
| Union::Str(.., access)
|
| Union::Str(.., access)
|
||||||
@ -913,6 +943,8 @@ impl Dynamic {
|
|||||||
/// Set the [`AccessMode`] for this [`Dynamic`].
|
/// Set the [`AccessMode`] for this [`Dynamic`].
|
||||||
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
|
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Unit(.., ref mut access)
|
Union::Unit(.., ref mut access)
|
||||||
| Union::Bool(.., ref mut access)
|
| Union::Bool(.., ref mut access)
|
||||||
| Union::Str(.., ref mut access)
|
| Union::Str(.., ref mut access)
|
||||||
@ -1107,6 +1139,7 @@ impl Dynamic {
|
|||||||
let _access = self.access_mode();
|
let _access = self.access_mode();
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
Union::Shared(..) => self,
|
Union::Shared(..) => self,
|
||||||
_ => Self(Union::Shared(
|
_ => Self(Union::Shared(
|
||||||
crate::Locked::new(self).into(),
|
crate::Locked::new(self).into(),
|
||||||
@ -1151,6 +1184,8 @@ impl Dynamic {
|
|||||||
reify!(self, |v: T| return Some(v));
|
reify!(self, |v: T| return Some(v));
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
|
|
||||||
Union::Int(v, ..) => reify!(v => Option<T>),
|
Union::Int(v, ..) => reify!(v => Option<T>),
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
Union::Float(v, ..) => reify!(*v => Option<T>),
|
Union::Float(v, ..) => reify!(*v => Option<T>),
|
||||||
@ -1485,6 +1520,7 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
|
Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => None,
|
Union::Shared(..) => None,
|
||||||
@ -1583,6 +1619,7 @@ impl Dynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
Union::Null => unreachable!(),
|
||||||
Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
|
Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(..) => None,
|
Union::Shared(..) => None,
|
||||||
|
0
unreachable!()
Normal file
0
unreachable!()
Normal file
Loading…
Reference in New Issue
Block a user