Add Dynamic::NULL to simplify this pointer binding.

This commit is contained in:
Stephen Chung 2022-11-08 16:16:42 +08:00
parent 6053aa1641
commit 8f128f37f0
16 changed files with 126 additions and 77 deletions

View File

@ -250,7 +250,9 @@ impl Engine {
) -> RhaiResult {
let statements = ast.statements();
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();

View File

@ -198,8 +198,10 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
];
let mut this = Dynamic::NULL;
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());

View File

@ -141,8 +141,9 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
AsRef::<crate::SharedModule>::as_ref(ast).clone(),
];
let mut this = crate::Dynamic::NULL;
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(())

View File

@ -45,7 +45,7 @@ impl Engine {
caches: &mut Caches,
lib: &[SharedModule],
level: usize,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
target: &mut Target,
root: (&str, Position),
_parent: &Expr,
@ -573,7 +573,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
expr: &Expr,
new_val: &mut Option<(Dynamic, &OpAssignment)>,
) -> RhaiResult {
@ -630,9 +630,10 @@ impl Engine {
let obj_ptr = &mut target;
let root = (x.3.as_str(), *var_pos);
let mut this = Dynamic::NULL;
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,
)
}
@ -664,7 +665,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
expr: &Expr,
parent_options: ASTFlags,
parent_chain_type: ChainType,

View File

@ -416,7 +416,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<()> {
if self.debugger.is_some() {
@ -443,7 +443,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<Option<DebuggerStatus>> {
if self.debugger.is_some() {
@ -466,7 +466,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
node: impl Into<ASTNode<'a>>,
) -> RhaiResultOf<Option<DebuggerStatus>> {
let node = node.into();
@ -513,7 +513,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
node: ASTNode<'a>,
event: DebuggerEvent,
) -> Result<Option<DebuggerStatus>, Box<crate::EvalAltResult>> {

View File

@ -8,7 +8,7 @@ use std::prelude::v1::*;
/// Context of a script evaluation process.
#[derive(Debug)]
#[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`].
engine: &'a Engine,
/// The current [`Scope`].
@ -20,12 +20,12 @@ pub struct EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
/// The current stack of imported [modules][Module].
lib: &'a [SharedModule],
/// 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.
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`].
#[inline(always)]
#[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],
level: usize,
scope: &'s mut Scope<'ps>,
this_ptr: &'t mut Option<&'pt mut Dynamic>,
this_ptr: &'t mut Dynamic,
) -> Self {
Self {
engine,
@ -104,8 +104,8 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
#[cfg(feature = "internals")]
#[inline(always)]
#[must_use]
pub fn global_runtime_state_mut(&mut self) -> &mut &'g mut GlobalRuntimeState {
&mut self.global
pub fn global_runtime_state_mut(&mut self) -> &mut GlobalRuntimeState {
self.global
}
/// Get an iterator over the namespaces containing definition of all script-defined functions.
#[inline]
@ -121,16 +121,24 @@ impl<'a, 's, 'ps, 'g, 'c, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'c, 't, 'pt> {
self.lib
}
/// The current bound `this` pointer, if any.
#[inline(always)]
#[inline]
#[must_use]
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.
#[inline(always)]
#[inline]
#[must_use]
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
self.this_ptr
pub fn this_ptr_mut(&mut self) -> Option<&mut Dynamic> {
if self.this_ptr.is_null() {
None
} else {
Some(self.this_ptr)
}
}
/// The current nesting level of function calls.
#[inline(always)]

View File

@ -54,7 +54,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &'s mut Scope,
this_ptr: &'s mut Option<&mut Dynamic>,
this_ptr: &'s mut Dynamic,
expr: &Expr,
) -> RhaiResultOf<(Target<'s>, Position)> {
match expr {
@ -140,7 +140,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &'s mut Scope,
this_ptr: &'s mut Option<&mut Dynamic>,
this_ptr: &'s mut Dynamic,
expr: &Expr,
) -> RhaiResultOf<(Target<'s>, Position)> {
// Make sure that the pointer indirection is taken only when absolutely necessary.
@ -148,10 +148,11 @@ impl Engine {
let (index, var_pos) = match expr {
// Check if the variable is `this`
Expr::Variable(v, None, pos) if v.0.is_none() && v.3 == KEYWORD_THIS => {
return this_ptr.as_mut().map_or_else(
|| Err(ERR::ErrorUnboundThis(*pos).into()),
|val| Ok(((*val).into(), *pos)),
)
return if this_ptr.is_null() {
Err(ERR::ErrorUnboundThis(*pos).into())
} else {
Ok((this_ptr.into(), *pos))
};
}
_ if global.always_search_scope => (0, expr.start_position()),
Expr::Variable(.., Some(i), pos) => (i.get() as usize, *pos),
@ -224,7 +225,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
expr: &Expr,
) -> RhaiResult {
// Coded this way for better branch prediction.
@ -256,10 +257,11 @@ impl Engine {
self.track_operation(global, expr.position())?;
return if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
this_ptr
.as_deref()
.cloned()
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
if this_ptr.is_null() {
ERR::ErrorUnboundThis(*var_pos).into()
} else {
Ok(this_ptr.clone())
}
} else {
self.search_namespace(global, caches, lib, level, scope, this_ptr, expr)
.map(|(val, ..)| val.take_or_clone())

View File

@ -29,7 +29,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
statements: &[Stmt],
restore_orig_state: bool,
) -> RhaiResult {
@ -203,7 +203,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
stmt: &Stmt,
rewind_scope: bool,
) -> RhaiResult {
@ -912,8 +912,10 @@ impl Engine {
scope: &mut Scope,
statements: &[Stmt],
) -> RhaiResult {
let mut this = Dynamic::NULL;
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 {
ERR::Return(out, ..) => Ok(out),

View File

@ -11,8 +11,8 @@ use crate::eval::{Caches, FnResolutionCacheEntry, GlobalRuntimeState};
use crate::tokenizer::{is_valid_function_name, Token};
use crate::types::RestoreOnDrop;
use crate::{
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString, SharedModule,
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, ERR,
calc_fn_hash, calc_fn_hash_full, Dynamic, Engine, FnArgsVec, FnPtr, ImmutableString,
OptimizationLevel, Position, RhaiError, RhaiResult, RhaiResultOf, Scope, SharedModule, ERR,
};
#[cfg(feature = "no_std")]
use hashbrown::hash_map::Entry;
@ -407,6 +407,7 @@ impl Engine {
};
if trigger {
let scope = &mut &mut Scope::new();
let mut this = Dynamic::NULL;
let node = crate::ast::Stmt::Noop(pos);
let node = (&node).into();
let event = match _result {
@ -415,7 +416,7 @@ impl Engine {
};
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);
}
@ -646,16 +647,7 @@ impl Engine {
let (first_arg, rest_args) = args.split_first_mut().unwrap();
self.call_script_fn(
global,
caches,
lib,
level,
scope,
&mut Some(*first_arg),
func,
rest_args,
true,
pos,
global, caches, lib, level, scope, first_arg, func, rest_args, true, pos,
)
} else {
// Normal call of script function
@ -672,8 +664,10 @@ impl Engine {
backup.restore_first_arg(a)
});
let mut this = Dynamic::NULL;
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));
@ -697,7 +691,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
arg_expr: &Expr,
) -> RhaiResultOf<(Dynamic, Position)> {
// Literal values
@ -956,7 +950,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
fn_name: &str,
op_token: Option<&Token>,
first_arg: Option<&Expr>,
@ -1247,7 +1241,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
namespace: &crate::ast::Namespace,
fn_name: &str,
args_expr: &[Expr],
@ -1376,12 +1370,13 @@ impl Engine {
Some(f) if f.is_script() => {
let fn_def = f.get_script_fn_def().expect("script-defined function");
let new_scope = &mut Scope::new();
let mut this = Dynamic::NULL;
let orig_source = mem::replace(&mut global.source, module.id_raw().cloned());
let global = &mut *RestoreOnDrop::lock(global, move |g| g.source = orig_source);
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],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
expr: &FnCallExpr,
pos: Position,
) -> RhaiResult {

View File

@ -29,7 +29,7 @@ impl Engine {
lib: &[SharedModule],
level: usize,
scope: &mut Scope,
this_ptr: &mut Option<&mut Dynamic>,
this_ptr: &mut Dynamic,
fn_def: &ScriptFnDef,
args: &mut FnCallArgs,
rewind_scope: bool,

View File

@ -50,7 +50,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, Option<Dynamic>)>,
variables: StaticVec<(Identifier, AccessMode, Dynamic)>,
/// Activate constants propagation?
propagate_constants: bool,
/// An [`Engine`] instance for eager function evaluation.
@ -108,12 +108,7 @@ impl<'a> OptimizerState<'a> {
}
/// Add a new variable to the list.
#[inline(always)]
pub fn push_var(
&mut self,
name: impl Into<Identifier>,
access: AccessMode,
value: Option<Dynamic>,
) {
pub fn push_var(&mut self, name: impl Into<Identifier>, access: AccessMode, value: Dynamic) {
self.variables.push((name.into(), access, value));
}
/// Look up a constant from the list.
@ -127,7 +122,8 @@ impl<'a> OptimizerState<'a> {
if n == name {
return match access {
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,
op_token: Option<&Token>,
arg_values: &mut [Dynamic],
) -> Option<Dynamic> {
) -> Dynamic {
#[cfg(not(feature = "no_function"))]
let lib = self.lib;
#[cfg(feature = "no_function")]
@ -160,8 +156,7 @@ impl<'a> OptimizerState<'a> {
false,
Position::NONE,
)
.ok()
.map(|(v, ..)| v)
.map_or(Dynamic::NULL, |(v, ..)| v)
}
}
@ -271,13 +266,13 @@ fn optimize_stmt_block(
state.push_var(
x.0.as_str(),
AccessMode::ReadOnly,
x.1.get_literal_value(),
x.1.get_literal_value().unwrap_or(Dynamic::NULL),
);
}
} else {
// Add variables into the state
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
@ -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 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"))]
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)
};
if let Some(result) = result {
if !result.is_null() {
state.set_dirty();
*expr = Expr::from_dynamic(result, *pos);
return;
@ -1289,15 +1284,15 @@ fn optimize_top_level(
.rev()
.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
for (name, constant, value) in scope.iter() {
if constant {
state.push_var(name, AccessMode::ReadOnly, Some(value));
state.push_var(name, AccessMode::ReadOnly, value);
} else {
state.push_var(name, AccessMode::ReadWrite, None);
state.push_var(name, AccessMode::ReadWrite, Dynamic::NULL);
}
}

View File

@ -2907,7 +2907,7 @@ impl Engine {
will_shadow,
};
let caches = &mut Caches::new();
let this_ptr = &mut None;
let mut this = Dynamic::NULL;
let context = EvalContext::new(
self,
@ -2916,7 +2916,7 @@ impl Engine {
&[],
level,
&mut state.stack,
this_ptr,
&mut this,
);
match filter(false, info, context) {

View File

@ -125,6 +125,8 @@ impl<'de> Deserializer<'de> for DynamicDeserializer<'de> {
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> RhaiResultOf<V::Value> {
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),

View File

@ -15,6 +15,8 @@ use crate::types::dynamic::Variant;
impl Serialize for Dynamic {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
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()),

View File

@ -55,6 +55,9 @@ pub struct Dynamic(pub(crate) Union);
///
/// Most variants are boxed to reduce the size.
pub enum Union {
/// An error value which should not exist.
Null,
/// The Unit value - ().
Unit((), Tag, AccessMode),
/// A boolean value.
@ -178,6 +181,8 @@ 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, _)
@ -203,6 +208,8 @@ 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, _)
@ -226,6 +233,12 @@ 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)]
@ -307,6 +320,8 @@ impl Dynamic {
#[must_use]
pub fn type_id(&self) -> TypeId {
match self.0 {
Union::Null => unreachable!(),
Union::Unit(..) => TypeId::of::<()>(),
Union::Bool(..) => TypeId::of::<bool>(),
Union::Str(..) => TypeId::of::<ImmutableString>(),
@ -341,6 +356,8 @@ 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",
@ -385,6 +402,8 @@ 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),
@ -416,6 +435,8 @@ 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),
@ -509,6 +530,8 @@ 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),
@ -619,6 +642,8 @@ 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)),
@ -666,6 +691,9 @@ 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`.
@ -888,6 +916,8 @@ 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)
@ -913,6 +943,8 @@ 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)
@ -1107,6 +1139,7 @@ impl Dynamic {
let _access = self.access_mode();
match self.0 {
Union::Null => unreachable!(),
Union::Shared(..) => self,
_ => Self(Union::Shared(
crate::Locked::new(self).into(),
@ -1151,6 +1184,8 @@ impl Dynamic {
reify!(self, |v: T| return Some(v));
match self.0 {
Union::Null => unreachable!(),
Union::Int(v, ..) => reify!(v => Option<T>),
#[cfg(not(feature = "no_float"))]
Union::Float(v, ..) => reify!(*v => Option<T>),
@ -1485,6 +1520,7 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,
@ -1583,6 +1619,7 @@ impl Dynamic {
}
match self.0 {
Union::Null => unreachable!(),
Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
#[cfg(not(feature = "no_closure"))]
Union::Shared(..) => None,

0
unreachable!() Normal file
View File