Add checks for is_empty.

This commit is contained in:
Stephen Chung 2022-03-03 13:02:57 +08:00
parent 83755bf936
commit 0e9a16e437
18 changed files with 202 additions and 110 deletions

View File

@ -101,7 +101,8 @@ impl Engine {
// Collect all `import` statements with a string constant path
ASTNode::Stmt(Stmt::Import(x, ..)) => match x.0 {
Expr::StringConstant(ref s, ..)
if !resolver.contains_path(s) && !imports.contains(s.as_str()) =>
if !resolver.contains_path(s)
&& (imports.is_empty() || !imports.contains(s.as_str())) =>
{
imports.insert(s.clone().into());
true

View File

@ -227,9 +227,10 @@ impl Engine {
// Standard or reserved keyword/symbol not in first position
_ if !segments.is_empty() && token.is_some() => {
// Make it a custom keyword/symbol if it is disabled or reserved
if (self.disabled_symbols.contains(s)
if ((!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s))
|| token.map_or(false, |v| v.is_reserved()))
&& !self.custom_keywords.contains_key(s)
&& (self.custom_keywords.is_empty()
|| !self.custom_keywords.contains_key(s))
{
self.custom_keywords.insert(s.into(), None);
}
@ -238,7 +239,7 @@ impl Engine {
// Standard keyword in first position but not disabled
_ if segments.is_empty()
&& token.as_ref().map_or(false, |v| v.is_standard_keyword())
&& !self.disabled_symbols.contains(s) =>
&& (self.disabled_symbols.is_empty() || !self.disabled_symbols.contains(s)) =>
{
return Err(LexError::ImproperSymbol(
s.to_string(),
@ -253,9 +254,11 @@ impl Engine {
// Identifier in first position
_ if segments.is_empty() && is_valid_identifier(s.chars()) => {
// Make it a custom keyword/symbol if it is disabled or reserved
if self.disabled_symbols.contains(s) || token.map_or(false, |v| v.is_reserved())
if (!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s))
|| token.map_or(false, |v| v.is_reserved())
{
if !self.custom_keywords.contains_key(s) {
if self.custom_keywords.is_empty() || !self.custom_keywords.contains_key(s)
{
self.custom_keywords.insert(s.into(), None);
}
}

View File

@ -162,18 +162,25 @@ impl Engine {
// Active standard keywords cannot be made custom
// Disabled keywords are OK
Some(token) if token.is_standard_keyword() => {
if !self.disabled_symbols.contains(&*token.syntax()) {
if self.disabled_symbols.is_empty()
|| !self.disabled_symbols.contains(&*token.syntax())
{
return Err(format!("'{}' is a reserved keyword", keyword.as_ref()));
}
}
// Active standard symbols cannot be made custom
Some(token) if token.is_standard_symbol() => {
if !self.disabled_symbols.contains(&*token.syntax()) {
if self.disabled_symbols.is_empty()
|| !self.disabled_symbols.contains(&*token.syntax())
{
return Err(format!("'{}' is a reserved operator", keyword.as_ref()));
}
}
// Active standard symbols cannot be made custom
Some(token) if !self.disabled_symbols.contains(&*token.syntax()) => {
Some(token)
if self.disabled_symbols.is_empty()
|| !self.disabled_symbols.contains(&*token.syntax()) =>
{
return Err(format!("'{}' is a reserved symbol", keyword.as_ref()))
}
// Disabled symbols are OK

View File

@ -1003,7 +1003,7 @@ impl Engine {
let sub_module = iter.next().expect("contains separator").trim();
let remainder = iter.next().expect("contains separator").trim();
if !root.contains_key(sub_module) {
if root.is_empty() || !root.contains_key(sub_module) {
let mut m = Module::new();
register_static_module_raw(m.sub_modules_mut(), remainder, module);
m.build_index();

View File

@ -907,7 +907,7 @@ impl Engine {
self.make_type_mismatch_err::<crate::ImmutableString>(idx.type_name(), idx_pos)
})?;
if _add_if_not_found && !map.contains_key(index.as_str()) {
if _add_if_not_found && (map.is_empty() || !map.contains_key(index.as_str())) {
map.insert(index.clone().into(), Dynamic::UNIT);
}

View File

@ -20,7 +20,7 @@ impl Engine {
state: &mut EvalState,
namespace: &crate::module::Namespace,
) -> Option<crate::Shared<Module>> {
let root = &namespace[0].name;
let root = namespace.root();
// Qualified - check if the root module is directly indexed
let index = if state.always_search_scope {
@ -72,32 +72,24 @@ impl Engine {
(_, Some((namespace, hash_var)), var_name) => {
// foo:bar::baz::VARIABLE
if let Some(module) = self.search_imports(global, state, namespace) {
return match module.get_qualified_var(*hash_var) {
Ok(target) => {
let mut target = target.clone();
// Module variables are constant
target.set_access_mode(AccessMode::ReadOnly);
Ok((target.into(), *_var_pos))
}
Err(err) => Err(match *err {
ERR::ErrorVariableNotFound(..) => ERR::ErrorVariableNotFound(
format!(
"{}{}{}",
namespace,
crate::tokenizer::Token::DoubleColon.literal_syntax(),
var_name
),
namespace[0].pos,
)
.into(),
_ => err.fill_position(*_var_pos),
}),
return if let Some(mut target) = module.get_qualified_var(*hash_var) {
// Module variables are constant
target.set_access_mode(AccessMode::ReadOnly);
Ok((target.into(), *_var_pos))
} else {
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
Err(ERR::ErrorVariableNotFound(
format!("{}{}{}", namespace, sep, var_name),
namespace.position(),
)
.into())
};
}
// global::VARIABLE
#[cfg(not(feature = "no_function"))]
if namespace.len() == 1 && namespace[0].name == crate::engine::KEYWORD_GLOBAL {
if namespace.len() == 1 && namespace.root() == crate::engine::KEYWORD_GLOBAL {
if let Some(ref constants) = global.constants {
if let Some(value) =
crate::func::locked_write(constants).get_mut(var_name)
@ -109,19 +101,19 @@ impl Engine {
}
}
let sep = crate::tokenizer::Token::DoubleColon.literal_syntax();
return Err(ERR::ErrorVariableNotFound(
format!(
"{}{}{}",
namespace,
crate::tokenizer::Token::DoubleColon.literal_syntax(),
var_name
),
namespace[0].pos,
format!("{}{}{}", namespace, sep, var_name),
namespace.position(),
)
.into());
}
Err(ERR::ErrorModuleNotFound(namespace.to_string(), namespace[0].pos).into())
Err(
ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position())
.into(),
)
}
},
_ => unreachable!("Expr::Variable expected but gets {:?}", expr),

View File

@ -288,7 +288,7 @@ pub fn get_builtin_binary_op_fn(op: &str, x: &Dynamic, y: &Dynamic) -> Option<Fn
OP_CONTAINS => Some(|_, args| {
let blob = &*args[0].read_lock::<Blob>().expect(BUILTIN);
let x = (args[1].as_int().expect("`INT`") & 0x000000ff) as u8;
Ok(blob.contains(&x).into())
Ok((!blob.is_empty() && blob.contains(&x)).into())
}),
_ => None,
};

View File

@ -1353,7 +1353,7 @@ impl Engine {
let module = self
.search_imports(global, state, namespace)
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace[0].pos))?;
.ok_or_else(|| ERR::ErrorModuleNotFound(namespace.to_string(), namespace.position()))?;
// First search in script-defined functions (can override built-in)
let func = match module.get_qualified_fn(hash) {

View File

@ -41,20 +41,30 @@ pub use std::sync::Arc as Shared;
#[allow(dead_code)]
pub use std::cell::RefCell as Locked;
/// Lock guard for synchronized shared object.
/// Read-only lock guard for synchronized shared object.
#[cfg(not(feature = "sync"))]
#[allow(dead_code)]
pub type LockGuard<'a, T> = std::cell::RefMut<'a, T>;
pub type LockGuard<'a, T> = std::cell::Ref<'a, T>;
/// Mutable lock guard for synchronized shared object.
#[cfg(not(feature = "sync"))]
#[allow(dead_code)]
pub type LockGuardMut<'a, T> = std::cell::RefMut<'a, T>;
/// Synchronized shared object.
#[cfg(feature = "sync")]
#[allow(dead_code)]
pub use std::sync::RwLock as Locked;
/// Lock guard for synchronized shared object.
/// Read-only lock guard for synchronized shared object.
#[cfg(feature = "sync")]
#[allow(dead_code)]
pub type LockGuard<'a, T> = std::sync::RwLockWriteGuard<'a, T>;
pub type LockGuard<'a, T> = std::sync::RwLockReadGuard<'a, T>;
/// Mutable lock guard for synchronized shared object.
#[cfg(feature = "sync")]
#[allow(dead_code)]
pub type LockGuardMut<'a, T> = std::sync::RwLockWriteGuard<'a, T>;
/// Context of a native Rust function call.
#[derive(Debug)]
@ -374,11 +384,23 @@ pub fn shared_take<T>(value: Shared<T>) -> T {
shared_try_take(value).ok().expect("not shared")
}
/// Lock a [`Locked`] resource.
/// Lock a [`Locked`] resource for mutable access.
#[inline(always)]
#[must_use]
#[allow(dead_code)]
pub fn locked_write<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
pub fn locked_read<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
#[cfg(not(feature = "sync"))]
return value.borrow();
#[cfg(feature = "sync")]
return value.read().unwrap();
}
/// Lock a [`Locked`] resource for mutable access.
#[inline(always)]
#[must_use]
#[allow(dead_code)]
pub fn locked_write<'a, T>(value: &'a Locked<T>) -> LockGuardMut<'a, T> {
#[cfg(not(feature = "sync"))]
return value.borrow_mut();

View File

@ -488,7 +488,11 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_var(&self, name: &str) -> bool {
self.variables.contains_key(name)
if !self.variables.is_empty() {
self.variables.contains_key(name)
} else {
false
}
}
/// Get the value of a [`Module`] variable.
@ -520,7 +524,11 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn get_var(&self, name: &str) -> Option<Dynamic> {
self.variables.get(name).cloned()
if !self.variables.is_empty() {
self.variables.get(name).cloned()
} else {
None
}
}
/// Set a variable into the [`Module`].
@ -552,14 +560,15 @@ impl Module {
self
}
/// Get a reference to a namespace-qualified variable.
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
/// Get a namespace-qualified [`Module`] variable as a [`Dynamic`].
#[cfg(not(feature = "no_module"))]
#[inline]
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> RhaiResultOf<&Dynamic> {
self.all_variables.get(&hash_var).ok_or_else(|| {
crate::ERR::ErrorVariableNotFound(String::new(), crate::Position::NONE).into()
})
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Option<Dynamic> {
if !self.all_variables.is_empty() {
self.all_variables.get(&hash_var).cloned()
} else {
None
}
}
/// Set a script-defined function into the [`Module`].
@ -610,14 +619,14 @@ impl Module {
name: impl AsRef<str>,
num_params: usize,
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
if self.functions.is_empty() {
None
} else {
if !self.functions.is_empty() {
let name = name.as_ref();
self.iter_fn()
.find(|f| f.metadata.params == num_params && f.metadata.name == name)
.and_then(|f| f.func.get_script_fn_def())
} else {
None
}
}
@ -656,7 +665,11 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_sub_module(&self, name: &str) -> bool {
self.modules.contains_key(name)
if !self.modules.is_empty() {
self.modules.contains_key(name)
} else {
false
}
}
/// Get a sub-module in the [`Module`].
@ -673,7 +686,11 @@ impl Module {
#[inline]
#[must_use]
pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
self.modules.get(name).map(|m| m.as_ref())
if !self.modules.is_empty() {
self.modules.get(name).map(|m| m.as_ref())
} else {
None
}
}
/// Set a sub-module into the [`Module`].
@ -716,7 +733,11 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_fn(&self, hash_fn: u64) -> bool {
self.functions.contains_key(&hash_fn)
if !self.functions.is_empty() {
self.functions.contains_key(&hash_fn)
} else {
false
}
}
/// _(metadata)_ Update the metadata (parameter names/types and return type) of a registered function.
@ -1357,7 +1378,11 @@ impl Module {
#[inline]
#[must_use]
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
if !self.functions.is_empty() {
self.functions.get(&hash_fn).map(|f| f.func.as_ref())
} else {
None
}
}
/// Does the particular namespace-qualified function exist in the [`Module`]?
@ -1366,7 +1391,11 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
self.all_functions.contains_key(&hash_fn)
if !self.all_functions.is_empty() {
self.all_functions.contains_key(&hash_fn)
} else {
false
}
}
/// Get a namespace-qualified function.
@ -1376,9 +1405,13 @@ impl Module {
#[inline]
#[must_use]
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
self.all_functions
.get(&hash_qualified_fn)
.map(|f| f.as_ref())
if !self.all_functions.is_empty() {
self.all_functions
.get(&hash_qualified_fn)
.map(|f| f.as_ref())
} else {
None
}
}
/// Combine another [`Module`] into this [`Module`].
@ -1906,14 +1939,22 @@ impl Module {
#[inline(always)]
#[must_use]
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
self.all_type_iterators.contains_key(&id)
if !self.all_type_iterators.is_empty() {
self.all_type_iterators.contains_key(&id)
} else {
false
}
}
/// Does a type iterator exist in the module?
#[inline(always)]
#[must_use]
pub fn contains_iter(&self, id: TypeId) -> bool {
self.type_iterators.contains_key(&id)
if !self.type_iterators.is_empty() {
self.type_iterators.contains_key(&id)
} else {
false
}
}
/// Set a type iterator into the [`Module`].
@ -1979,14 +2020,22 @@ impl Module {
#[inline]
#[must_use]
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<&IteratorFn> {
self.all_type_iterators.get(&id).map(|f| f.as_ref())
if !self.all_type_iterators.is_empty() {
self.all_type_iterators.get(&id).map(|f| f.as_ref())
} else {
None
}
}
/// Get the specified type iterator.
#[inline]
#[must_use]
pub(crate) fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
self.type_iterators.get(&id).map(|f| f.as_ref())
if !self.type_iterators.is_empty() {
self.type_iterators.get(&id).map(|f| f.as_ref())
} else {
None
}
}
}

View File

@ -24,8 +24,8 @@ use std::{
/// one level, and it is wasteful to always allocate a [`Vec`] with one element.
#[derive(Clone, Eq, PartialEq, Default, Hash)]
pub struct Namespace {
index: Option<NonZeroUsize>,
path: StaticVec<Ident>,
index: Option<NonZeroUsize>,
}
impl fmt::Debug for Namespace {
@ -119,7 +119,19 @@ impl Namespace {
/// # Panics
///
/// Panics if the path is empty.
#[inline(always)]
#[must_use]
pub fn position(&self) -> Position {
self.path[0].pos
}
/// Get the first path segment of this [`Namespace`].
///
/// # Panics
///
/// Panics if the path is empty.
#[inline(always)]
#[must_use]
pub fn root(&self) -> &str {
&self.path[0].name
}
}

View File

@ -2,7 +2,7 @@
#![cfg(not(target_family = "wasm"))]
use crate::eval::GlobalRuntimeState;
use crate::func::native::locked_write;
use crate::func::native::{locked_read, locked_write};
use crate::{
Engine, Identifier, Module, ModuleResolver, Position, RhaiResultOf, Scope, Shared, ERR,
};
@ -208,7 +208,13 @@ impl FileModuleResolver {
let file_path = self.get_file_path(path.as_ref(), source_path);
locked_write(&self.cache).contains_key(&file_path)
let cache = locked_read(&self.cache);
if !cache.is_empty() {
cache.contains_key(&file_path)
} else {
false
}
}
/// Empty the internal cache.
#[inline]

View File

@ -62,7 +62,11 @@ impl StaticModuleResolver {
#[inline(always)]
#[must_use]
pub fn contains_path(&self, path: &str) -> bool {
self.0.contains_key(path)
if !self.0.is_empty() {
self.0.contains_key(path)
} else {
false
}
}
/// Get an iterator of all the [modules][Module].
#[inline]

View File

@ -484,8 +484,8 @@ impl Engine {
eat_token(input, Token::RightParen);
#[cfg(not(feature = "no_module"))]
let hash = if let Some(modules) = namespace.as_mut() {
let index = state.find_module(&modules[0].name);
let hash = if let Some(namespace) = namespace.as_mut() {
let index = state.find_module(namespace.root());
#[cfg(not(feature = "no_function"))]
let relax = settings.is_function_scope;
@ -493,13 +493,13 @@ impl Engine {
let relax = false;
if !relax && settings.options.strict_var && index.is_none() {
return Err(PERR::ModuleUndefined(modules[0].name.to_string())
.into_err(modules[0].pos));
return Err(PERR::ModuleUndefined(namespace.root().to_string())
.into_err(namespace.position()));
}
modules.set_index(index);
namespace.set_index(index);
crate::calc_qualified_fn_hash(modules.iter().map(|m| m.name.as_str()), &id, 0)
crate::calc_qualified_fn_hash(namespace.iter().map(|m| m.name.as_str()), &id, 0)
} else {
calc_fn_hash(&id, 0)
};
@ -545,8 +545,8 @@ impl Engine {
eat_token(input, Token::RightParen);
#[cfg(not(feature = "no_module"))]
let hash = if let Some(modules) = namespace.as_mut() {
let index = state.find_module(&modules[0].name);
let hash = if let Some(namespace) = namespace.as_mut() {
let index = state.find_module(namespace.root());
#[cfg(not(feature = "no_function"))]
let relax = settings.is_function_scope;
@ -554,14 +554,14 @@ impl Engine {
let relax = false;
if !relax && settings.options.strict_var && index.is_none() {
return Err(PERR::ModuleUndefined(modules[0].name.to_string())
.into_err(modules[0].pos));
return Err(PERR::ModuleUndefined(namespace.root().to_string())
.into_err(namespace.position()));
}
modules.set_index(index);
namespace.set_index(index);
crate::calc_qualified_fn_hash(
modules.iter().map(|m| m.name.as_str()),
namespace.iter().map(|m| m.name.as_str()),
&id,
args.len(),
)
@ -1084,7 +1084,7 @@ impl Engine {
value.hash(hasher);
let hash = hasher.finish();
if cases.contains_key(&hash) {
if !cases.is_empty() && cases.contains_key(&hash) {
return Err(PERR::DuplicatedSwitchCase.into_err(expr.start_position()));
}
(Some(hash), None)
@ -1378,7 +1378,7 @@ impl Engine {
// Custom syntax.
Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key)
if self.custom_syntax.contains_key(&**key) =>
if !self.custom_syntax.is_empty() && self.custom_syntax.contains_key(&**key) =>
{
let (key, syntax) = self.custom_syntax.get_key_value(&**key).unwrap();
let (.., pos) = input.next().expect(NEVER_ENDS);
@ -1657,7 +1657,7 @@ impl Engine {
#[cfg(not(feature = "no_module"))]
{
let index = state.find_module(&namespace[0].name);
let index = state.find_module(namespace.root());
#[cfg(not(feature = "no_function"))]
let relax = settings.is_function_scope;
@ -1665,8 +1665,8 @@ impl Engine {
let relax = false;
if !relax && settings.options.strict_var && index.is_none() {
return Err(PERR::ModuleUndefined(namespace[0].name.to_string())
.into_err(namespace[0].pos));
return Err(PERR::ModuleUndefined(namespace.root().to_string())
.into_err(namespace.position()));
}
namespace.set_index(index);
@ -3092,7 +3092,7 @@ impl Engine {
let hash = calc_fn_hash(&func.name, func.params.len());
if lib.contains_key(&hash) {
if !lib.is_empty() && lib.contains_key(&hash) {
return Err(PERR::FnDuplicatedDefinition(
func.name.to_string(),
func.params.len(),

View File

@ -2251,7 +2251,7 @@ impl<'a> Iterator for TokenIterator<'a> {
}
// Reserved keyword/symbol
Some((Token::Reserved(s), pos)) => (match
(&*s, self.engine.custom_keywords.contains_key(&*s))
(&*s, !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s))
{
("===", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(),
"'===' is not a valid operator. This is not JavaScript! Should it be '=='?".to_string(),
@ -2282,7 +2282,7 @@ impl<'a> Iterator for TokenIterator<'a> {
// Reserved keyword/operator that is custom.
(.., true) => Token::Custom(s),
// Reserved keyword that is not custom and disabled.
(token, false) if self.engine.disabled_symbols.contains(token) => {
(token, false) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token) => {
let msg = format!("reserved {} '{}' is disabled", if is_valid_identifier(token.chars()) { "keyword"} else {"symbol"}, token);
Token::LexError(LERR::ImproperSymbol(s.to_string(), msg).into())
},
@ -2290,12 +2290,12 @@ impl<'a> Iterator for TokenIterator<'a> {
(.., false) => Token::Reserved(s),
}, pos),
// Custom keyword
Some((Token::Identifier(s), pos)) if self.engine.custom_keywords.contains_key(&*s) => {
Some((Token::Identifier(s), pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(&*s) => {
(Token::Custom(s), pos)
}
// Custom keyword/symbol - must be disabled
Some((token, pos)) if self.engine.custom_keywords.contains_key(token.literal_syntax()) => {
if self.engine.disabled_symbols.contains(token.literal_syntax()) {
Some((token, pos)) if !self.engine.custom_keywords.is_empty() && self.engine.custom_keywords.contains_key(token.literal_syntax()) => {
if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) {
// Disabled standard keyword/symbol
(Token::Custom(token.literal_syntax().into()), pos)
} else {
@ -2304,7 +2304,7 @@ impl<'a> Iterator for TokenIterator<'a> {
}
}
// Disabled symbol
Some((token, pos)) if self.engine.disabled_symbols.contains(token.literal_syntax()) => {
Some((token, pos)) if !self.engine.disabled_symbols.is_empty() && self.engine.disabled_symbols.contains(token.literal_syntax()) => {
(Token::Reserved(token.literal_syntax().into()), pos)
}
// Normal symbol

View File

@ -206,14 +206,10 @@ enum DynamicReadLockInner<'d, T: Clone> {
/// A simple reference to a non-shared value.
Reference(&'d T),
/// A read guard to a shared [`RefCell`][std::cell::RefCell].
/// A read guard to a shared value.
#[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))]
Guard(std::cell::Ref<'d, Dynamic>),
/// A read guard to a shared [`RwLock`][std::sync::RwLock].
#[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")]
Guard(std::sync::RwLockReadGuard<'d, Dynamic>),
Guard(crate::func::native::LockGuard<'d, Dynamic>),
}
impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
@ -245,7 +241,7 @@ enum DynamicWriteLockInner<'d, T: Clone> {
/// A write guard to a shared value.
#[cfg(not(feature = "no_closure"))]
Guard(crate::func::native::LockGuard<'d, Dynamic>),
Guard(crate::func::native::LockGuardMut<'d, Dynamic>),
}
impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {

View File

@ -59,7 +59,7 @@ impl StringsInterner {
_ => unreachable!("unsupported prefix {}", prefix.as_ref()),
};
if dict.contains_key(text.as_ref()) {
if !dict.is_empty() && dict.contains_key(text.as_ref()) {
dict.get(text.as_ref()).unwrap().clone()
} else {
let value: ImmutableString = mapper(text.as_ref()).into();

View File

@ -516,7 +516,7 @@ impl Scope<'_> {
#[inline]
pub(crate) fn add_entry_alias(&mut self, index: usize, alias: Identifier) -> &mut Self {
let aliases = self.aliases.get_mut(index).unwrap();
if !aliases.contains(&alias) {
if aliases.is_empty() || !aliases.contains(&alias) {
aliases.push(alias);
}
self
@ -533,7 +533,7 @@ impl Scope<'_> {
.rev()
.enumerate()
.fold(Self::new(), |mut entries, (index, name)| {
if !entries.names.contains(name) {
if entries.names.is_empty() || !entries.names.contains(name) {
let orig_value = &self.values[len - 1 - index];
let alias = &self.aliases[len - 1 - index];
let mut value = orig_value.clone();