Clean up more clippy.

This commit is contained in:
Stephen Chung 2022-07-27 18:04:59 +08:00
parent 39dee556c4
commit 2f948a784c
47 changed files with 412 additions and 377 deletions

View File

@ -120,14 +120,14 @@ pub fn inner_item_attributes<T: ExportedParams>(
// Find the #[rhai_fn] attribute which will turn be read for function parameters. // Find the #[rhai_fn] attribute which will turn be read for function parameters.
if let Some(index) = attrs if let Some(index) = attrs
.iter() .iter()
.position(|a| a.path.get_ident().map(|i| *i == attr_name).unwrap_or(false)) .position(|a| a.path.get_ident().map_or(false, |i| *i == attr_name))
{ {
let rhai_fn_attr = attrs.remove(index); let rhai_fn_attr = attrs.remove(index);
// Cannot have more than one #[rhai_fn] // Cannot have more than one #[rhai_fn]
if let Some(duplicate) = attrs if let Some(duplicate) = attrs
.iter() .iter()
.find(|a| a.path.get_ident().map(|i| *i == attr_name).unwrap_or(false)) .find(|a| a.path.get_ident().map_or(false, |i| *i == attr_name))
{ {
return Err(syn::Error::new( return Err(syn::Error::new(
duplicate.span(), duplicate.span(),
@ -177,7 +177,7 @@ pub fn doc_attributes(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {
pub fn collect_cfg_attr(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> { pub fn collect_cfg_attr(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {
attrs attrs
.iter() .iter()
.filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) .filter(|&a| a.path.get_ident().map_or(false, |i| *i == "cfg"))
.cloned() .cloned()
.collect() .collect()
} }

View File

@ -252,7 +252,7 @@ impl Engine {
} }
// Standard keyword in first position but not disabled // Standard keyword in first position but not disabled
_ if segments.is_empty() _ if segments.is_empty()
&& token.as_ref().map_or(false, |v| v.is_standard_keyword()) && token.as_ref().map_or(false, Token::is_standard_keyword)
&& (self.disabled_symbols.is_empty() || !self.disabled_symbols.contains(s)) => && (self.disabled_symbols.is_empty() || !self.disabled_symbols.contains(s)) =>
{ {
return Err(LexError::ImproperSymbol( return Err(LexError::ImproperSymbol(

View File

@ -291,20 +291,18 @@ impl FuncInfo {
} }
first = false; first = false;
let (param_name, param_type) = self let (param_name, param_type) =
.metadata self.metadata
.params_info .params_info
.get(i) .get(i)
.map(|s| { .map_or(("_", "?".into()), |s| {
let mut s = s.splitn(2, ':'); let mut s = s.splitn(2, ':');
( (
s.next().unwrap_or("_").split(' ').last().unwrap(), s.next().unwrap_or("_").split(' ').last().unwrap(),
s.next() s.next()
.map(|ty| def_type_name(ty, def.engine)) .map_or(Cow::Borrowed("?"), |ty| def_type_name(ty, def.engine)),
.unwrap_or(Cow::Borrowed("?")), )
) });
})
.unwrap_or(("_", "?".into()));
if operator { if operator {
write!(writer, "{param_type}")?; write!(writer, "{param_type}")?;
@ -338,8 +336,7 @@ fn def_type_name<'a>(ty: &'a str, engine: &'a Engine) -> Cow<'a, str> {
let ty = ty let ty = ty
.strip_prefix("RhaiResultOf<") .strip_prefix("RhaiResultOf<")
.and_then(|s| s.strip_suffix('>')) .and_then(|s| s.strip_suffix('>'))
.map(str::trim) .map_or(ty, str::trim);
.unwrap_or(ty);
let ty = ty let ty = ty
.replace("Iterator<Item=", "Iterator<") .replace("Iterator<Item=", "Iterator<")

View File

@ -152,6 +152,7 @@ impl Engine {
/// ///
/// Data types not supported by JSON serialize into formats that may invalidate the result. /// Data types not supported by JSON serialize into formats that may invalidate the result.
#[inline] #[inline]
#[must_use]
pub fn format_map_as_json(map: &Map) -> String { pub fn format_map_as_json(map: &Map) -> String {
let mut result = String::from('{'); let mut result = String::from('{');

View File

@ -51,17 +51,20 @@ impl Engine {
/// Is `if`-expression allowed? /// Is `if`-expression allowed?
/// Default is `true`. /// Default is `true`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_if_expression(&self) -> bool { pub const fn allow_if_expression(&self) -> bool {
self.options.contains(LangOptions::IF_EXPR) self.options.contains(LangOptions::IF_EXPR)
} }
/// Set whether `if`-expression is allowed. /// Set whether `if`-expression is allowed.
#[inline(always)] #[inline(always)]
#[must_use]
pub fn set_allow_if_expression(&mut self, enable: bool) { pub fn set_allow_if_expression(&mut self, enable: bool) {
self.options.set(LangOptions::IF_EXPR, enable) self.options.set(LangOptions::IF_EXPR, enable);
} }
/// Is `switch` expression allowed? /// Is `switch` expression allowed?
/// Default is `true`. /// Default is `true`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_switch_expression(&self) -> bool { pub const fn allow_switch_expression(&self) -> bool {
self.options.contains(LangOptions::SWITCH_EXPR) self.options.contains(LangOptions::SWITCH_EXPR)
} }
@ -73,6 +76,7 @@ impl Engine {
/// Is statement-expression allowed? /// Is statement-expression allowed?
/// Default is `true`. /// Default is `true`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_statement_expression(&self) -> bool { pub const fn allow_statement_expression(&self) -> bool {
self.options.contains(LangOptions::STMT_EXPR) self.options.contains(LangOptions::STMT_EXPR)
} }
@ -87,6 +91,7 @@ impl Engine {
/// Not available under `no_function`. /// Not available under `no_function`.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_anonymous_fn(&self) -> bool { pub const fn allow_anonymous_fn(&self) -> bool {
self.options.contains(LangOptions::ANON_FN) self.options.contains(LangOptions::ANON_FN)
} }
@ -101,6 +106,7 @@ impl Engine {
/// Is looping allowed? /// Is looping allowed?
/// Default is `true`. /// Default is `true`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_looping(&self) -> bool { pub const fn allow_looping(&self) -> bool {
self.options.contains(LangOptions::LOOPING) self.options.contains(LangOptions::LOOPING)
} }
@ -112,6 +118,7 @@ impl Engine {
/// Is variables shadowing allowed? /// Is variables shadowing allowed?
/// Default is `true`. /// Default is `true`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn allow_shadowing(&self) -> bool { pub const fn allow_shadowing(&self) -> bool {
self.options.contains(LangOptions::SHADOW) self.options.contains(LangOptions::SHADOW)
} }
@ -123,6 +130,7 @@ impl Engine {
/// Is strict variables mode enabled? /// Is strict variables mode enabled?
/// Default is `false`. /// Default is `false`.
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn strict_variables(&self) -> bool { pub const fn strict_variables(&self) -> bool {
self.options.contains(LangOptions::STRICT_VAR) self.options.contains(LangOptions::STRICT_VAR)
} }
@ -137,6 +145,7 @@ impl Engine {
/// Not available under `no_object`. /// Not available under `no_object`.
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn fail_on_invalid_map_property(&self) -> bool { pub const fn fail_on_invalid_map_property(&self) -> bool {
self.options self.options
.contains(LangOptions::FAIL_ON_INVALID_MAP_PROPERTY) .contains(LangOptions::FAIL_ON_INVALID_MAP_PROPERTY)

View File

@ -70,7 +70,7 @@ impl Engine {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_type_names: crate::StaticVec<_> = let param_type_names: crate::StaticVec<_> =
param_type_names.iter().map(|ty| ty.as_str()).collect(); param_type_names.iter().map(String::as_str).collect();
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_type_names = Some(param_type_names.as_ref()); let param_type_names = Some(param_type_names.as_ref());
@ -128,7 +128,7 @@ impl Engine {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_type_names: crate::StaticVec<_> = let param_type_names: crate::StaticVec<_> =
param_type_names.iter().map(|ty| ty.as_str()).collect(); param_type_names.iter().map(String::as_str).collect();
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_type_names = Some(param_type_names.as_ref()); let param_type_names = Some(param_type_names.as_ref());
@ -989,16 +989,7 @@ impl Engine {
let separator = crate::tokenizer::Token::DoubleColon.syntax(); let separator = crate::tokenizer::Token::DoubleColon.syntax();
let separator = separator.as_ref(); let separator = separator.as_ref();
if !name.contains(separator) { if name.contains(separator) {
if !module.is_indexed() {
// Index the module (making a clone copy if necessary) if it is not indexed
let mut module = crate::func::shared_take_or_clone(module);
module.build_index();
root.insert(name.into(), module.into());
} else {
root.insert(name.into(), module);
}
} else {
let mut iter = name.splitn(2, separator); let mut iter = name.splitn(2, separator);
let sub_module = iter.next().expect("contains separator").trim(); let sub_module = iter.next().expect("contains separator").trim();
let remainder = iter.next().expect("contains separator").trim(); let remainder = iter.next().expect("contains separator").trim();
@ -1015,6 +1006,13 @@ impl Engine {
m.build_index(); m.build_index();
root.insert(sub_module.into(), m.into()); root.insert(sub_module.into(), m.into());
} }
} else if module.is_indexed() {
root.insert(name.into(), module);
} else {
// Index the module (making a clone copy if necessary) if it is not indexed
let mut module = crate::func::shared_take_or_clone(module);
module.build_index();
root.insert(name.into(), module.into());
} }
} }
@ -1039,7 +1037,7 @@ impl Engine {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
for (name, m) in &self.global_sub_modules { for (name, m) in &self.global_sub_modules {
signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f))) signatures.extend(m.gen_fn_signatures().map(|f| format!("{}::{}", name, f)));
} }
signatures.extend( signatures.extend(

View File

@ -51,7 +51,7 @@ impl Engine {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
ast.as_ref(), ast.as_ref(),
]; ];
let lib = if lib.first().map(|m: &&Module| m.is_empty()).unwrap_or(true) { let lib = if lib.first().map_or(true, |m: &&Module| m.is_empty()) {
&lib[0..0] &lib[0..0]
} else { } else {
&lib &lib

View File

@ -147,10 +147,10 @@ impl Engine {
if let Some(x) = name.strip_prefix("&mut ") { if let Some(x) = name.strip_prefix("&mut ") {
let r = self.format_type_name(x); let r = self.format_type_name(x);
return if x != r { return if x == r {
format!("&mut {}", r).into()
} else {
name.into() name.into()
} else {
format!("&mut {}", r).into()
}; };
} }

View File

@ -554,19 +554,19 @@ impl AST {
lib lib
}; };
let mut _ast = if !other.source.is_empty() { let mut _ast = if other.source.is_empty() {
Self::new(
merged,
#[cfg(not(feature = "no_function"))]
lib,
)
} else {
Self::new_with_source( Self::new_with_source(
merged, merged,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
lib, lib,
other.source.clone(), other.source.clone(),
) )
} else {
Self::new(
merged,
#[cfg(not(feature = "no_function"))]
lib,
)
}; };
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -977,6 +977,7 @@ impl Eq for ASTNode<'_> {}
impl ASTNode<'_> { impl ASTNode<'_> {
/// Get the [`Position`] of this [`ASTNode`]. /// Get the [`Position`] of this [`ASTNode`].
#[must_use]
pub fn position(&self) -> Position { pub fn position(&self) -> Position {
match self { match self {
ASTNode::Stmt(stmt) => stmt.position(), ASTNode::Stmt(stmt) => stmt.position(),

View File

@ -326,10 +326,10 @@ impl<F: Float + FromStr> FromStr for FloatWrapper<F> {
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
impl<F: Float> FloatWrapper<F> { impl<F: Float> FloatWrapper<F> {
/// Maximum floating-point number for natural display before switching to scientific notation. /// Maximum floating-point number for natural display before switching to scientific notation.
pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10000000000000.0; pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10_000_000_000_000.0;
/// Minimum floating-point number for natural display before switching to scientific notation. /// Minimum floating-point number for natural display before switching to scientific notation.
pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.0000000000001; pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.000_000_000_000_1;
/// Create a new [`FloatWrapper`]. /// Create a new [`FloatWrapper`].
#[inline(always)] #[inline(always)]
@ -728,10 +728,10 @@ impl Expr {
match self { match self {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Self::Variable(x, ..) => { Self::Variable(x, ..) => {
if !x.1.is_empty() { if x.1.is_empty() {
x.1.position()
} else {
self.position() self.position()
} else {
x.1.position()
} }
} }

View File

@ -58,6 +58,7 @@ impl Ident {
/// Get the name of the identifier as a string slice. /// Get the name of the identifier as a string slice.
#[inline(always)] #[inline(always)]
#[must_use]
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
self.name.as_str() self.name.as_str()
} }

View File

@ -42,7 +42,7 @@ impl fmt::Debug for Namespace {
&self &self
.path .path
.iter() .iter()
.map(|m| m.as_str()) .map(Ident::as_str)
.collect::<StaticVec<_>>() .collect::<StaticVec<_>>()
.join(Token::DoubleColon.literal_syntax()), .join(Token::DoubleColon.literal_syntax()),
) )
@ -59,7 +59,7 @@ impl fmt::Display for Namespace {
&self &self
.path .path
.iter() .iter()
.map(|m| m.as_str()) .map(Ident::as_str)
.collect::<StaticVec<_>>() .collect::<StaticVec<_>>()
.join(Token::DoubleColon.literal_syntax()), .join(Token::DoubleColon.literal_syntax()),
) )
@ -126,7 +126,7 @@ impl Namespace {
/// Set the [`Scope`][crate::Scope] index offset. /// Set the [`Scope`][crate::Scope] index offset.
#[inline(always)] #[inline(always)]
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) { pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
self.index = index self.index = index;
} }
/// Get the [position][Position] of this [`Namespace`]. /// Get the [position][Position] of this [`Namespace`].
/// ///

View File

@ -2,7 +2,7 @@
#![cfg(not(feature = "no_function"))] #![cfg(not(feature = "no_function"))]
use super::{FnAccess, StmtBlock}; use super::{FnAccess, StmtBlock};
use crate::{Identifier, StaticVec}; use crate::{Identifier, SmartString, StaticVec};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{fmt, hash::Hash}; use std::{fmt, hash::Hash};
@ -71,7 +71,7 @@ impl fmt::Display for ScriptFnDef {
self.name, self.name,
self.params self.params
.iter() .iter()
.map(|s| s.as_str()) .map(SmartString::as_str)
.collect::<StaticVec<_>>() .collect::<StaticVec<_>>()
.join(", ") .join(", ")
) )
@ -120,7 +120,7 @@ impl fmt::Display for ScriptFnMetadata<'_> {
self.name, self.name,
self.params self.params
.iter() .iter()
.cloned() .copied()
.collect::<StaticVec<_>>() .collect::<StaticVec<_>>()
.join(", ") .join(", ")
) )
@ -132,7 +132,7 @@ impl<'a> From<&'a ScriptFnDef> for ScriptFnMetadata<'a> {
fn from(value: &'a ScriptFnDef) -> Self { fn from(value: &'a ScriptFnDef) -> Self {
Self { Self {
name: &value.name, name: &value.name,
params: value.params.iter().map(|s| s.as_str()).collect(), params: value.params.iter().map(SmartString::as_str).collect(),
access: value.access, access: value.access,
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
comments: value.comments.iter().map(<_>::as_ref).collect(), comments: value.comments.iter().map(<_>::as_ref).collect(),

View File

@ -507,7 +507,7 @@ impl<'a> IntoIterator for &'a StmtBlock {
impl Extend<Stmt> for StmtBlock { impl Extend<Stmt> for StmtBlock {
#[inline(always)] #[inline(always)]
fn extend<T: IntoIterator<Item = Stmt>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = Stmt>>(&mut self, iter: T) {
self.block.extend(iter) self.block.extend(iter);
} }
} }
@ -799,7 +799,7 @@ impl Stmt {
Self::For(x, ..) => x.2.is_pure() && x.3.iter().all(Stmt::is_pure), Self::For(x, ..) => x.2.is_pure() && x.3.iter().all(Stmt::is_pure),
Self::Var(..) | Self::Assignment(..) | Self::FnCall(..) => false, Self::Var(..) | Self::Assignment(..) | Self::FnCall(..) => false,
Self::Block(block, ..) => block.iter().all(|stmt| stmt.is_pure()), Self::Block(block, ..) => block.iter().all(Stmt::is_pure),
Self::BreakLoop(..) | Self::Return(..) => false, Self::BreakLoop(..) | Self::Return(..) => false,
Self::TryCatch(x, ..) => { Self::TryCatch(x, ..) => {
x.try_block.iter().all(Stmt::is_pure) && x.catch_block.iter().all(Stmt::is_pure) x.try_block.iter().all(Stmt::is_pure) && x.catch_block.iter().all(Stmt::is_pure)

View File

@ -169,7 +169,7 @@ impl fmt::Debug for Engine {
&self &self
.custom_syntax .custom_syntax
.keys() .keys()
.map(|s| s.as_str()) .map(crate::SmartString::as_str)
.collect::<String>(), .collect::<String>(),
); );

View File

@ -147,10 +147,10 @@ impl fmt::Display for BreakPoint {
pos, pos,
enabled, enabled,
} => { } => {
if !source.is_empty() { if source.is_empty() {
write!(f, "{} @ {:?}", source, pos)?;
} else {
write!(f, "@ {:?}", pos)?; write!(f, "@ {:?}", pos)?;
} else {
write!(f, "{} @ {:?}", source, pos)?;
} }
if !*enabled { if !*enabled {
f.write_str(" (disabled)")?; f.write_str(" (disabled)")?;
@ -201,6 +201,7 @@ impl fmt::Display for BreakPoint {
impl BreakPoint { impl BreakPoint {
/// Is this [`BreakPoint`] enabled? /// Is this [`BreakPoint`] enabled?
#[inline(always)] #[inline(always)]
#[must_use]
pub fn is_enabled(&self) -> bool { pub fn is_enabled(&self) -> bool {
match self { match self {
#[cfg(not(feature = "no_position"))] #[cfg(not(feature = "no_position"))]

View File

@ -113,7 +113,7 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, '
/// 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]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> { pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned() self.lib.iter().copied()
} }
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions. /// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
@ -133,7 +133,7 @@ impl<'a, 's, 'ps, 'g, 'pg, 'c, 'pc, 't, 'pt> EvalContext<'a, 's, 'ps, 'g, 'pg, '
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> { pub fn this_ptr_mut(&mut self) -> &mut Option<&'pt mut Dynamic> {
&mut self.this_ptr self.this_ptr
} }
/// The current nesting level of function calls. /// The current nesting level of function calls.
#[inline(always)] #[inline(always)]

View File

@ -149,7 +149,7 @@ impl Engine {
} }
_ 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),
Expr::Variable(v, None, pos) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos), Expr::Variable(v, None, pos) => (v.0.map_or(0, NonZeroUsize::get), *pos),
_ => unreachable!("Expr::Variable expected but gets {:?}", expr), _ => unreachable!("Expr::Variable expected but gets {:?}", expr),
}; };
@ -485,7 +485,7 @@ impl Engine {
let custom_def = self.custom_syntax.get(key_token).ok_or_else(|| { let custom_def = self.custom_syntax.get(key_token).ok_or_else(|| {
Box::new(ERR::ErrorCustomSyntax( Box::new(ERR::ErrorCustomSyntax(
format!("Invalid custom syntax prefix: {}", key_token), format!("Invalid custom syntax prefix: {}", key_token),
custom.tokens.iter().map(|s| s.to_string()).collect(), custom.tokens.iter().map(<_>::to_string).collect(),
*pos, *pos,
)) ))
})?; })?;

View File

@ -284,26 +284,26 @@ impl GlobalRuntimeState<'_> {
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use] #[must_use]
pub(crate) fn hash_idx_get(&mut self) -> u64 { pub(crate) fn hash_idx_get(&mut self) -> u64 {
if self.fn_hash_indexing != (0, 0) { if self.fn_hash_indexing == (0, 0) {
self.fn_hash_indexing.0
} else {
let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2); let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2);
let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3); let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3);
self.fn_hash_indexing = (n1, n2); self.fn_hash_indexing = (n1, n2);
n1 n1
} else {
self.fn_hash_indexing.0
} }
} }
/// Get the pre-calculated index setter hash. /// Get the pre-calculated index setter hash.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[must_use] #[must_use]
pub(crate) fn hash_idx_set(&mut self) -> u64 { pub(crate) fn hash_idx_set(&mut self) -> u64 {
if self.fn_hash_indexing != (0, 0) { if self.fn_hash_indexing == (0, 0) {
self.fn_hash_indexing.1
} else {
let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2); let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2);
let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3); let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3);
self.fn_hash_indexing = (n1, n2); self.fn_hash_indexing = (n1, n2);
n2 n2
} else {
self.fn_hash_indexing.1
} }
} }
} }

View File

@ -368,21 +368,21 @@ impl Engine {
match guard_val { match guard_val {
Ok(true) => { Ok(true) => {
if !if_block.is_empty() { if if_block.is_empty() {
Ok(Dynamic::UNIT)
} else {
self.eval_stmt_block( self.eval_stmt_block(
scope, global, caches, lib, this_ptr, if_block, true, level, scope, global, caches, lib, this_ptr, if_block, true, level,
) )
} else {
Ok(Dynamic::UNIT)
} }
} }
Ok(false) => { Ok(false) => {
if !else_block.is_empty() { if else_block.is_empty() {
Ok(Dynamic::UNIT)
} else {
self.eval_stmt_block( self.eval_stmt_block(
scope, global, caches, lib, this_ptr, else_block, true, level, scope, global, caches, lib, this_ptr, else_block, true, level,
) )
} else {
Ok(Dynamic::UNIT)
} }
} }
err => err.map(Into::into), err => err.map(Into::into),
@ -510,7 +510,10 @@ impl Engine {
Stmt::While(x, ..) if matches!(x.0, Expr::Unit(..)) => loop { Stmt::While(x, ..) if matches!(x.0, Expr::Unit(..)) => loop {
let (.., body) = &**x; let (.., body) = &**x;
if !body.is_empty() { if body.is_empty() {
#[cfg(not(feature = "unchecked"))]
self.inc_operations(&mut global.num_operations, body.position())?;
} else {
match self match self
.eval_stmt_block(scope, global, caches, lib, this_ptr, body, true, level) .eval_stmt_block(scope, global, caches, lib, this_ptr, body, true, level)
{ {
@ -521,9 +524,6 @@ impl Engine {
_ => break Err(err), _ => break Err(err),
}, },
} }
} else {
#[cfg(not(feature = "unchecked"))]
self.inc_operations(&mut global.num_operations, body.position())?;
} }
}, },
@ -624,11 +624,11 @@ impl Engine {
if let Some(func) = func { if let Some(func) = func {
// Add the loop variables // Add the loop variables
let orig_scope_len = scope.len(); let orig_scope_len = scope.len();
let counter_index = if !counter.is_empty() { let counter_index = if counter.is_empty() {
usize::MAX
} else {
scope.push(counter.name.clone(), 0 as INT); scope.push(counter.name.clone(), 0 as INT);
scope.len() - 1 scope.len() - 1
} else {
usize::MAX
}; };
scope.push(var_name.name.clone(), ()); scope.push(var_name.name.clone(), ());
@ -979,13 +979,13 @@ impl Engine {
if let Ok(module) = module_result { if let Ok(module) = module_result {
if !export.is_empty() { if !export.is_empty() {
if !module.is_indexed() { if module.is_indexed() {
global.push_import(export.name.clone(), module);
} else {
// Index the module (making a clone copy if necessary) if it is not indexed // Index the module (making a clone copy if necessary) if it is not indexed
let mut m = crate::func::shared_take_or_clone(module); let mut m = crate::func::shared_take_or_clone(module);
m.build_index(); m.build_index();
global.push_import(export.name.clone(), m); global.push_import(export.name.clone(), m);
} else {
global.push_import(export.name.clone(), module);
} }
} }

View File

@ -287,7 +287,7 @@ pub fn get_builtin_binary_op_fn(op: &str, x: &Dynamic, y: &Dynamic) -> Option<Fn
return match op { return match op {
OP_CONTAINS => Some(|_, args| { OP_CONTAINS => Some(|_, args| {
let blob = &*args[0].read_lock::<Blob>().expect(BUILTIN); let blob = &*args[0].read_lock::<Blob>().expect(BUILTIN);
let x = (args[1].as_int().expect("`INT`") & 0x000000ff) as u8; let x = (args[1].as_int().expect("`INT`") & 0x0000_00ff) as u8;
Ok((!blob.is_empty() && blob.contains(&x)).into()) Ok((!blob.is_empty() && blob.contains(&x)).into())
}), }),
_ => None, _ => None,
@ -517,16 +517,14 @@ pub fn get_builtin_binary_op_fn(op: &str, x: &Dynamic, y: &Dynamic) -> Option<Fn
let blob1 = &*args[0].read_lock::<Blob>().expect(BUILTIN); let blob1 = &*args[0].read_lock::<Blob>().expect(BUILTIN);
let blob2 = &*args[1].read_lock::<Blob>().expect(BUILTIN); let blob2 = &*args[1].read_lock::<Blob>().expect(BUILTIN);
Ok(Dynamic::from_blob(if !blob2.is_empty() { Ok(Dynamic::from_blob(if blob2.is_empty() {
if blob1.is_empty() {
blob2.clone()
} else {
let mut blob = blob1.clone();
blob.extend(blob2);
blob
}
} else {
blob1.clone() blob1.clone()
} else if blob1.is_empty() {
blob2.clone()
} else {
let mut blob = blob1.clone();
blob.extend(blob2);
blob
})) }))
}), }),
"==" => Some(impl_op!(Blob == Blob)), "==" => Some(impl_op!(Blob == Blob)),

View File

@ -140,10 +140,10 @@ impl Engine {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let (ns, sep) = ( let (ns, sep) = (
namespace.to_string(), namespace.to_string(),
if !namespace.is_empty() { if namespace.is_empty() {
crate::tokenizer::Token::DoubleColon.literal_syntax()
} else {
"" ""
} else {
crate::tokenizer::Token::DoubleColon.literal_syntax()
}, },
); );
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
@ -169,7 +169,7 @@ impl Engine {
/// ///
/// Search order: /// Search order:
/// 1) AST - script functions in the AST /// 1) AST - script functions in the AST
/// 2) Global namespace - functions registered via Engine::register_XXX /// 2) Global namespace - functions registered via `Engine::register_XXX`
/// 3) Global registered modules - packages /// 3) Global registered modules - packages
/// 4) Imported modules - functions marked with global namespace /// 4) Imported modules - functions marked with global namespace
/// 5) Static registered modules /// 5) Static registered modules
@ -280,16 +280,7 @@ impl Engine {
} }
return args.and_then(|args| { return args.and_then(|args| {
if !is_op_assignment { if is_op_assignment {
get_builtin_binary_op_fn(fn_name, args[0], args[1]).map(|f| {
FnResolutionCacheEntry {
func: CallableFunction::from_method(
Box::new(f) as Box<FnAny>
),
source: None,
}
})
} else {
let (first_arg, rest_args) = args.split_first().unwrap(); let (first_arg, rest_args) = args.split_first().unwrap();
get_builtin_op_assignment_fn(fn_name, *first_arg, rest_args[0]).map( get_builtin_op_assignment_fn(fn_name, *first_arg, rest_args[0]).map(
@ -300,6 +291,15 @@ impl Engine {
source: None, source: None,
}, },
) )
} else {
get_builtin_binary_op_fn(fn_name, args[0], args[1]).map(|f| {
FnResolutionCacheEntry {
func: CallableFunction::from_method(
Box::new(f) as Box<FnAny>
),
source: None,
}
})
} }
}); });
} }
@ -312,11 +312,11 @@ impl Engine {
.enumerate() .enumerate()
.map(|(i, a)| { .map(|(i, a)| {
let mask = 1usize << (num_args - i - 1); let mask = 1usize << (num_args - i - 1);
if bitmask & mask != 0 { if bitmask & mask == 0 {
a.type_id()
} else {
// Replace with `Dynamic` // Replace with `Dynamic`
TypeId::of::<Dynamic>() TypeId::of::<Dynamic>()
} else {
a.type_id()
} }
}), }),
); );
@ -371,7 +371,7 @@ impl Engine {
); );
if func.is_some() { if func.is_some() {
let is_method = func.map(|f| f.func.is_method()).unwrap_or(false); let is_method = func.map_or(false, |f| f.func.is_method());
// Push a new call stack frame // Push a new call stack frame
#[cfg(feature = "debugging")] #[cfg(feature = "debugging")]
@ -680,8 +680,7 @@ impl Engine {
&mut global.source, &mut global.source,
source source
.as_ref() .as_ref()
.map(|s| (**s).clone()) .map_or(crate::Identifier::new_const(), |s| (**s).clone()),
.unwrap_or(crate::Identifier::new_const()),
); );
let result = if _is_method_call { let result = if _is_method_call {
@ -841,14 +840,12 @@ impl Engine {
) )
} }
KEYWORD_FN_PTR_CALL => { KEYWORD_FN_PTR_CALL => {
if !call_args.is_empty() { if call_args.is_empty() {
if !call_args[0].is::<FnPtr>() {
let typ = self.map_type_name(call_args[0].type_name());
return Err(self.make_type_mismatch_err::<FnPtr>(typ, first_arg_pos));
}
} else {
let typ = self.map_type_name(target.type_name()); let typ = self.map_type_name(target.type_name());
return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos)); return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos));
} else if !call_args[0].is::<FnPtr>() {
let typ = self.map_type_name(call_args[0].type_name());
return Err(self.make_type_mismatch_err::<FnPtr>(typ, first_arg_pos));
} }
// FnPtr call on object // FnPtr call on object
@ -1036,10 +1033,10 @@ impl Engine {
// Recalculate hash // Recalculate hash
let args_len = total_args + curry.len(); let args_len = total_args + curry.len();
hashes = if !hashes.is_native_only() { hashes = if hashes.is_native_only() {
calc_fn_hash(name, args_len).into()
} else {
FnCallHashes::from_native(calc_fn_hash(name, args_len)) FnCallHashes::from_native(calc_fn_hash(name, args_len))
} else {
calc_fn_hash(name, args_len).into()
}; };
} }
// Handle Fn() // Handle Fn()
@ -1236,7 +1233,7 @@ impl Engine {
if target_is_shared || target.is_temp_value() { if target_is_shared || target.is_temp_value() {
arg_values.insert(0, target.take_or_clone().flatten()); arg_values.insert(0, target.take_or_clone().flatten());
args.extend(arg_values.iter_mut()) args.extend(arg_values.iter_mut());
} else { } else {
// Turn it into a method call only if the object is not shared and not a simple value // Turn it into a method call only if the object is not shared and not a simple value
is_ref_mut = true; is_ref_mut = true;
@ -1370,11 +1367,11 @@ impl Engine {
while bitmask < max_bitmask { while bitmask < max_bitmask {
let hash_params = calc_fn_params_hash(args.iter().enumerate().map(|(i, a)| { let hash_params = calc_fn_params_hash(args.iter().enumerate().map(|(i, a)| {
let mask = 1usize << (num_args - i - 1); let mask = 1usize << (num_args - i - 1);
if bitmask & mask != 0 { if bitmask & mask == 0 {
a.type_id()
} else {
// Replace with `Dynamic` // Replace with `Dynamic`
TypeId::of::<Dynamic>() TypeId::of::<Dynamic>()
} else {
a.type_id()
} }
})); }));
let hash_qualified_fn = combine_hashes(hash, hash_params); let hash_qualified_fn = combine_hashes(hash, hash_params);
@ -1392,7 +1389,7 @@ impl Engine {
} }
// Clone first argument if the function is not a method after-all // Clone first argument if the function is not a method after-all
if !func.map(|f| f.is_method()).unwrap_or(true) { if !func.map_or(true, CallableFunction::is_method) {
if let Some(first) = first_arg_value { if let Some(first) = first_arg_value {
*first = args[0].clone(); *first = args[0].clone();
args[0] = first; args[0] = first;

View File

@ -47,7 +47,7 @@ impl Hasher for StraightHasher {
self.0 = u64::from_ne_bytes(key); self.0 = u64::from_ne_bytes(key);
if self.0 == 0 { if self.0 == 0 {
self.0 = ALT_ZERO_HASH self.0 = ALT_ZERO_HASH;
} }
} }
} }
@ -175,7 +175,7 @@ pub fn calc_fn_params_hash(params: impl IntoIterator<Item = TypeId>) -> u64 {
let mut len = 0; let mut len = 0;
params.into_iter().for_each(|t| { params.into_iter().for_each(|t| {
len += 1; len += 1;
t.hash(s) t.hash(s);
}); });
len.hash(s); len.hash(s);

View File

@ -252,7 +252,7 @@ impl<'a> NativeCallContext<'a> {
/// in reverse order. /// in reverse order.
#[inline] #[inline]
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> { pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().rev().cloned() self.lib.iter().rev().copied()
} }
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions. /// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.

View File

@ -28,7 +28,7 @@ use std::{any::TypeId, mem};
pub struct Mut<T>(T); pub struct Mut<T>(T);
//pub struct Ref<T>(T); //pub struct Ref<T>(T);
/// Dereference into DynamicWriteLock /// Dereference into [`DynamicWriteLock`]
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<T> { pub fn by_ref<T: Variant + Clone>(data: &mut Dynamic) -> DynamicWriteLock<T> {

View File

@ -128,7 +128,7 @@ impl Engine {
} else { } else {
caches.push_fn_resolution_cache(); caches.push_fn_resolution_cache();
lib_merged.push(&**fn_lib); lib_merged.push(&**fn_lib);
lib_merged.extend(lib.iter().cloned()); lib_merged.extend(lib.iter().copied());
&lib_merged &lib_merged
}, },
Some(mem::replace(&mut global.constants, constants.clone())), Some(mem::replace(&mut global.constants, constants.clone())),
@ -205,7 +205,7 @@ impl Engine {
scope.rewind(orig_scope_len); scope.rewind(orig_scope_len);
} else if !args.is_empty() { } else if !args.is_empty() {
// Remove arguments only, leaving new variables in the scope // Remove arguments only, leaving new variables in the scope
scope.remove_range(orig_scope_len, args.len()) scope.remove_range(orig_scope_len, args.len());
} }
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
global.truncate_imports(orig_imports_len); global.truncate_imports(orig_imports_len);
@ -233,7 +233,7 @@ impl Engine {
) -> bool { ) -> bool {
let cache = caches.fn_resolution_cache_mut(); let cache = caches.fn_resolution_cache_mut();
if let Some(result) = cache.get(&hash_script).map(|v| v.is_some()) { if let Some(result) = cache.get(&hash_script).map(Option::is_some) {
return result; return result;
} }

View File

@ -8,7 +8,7 @@ use crate::func::{
use crate::types::{dynamic::Variant, CustomTypesCollection}; use crate::types::{dynamic::Variant, CustomTypesCollection};
use crate::{ use crate::{
calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes, Dynamic, Identifier, calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes, Dynamic, Identifier,
ImmutableString, NativeCallContext, RhaiResultOf, Shared, StaticVec, ImmutableString, NativeCallContext, RhaiResultOf, Shared, SmartString, StaticVec,
}; };
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
@ -181,7 +181,15 @@ impl FuncInfo {
let return_type = Self::format_type(&self.metadata.return_type, true); let return_type = Self::format_type(&self.metadata.return_type, true);
if !self.metadata.params_info.is_empty() { if self.metadata.params_info.is_empty() {
for x in 0..self.metadata.params {
sig.push('_');
if x < self.metadata.params - 1 {
sig.push_str(", ");
}
}
sig.push(')');
} else {
let params: StaticVec<_> = self let params: StaticVec<_> = self
.metadata .metadata
.params_info .params_info
@ -203,14 +211,6 @@ impl FuncInfo {
.collect(); .collect();
sig.push_str(&params.join(", ")); sig.push_str(&params.join(", "));
sig.push(')'); sig.push(')');
} else {
for x in 0..self.metadata.params {
sig.push('_');
if x < self.metadata.params - 1 {
sig.push_str(", ");
}
}
sig.push(')');
} }
if !self.func.is_script() && !return_type.is_empty() { if !self.func.is_script() && !return_type.is_empty() {
@ -238,7 +238,7 @@ pub fn calc_native_fn_hash<'a>(
params: &[TypeId], params: &[TypeId],
) -> u64 { ) -> u64 {
let hash_script = calc_qualified_fn_hash(modules, fn_name, params.len()); let hash_script = calc_qualified_fn_hash(modules, fn_name, params.len());
let hash_params = calc_fn_params_hash(params.iter().cloned()); let hash_params = calc_fn_params_hash(params.iter().copied());
combine_hashes(hash_script, hash_params) combine_hashes(hash_script, hash_params)
} }
@ -298,7 +298,7 @@ impl fmt::Debug for Module {
&self &self
.modules .modules
.keys() .keys()
.map(|m| m.as_str()) .map(SmartString::as_str)
.collect::<BTreeSet<_>>(), .collect::<BTreeSet<_>>(),
) )
.field("vars", &self.variables) .field("vars", &self.variables)
@ -584,6 +584,7 @@ impl Module {
/// assert_eq!(module.get_custom_type(name), Some("MyType")); /// assert_eq!(module.get_custom_type(name), Some("MyType"));
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use]
pub fn get_custom_type(&self, key: &str) -> Option<&str> { pub fn get_custom_type(&self, key: &str) -> Option<&str> {
self.custom_types.get(key) self.custom_types.get(key)
} }
@ -647,7 +648,7 @@ impl Module {
FnAccess::Public => true, FnAccess::Public => true,
FnAccess::Private => false, FnAccess::Private => false,
}) })
.map(|f| f.gen_signature()) .map(FuncInfo::gen_signature)
} }
/// Does a variable exist in the [`Module`]? /// Does a variable exist in the [`Module`]?
@ -663,10 +664,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_var(&self, name: &str) -> bool { pub fn contains_var(&self, name: &str) -> bool {
if !self.variables.is_empty() { if self.variables.is_empty() {
self.variables.contains_key(name)
} else {
false false
} else {
self.variables.contains_key(name)
} }
} }
@ -699,10 +700,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn get_var(&self, name: &str) -> Option<Dynamic> { pub fn get_var(&self, name: &str) -> Option<Dynamic> {
if !self.variables.is_empty() { if self.variables.is_empty() {
self.variables.get(name).cloned()
} else {
None None
} else {
self.variables.get(name).cloned()
} }
} }
@ -739,10 +740,10 @@ impl Module {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline] #[inline]
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Option<Dynamic> { pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Option<Dynamic> {
if !self.all_variables.is_empty() { if self.all_variables.is_empty() {
self.all_variables.get(&hash_var).cloned()
} else {
None None
} else {
self.all_variables.get(&hash_var).cloned()
} }
} }
@ -794,14 +795,14 @@ impl Module {
name: impl AsRef<str>, name: impl AsRef<str>,
num_params: usize, num_params: usize,
) -> Option<&Shared<crate::ast::ScriptFnDef>> { ) -> Option<&Shared<crate::ast::ScriptFnDef>> {
if !self.functions.is_empty() { if self.functions.is_empty() {
None
} else {
let name = name.as_ref(); let name = name.as_ref();
self.iter_fn() self.iter_fn()
.find(|f| f.metadata.params == num_params && f.metadata.name == name) .find(|f| f.metadata.params == num_params && f.metadata.name == name)
.and_then(|f| f.func.get_script_fn_def()) .and_then(|f| f.func.get_script_fn_def())
} else {
None
} }
} }
@ -840,10 +841,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_sub_module(&self, name: &str) -> bool { pub fn contains_sub_module(&self, name: &str) -> bool {
if !self.modules.is_empty() { if self.modules.is_empty() {
self.modules.contains_key(name)
} else {
false false
} else {
self.modules.contains_key(name)
} }
} }
@ -861,10 +862,10 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn get_sub_module(&self, name: &str) -> Option<&Module> { pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
if !self.modules.is_empty() { if self.modules.is_empty() {
self.modules.get(name).map(|m| &**m)
} else {
None None
} else {
self.modules.get(name).map(|m| &**m)
} }
} }
@ -908,10 +909,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_fn(&self, hash_fn: u64) -> bool { pub fn contains_fn(&self, hash_fn: u64) -> bool {
if !self.functions.is_empty() { if self.functions.is_empty() {
self.functions.contains_key(&hash_fn)
} else {
false false
} else {
self.functions.contains_key(&hash_fn)
} }
} }
@ -1061,7 +1062,7 @@ impl Module {
let mut param_types: StaticVec<_> = arg_types let mut param_types: StaticVec<_> = arg_types
.as_ref() .as_ref()
.iter() .iter()
.cloned() .copied()
.enumerate() .enumerate()
.map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id)) .map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id))
.collect(); .collect();
@ -1327,8 +1328,10 @@ impl Module {
where where
A: Variant + Clone, A: Variant + Clone,
T: Variant + Clone, T: Variant + Clone,
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>, F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
F: Fn(&mut A) -> RhaiResultOf<T> + SendSync + 'static, + Fn(&mut A) -> RhaiResultOf<T>
+ SendSync
+ 'static,
{ {
self.set_fn( self.set_fn(
crate::engine::make_getter(name.as_ref()).as_str(), crate::engine::make_getter(name.as_ref()).as_str(),
@ -1369,8 +1372,10 @@ impl Module {
where where
A: Variant + Clone, A: Variant + Clone,
B: Variant + Clone, B: Variant + Clone,
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>, F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
F: Fn(&mut A, B) -> RhaiResultOf<()> + SendSync + 'static, + Fn(&mut A, B) -> RhaiResultOf<()>
+ SendSync
+ 'static,
{ {
self.set_fn( self.set_fn(
crate::engine::make_setter(name.as_ref()).as_str(), crate::engine::make_setter(name.as_ref()).as_str(),
@ -1416,8 +1421,10 @@ impl Module {
A: Variant + Clone, A: Variant + Clone,
B: Variant + Clone, B: Variant + Clone,
T: Variant + Clone, T: Variant + Clone,
F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>, F: RegisterNativeFunction<ARGS, RhaiResultOf<T>>
F: Fn(&mut A, B) -> RhaiResultOf<T> + SendSync + 'static, + Fn(&mut A, B) -> RhaiResultOf<T>
+ SendSync
+ 'static,
{ {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if TypeId::of::<A>() == TypeId::of::<crate::Array>() { if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
@ -1478,8 +1485,10 @@ impl Module {
A: Variant + Clone, A: Variant + Clone,
B: Variant + Clone, B: Variant + Clone,
C: Variant + Clone, C: Variant + Clone,
F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>, F: RegisterNativeFunction<ARGS, RhaiResultOf<()>>
F: Fn(&mut A, B, C) -> RhaiResultOf<()> + SendSync + 'static, + Fn(&mut A, B, C) -> RhaiResultOf<()>
+ SendSync
+ 'static,
{ {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if TypeId::of::<A>() == TypeId::of::<crate::Array>() { if TypeId::of::<A>() == TypeId::of::<crate::Array>() {
@ -1563,10 +1572,10 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub(crate) fn get_fn(&self, hash_native: u64) -> Option<&CallableFunction> { pub(crate) fn get_fn(&self, hash_native: u64) -> Option<&CallableFunction> {
if !self.functions.is_empty() { if self.functions.is_empty() {
self.functions.get(&hash_native).map(|f| &f.func)
} else {
None None
} else {
self.functions.get(&hash_native).map(|f| &f.func)
} }
} }
@ -1574,10 +1583,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub(crate) fn contains_dynamic_fn(&self, hash_script: u64) -> bool { pub(crate) fn contains_dynamic_fn(&self, hash_script: u64) -> bool {
if !self.dynamic_functions.is_empty() { if self.dynamic_functions.is_empty() {
self.dynamic_functions.contains(&hash_script)
} else {
false false
} else {
self.dynamic_functions.contains(&hash_script)
} }
} }
@ -1587,10 +1596,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool { pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
if !self.all_functions.is_empty() { if self.all_functions.is_empty() {
self.all_functions.contains_key(&hash_fn)
} else {
false false
} else {
self.all_functions.contains_key(&hash_fn)
} }
} }
@ -1601,10 +1610,10 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> { pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
if !self.all_functions.is_empty() { if self.all_functions.is_empty() {
self.all_functions.get(&hash_qualified_fn)
} else {
None None
} else {
self.all_functions.get(&hash_qualified_fn)
} }
} }
@ -1683,7 +1692,7 @@ impl Module {
self.functions.entry(k).or_insert_with(|| v.clone()); self.functions.entry(k).or_insert_with(|| v.clone());
} }
self.dynamic_functions self.dynamic_functions
.extend(other.dynamic_functions.iter().cloned()); .extend(other.dynamic_functions.iter().copied());
for (&k, v) in &other.type_iterators { for (&k, v) in &other.type_iterators {
self.type_iterators.entry(k).or_insert_with(|| v.clone()); self.type_iterators.entry(k).or_insert_with(|| v.clone());
} }
@ -1745,7 +1754,7 @@ impl Module {
); );
// This may introduce entries that are superfluous because the function has been filtered away. // This may introduce entries that are superfluous because the function has been filtered away.
self.dynamic_functions self.dynamic_functions
.extend(other.dynamic_functions.iter().cloned()); .extend(other.dynamic_functions.iter().copied());
self.type_iterators self.type_iterators
.extend(other.type_iterators.iter().map(|(&k, v)| (k, v.clone()))); .extend(other.type_iterators.iter().map(|(&k, v)| (k, v.clone())));
@ -2145,14 +2154,14 @@ impl Module {
if !f.func.is_script() { if !f.func.is_script() {
let hash_qualified_fn = calc_native_fn_hash( let hash_qualified_fn = calc_native_fn_hash(
path.iter().cloned(), path.iter().copied(),
f.metadata.name.as_str(), f.metadata.name.as_str(),
&f.param_types, &f.param_types,
); );
functions.insert(hash_qualified_fn, f.func.clone()); functions.insert(hash_qualified_fn, f.func.clone());
} else if cfg!(not(feature = "no_function")) { } else if cfg!(not(feature = "no_function")) {
let hash_qualified_script = crate::calc_qualified_fn_hash( let hash_qualified_script = crate::calc_qualified_fn_hash(
path.iter().cloned(), path.iter().copied(),
f.metadata.name.as_str(), f.metadata.name.as_str(),
f.metadata.params, f.metadata.params,
); );
@ -2192,10 +2201,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_qualified_iter(&self, id: TypeId) -> bool { pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
if !self.all_type_iterators.is_empty() { if self.all_type_iterators.is_empty() {
self.all_type_iterators.contains_key(&id)
} else {
false false
} else {
self.all_type_iterators.contains_key(&id)
} }
} }
@ -2203,10 +2212,10 @@ impl Module {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_iter(&self, id: TypeId) -> bool { pub fn contains_iter(&self, id: TypeId) -> bool {
if !self.type_iterators.is_empty() { if self.type_iterators.is_empty() {
self.type_iterators.contains_key(&id)
} else {
false false
} else {
self.type_iterators.contains_key(&id)
} }
} }
@ -2273,10 +2282,10 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<&IteratorFn> { pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<&IteratorFn> {
if !self.all_type_iterators.is_empty() { if self.all_type_iterators.is_empty() {
self.all_type_iterators.get(&id).map(|f| &**f)
} else {
None None
} else {
self.all_type_iterators.get(&id).map(|f| &**f)
} }
} }
@ -2284,10 +2293,10 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub(crate) fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> { pub(crate) fn get_iter(&self, id: TypeId) -> Option<&IteratorFn> {
if !self.type_iterators.is_empty() { if self.type_iterators.is_empty() {
self.type_iterators.get(&id).map(|f| &**f)
} else {
None None
} else {
self.type_iterators.get(&id).map(|f| &**f)
} }
} }
} }

View File

@ -42,7 +42,7 @@ impl ModuleResolversCollection {
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub const fn new() -> Self { pub fn new() -> Self {
Self(Vec::new()) Self(Vec::new())
} }
/// Append a [module resolver][ModuleResolver] to the end. /// Append a [module resolver][ModuleResolver] to the end.

View File

@ -31,6 +31,7 @@ impl DummyModuleResolver {
/// engine.set_module_resolver(resolver); /// engine.set_module_resolver(resolver);
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn new() -> Self { pub const fn new() -> Self {
Self Self
} }

View File

@ -244,10 +244,10 @@ impl FileModuleResolver {
let cache = locked_read(&self.cache); let cache = locked_read(&self.cache);
if !cache.is_empty() { if cache.is_empty() {
cache.contains_key(path.as_ref())
} else {
false false
} else {
cache.contains_key(path.as_ref())
} }
} }
/// Empty the internal cache. /// Empty the internal cache.
@ -277,7 +277,7 @@ impl FileModuleResolver {
file_path = self file_path = self
.base_path .base_path
.clone() .clone()
.or_else(|| source_path.map(|p| p.into())) .or_else(|| source_path.map(Into::into))
.unwrap_or_default(); .unwrap_or_default();
file_path.push(path); file_path.push(path);
} else { } else {

View File

@ -66,10 +66,10 @@ impl StaticModuleResolver {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn contains_path(&self, path: &str) -> bool { pub fn contains_path(&self, path: &str) -> bool {
if !self.0.is_empty() { if self.0.is_empty() {
self.0.contains_key(path)
} else {
false false
} else {
self.0.contains_key(path)
} }
} }
/// Get an iterator of all the [modules][Module]. /// Get an iterator of all the [modules][Module].
@ -85,7 +85,7 @@ impl StaticModuleResolver {
/// Get an iterator of all the [module][Module] paths. /// Get an iterator of all the [module][Module] paths.
#[inline] #[inline]
pub fn paths(&self) -> impl Iterator<Item = &str> { pub fn paths(&self) -> impl Iterator<Item = &str> {
self.0.keys().map(|s| s.as_str()) self.0.keys().map(SmartString::as_str)
} }
/// Get an iterator of all the [modules][Module]. /// Get an iterator of all the [modules][Module].
#[inline(always)] #[inline(always)]
@ -100,6 +100,7 @@ impl StaticModuleResolver {
} }
/// Is this [`StaticModuleResolver`] empty? /// Is this [`StaticModuleResolver`] empty?
#[inline(always)] #[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.0.is_empty() self.0.is_empty()
} }

View File

@ -103,7 +103,7 @@ impl<'a> OptimizerState<'a> {
/// Prune the list of constants back to a specified size. /// Prune the list of constants back to a specified size.
#[inline(always)] #[inline(always)]
pub fn restore_var(&mut self, len: usize) { pub fn restore_var(&mut self, len: usize) {
self.variables.truncate(len) self.variables.truncate(len);
} }
/// Add a new variable to the list. /// Add a new variable to the list.
#[inline(always)] #[inline(always)]
@ -113,7 +113,7 @@ impl<'a> OptimizerState<'a> {
access: AccessMode, access: AccessMode,
value: Option<Dynamic>, 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.
#[inline] #[inline]
@ -169,7 +169,7 @@ fn has_native_fn_override(
hash_script: u64, hash_script: u64,
arg_types: impl AsRef<[TypeId]>, arg_types: impl AsRef<[TypeId]>,
) -> bool { ) -> bool {
let hash_params = calc_fn_params_hash(arg_types.as_ref().iter().cloned()); let hash_params = calc_fn_params_hash(arg_types.as_ref().iter().copied());
let hash = combine_hashes(hash_script, hash_params); let hash = combine_hashes(hash_script, hash_params);
// First check the global namespace and packages, but skip modules that are standard because // First check the global namespace and packages, but skip modules that are standard because
@ -433,7 +433,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
if !x.0.is_op_assignment() if !x.0.is_op_assignment()
&& x.1.lhs.is_variable_access(true) && x.1.lhs.is_variable_access(true)
&& matches!(&x.1.rhs, Expr::FnCall(x2, ..) && matches!(&x.1.rhs, Expr::FnCall(x2, ..)
if Token::lookup_from_syntax(&x2.name).map(|t| t.has_op_assignment()).unwrap_or(false) if Token::lookup_from_syntax(&x2.name).map_or(false, |t| t.has_op_assignment())
&& x2.args.len() == 2 && x2.args.len() == 2
&& x2.args[0].get_variable_name(true) == x.1.lhs.get_variable_name(true) && x2.args[0].get_variable_name(true) == x.1.lhs.get_variable_name(true)
) => ) =>
@ -721,12 +721,11 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
} }
} }
// Remove if no entry left // Remove if no entry left
match list.is_empty() { if list.is_empty() {
true => { state.set_dirty();
state.set_dirty(); false
false } else {
} true
false => true,
} }
}); });
@ -766,7 +765,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
Stmt::While(x, ..) if matches!(x.0, Expr::BoolConstant(false, ..)) => match x.0 { Stmt::While(x, ..) if matches!(x.0, Expr::BoolConstant(false, ..)) => match x.0 {
Expr::BoolConstant(false, pos) => { Expr::BoolConstant(false, pos) => {
state.set_dirty(); state.set_dirty();
*stmt = Stmt::Noop(pos) *stmt = Stmt::Noop(pos);
} }
_ => unreachable!("`Expr::BoolConstant"), _ => unreachable!("`Expr::BoolConstant"),
}, },
@ -785,14 +784,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
Stmt::BreakLoop(options, pos) if options.contains(ASTFlags::BREAK) => { Stmt::BreakLoop(options, pos) if options.contains(ASTFlags::BREAK) => {
// Only a single break statement - turn into running the guard expression once // Only a single break statement - turn into running the guard expression once
state.set_dirty(); state.set_dirty();
if !condition.is_unit() { if condition.is_unit() {
*stmt = Stmt::Noop(pos);
} else {
let mut statements = vec![Stmt::Expr(mem::take(condition).into())]; let mut statements = vec![Stmt::Expr(mem::take(condition).into())];
if preserve_result { if preserve_result {
statements.push(Stmt::Noop(pos)) statements.push(Stmt::Noop(pos));
} }
*stmt = (statements, Span::new(pos, Position::NONE)).into(); *stmt = (statements, Span::new(pos, Position::NONE)).into();
} else {
*stmt = Stmt::Noop(pos);
}; };
} }
_ => (), _ => (),
@ -835,7 +834,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
} }
// let id = expr; // let id = expr;
Stmt::Var(x, options, ..) if !options.contains(ASTFlags::CONSTANT) => { Stmt::Var(x, options, ..) if !options.contains(ASTFlags::CONSTANT) => {
optimize_expr(&mut x.1, state, false) optimize_expr(&mut x.1, state, false);
} }
// import expr as var; // import expr as var;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -969,8 +968,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
// All other items can be thrown away. // All other items can be thrown away.
state.set_dirty(); state.set_dirty();
*expr = mem::take(&mut m.0).into_iter().find(|(x, ..)| x.as_str() == prop) *expr = mem::take(&mut m.0).into_iter().find(|(x, ..)| x.as_str() == prop)
.map(|(.., mut expr)| { expr.set_position(*pos); expr }) .map_or_else(|| Expr::Unit(*pos), |(.., mut expr)| { expr.set_position(*pos); expr });
.unwrap_or_else(|| Expr::Unit(*pos));
} }
// var.rhs // var.rhs
(Expr::Variable(..), rhs) => optimize_expr(rhs, state, true), (Expr::Variable(..), rhs) => optimize_expr(rhs, state, true),
@ -1015,8 +1013,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
// All other items can be thrown away. // All other items can be thrown away.
state.set_dirty(); state.set_dirty();
*expr = mem::take(&mut m.0).into_iter().find(|(x, ..)| x.as_str() == s.as_str()) *expr = mem::take(&mut m.0).into_iter().find(|(x, ..)| x.as_str() == s.as_str())
.map(|(.., mut expr)| { expr.set_position(*pos); expr }) .map_or_else(|| Expr::Unit(*pos), |(.., mut expr)| { expr.set_position(*pos); expr });
.unwrap_or_else(|| Expr::Unit(*pos));
} }
// int[int] // int[int]
(Expr::IntegerConstant(n, pos), Expr::IntegerConstant(i, ..)) if *i >= 0 && (*i as usize) < crate::INT_BITS => { (Expr::IntegerConstant(n, pos), Expr::IntegerConstant(i, ..)) if *i >= 0 && (*i as usize) < crate::INT_BITS => {
@ -1148,7 +1145,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
_ => Dynamic::UNIT _ => Dynamic::UNIT
}; };
if let Ok(fn_ptr) = fn_name.into_immutable_string().map_err(|err| err.into()).and_then(FnPtr::try_from) { if let Ok(fn_ptr) = fn_name.into_immutable_string().map_err(Into::into).and_then(FnPtr::try_from) {
state.set_dirty(); state.set_dirty();
*expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos); *expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
} else { } else {
@ -1338,10 +1335,10 @@ fn optimize_top_level(
// 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::ReadWrite, None);
} else {
state.push_var(name, AccessMode::ReadOnly, Some(value)); state.push_var(name, AccessMode::ReadOnly, Some(value));
} else {
state.push_var(name, AccessMode::ReadWrite, None);
} }
} }

View File

@ -145,16 +145,14 @@ pub mod array_functions {
/// ``` /// ```
#[rhai_fn(name = "+")] #[rhai_fn(name = "+")]
pub fn concat(array1: Array, array2: Array) -> Array { pub fn concat(array1: Array, array2: Array) -> Array {
if !array2.is_empty() { if array2.is_empty() {
if array1.is_empty() {
array2
} else {
let mut array = array1;
array.extend(array2);
array
}
} else {
array1 array1
} else if array1.is_empty() {
array2
} else {
let mut array = array1;
array.extend(array2);
array
} }
} }
/// Add a new element into the array at a particular `index` position. /// Add a new element into the array at a particular `index` position.
@ -432,7 +430,7 @@ pub mod array_functions {
pub fn splice_range(array: &mut Array, range: ExclusiveRange, replace: Array) { pub fn splice_range(array: &mut Array, range: ExclusiveRange, replace: Array) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
splice(array, start, end - start, replace) splice(array, start, end - start, replace);
} }
/// Replace an inclusive range of the array with another array. /// Replace an inclusive range of the array with another array.
/// ///
@ -450,7 +448,7 @@ pub mod array_functions {
pub fn splice_inclusive_range(array: &mut Array, range: InclusiveRange, replace: Array) { pub fn splice_inclusive_range(array: &mut Array, range: InclusiveRange, replace: Array) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
splice(array, start, end - start + 1, replace) splice(array, start, end - start + 1, replace);
} }
/// Replace a portion of the array with another array. /// Replace a portion of the array with another array.
/// ///
@ -1739,13 +1737,15 @@ pub mod array_functions {
.call_raw(&ctx, None, [x.clone(), y.clone()]) .call_raw(&ctx, None, [x.clone(), y.clone()])
.ok() .ok()
.and_then(|v| v.as_int().ok()) .and_then(|v| v.as_int().ok())
.map(|v| match v { .map_or_else(
v if v > 0 => Ordering::Greater, || x.type_id().cmp(&y.type_id()),
v if v < 0 => Ordering::Less, |v| match v {
0 => Ordering::Equal, v if v > 0 => Ordering::Greater,
_ => unreachable!("v is {}", v), v if v < 0 => Ordering::Less,
}) 0 => Ordering::Equal,
.unwrap_or_else(|| x.type_id().cmp(&y.type_id())) _ => unreachable!("v is {}", v),
},
)
}); });
Ok(()) Ok(())
@ -2119,7 +2119,7 @@ pub mod array_functions {
let mut x = 0; let mut x = 0;
while x < array.len() { while x < array.len() {
if !filter if filter
.call_raw(&ctx, None, [array[x].clone()]) .call_raw(&ctx, None, [array[x].clone()])
.or_else(|err| match *err { .or_else(|err| match *err {
ERR::ErrorFunctionNotFound(fn_sig, ..) ERR::ErrorFunctionNotFound(fn_sig, ..)
@ -2140,9 +2140,9 @@ pub mod array_functions {
.as_bool() .as_bool()
.unwrap_or(false) .unwrap_or(false)
{ {
drained.push(array.remove(x));
} else {
x += 1; x += 1;
} else {
drained.push(array.remove(x));
} }
i += 1; i += 1;

View File

@ -86,7 +86,7 @@ pub mod blob_functions {
} }
let mut blob = Blob::new(); let mut blob = Blob::new();
blob.resize(len, (value & 0x000000ff) as u8); blob.resize(len, (value & 0x0000_00ff) as u8);
Ok(blob) Ok(blob)
} }
/// Convert the BLOB into an array of integers. /// Convert the BLOB into an array of integers.
@ -205,7 +205,7 @@ pub mod blob_functions {
let (index, ..) = calc_offset_len(blob.len(), index, 0); let (index, ..) = calc_offset_len(blob.len(), index, 0);
if index < blob.len() { if index < blob.len() {
blob[index] = (value & 0x000000ff) as u8; blob[index] = (value & 0x0000_00ff) as u8;
} }
} }
/// Add a new byte `value` to the end of the BLOB. /// Add a new byte `value` to the end of the BLOB.
@ -223,7 +223,7 @@ pub mod blob_functions {
/// ``` /// ```
#[rhai_fn(name = "push", name = "append")] #[rhai_fn(name = "push", name = "append")]
pub fn push(blob: &mut Blob, value: INT) { pub fn push(blob: &mut Blob, value: INT) {
blob.push((value & 0x000000ff) as u8); blob.push((value & 0x0000_00ff) as u8);
} }
/// Add another BLOB to the end of the BLOB. /// Add another BLOB to the end of the BLOB.
/// ///
@ -298,7 +298,7 @@ pub mod blob_functions {
/// print(b); // prints "[4242184242]" /// print(b); // prints "[4242184242]"
/// ``` /// ```
pub fn insert(blob: &mut Blob, index: INT, value: INT) { pub fn insert(blob: &mut Blob, index: INT, value: INT) {
let value = (value & 0x000000ff) as u8; let value = (value & 0x0000_00ff) as u8;
if blob.is_empty() { if blob.is_empty() {
blob.push(value); blob.push(value);
@ -338,7 +338,7 @@ pub mod blob_functions {
return Ok(()); return Ok(());
} }
let value = (value & 0x000000ff) as u8; let value = (value & 0x0000_00ff) as u8;
let _ctx = ctx; let _ctx = ctx;
// Check if blob will be over max size limit // Check if blob will be over max size limit
@ -528,7 +528,7 @@ pub mod blob_functions {
pub fn splice_range(blob: &mut Blob, range: ExclusiveRange, replace: Blob) { pub fn splice_range(blob: &mut Blob, range: ExclusiveRange, replace: Blob) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
splice(blob, start, end - start, replace) splice(blob, start, end - start, replace);
} }
/// Replace an inclusive `range` of the BLOB with another BLOB. /// Replace an inclusive `range` of the BLOB with another BLOB.
/// ///
@ -546,7 +546,7 @@ pub mod blob_functions {
pub fn splice_range_inclusive(blob: &mut Blob, range: InclusiveRange, replace: Blob) { pub fn splice_range_inclusive(blob: &mut Blob, range: InclusiveRange, replace: Blob) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
splice(blob, start, end - start + 1, replace) splice(blob, start, end - start + 1, replace);
} }
/// Replace a portion of the BLOB with another BLOB. /// Replace a portion of the BLOB with another BLOB.
/// ///
@ -1220,7 +1220,7 @@ mod write_int_functions {
pub fn write_le_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) { pub fn write_le_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_le_int(blob, start, end - start, value) write_le_int(blob, start, end - start, value);
} }
/// Write an `INT` value to the bytes within an inclusive `range` in the BLOB /// Write an `INT` value to the bytes within an inclusive `range` in the BLOB
/// in little-endian byte order. /// in little-endian byte order.
@ -1239,7 +1239,7 @@ mod write_int_functions {
pub fn write_le_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) { pub fn write_le_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_le_int(blob, start, end - start + 1, value) write_le_int(blob, start, end - start + 1, value);
} }
/// Write an `INT` value to the bytes beginning at the `start` position in the BLOB /// Write an `INT` value to the bytes beginning at the `start` position in the BLOB
/// in little-endian byte order. /// in little-endian byte order.
@ -1262,7 +1262,7 @@ mod write_int_functions {
/// ``` /// ```
#[rhai_fn(name = "write_le")] #[rhai_fn(name = "write_le")]
pub fn write_le_int(blob: &mut Blob, start: INT, len: INT, value: INT) { pub fn write_le_int(blob: &mut Blob, start: INT, len: INT, value: INT) {
write_int(blob, start, len, value, true) write_int(blob, start, len, value, true);
} }
/// Write an `INT` value to the bytes within an exclusive `range` in the BLOB /// Write an `INT` value to the bytes within an exclusive `range` in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1281,7 +1281,7 @@ mod write_int_functions {
pub fn write_be_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) { pub fn write_be_int_range(blob: &mut Blob, range: ExclusiveRange, value: INT) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_be_int(blob, start, end - start, value) write_be_int(blob, start, end - start, value);
} }
/// Write an `INT` value to the bytes within an inclusive `range` in the BLOB /// Write an `INT` value to the bytes within an inclusive `range` in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1300,7 +1300,7 @@ mod write_int_functions {
pub fn write_be_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) { pub fn write_be_int_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: INT) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_be_int(blob, start, end - start + 1, value) write_be_int(blob, start, end - start + 1, value);
} }
/// Write an `INT` value to the bytes beginning at the `start` position in the BLOB /// Write an `INT` value to the bytes beginning at the `start` position in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1323,7 +1323,7 @@ mod write_int_functions {
/// ``` /// ```
#[rhai_fn(name = "write_be")] #[rhai_fn(name = "write_be")]
pub fn write_be_int(blob: &mut Blob, start: INT, len: INT, value: INT) { pub fn write_be_int(blob: &mut Blob, start: INT, len: INT, value: INT) {
write_int(blob, start, len, value, false) write_int(blob, start, len, value, false);
} }
} }
@ -1360,7 +1360,7 @@ mod write_float_functions {
pub fn write_le_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) { pub fn write_le_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_le_float(blob, start, end - start, value) write_le_float(blob, start, end - start, value);
} }
/// Write a `FLOAT` value to the bytes within an inclusive `range` in the BLOB /// Write a `FLOAT` value to the bytes within an inclusive `range` in the BLOB
/// in little-endian byte order. /// in little-endian byte order.
@ -1371,7 +1371,7 @@ mod write_float_functions {
pub fn write_le_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) { pub fn write_le_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_le_float(blob, start, end - start + 1, value) write_le_float(blob, start, end - start + 1, value);
} }
/// Write a `FLOAT` value to the bytes beginning at the `start` position in the BLOB /// Write a `FLOAT` value to the bytes beginning at the `start` position in the BLOB
/// in little-endian byte order. /// in little-endian byte order.
@ -1386,7 +1386,7 @@ mod write_float_functions {
/// * If number of bytes in `range` > number of bytes for `FLOAT`, extra bytes in `range` are not modified. /// * If number of bytes in `range` > number of bytes for `FLOAT`, extra bytes in `range` are not modified.
#[rhai_fn(name = "write_le")] #[rhai_fn(name = "write_le")]
pub fn write_le_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) { pub fn write_le_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) {
write_float(blob, start, len, value, true) write_float(blob, start, len, value, true);
} }
/// Write a `FLOAT` value to the bytes within an exclusive `range` in the BLOB /// Write a `FLOAT` value to the bytes within an exclusive `range` in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1397,7 +1397,7 @@ mod write_float_functions {
pub fn write_be_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) { pub fn write_be_float_range(blob: &mut Blob, range: ExclusiveRange, value: FLOAT) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_be_float(blob, start, end - start, value) write_be_float(blob, start, end - start, value);
} }
/// Write a `FLOAT` value to the bytes within an inclusive `range` in the BLOB /// Write a `FLOAT` value to the bytes within an inclusive `range` in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1408,7 +1408,7 @@ mod write_float_functions {
pub fn write_be_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) { pub fn write_be_float_range_inclusive(blob: &mut Blob, range: InclusiveRange, value: FLOAT) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_be_float(blob, start, end - start + 1, value) write_be_float(blob, start, end - start + 1, value);
} }
/// Write a `FLOAT` value to the bytes beginning at the `start` position in the BLOB /// Write a `FLOAT` value to the bytes beginning at the `start` position in the BLOB
/// in big-endian byte order. /// in big-endian byte order.
@ -1423,7 +1423,7 @@ mod write_float_functions {
/// * If number of bytes in `range` > number of bytes for `FLOAT`, extra bytes in `range` are not modified. /// * If number of bytes in `range` > number of bytes for `FLOAT`, extra bytes in `range` are not modified.
#[rhai_fn(name = "write_be")] #[rhai_fn(name = "write_be")]
pub fn write_be_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) { pub fn write_be_float(blob: &mut Blob, start: INT, len: INT, value: FLOAT) {
write_float(blob, start, len, value, false) write_float(blob, start, len, value, false);
} }
} }
@ -1471,7 +1471,7 @@ mod write_string_functions {
pub fn write_utf8_string_range(blob: &mut Blob, range: ExclusiveRange, string: &str) { pub fn write_utf8_string_range(blob: &mut Blob, range: ExclusiveRange, string: &str) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_string(blob, start, end - start, string, false) write_string(blob, start, end - start, string, false);
} }
/// Write a string to the bytes within an inclusive `range` in the BLOB in UTF-8 encoding. /// Write a string to the bytes within an inclusive `range` in the BLOB in UTF-8 encoding.
/// ///
@ -1489,7 +1489,7 @@ mod write_string_functions {
pub fn write_utf8_string_range_inclusive(blob: &mut Blob, range: InclusiveRange, string: &str) { pub fn write_utf8_string_range_inclusive(blob: &mut Blob, range: InclusiveRange, string: &str) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_string(blob, start, end - start + 1, string, false) write_string(blob, start, end - start + 1, string, false);
} }
/// Write a string to the bytes within an inclusive `range` in the BLOB in UTF-8 encoding. /// Write a string to the bytes within an inclusive `range` in the BLOB in UTF-8 encoding.
/// ///
@ -1511,7 +1511,7 @@ mod write_string_functions {
/// ``` /// ```
#[rhai_fn(name = "write_utf8")] #[rhai_fn(name = "write_utf8")]
pub fn write_utf8_string(blob: &mut Blob, start: INT, len: INT, string: &str) { pub fn write_utf8_string(blob: &mut Blob, start: INT, len: INT, string: &str) {
write_string(blob, start, len, string, false) write_string(blob, start, len, string, false);
} }
/// Write an ASCII string to the bytes within an exclusive `range` in the BLOB. /// Write an ASCII string to the bytes within an exclusive `range` in the BLOB.
/// ///
@ -1532,7 +1532,7 @@ mod write_string_functions {
pub fn write_ascii_string_range(blob: &mut Blob, range: ExclusiveRange, string: &str) { pub fn write_ascii_string_range(blob: &mut Blob, range: ExclusiveRange, string: &str) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
write_string(blob, start, end - start, string, true) write_string(blob, start, end - start, string, true);
} }
/// Write an ASCII string to the bytes within an inclusive `range` in the BLOB. /// Write an ASCII string to the bytes within an inclusive `range` in the BLOB.
/// ///
@ -1557,7 +1557,7 @@ mod write_string_functions {
) { ) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
write_string(blob, start, end - start + 1, string, true) write_string(blob, start, end - start + 1, string, true);
} }
/// Write an ASCII string to the bytes within an exclusive `range` in the BLOB. /// Write an ASCII string to the bytes within an exclusive `range` in the BLOB.
/// ///
@ -1579,6 +1579,6 @@ mod write_string_functions {
/// ``` /// ```
#[rhai_fn(name = "write_ascii")] #[rhai_fn(name = "write_ascii")]
pub fn write_ascii_string(blob: &mut Blob, start: INT, len: INT, string: &str) { pub fn write_ascii_string(blob: &mut Blob, start: INT, len: INT, string: &str) {
write_string(blob, start, len, string, true) write_string(blob, start, len, string, true);
} }
} }

View File

@ -28,7 +28,7 @@ where
} }
// Range iterator with step // Range iterator with step
#[derive(Clone, Copy, Hash, Eq, PartialEq)] #[derive(Clone, Hash, Eq, PartialEq)]
pub struct StepRange<T: Debug + Copy + PartialOrd> { pub struct StepRange<T: Debug + Copy + PartialOrd> {
pub from: T, pub from: T,
pub to: T, pub to: T,
@ -110,7 +110,7 @@ impl<T: Debug + Copy + PartialOrd> Iterator for StepRange<T> {
impl<T: Debug + Copy + PartialOrd> FusedIterator for StepRange<T> {} impl<T: Debug + Copy + PartialOrd> FusedIterator for StepRange<T> {}
// Bit-field iterator with step // Bit-field iterator with step
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct BitRange(INT, INT, usize); pub struct BitRange(INT, INT, usize);
impl BitRange { impl BitRange {

View File

@ -220,7 +220,7 @@ fn collect_fn_metadata(
f, f,
) )
.into(), .into(),
) );
}); });
ctx.engine() ctx.engine()
@ -237,7 +237,7 @@ fn collect_fn_metadata(
f, f,
) )
.into(), .into(),
) );
}); });
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -255,7 +255,7 @@ fn collect_fn_metadata(
f, f,
) )
.into(), .into(),
) );
}); });
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -264,7 +264,7 @@ fn collect_fn_metadata(
fn scan_module( fn scan_module(
list: &mut Array, list: &mut Array,
dict: &BTreeSet<Identifier>, dict: &BTreeSet<Identifier>,
namespace: Identifier, namespace: &str,
module: &Module, module: &Module,
filter: impl Fn( filter: impl Fn(
FnNamespace, FnNamespace,
@ -278,7 +278,7 @@ fn collect_fn_metadata(
module module
.iter_script_fn() .iter_script_fn()
.filter(|(s, a, n, p, f)| filter(*s, *a, n, *p, f)) .filter(|(s, a, n, p, f)| filter(*s, *a, n, *p, f))
.for_each(|(.., f)| list.push(make_metadata(dict, namespace.clone(), f).into())); .for_each(|(.., f)| list.push(make_metadata(dict, namespace.into(), f).into()));
for (ns, m) in module.iter_sub_modules() { for (ns, m) in module.iter_sub_modules() {
let ns = format!( let ns = format!(
"{}{}{}", "{}{}{}",
@ -286,12 +286,12 @@ fn collect_fn_metadata(
crate::tokenizer::Token::DoubleColon.literal_syntax(), crate::tokenizer::Token::DoubleColon.literal_syntax(),
ns ns
); );
scan_module(list, dict, ns.into(), &**m, filter) scan_module(list, dict, &ns, &**m, filter);
} }
} }
for (ns, m) in ctx.iter_imports_raw() { for (ns, m) in ctx.iter_imports_raw() {
scan_module(&mut list, &dict, ns.clone(), &**m, filter) scan_module(&mut list, &dict, ns, &**m, filter);
} }
} }

View File

@ -92,10 +92,10 @@ mod map_functions {
/// print(m); // prints "#{a:1, c:3}" /// print(m); // prints "#{a:1, c:3}"
/// ``` /// ```
pub fn remove(map: &mut Map, property: &str) -> Dynamic { pub fn remove(map: &mut Map, property: &str) -> Dynamic {
if !map.is_empty() { if map.is_empty() {
map.remove(property).unwrap_or(Dynamic::UNIT)
} else {
Dynamic::UNIT Dynamic::UNIT
} else {
map.remove(property).unwrap_or(Dynamic::UNIT)
} }
} }
/// Add all property values of another object map into the object map. /// Add all property values of another object map into the object map.
@ -160,9 +160,9 @@ mod map_functions {
if map.is_empty() { if map.is_empty() {
*map = map2; *map = map2;
} else { } else {
map2.into_iter().for_each(|(key, value)| { for (key, value) in map2 {
map.entry(key).or_insert(value); map.entry(key).or_insert(value);
}); }
} }
} }
} }

View File

@ -98,6 +98,7 @@ macro_rules! def_package {
impl $package { impl $package {
#[doc=concat!("Create a new `", stringify!($package), "`")] #[doc=concat!("Create a new `", stringify!($package), "`")]
#[must_use]
pub fn new() -> Self { pub fn new() -> Self {
let mut module = $crate::Module::new(); let mut module = $crate::Module::new();
<Self as $crate::packages::Package>::init(&mut module); <Self as $crate::packages::Package>::init(&mut module);

View File

@ -114,7 +114,7 @@ mod string_functions {
} }
} }
#[rhai_fn(name = "+")] #[rhai_fn(name = "+")]
pub fn add_prepend(utf8: Blob, string: ImmutableString) -> ImmutableString { pub fn add_prepend(utf8: Blob, string: &str) -> ImmutableString {
let s = String::from_utf8_lossy(&utf8); let s = String::from_utf8_lossy(&utf8);
let mut s = match s { let mut s = match s {
std::borrow::Cow::Borrowed(_) => String::from_utf8(utf8).unwrap(), std::borrow::Cow::Borrowed(_) => String::from_utf8(utf8).unwrap(),
@ -122,7 +122,7 @@ mod string_functions {
}; };
if !string.is_empty() { if !string.is_empty() {
s.push_str(&string); s.push_str(string);
} }
s.into() s.into()
@ -440,7 +440,7 @@ mod string_functions {
/// ``` /// ```
#[rhai_fn(name = "make_upper")] #[rhai_fn(name = "make_upper")]
pub fn make_upper_char(character: &mut char) { pub fn make_upper_char(character: &mut char) {
*character = to_upper_char(*character) *character = to_upper_char(*character);
} }
/// Convert the character to lower-case and return it as a new character. /// Convert the character to lower-case and return it as a new character.
/// ///
@ -476,7 +476,7 @@ mod string_functions {
/// ``` /// ```
#[rhai_fn(name = "make_lower")] #[rhai_fn(name = "make_lower")]
pub fn make_lower_char(character: &mut char) { pub fn make_lower_char(character: &mut char) {
*character = to_lower_char(*character) *character = to_lower_char(*character);
} }
/// Return `true` if the string starts with a specified string. /// Return `true` if the string starts with a specified string.
@ -558,10 +558,9 @@ mod string_functions {
.len() .len()
}; };
string[start..] string[start..].find(character).map_or(-1 as INT, |index| {
.find(character) string[0..start + index].chars().count() as INT
.map(|index| string[0..start + index].chars().count() as INT) })
.unwrap_or(-1 as INT)
} }
/// Find the specified `character` in the string and return the first index where it is found. /// Find the specified `character` in the string and return the first index where it is found.
/// If the `character` is not found, `-1` is returned. /// If the `character` is not found, `-1` is returned.
@ -582,8 +581,7 @@ mod string_functions {
} else { } else {
string string
.find(character) .find(character)
.map(|index| string[0..index].chars().count() as INT) .map_or(-1 as INT, |index| string[0..index].chars().count() as INT)
.unwrap_or(-1 as INT)
} }
} }
/// Find the specified sub-string in the string, starting from the specified `start` position, /// Find the specified sub-string in the string, starting from the specified `start` position,
@ -638,8 +636,9 @@ mod string_functions {
string[start..] string[start..]
.find(find_string) .find(find_string)
.map(|index| string[0..start + index].chars().count() as INT) .map_or(-1 as INT, |index| {
.unwrap_or(-1 as INT) string[0..start + index].chars().count() as INT
})
} }
/// Find the specified `character` in the string and return the first index where it is found. /// Find the specified `character` in the string and return the first index where it is found.
/// If the `character` is not found, `-1` is returned. /// If the `character` is not found, `-1` is returned.
@ -660,8 +659,7 @@ mod string_functions {
} else { } else {
string string
.find(find_string) .find(find_string)
.map(|index| string[0..index].chars().count() as INT) .map_or(-1 as INT, |index| string[0..index].chars().count() as INT)
.unwrap_or(-1 as INT)
} }
} }
@ -840,7 +838,7 @@ mod string_functions {
.iter() .iter()
.skip(offset) .skip(offset)
.take(len) .take(len)
.cloned() .copied()
.collect::<String>() .collect::<String>()
.into() .into()
} }
@ -889,7 +887,7 @@ mod string_functions {
pub fn crop_range(string: &mut ImmutableString, range: ExclusiveRange) { pub fn crop_range(string: &mut ImmutableString, range: ExclusiveRange) {
let start = INT::max(range.start, 0); let start = INT::max(range.start, 0);
let end = INT::max(range.end, start); let end = INT::max(range.end, start);
crop(string, start, end - start) crop(string, start, end - start);
} }
/// Remove all characters from the string except those within an inclusive `range`. /// Remove all characters from the string except those within an inclusive `range`.
/// ///
@ -906,7 +904,7 @@ mod string_functions {
pub fn crop_inclusive_range(string: &mut ImmutableString, range: InclusiveRange) { pub fn crop_inclusive_range(string: &mut ImmutableString, range: InclusiveRange) {
let start = INT::max(*range.start(), 0); let start = INT::max(*range.start(), 0);
let end = INT::max(*range.end(), start); let end = INT::max(*range.end(), start);
crop(string, start, end - start + 1) crop(string, start, end - start + 1);
} }
/// Remove all characters from the string except those within a range. /// Remove all characters from the string except those within a range.

View File

@ -130,6 +130,7 @@ impl<'e> ParseState<'e> {
/// If the variable is not present in the scope, the first return value is zero. /// If the variable is not present in the scope, the first return value is zero.
/// ///
/// The second return value indicates whether the barrier has been hit before finding the variable. /// The second return value indicates whether the barrier has been hit before finding the variable.
#[must_use]
pub fn find_var(&self, name: &str) -> (usize, bool) { pub fn find_var(&self, name: &str) -> (usize, bool) {
let mut hit_barrier = false; let mut hit_barrier = false;
@ -175,7 +176,7 @@ impl<'e> ParseState<'e> {
}); });
} }
} else { } else {
self.allow_capture = true self.allow_capture = true;
} }
if hit_barrier { if hit_barrier {
@ -360,7 +361,10 @@ impl Expr {
/// Make sure that the next expression is not a statement expression (i.e. wrapped in `{}`). /// Make sure that the next expression is not a statement expression (i.e. wrapped in `{}`).
#[inline] #[inline]
fn ensure_not_statement_expr(input: &mut TokenStream, type_name: impl ToString) -> ParseResult<()> { fn ensure_not_statement_expr(
input: &mut TokenStream,
type_name: &(impl ToString + ?Sized),
) -> ParseResult<()> {
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
(Token::LeftBrace, pos) => Err(PERR::ExprExpected(type_name.to_string()).into_err(*pos)), (Token::LeftBrace, pos) => Err(PERR::ExprExpected(type_name.to_string()).into_err(*pos)),
_ => Ok(()), _ => Ok(()),
@ -519,7 +523,9 @@ impl Engine {
} }
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let hash = if !namespace.is_empty() { let hash = if namespace.is_empty() {
calc_fn_hash(&id, 0)
} else {
let root = namespace.root(); let root = namespace.root();
let index = state.find_module(root); let index = state.find_module(root);
@ -541,9 +547,7 @@ impl Engine {
namespace.set_index(index); namespace.set_index(index);
crate::calc_qualified_fn_hash(namespace.iter().map(|m| m.as_str()), &id, 0) crate::calc_qualified_fn_hash(namespace.iter().map(Ident::as_str), &id, 0)
} else {
calc_fn_hash(&id, 0)
}; };
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
let hash = calc_fn_hash(&id, 0); let hash = calc_fn_hash(&id, 0);
@ -586,7 +590,9 @@ impl Engine {
eat_token(input, Token::RightParen); eat_token(input, Token::RightParen);
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let hash = if !namespace.is_empty() { let hash = if namespace.is_empty() {
calc_fn_hash(&id, args.len())
} else {
let root = namespace.root(); let root = namespace.root();
let index = state.find_module(root); let index = state.find_module(root);
@ -608,12 +614,10 @@ impl Engine {
namespace.set_index(index); namespace.set_index(index);
crate::calc_qualified_fn_hash( crate::calc_qualified_fn_hash(
namespace.iter().map(|m| m.as_str()), namespace.iter().map(Ident::as_str),
&id, &id,
args.len(), args.len(),
) )
} else {
calc_fn_hash(&id, args.len())
}; };
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
let hash = calc_fn_hash(&id, args.len()); let hash = calc_fn_hash(&id, args.len());
@ -788,7 +792,7 @@ impl Engine {
// Any more indexing following? // Any more indexing following?
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
// If another indexing level, right-bind it // If another indexing level, right-bind it
(Token::LeftBracket, ..) | (Token::QuestionBracket, ..) => { (Token::LeftBracket | Token::QuestionBracket, ..) => {
let (token, pos) = input.next().expect(NEVER_ENDS); let (token, pos) = input.next().expect(NEVER_ENDS);
let prev_pos = settings.pos; let prev_pos = settings.pos;
settings.pos = pos; settings.pos = pos;
@ -1088,7 +1092,10 @@ impl Engine {
return Err(PERR::WrongSwitchCaseCondition.into_err(if_pos)); return Err(PERR::WrongSwitchCaseCondition.into_err(if_pos));
} }
(Default::default(), Expr::BoolConstant(true, Position::NONE)) (
StaticVec::default(),
Expr::BoolConstant(true, Position::NONE),
)
} }
_ if def_case.is_some() => { _ if def_case.is_some() => {
return Err(PERR::WrongSwitchDefaultCase.into_err(def_case_pos)) return Err(PERR::WrongSwitchDefaultCase.into_err(def_case_pos))
@ -1149,7 +1156,9 @@ impl Engine {
expressions.push((condition, Expr::Stmt(stmt_block.into())).into()); expressions.push((condition, Expr::Stmt(stmt_block.into())).into());
let index = expressions.len() - 1; let index = expressions.len() - 1;
if !case_expr_list.is_empty() { if case_expr_list.is_empty() {
def_case = Some(index);
} else {
for expr in case_expr_list { for expr in case_expr_list {
let value = expr.get_literal_value().ok_or_else(|| { let value = expr.get_literal_value().ok_or_else(|| {
PERR::ExprExpected("a literal".to_string()).into_err(expr.start_position()) PERR::ExprExpected("a literal".to_string()).into_err(expr.start_position())
@ -1200,8 +1209,6 @@ impl Engine {
.and_modify(|cases| cases.push(index)) .and_modify(|cases| cases.push(index))
.or_insert_with(|| [index].into()); .or_insert_with(|| [index].into());
} }
} else {
def_case = Some(index);
} }
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
@ -1690,7 +1697,7 @@ impl Engine {
} }
// Indexing // Indexing
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
(expr, token @ Token::LeftBracket) | (expr, token @ Token::QuestionBracket) => { (expr, token @ (Token::LeftBracket | Token::QuestionBracket)) => {
let opt = match token { let opt = match token {
Token::LeftBracket => ASTFlags::NONE, Token::LeftBracket => ASTFlags::NONE,
Token::QuestionBracket => ASTFlags::NEGATED, Token::QuestionBracket => ASTFlags::NEGATED,
@ -1700,7 +1707,7 @@ impl Engine {
} }
// Property access // Property access
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
(expr, op @ Token::Period) | (expr, op @ Token::Elvis) => { (expr, op @ (Token::Period | Token::Elvis)) => {
// Expression after dot must start with an identifier // Expression after dot must start with an identifier
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
(Token::Identifier(..), ..) => { (Token::Identifier(..), ..) => {
@ -1745,7 +1752,7 @@ impl Engine {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
if let Some((.., namespace, hash, name)) = namespaced_variable { if let Some((.., namespace, hash, name)) = namespaced_variable {
if !namespace.is_empty() { if !namespace.is_empty() {
*hash = crate::calc_qualified_var_hash(namespace.iter().map(|v| v.as_str()), name); *hash = crate::calc_qualified_var_hash(namespace.iter().map(Ident::as_str), name);
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
{ {
@ -2196,7 +2203,7 @@ impl Engine {
Token::Custom(c) => self Token::Custom(c) => self
.custom_keywords .custom_keywords
.get(c) .get(c)
.cloned() .copied()
.ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*current_pos))?, .ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*current_pos))?,
Token::Reserved(c) if !is_valid_identifier(c.chars()) => { Token::Reserved(c) if !is_valid_identifier(c.chars()) => {
return Err(PERR::UnknownOperator(c.to_string()).into_err(*current_pos)) return Err(PERR::UnknownOperator(c.to_string()).into_err(*current_pos))
@ -2221,7 +2228,7 @@ impl Engine {
Token::Custom(c) => self Token::Custom(c) => self
.custom_keywords .custom_keywords
.get(c) .get(c)
.cloned() .copied()
.ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*next_pos))?, .ok_or_else(|| PERR::Reserved(c.to_string()).into_err(*next_pos))?,
Token::Reserved(c) if !is_valid_identifier(c.chars()) => { Token::Reserved(c) if !is_valid_identifier(c.chars()) => {
return Err(PERR::UnknownOperator(c.to_string()).into_err(*next_pos)) return Err(PERR::UnknownOperator(c.to_string()).into_err(*next_pos))
@ -3429,7 +3436,7 @@ impl Engine {
} }
let s = state.get_identifier("", s); let s = state.get_identifier("", s);
state.stack.push(s.clone(), ()); state.stack.push(s.clone(), ());
params.push((s, pos)) params.push((s, pos));
} }
(Token::LexError(err), pos) => return Err(err.into_err(pos)), (Token::LexError(err), pos) => return Err(err.into_err(pos)),
(.., pos) => { (.., pos) => {
@ -3565,7 +3572,7 @@ impl Engine {
} }
let s = state.get_identifier("", s); let s = state.get_identifier("", s);
state.stack.push(s.clone(), ()); state.stack.push(s.clone(), ());
params_list.push(s) params_list.push(s);
} }
(Token::LexError(err), pos) => return Err(err.into_err(pos)), (Token::LexError(err), pos) => return Err(err.into_err(pos)),
(.., pos) => { (.., pos) => {

View File

@ -1,7 +1,9 @@
//! Implement deserialization support of [`Dynamic`][crate::Dynamic] for [`serde`]. //! Implement deserialization support of [`Dynamic`][crate::Dynamic] for [`serde`].
use crate::types::dynamic::Union; use crate::types::dynamic::Union;
use crate::{Dynamic, ImmutableString, LexError, Position, RhaiError, RhaiResultOf, ERR}; use crate::{
Dynamic, ImmutableString, LexError, Position, RhaiError, RhaiResultOf, SmartString, ERR,
};
use serde::de::{Error, IntoDeserializer, Visitor}; use serde::de::{Error, IntoDeserializer, Visitor};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
@ -420,7 +422,7 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|| self.type_error(), || self.type_error(),
|map| { |map| {
_visitor.visit_map(IterateMap::new( _visitor.visit_map(IterateMap::new(
map.keys().map(|key| key.as_str()), map.keys().map(SmartString::as_str),
map.values(), map.values(),
)) ))
}, },

View File

@ -181,7 +181,7 @@ impl ModuleMetadata<'_> {
impl<'a> From<&'a crate::Module> for ModuleMetadata<'a> { impl<'a> From<&'a crate::Module> for ModuleMetadata<'a> {
fn from(module: &'a crate::Module) -> Self { fn from(module: &'a crate::Module) -> Self {
let mut functions: Vec<_> = module.iter_fn().map(|f| f.into()).collect(); let mut functions: Vec<_> = module.iter_fn().map(Into::into).collect();
functions.sort(); functions.sort();
Self { Self {

View File

@ -210,7 +210,7 @@ impl Position {
} }
/// Print this [`Position`] for debug purposes. /// Print this [`Position`] for debug purposes.
#[inline] #[inline]
pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { pub(crate) fn debug_print(self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.is_none() { if !self.is_none() {
write!(_f, " @ {:?}", self)?; write!(_f, " @ {:?}", self)?;
} }
@ -1215,7 +1215,7 @@ pub fn parse_string_literal(
if allow_interpolation if allow_interpolation
&& next_char == '$' && next_char == '$'
&& escape.is_empty() && escape.is_empty()
&& stream.peek_next().map(|ch| ch == '{').unwrap_or(false) && stream.peek_next().map_or(false, |ch| ch == '{')
{ {
interpolated = true; interpolated = true;
state.is_within_text_terminated_by = None; state.is_within_text_terminated_by = None;
@ -1245,7 +1245,7 @@ pub fn parse_string_literal(
match next_char { match next_char {
// \r - ignore if followed by \n // \r - ignore if followed by \n
'\r' if stream.peek_next().map(|ch| ch == '\n').unwrap_or(false) => (), '\r' if stream.peek_next().map_or(false, |ch| ch == '\n') => (),
// \... // \...
'\\' if !verbatim && escape.is_empty() => { '\\' if !verbatim && escape.is_empty() => {
escape.push('\\'); escape.push('\\');
@ -1271,7 +1271,7 @@ pub fn parse_string_literal(
result.push('\r'); result.push('\r');
} }
// \x??, \u????, \U???????? // \x??, \u????, \U????????
ch @ 'x' | ch @ 'u' | ch @ 'U' if !escape.is_empty() => { ch @ ('x' | 'u' | 'U') if !escape.is_empty() => {
let mut seq = escape.clone(); let mut seq = escape.clone();
escape.clear(); escape.clear();
seq.push(ch); seq.push(ch);
@ -1307,7 +1307,7 @@ pub fn parse_string_literal(
// \{termination_char} - escaped // \{termination_char} - escaped
_ if termination_char == next_char && !escape.is_empty() => { _ if termination_char == next_char && !escape.is_empty() => {
escape.clear(); escape.clear();
result.push(next_char) result.push(next_char);
} }
// Verbatim // Verbatim
@ -1598,7 +1598,7 @@ fn get_next_token_inner(
} }
} }
// 0x????, 0o????, 0b???? at beginning // 0x????, 0o????, 0b???? at beginning
ch @ 'x' | ch @ 'o' | ch @ 'b' | ch @ 'X' | ch @ 'O' | ch @ 'B' ch @ ('x' | 'o' | 'b' | 'X' | 'O' | 'B')
if c == '0' && result.len() <= 1 => if c == '0' && result.len() <= 1 =>
{ {
result.push(next_char); result.push(next_char);
@ -1639,12 +1639,14 @@ fn get_next_token_inner(
UNSIGNED_INT::from_str_radix(&out, radix) UNSIGNED_INT::from_str_radix(&out, radix)
.map(|v| v as INT) .map(|v| v as INT)
.map(Token::IntegerConstant) .map_or_else(
.unwrap_or_else(|_| { |_| {
Token::LexError( Token::LexError(
LERR::MalformedNumber(result.into_iter().collect()).into(), LERR::MalformedNumber(result.into_iter().collect()).into(),
) )
}) },
Token::IntegerConstant,
)
} else { } else {
let out: String = let out: String =
result.iter().filter(|&&c| c != NUMBER_SEPARATOR).collect(); result.iter().filter(|&&c| c != NUMBER_SEPARATOR).collect();
@ -1680,7 +1682,7 @@ fn get_next_token_inner(
// letter or underscore ... // letter or underscore ...
#[cfg(not(feature = "unicode-xid-ident"))] #[cfg(not(feature = "unicode-xid-ident"))]
('a'..='z', ..) | ('_', ..) | ('A'..='Z', ..) => { ('a'..='z' | '_' | 'A'..='Z', ..) => {
return get_identifier(stream, pos, start_pos, c); return get_identifier(stream, pos, start_pos, c);
} }
#[cfg(feature = "unicode-xid-ident")] #[cfg(feature = "unicode-xid-ident")]
@ -2161,7 +2163,7 @@ fn get_identifier(
} }
} }
let is_valid_identifier = is_valid_identifier(result.iter().cloned()); let is_valid_identifier = is_valid_identifier(result.iter().copied());
let identifier: String = result.into_iter().collect(); let identifier: String = result.into_iter().collect();
@ -2384,7 +2386,7 @@ impl<'a> Iterator for TokenIterator<'a> {
("::<", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), ("::<", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(),
"'::<>' is not a valid symbol. This is not Rust! Should it be '::'?".to_string(), "'::<>' is not a valid symbol. This is not Rust! Should it be '::'?".to_string(),
).into()), ).into()),
("(*", false) | ("*)", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), ("(*" | "*)", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(),
"'(* .. *)' is not a valid comment format. This is not Pascal! Should it be '/* .. */'?".to_string(), "'(* .. *)' is not a valid comment format. This is not Pascal! Should it be '/* .. */'?".to_string(),
).into()), ).into()),
("# {", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), ("# {", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(),

View File

@ -739,7 +739,7 @@ impl Dynamic {
/// A [`Dynamic`] containing the integer 1,000. /// A [`Dynamic`] containing the integer 1,000.
pub const THOUSAND: Self = Self::from_int(1000); pub const THOUSAND: Self = Self::from_int(1000);
/// A [`Dynamic`] containing the integer 1,000,000. /// A [`Dynamic`] containing the integer 1,000,000.
pub const MILLION: Self = Self::from_int(1000000); pub const MILLION: Self = Self::from_int(1_000_000);
/// A [`Dynamic`] containing the integer -1. /// A [`Dynamic`] containing the integer -1.
pub const NEGATIVE_ONE: Self = Self::from_int(-1); pub const NEGATIVE_ONE: Self = Self::from_int(-1);
/// A [`Dynamic`] containing the integer -2. /// A [`Dynamic`] containing the integer -2.
@ -778,7 +778,7 @@ impl Dynamic {
/// ///
/// Not available under `no_float`. /// Not available under `no_float`.
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
pub const FLOAT_MILLION: Self = Self::from_float(1000000.0); pub const FLOAT_MILLION: Self = Self::from_float(1_000_000.0);
/// A [`Dynamic`] containing `-1.0`. /// A [`Dynamic`] containing `-1.0`.
/// ///
/// Not available under `no_float`. /// Not available under `no_float`.
@ -823,7 +823,7 @@ impl Dynamic {
/// ///
/// Not available under `no_float`. /// Not available under `no_float`.
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
pub const FLOAT_MILLIONTH: Self = Self::from_float(0.000001); pub const FLOAT_MILLIONTH: Self = Self::from_float(0.000_001);
/// A [`Dynamic`] containing π. /// A [`Dynamic`] containing π.
/// ///
/// Not available under `no_float`. /// Not available under `no_float`.
@ -867,16 +867,19 @@ impl Dynamic {
/// Create a new [`Dynamic`] from a [`bool`]. /// Create a new [`Dynamic`] from a [`bool`].
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn from_bool(value: bool) -> Self { pub const fn from_bool(value: bool) -> Self {
Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
} }
/// Create a new [`Dynamic`] from an [`INT`]. /// Create a new [`Dynamic`] from an [`INT`].
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn from_int(value: INT) -> Self { pub const fn from_int(value: INT) -> Self {
Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
} }
/// Create a new [`Dynamic`] from a [`char`]. /// Create a new [`Dynamic`] from a [`char`].
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn from_char(value: char) -> Self { pub const fn from_char(value: char) -> Self {
Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
} }
@ -885,6 +888,7 @@ impl Dynamic {
/// Not available under `no_float`. /// Not available under `no_float`.
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub const fn from_float(value: crate::FLOAT) -> Self { pub const fn from_float(value: crate::FLOAT) -> Self {
Self(Union::Float( Self(Union::Float(
crate::ast::FloatWrapper::new_const(value), crate::ast::FloatWrapper::new_const(value),
@ -897,24 +901,28 @@ impl Dynamic {
/// Exported under the `decimal` feature only. /// Exported under the `decimal` feature only.
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
#[inline(always)] #[inline(always)]
#[must_use]
pub fn from_decimal(value: rust_decimal::Decimal) -> Self { pub fn from_decimal(value: rust_decimal::Decimal) -> Self {
Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
} }
/// Create a [`Dynamic`] from an [`Array`][crate::Array]. /// Create a [`Dynamic`] from an [`Array`][crate::Array].
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub fn from_array(array: crate::Array) -> Self { pub fn from_array(array: crate::Array) -> Self {
Self(Union::Array(array.into(), DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Array(array.into(), DEFAULT_TAG_VALUE, ReadWrite))
} }
/// Create a [`Dynamic`] from a [`Blob`][crate::Blob]. /// Create a [`Dynamic`] from a [`Blob`][crate::Blob].
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub fn from_blob(blob: crate::Blob) -> Self { pub fn from_blob(blob: crate::Blob) -> Self {
Self(Union::Blob(blob.into(), DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Blob(blob.into(), DEFAULT_TAG_VALUE, ReadWrite))
} }
/// Create a [`Dynamic`] from a [`Map`][crate::Map]. /// Create a [`Dynamic`] from a [`Map`][crate::Map].
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub fn from_map(map: crate::Map) -> Self { pub fn from_map(map: crate::Map) -> Self {
Self(Union::Map(map.into(), DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::Map(map.into(), DEFAULT_TAG_VALUE, ReadWrite))
} }
@ -923,6 +931,7 @@ impl Dynamic {
/// Not available under `no-std`. /// Not available under `no-std`.
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
#[inline(always)] #[inline(always)]
#[must_use]
pub fn from_timestamp(value: Instant) -> Self { pub fn from_timestamp(value: Instant) -> Self {
Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite)) Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
} }
@ -993,6 +1002,7 @@ impl Dynamic {
} }
/// Make this [`Dynamic`] read-only (i.e. a constant). /// Make this [`Dynamic`] read-only (i.e. a constant).
#[inline(always)] #[inline(always)]
#[must_use]
pub fn into_read_only(self) -> Self { pub fn into_read_only(self) -> Self {
let mut value = self; let mut value = self;
value.set_access_mode(AccessMode::ReadOnly); value.set_access_mode(AccessMode::ReadOnly);
@ -1388,13 +1398,13 @@ impl Dynamic {
Union::Shared(ref cell, ..) => { Union::Shared(ref cell, ..) => {
let value = locked_read(cell); let value = locked_read(cell);
if (*value).type_id() != TypeId::of::<T>() return if (*value).type_id() != TypeId::of::<T>()
&& TypeId::of::<Dynamic>() != TypeId::of::<T>() && TypeId::of::<Dynamic>() != TypeId::of::<T>()
{ {
return None; None
} else { } else {
return Some(DynamicReadLock(DynamicReadLockInner::Guard(value))); Some(DynamicReadLock(DynamicReadLockInner::Guard(value)))
} };
} }
_ => (), _ => (),
} }
@ -1420,13 +1430,13 @@ impl Dynamic {
Union::Shared(ref cell, ..) => { Union::Shared(ref cell, ..) => {
let guard = crate::func::locked_write(cell); let guard = crate::func::locked_write(cell);
if (*guard).type_id() != TypeId::of::<T>() return if (*guard).type_id() != TypeId::of::<T>()
&& TypeId::of::<Dynamic>() != TypeId::of::<T>() && TypeId::of::<Dynamic>() != TypeId::of::<T>()
{ {
return None; None
} else { } else {
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(guard))); Some(DynamicWriteLock(DynamicWriteLockInner::Guard(guard)))
} };
} }
_ => (), _ => (),
} }

View File

@ -24,15 +24,15 @@ pub struct FnPtr {
impl fmt::Debug for FnPtr { impl fmt::Debug for FnPtr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.is_curried() { if self.is_curried() {
write!(f, "Fn({})", self.fn_name())
} else {
self.curry self.curry
.iter() .iter()
.fold(f.debug_tuple("Fn").field(&self.name), |f, curry| { .fold(f.debug_tuple("Fn").field(&self.name), |f, curry| {
f.field(curry) f.field(curry)
}) })
.finish() .finish()
} else {
write!(f, "Fn({})", self.fn_name())
} }
} }
} }
@ -149,7 +149,7 @@ impl FnPtr {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
_ast.as_ref(), _ast.as_ref(),
]; ];
let lib = if lib.first().map(|m: &&Module| m.is_empty()).unwrap_or(true) { let lib = if lib.first().map_or(true, |m: &&Module| m.is_empty()) {
&lib[0..0] &lib[0..0]
} else { } else {
&lib &lib

View File

@ -159,7 +159,7 @@ impl FromIterator<char> for ImmutableString {
impl<'a> FromIterator<&'a char> for ImmutableString { impl<'a> FromIterator<&'a char> for ImmutableString {
#[inline] #[inline]
fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
Self(iter.into_iter().cloned().collect::<SmartString>().into()) Self(iter.into_iter().copied().collect::<SmartString>().into())
} }
} }
@ -576,6 +576,7 @@ impl PartialOrd<ImmutableString> for String {
impl ImmutableString { impl ImmutableString {
/// Create a new [`ImmutableString`]. /// Create a new [`ImmutableString`].
#[inline(always)] #[inline(always)]
#[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self(SmartString::new_const().into()) Self(SmartString::new_const().into())
} }
@ -583,6 +584,7 @@ impl ImmutableString {
/// ///
/// If there are other references to the same string, a cloned copy is returned. /// If there are other references to the same string, a cloned copy is returned.
#[inline] #[inline]
#[must_use]
pub fn into_owned(mut self) -> String { pub fn into_owned(mut self) -> String {
self.make_mut(); // Make sure it is unique reference self.make_mut(); // Make sure it is unique reference
shared_take(self.0).into() // Should succeed shared_take(self.0).into() // Should succeed
@ -620,6 +622,7 @@ impl ImmutableString {
/// assert!(!s2.ptr_eq(&s3)); /// assert!(!s2.ptr_eq(&s3));
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use]
pub fn ptr_eq(&self, other: &Self) -> bool { pub fn ptr_eq(&self, other: &Self) -> bool {
Shared::ptr_eq(&self.0, &other.0) Shared::ptr_eq(&self.0, &other.0)
} }

View File

@ -436,6 +436,7 @@ impl Scope<'_> {
/// assert_eq!(my_scope.is_constant("y"), None); /// assert_eq!(my_scope.is_constant("y"), None);
/// ``` /// ```
#[inline] #[inline]
#[must_use]
pub fn is_constant(&self, name: &str) -> Option<bool> { pub fn is_constant(&self, name: &str) -> Option<bool> {
self.get_index(name).map(|(.., access)| match access { self.get_index(name).map(|(.., access)| match access {
AccessMode::ReadWrite => false, AccessMode::ReadWrite => false,