From 5acd18c3b23b0aa9d1a7d988dbd26d7f7051b2b3 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 6 Sep 2023 18:02:09 +0800 Subject: [PATCH] Satisfy clippy. --- src/func/builtin.rs | 17 +++ src/func/call.rs | 175 ++++++++++++++++------------- src/func/native.rs | 8 +- src/lib.rs | 3 +- src/module/mod.rs | 191 ++++++++++++++++--------------- src/optimizer.rs | 65 +++++------ src/packages/arithmetic.rs | 30 ++--- src/packages/array_basic.rs | 5 +- src/packages/blob_basic.rs | 5 +- src/packages/debugging.rs | 91 ++++++++------- src/packages/lang_core.rs | 2 +- src/packages/logic.rs | 19 +++- src/packages/math_basic.rs | 6 +- src/packages/string_basic.rs | 2 +- src/packages/string_more.rs | 40 +++---- src/packages/time_basic.rs | 3 +- src/parser.rs | 210 +++++++++++++++++------------------ src/reify.rs | 2 + src/serde/metadata.rs | 6 +- src/tokenizer.rs | 23 ++-- src/types/custom_types.rs | 5 +- src/types/dynamic.rs | 4 +- src/types/fn_ptr.rs | 59 +++++----- src/types/position.rs | 8 +- src/types/scope.rs | 7 +- 25 files changed, 515 insertions(+), 471 deletions(-) diff --git a/src/func/builtin.rs b/src/func/builtin.rs index c191ab7ef..140ba8271 100644 --- a/src/func/builtin.rs +++ b/src/func/builtin.rs @@ -359,8 +359,25 @@ pub fn get_builtin_binary_op_fn(op: &Token, x: &Dynamic, y: &Dynamic) -> Option< Divide => impl_op!(FLOAT => $xx / $yy), Modulo => impl_op!(FLOAT => $xx % $yy), PowerOf => impl_op!(FLOAT => $xx.powf($yy as FLOAT)), + + #[cfg(feature = "unchecked")] EqualsTo => impl_op!(FLOAT => $xx == $yy), + #[cfg(not(feature = "unchecked"))] + EqualsTo => Some((|_, args| { + let x = args[0].$xx().unwrap() as FLOAT; + let y = args[1].$yy().unwrap() as FLOAT; + Ok(((x - y).abs() <= FLOAT::EPSILON).into()) + }, false)), + + #[cfg(feature = "unchecked")] NotEqualsTo => impl_op!(FLOAT => $xx != $yy), + #[cfg(not(feature = "unchecked"))] + NotEqualsTo => Some((|_, args| { + let x = args[0].$xx().unwrap() as FLOAT; + let y = args[1].$yy().unwrap() as FLOAT; + Ok(((x - y).abs() > FLOAT::EPSILON).into()) + }, false)), + GreaterThan => impl_op!(FLOAT => $xx > $yy), GreaterThanEqualsTo => impl_op!(FLOAT => $xx >= $yy), LessThan => impl_op!(FLOAT => $xx < $yy), diff --git a/src/func/call.rs b/src/func/call.rs index 1da45c360..d05facb4a 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -26,6 +26,9 @@ use std::{ mem, }; +#[cfg(not(feature = "no_float"))] +use crate::FLOAT; + /// Arguments to a function call, which is a list of [`&mut Dynamic`][Dynamic]. pub type FnCallArgs<'a> = [&'a mut Dynamic]; @@ -569,34 +572,32 @@ impl Engine { pos: Position, ) -> RhaiResultOf<(Dynamic, bool)> { // These may be redirected from method style calls. - if hashes.is_native_only() { - loop { - match fn_name { - // Handle type_of() - KEYWORD_TYPE_OF if args.len() == 1 => { - let typ = self.get_interned_string(self.map_type_name(args[0].type_name())); - return Ok((typ.into(), false)); - } - - #[cfg(not(feature = "no_closure"))] - crate::engine::KEYWORD_IS_SHARED if args.len() == 1 => { - return Ok((args[0].is_shared().into(), false)) - } - #[cfg(not(feature = "no_closure"))] - crate::engine::KEYWORD_IS_SHARED => (), + if hashes.is_native_only() + && match fn_name { + // Handle type_of() + KEYWORD_TYPE_OF if args.len() == 1 => { + let typ = self.get_interned_string(self.map_type_name(args[0].type_name())); + return Ok((typ.into(), false)); + } - #[cfg(not(feature = "no_function"))] - crate::engine::KEYWORD_IS_DEF_FN => (), + #[cfg(not(feature = "no_closure"))] + crate::engine::KEYWORD_IS_SHARED if args.len() == 1 => { + return Ok((args[0].is_shared().into(), false)) + } + #[cfg(not(feature = "no_closure"))] + crate::engine::KEYWORD_IS_SHARED => true, - KEYWORD_TYPE_OF | KEYWORD_FN_PTR | KEYWORD_EVAL | KEYWORD_IS_DEF_VAR - | KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY => (), + #[cfg(not(feature = "no_function"))] + crate::engine::KEYWORD_IS_DEF_FN => true, - _ => break, - } + KEYWORD_TYPE_OF | KEYWORD_FN_PTR | KEYWORD_EVAL | KEYWORD_IS_DEF_VAR + | KEYWORD_FN_PTR_CALL | KEYWORD_FN_PTR_CURRY => true, - let sig = self.gen_fn_call_signature(fn_name, args); - return Err(ERR::ErrorFunctionNotFound(sig, pos).into()); + _ => false, } + { + let sig = self.gen_fn_call_signature(fn_name, args); + return Err(ERR::ErrorFunctionNotFound(sig, pos).into()); } // Check for data race. @@ -610,8 +611,8 @@ impl Engine { if !hashes.is_native_only() { let hash = hashes.script(); let local_entry = &mut None; - let mut resolved = None; + #[cfg(not(feature = "no_object"))] if _is_method_call && !args.is_empty() { let typed_hash = @@ -636,23 +637,20 @@ impl Engine { } let mut empty_scope; - let scope = match _scope { - Some(scope) => scope, - None => { - empty_scope = Scope::new(); - &mut empty_scope - } + let scope = if let Some(scope) = _scope { + scope + } else { + empty_scope = Scope::new(); + &mut empty_scope }; let orig_source = mem::replace(&mut global.source, source); defer! { global => move |g| g.source = orig_source } return if _is_method_call { - use std::ops::DerefMut; - // Method call of script function - map first argument to `this` let (first_arg, args) = args.split_first_mut().unwrap(); - let this_ptr = Some(first_arg.deref_mut()); + let this_ptr = Some(&mut **first_arg); self.call_script_fn( global, caches, scope, this_ptr, environ, func, args, true, pos, ) @@ -751,7 +749,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] Some(fn_def) if fn_def.params.len() == args.len() => { let scope = &mut Scope::new(); - let environ = fn_ptr.encapsulated_environ().map(|r| r.as_ref()); + let environ = fn_ptr.encapsulated_environ().map(<_>::as_ref); self.call_script_fn( global, caches, scope, None, environ, fn_def, args, true, pos, @@ -966,7 +964,7 @@ impl Engine { let args = &mut call_args.iter_mut().collect::>(); self.call_script_fn( - global, caches, scope, this_ptr, environ, &*fn_def, args, true, pos, + global, caches, scope, this_ptr, environ, &fn_def, args, true, pos, ) .map(|v| (v, false)) } @@ -1648,15 +1646,14 @@ impl Engine { .0 .flatten(); - return match value.0 { - Union::Bool(b, ..) => Ok((!b).into()), - _ => { - let operand = &mut [&mut value]; - self.exec_fn_call( - global, caches, None, name, op_token, *hashes, operand, false, false, pos, - ) - .map(|(v, ..)| v) - } + return if let Union::Bool(b, ..) = value.0 { + Ok((!b).into()) + } else { + let operand = &mut [&mut value]; + self.exec_fn_call( + global, caches, None, name, op_token, *hashes, operand, false, false, pos, + ) + .map(|(v, ..)| v) }; } @@ -1675,16 +1672,19 @@ impl Engine { .0 .flatten(); + #[allow(clippy::unnecessary_unwrap)] + let op_token = op_token.unwrap(); + // For extremely simple primary data operations, do it directly // to avoid the overhead of calling a function. match (&lhs.0, &rhs.0) { - (Union::Unit(..), Union::Unit(..)) => match op_token.unwrap() { + (Union::Unit(..), Union::Unit(..)) => match op_token { EqualsTo => return Ok(Dynamic::TRUE), NotEqualsTo | GreaterThan | GreaterThanEqualsTo | LessThan | LessThanEqualsTo => return Ok(Dynamic::FALSE), _ => (), }, - (Union::Bool(b1, ..), Union::Bool(b2, ..)) => match op_token.unwrap() { + (Union::Bool(b1, ..), Union::Bool(b2, ..)) => match op_token { EqualsTo => return Ok((b1 == b2).into()), NotEqualsTo => return Ok((b1 != b2).into()), GreaterThan | GreaterThanEqualsTo | LessThan | LessThanEqualsTo => { @@ -1700,7 +1700,7 @@ impl Engine { use crate::packages::arithmetic::arith_basic::INT::functions::*; #[cfg(not(feature = "unchecked"))] - match op_token.unwrap() { + match op_token { EqualsTo => return Ok((n1 == n2).into()), NotEqualsTo => return Ok((n1 != n2).into()), GreaterThan => return Ok((n1 > n2).into()), @@ -1715,7 +1715,7 @@ impl Engine { _ => (), } #[cfg(feature = "unchecked")] - match op_token.unwrap() { + match op_token { EqualsTo => return Ok((n1 == n2).into()), NotEqualsTo => return Ok((n1 != n2).into()), GreaterThan => return Ok((n1 > n2).into()), @@ -1731,9 +1731,15 @@ impl Engine { } } #[cfg(not(feature = "no_float"))] - (Union::Float(f1, ..), Union::Float(f2, ..)) => match op_token.unwrap() { + (Union::Float(f1, ..), Union::Float(f2, ..)) => match op_token { + #[cfg(feature = "unchecked")] EqualsTo => return Ok((**f1 == **f2).into()), + #[cfg(not(feature = "unchecked"))] + EqualsTo => return Ok(((**f1 - **f2).abs() <= FLOAT::EPSILON).into()), + #[cfg(feature = "unchecked")] NotEqualsTo => return Ok((**f1 != **f2).into()), + #[cfg(not(feature = "unchecked"))] + NotEqualsTo => return Ok(((**f1 - **f2).abs() > FLOAT::EPSILON).into()), GreaterThan => return Ok((**f1 > **f2).into()), GreaterThanEqualsTo => return Ok((**f1 >= **f2).into()), LessThan => return Ok((**f1 < **f2).into()), @@ -1746,36 +1752,52 @@ impl Engine { _ => (), }, #[cfg(not(feature = "no_float"))] - (Union::Float(f1, ..), Union::Int(n2, ..)) => match op_token.unwrap() { - EqualsTo => return Ok((**f1 == (*n2 as crate::FLOAT)).into()), - NotEqualsTo => return Ok((**f1 != (*n2 as crate::FLOAT)).into()), - GreaterThan => return Ok((**f1 > (*n2 as crate::FLOAT)).into()), - GreaterThanEqualsTo => return Ok((**f1 >= (*n2 as crate::FLOAT)).into()), - LessThan => return Ok((**f1 < (*n2 as crate::FLOAT)).into()), - LessThanEqualsTo => return Ok((**f1 <= (*n2 as crate::FLOAT)).into()), - Plus => return Ok((**f1 + (*n2 as crate::FLOAT)).into()), - Minus => return Ok((**f1 - (*n2 as crate::FLOAT)).into()), - Multiply => return Ok((**f1 * (*n2 as crate::FLOAT)).into()), - Divide => return Ok((**f1 / (*n2 as crate::FLOAT)).into()), - Modulo => return Ok((**f1 % (*n2 as crate::FLOAT)).into()), + (Union::Float(f1, ..), Union::Int(n2, ..)) => match op_token { + #[cfg(feature = "unchecked")] + EqualsTo => return Ok((**f1 == (*n2 as FLOAT)).into()), + #[cfg(not(feature = "unchecked"))] + EqualsTo => return Ok(((**f1 - (*n2 as FLOAT)).abs() <= FLOAT::EPSILON).into()), + #[cfg(feature = "unchecked")] + NotEqualsTo => return Ok((**f1 != (*n2 as FLOAT)).into()), + #[cfg(not(feature = "unchecked"))] + NotEqualsTo => { + return Ok(((**f1 - (*n2 as FLOAT)).abs() > FLOAT::EPSILON).into()) + } + GreaterThan => return Ok((**f1 > (*n2 as FLOAT)).into()), + GreaterThanEqualsTo => return Ok((**f1 >= (*n2 as FLOAT)).into()), + LessThan => return Ok((**f1 < (*n2 as FLOAT)).into()), + LessThanEqualsTo => return Ok((**f1 <= (*n2 as FLOAT)).into()), + Plus => return Ok((**f1 + (*n2 as FLOAT)).into()), + Minus => return Ok((**f1 - (*n2 as FLOAT)).into()), + Multiply => return Ok((**f1 * (*n2 as FLOAT)).into()), + Divide => return Ok((**f1 / (*n2 as FLOAT)).into()), + Modulo => return Ok((**f1 % (*n2 as FLOAT)).into()), _ => (), }, #[cfg(not(feature = "no_float"))] - (Union::Int(n1, ..), Union::Float(f2, ..)) => match op_token.unwrap() { - EqualsTo => return Ok(((*n1 as crate::FLOAT) == **f2).into()), - NotEqualsTo => return Ok(((*n1 as crate::FLOAT) != **f2).into()), - GreaterThan => return Ok(((*n1 as crate::FLOAT) > **f2).into()), - GreaterThanEqualsTo => return Ok(((*n1 as crate::FLOAT) >= **f2).into()), - LessThan => return Ok(((*n1 as crate::FLOAT) < **f2).into()), - LessThanEqualsTo => return Ok(((*n1 as crate::FLOAT) <= **f2).into()), - Plus => return Ok(((*n1 as crate::FLOAT) + **f2).into()), - Minus => return Ok(((*n1 as crate::FLOAT) - **f2).into()), - Multiply => return Ok(((*n1 as crate::FLOAT) * **f2).into()), - Divide => return Ok(((*n1 as crate::FLOAT) / **f2).into()), - Modulo => return Ok(((*n1 as crate::FLOAT) % **f2).into()), + (Union::Int(n1, ..), Union::Float(f2, ..)) => match op_token { + #[cfg(feature = "unchecked")] + EqualsTo => return Ok(((*n1 as FLOAT) == **f2).into()), + #[cfg(not(feature = "unchecked"))] + EqualsTo => return Ok((((*n1 as FLOAT) - **f2).abs() <= FLOAT::EPSILON).into()), + #[cfg(feature = "unchecked")] + NotEqualsTo => return Ok(((*n1 as FLOAT) != **f2).into()), + #[cfg(not(feature = "unchecked"))] + NotEqualsTo => { + return Ok((((*n1 as FLOAT) - **f2).abs() > FLOAT::EPSILON).into()) + } + GreaterThan => return Ok(((*n1 as FLOAT) > **f2).into()), + GreaterThanEqualsTo => return Ok(((*n1 as FLOAT) >= **f2).into()), + LessThan => return Ok(((*n1 as FLOAT) < **f2).into()), + LessThanEqualsTo => return Ok(((*n1 as FLOAT) <= **f2).into()), + Plus => return Ok(((*n1 as FLOAT) + **f2).into()), + Minus => return Ok(((*n1 as FLOAT) - **f2).into()), + Multiply => return Ok(((*n1 as FLOAT) * **f2).into()), + Divide => return Ok(((*n1 as FLOAT) / **f2).into()), + Modulo => return Ok(((*n1 as FLOAT) % **f2).into()), _ => (), }, - (Union::Str(s1, ..), Union::Str(s2, ..)) => match op_token.unwrap() { + (Union::Str(s1, ..), Union::Str(s2, ..)) => match op_token { EqualsTo => return Ok((s1 == s2).into()), NotEqualsTo => return Ok((s1 != s2).into()), GreaterThan => return Ok((s1 > s2).into()), @@ -1790,7 +1812,7 @@ impl Engine { Minus => return Ok((s1 - s2).into()), _ => (), }, - (Union::Char(c1, ..), Union::Char(c2, ..)) => match op_token.unwrap() { + (Union::Char(c1, ..), Union::Char(c2, ..)) => match op_token { EqualsTo => return Ok((c1 == c2).into()), NotEqualsTo => return Ok((c1 != c2).into()), GreaterThan => return Ok((c1 > c2).into()), @@ -1812,7 +1834,7 @@ impl Engine { (Union::Variant(..), _) | (_, Union::Variant(..)) => (), _ => { if let Some((func, need_context)) = - get_builtin_binary_op_fn(op_token.as_ref().unwrap(), &mut lhs, &mut rhs) + get_builtin_binary_op_fn(op_token, &lhs, &rhs) { // We may not need to bump the level because built-in's do not need it. //defer! { let orig_level = global.level; global.level += 1 } @@ -1825,6 +1847,7 @@ impl Engine { } let operands = &mut [&mut lhs, &mut rhs]; + let op_token = Some(op_token); return self .exec_fn_call( diff --git a/src/func/native.rs b/src/func/native.rs index 28863635a..9a5ecc401 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -316,8 +316,8 @@ impl<'a> NativeCallContext<'a> { result.try_cast_raw().map_err(|r| { let result_type = self.engine().map_type_name(r.type_name()); let cast_type = match type_name::() { - typ @ _ if typ.contains("::") => self.engine.map_type_name(typ), - typ @ _ => typ, + typ if typ.contains("::") => self.engine.map_type_name(typ), + typ => typ, }; ERR::ErrorMismatchOutputType( cast_type.into(), @@ -349,8 +349,8 @@ impl<'a> NativeCallContext<'a> { result.try_cast_raw().map_err(|r| { let result_type = self.engine().map_type_name(r.type_name()); let cast_type = match type_name::() { - typ @ _ if typ.contains("::") => self.engine.map_type_name(typ), - typ @ _ => typ, + typ if typ.contains("::") => self.engine.map_type_name(typ), + typ => typ, }; ERR::ErrorMismatchOutputType( cast_type.into(), diff --git a/src/lib.rs b/src/lib.rs index 3023ec4cf..90ba3920b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,7 +66,7 @@ // #![warn(clippy::pedantic)] // #![warn(clippy::nursery)] #![warn(clippy::cargo)] -// #![warn(clippy::undocumented_unsafe_blocks)] +#![warn(clippy::undocumented_unsafe_blocks)] #![allow(clippy::unit_arg)] #![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_panics_doc)] @@ -80,6 +80,7 @@ #![allow(clippy::upper_case_acronyms)] #![allow(clippy::match_same_arms)] // The lints below can be turned off to reduce signal/noise ratio +#![allow(clippy::cognitive_complexity)] #![allow(clippy::too_many_lines)] #![allow(let_underscore_drop)] #![allow(clippy::absurd_extreme_comparisons)] diff --git a/src/module/mod.rs b/src/module/mod.rs index 5a2273c1a..007ea75c0 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -134,10 +134,10 @@ impl FuncInfo { "" => "_", s => s, }; - let result: std::borrow::Cow = match segment.next() { - Some(typ) => format!("{name}: {}", format_type(typ, false)).into(), - None => name.into(), - }; + let result: std::borrow::Cow = segment.next().map_or_else( + || name.into(), + |typ| format!("{name}: {}", format_type(typ, false)).into(), + ); result }) .collect::>(); @@ -283,7 +283,7 @@ impl> Add for &Module { } } -impl> Add for Module { +impl> Add for Module { type Output = Self; #[inline(always)] @@ -293,7 +293,7 @@ impl> Add for Module { } } -impl> AddAssign for Module { +impl> AddAssign for Module { #[inline(always)] fn add_assign(&mut self, rhs: M) { self.combine(rhs.into()); @@ -374,7 +374,7 @@ impl Module { #[inline(always)] pub fn set_id(&mut self, id: impl Into) -> &mut Self { let id = id.into(); - self.id = (!id.is_empty()).then(|| id); + self.id = (!id.is_empty()).then_some(id); self } @@ -588,7 +588,6 @@ impl Module { /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] #[inline] - #[must_use] pub fn get_custom_type_comments(&self, key: &str) -> impl Iterator { self.custom_types .get(key) @@ -740,7 +739,11 @@ impl Module { // Catch hash collisions in testing environment only. #[cfg(feature = "testing-environ")] - if let Some(_) = self.all_variables.as_ref().and_then(|f| f.get(&hash_var)) { + if self + .all_variables + .as_ref() + .map_or(false, |f| f.contains_key(&hash_var)) + { panic!( "Hash {} already exists when registering variable {}", hash_var, ident @@ -777,13 +780,16 @@ impl Module { let num_params = fn_def.params.len(); let hash_script = crate::calc_fn_hash(None, &fn_def.name, num_params); #[cfg(not(feature = "no_object"))] - let (hash_script, namespace) = match fn_def.this_type { - Some(ref this_type) => { - let hash = crate::calc_typed_method_hash(hash_script, this_type); - (hash, FnNamespace::Global) - } - None => (hash_script, namespace), - }; + let (hash_script, namespace) = + fn_def + .this_type + .as_ref() + .map_or((hash_script, namespace), |this_type| { + ( + crate::calc_typed_method_hash(hash_script, this_type), + FnNamespace::Global, + ) + }); // Catch hash collisions in testing environment only. #[cfg(feature = "testing-environ")] @@ -810,7 +816,7 @@ impl Module { #[cfg(not(feature = "no_object"))] this_type: fn_def.this_type.clone(), num_params, - param_types: Default::default(), + param_types: <_>::default(), #[cfg(feature = "metadata")] params_info, #[cfg(feature = "metadata")] @@ -900,7 +906,7 @@ impl Module { /// ``` #[inline] #[must_use] - pub fn get_sub_module(&self, name: &str) -> Option<&Module> { + pub fn get_sub_module(&self, name: &str) -> Option<&Self> { self.modules.get(name).map(|m| &**m) } @@ -1548,19 +1554,22 @@ impl Module { F: RegisterNativeFunction<(Mut, B), 2, C, T, true> + SendSync + 'static, { #[cfg(not(feature = "no_index"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for arrays."); - } + assert!( + TypeId::of::() != TypeId::of::(), + "Cannot register indexer for arrays." + ); #[cfg(not(feature = "no_object"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for object maps."); - } - if TypeId::of::() == TypeId::of::() - || TypeId::of::() == TypeId::of::<&str>() - || TypeId::of::() == TypeId::of::() - { - panic!("Cannot register indexer for strings."); - } + assert!( + TypeId::of::() != TypeId::of::(), + "Cannot register indexer for object maps." + ); + + assert!( + TypeId::of::() != TypeId::of::() + && TypeId::of::() != TypeId::of::<&str>() + && TypeId::of::() != TypeId::of::(), + "Cannot register indexer for strings." + ); self.set_fn( crate::engine::FN_IDX_GET, @@ -1609,19 +1618,22 @@ impl Module { F: RegisterNativeFunction<(Mut, B, T), 3, C, (), true> + SendSync + 'static, { #[cfg(not(feature = "no_index"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for arrays."); - } + assert!( + TypeId::of::() != TypeId::of::(), + "Cannot register indexer for arrays." + ); #[cfg(not(feature = "no_object"))] - if TypeId::of::() == TypeId::of::() { - panic!("Cannot register indexer for object maps."); - } - if TypeId::of::() == TypeId::of::() - || TypeId::of::() == TypeId::of::<&str>() - || TypeId::of::() == TypeId::of::() - { - panic!("Cannot register indexer for strings."); - } + assert!( + TypeId::of::() != TypeId::of::(), + "Cannot register indexer for object maps." + ); + + assert!( + TypeId::of::() != TypeId::of::() + && TypeId::of::() != TypeId::of::<&str>() + && TypeId::of::() != TypeId::of::(), + "Cannot register indexer for strings." + ); self.set_fn( crate::engine::FN_IDX_SET, @@ -1704,7 +1716,7 @@ impl Module { /// A `true` return value does not automatically imply that the function _must_ exist. #[inline(always)] #[must_use] - pub(crate) fn may_contain_dynamic_fn(&self, hash_script: u64) -> bool { + pub(crate) const fn may_contain_dynamic_fn(&self, hash_script: u64) -> bool { !self.dynamic_functions_filter.is_absent(hash_script) } @@ -1802,12 +1814,12 @@ impl Module { /// Only items not existing in this [`Module`] are added. #[inline] pub fn fill_with(&mut self, other: &Self) -> &mut Self { - for (k, v) in other.modules.iter() { + for (k, v) in &other.modules { if !self.modules.contains_key(k) { self.modules.insert(k.clone(), v.clone()); } } - for (k, v) in other.variables.iter() { + for (k, v) in &other.variables { if !self.variables.contains_key(k) { self.variables.insert(k.clone(), v.clone()); } @@ -1824,7 +1836,7 @@ impl Module { } } self.dynamic_functions_filter += &other.dynamic_functions_filter; - for (&k, v) in other.type_iterators.iter() { + for (&k, v) in &other.type_iterators { self.type_iterators.entry(k).or_insert_with(|| v.clone()); } @@ -1857,7 +1869,7 @@ impl Module { other: &Self, _filter: impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool + Copy, ) -> &mut Self { - for (k, v) in other.modules.iter() { + for (k, v) in &other.modules { let mut m = Self::new(); m.merge_filtered(v, _filter); self.set_sub_module(k.clone(), m); @@ -2135,7 +2147,7 @@ impl Module { let result = engine.eval_ast_with_scope_raw(global, caches, scope, ast); // Create new module - let mut module = Module::new(); + let mut module = Self::new(); // Extra modules left become sub-modules let mut imports = Vec::new(); @@ -2168,7 +2180,7 @@ impl Module { let environ = Shared::new(crate::func::EncapsulatedEnviron { #[cfg(not(feature = "no_function"))] lib: ast.shared_lib().clone(), - imports: imports.into(), + imports, #[cfg(not(feature = "no_function"))] constants, }); @@ -2259,7 +2271,7 @@ impl Module { /// Panics if the [`Module`] is not yet indexed via [`build_index`][Module::build_index]. #[inline(always)] #[must_use] - pub fn contains_indexed_global_functions(&self) -> bool { + pub const fn contains_indexed_global_functions(&self) -> bool { self.flags.contains(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS) } @@ -2278,7 +2290,7 @@ impl Module { ) -> bool { let mut contains_indexed_global_functions = false; - for (name, m) in module.modules.iter() { + for (name, m) in &module.modules { // Index all the sub-modules first. path.push(name); if index_module(m, path, variables, functions, type_iterators) { @@ -2288,23 +2300,23 @@ impl Module { } // Index all variables - for (var_name, value) in module.variables.iter() { + for (var_name, value) in &module.variables { let hash_var = crate::calc_var_hash(path.iter().copied(), var_name); // Catch hash collisions in testing environment only. #[cfg(feature = "testing-environ")] - if variables.get(&hash_var).is_some() { - panic!( - "Hash {} already exists when indexing variable {}", - hash_var, var_name - ); - } + assert!( + !variables.contains_key(&hash_var), + "Hash {} already exists when indexing variable {}", + hash_var, + var_name + ); variables.insert(hash_var, value.clone()); } // Index all type iterators - for (&type_id, func) in module.type_iterators.iter() { + for (&type_id, func) in &module.type_iterators { type_iterators.insert(type_id, func.clone()); } @@ -2332,50 +2344,51 @@ impl Module { FnAccess::Private => continue, // Do not index private functions } - if !f.func.is_script() { - let hash_qualified_fn = calc_native_fn_hash( - path.iter().copied(), - f.metadata.name.as_str(), - &f.metadata.param_types, - ); - - // Catch hash collisions in testing environment only. - #[cfg(feature = "testing-environ")] - if let Some(fx) = functions.get(&hash_qualified_fn) { - panic!( - "Hash {} already exists when indexing function {:#?}:\n{:#?}", - hash_qualified_fn, f.func, fx - ); - } - - functions.insert(hash_qualified_fn, f.func.clone()); - } else { + if f.func.is_script() { #[cfg(not(feature = "no_function"))] { - let hash_qualified_script = crate::calc_fn_hash( + let hash_script = crate::calc_fn_hash( path.iter().copied(), &f.metadata.name, f.metadata.num_params, ); #[cfg(not(feature = "no_object"))] - let hash_qualified_script = match f.metadata.this_type { - Some(ref this_type) => { - crate::calc_typed_method_hash(hash_qualified_script, this_type) - } - None => hash_qualified_script, - }; + let hash_script = f + .metadata + .this_type + .as_ref() + .map_or(hash_script, |this_type| { + crate::calc_typed_method_hash(hash_script, this_type) + }); // Catch hash collisions in testing environment only. #[cfg(feature = "testing-environ")] - if let Some(fx) = functions.get(&hash_qualified_script) { + if let Some(fx) = functions.get(&hash_script) { panic!( "Hash {} already exists when indexing function {:#?}:\n{:#?}", - hash_qualified_script, f.func, fx + hash_script, f.func, fx ); } - functions.insert(hash_qualified_script, f.func.clone()); + functions.insert(hash_script, f.func.clone()); } + } else { + let hash_fn = calc_native_fn_hash( + path.iter().copied(), + f.metadata.name.as_str(), + &f.metadata.param_types, + ); + + // Catch hash collisions in testing environment only. + #[cfg(feature = "testing-environ")] + if let Some(fx) = functions.get(&hash_fn) { + panic!( + "Hash {} already exists when indexing function {:#?}:\n{:#?}", + hash_fn, f.func, fx + ); + } + + functions.insert(hash_fn, f.func.clone()); } } @@ -2402,8 +2415,8 @@ impl Module { self.flags .set(ModuleFlags::INDEXED_GLOBAL_FUNCTIONS, has_global_functions); - self.all_variables = (!variables.is_empty()).then(|| variables.into()); - self.all_functions = (!functions.is_empty()).then(|| functions.into()); + self.all_variables = (!variables.is_empty()).then_some(variables); + self.all_functions = (!functions.is_empty()).then_some(functions); self.all_type_iterators = type_iterators; self.flags |= ModuleFlags::INDEXED; diff --git a/src/optimizer.rs b/src/optimizer.rs index 1182af378..1371373d7 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -73,7 +73,7 @@ impl<'a> OptimizerState<'a> { #[cfg(not(feature = "no_function"))] { - _global.lib = _lib.iter().cloned().collect(); + _global.lib = _lib.to_vec(); } Self { @@ -511,15 +511,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def } optimize_expr(&mut b.condition, state, false); - let branch = match def_case { - Some(index) => { - let mut def_stmt = - Stmt::Expr(expressions[*index].expr.take().into()); - optimize_stmt(&mut def_stmt, state, true); - def_stmt.into() - } - _ => StmtBlock::NONE, - }; + let branch = def_case.map_or(StmtBlock::NONE, |index| { + let mut def_stmt = + Stmt::Expr(expressions[index].expr.take().into()); + optimize_stmt(&mut def_stmt, state, true); + def_stmt.into() + }); let body = Stmt::Expr(b.expr.take().into()).into(); let expr = b.condition.take(); @@ -572,15 +569,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // switch const { range if condition => stmt, _ => def } => if condition { stmt } else { def } optimize_expr(&mut expr, state, false); - let branch = match def_case { - Some(index) => { - let mut def_stmt = - Stmt::Expr(expressions[*index].expr.take().into()); - optimize_stmt(&mut def_stmt, state, true); - def_stmt.into() - } - _ => StmtBlock::NONE, - }; + let branch = def_case.map_or(StmtBlock::NONE, |index| { + let mut def_stmt = + Stmt::Expr(expressions[index].expr.take().into()); + optimize_stmt(&mut def_stmt, state, true); + def_stmt.into() + }); let body = Stmt::Expr(expressions[r.index()].expr.take().into()).into(); @@ -608,11 +602,11 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b state.set_dirty(); } - ranges.iter().for_each(|r| { + for r in ranges { let b = &mut expressions[r.index()]; optimize_expr(&mut b.condition, state, false); optimize_expr(&mut b.expr, state, false); - }); + } return; } } @@ -645,7 +639,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b optimize_expr(match_expr, state, false); // Optimize blocks - expressions.iter_mut().for_each(|b| { + for b in expressions.iter_mut() { optimize_expr(&mut b.condition, state, false); optimize_expr(&mut b.expr, state, false); @@ -653,7 +647,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b b.expr = Expr::Unit(b.expr.position()); state.set_dirty(); } - }); + } // Remove false cases cases.retain(|_, list| { @@ -700,17 +694,12 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b } // Remove unused block statements - (0..expressions.len()).into_iter().for_each(|index| { - if *def_case == Some(index) - || cases.values().flat_map(|c| c.iter()).any(|&n| n == index) - || ranges.iter().any(|r| r.index() == index) + expressions.iter_mut().enumerate().for_each(|(index, b)| { + if *def_case != Some(index) + && cases.values().flat_map(|c| c.iter()).all(|&n| n != index) + && ranges.iter().all(|r| r.index() != index) + && !b.expr.is_unit() { - return; - } - - let b = &mut expressions[index]; - - if !b.expr.is_unit() { b.expr = Expr::Unit(b.expr.position()); state.set_dirty(); } @@ -916,7 +905,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) { // const.is_shared() #[cfg(not(feature = "no_closure"))] (lhs, Expr::MethodCall(x, pos)) if lhs.is_constant() && x.name == crate::engine::KEYWORD_IS_SHARED && x.args.is_empty() => { - if let Some(..) = lhs.get_literal_value() { + if lhs.get_literal_value().is_some() { state.set_dirty(); *expr = Expr::from_dynamic(Dynamic::FALSE, *pos); } @@ -1346,9 +1335,9 @@ impl Engine { let mut module = crate::Module::new(); if optimization_level == OptimizationLevel::None { - functions.into_iter().for_each(|fn_def| { + for fn_def in functions { module.set_script_fn(fn_def); - }); + } } else { // We only need the script library's signatures for optimization purposes let mut lib2 = crate::Module::new(); @@ -1371,7 +1360,7 @@ impl Engine { let lib2 = &[lib2.into()]; - functions.into_iter().for_each(|fn_def| { + for fn_def in functions { let mut fn_def = crate::func::shared_take_or_clone(fn_def); // Optimize the function body let body = fn_def.body.take_statements(); @@ -1379,7 +1368,7 @@ impl Engine { *fn_def.body = self.optimize_top_level(body, scope, lib2, optimization_level); module.set_script_fn(fn_def); - }); + } } module.into() diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 49f84df12..9d5484273 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -116,30 +116,30 @@ macro_rules! gen_arithmetic_functions { } } #[rhai_fn(name = "&")] - pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type { + pub const fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type { x & y } #[rhai_fn(name = "|")] - pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type { + pub const fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type { x | y } #[rhai_fn(name = "^")] - pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type { + pub const fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type { x ^ y } /// Return true if the number is zero. #[rhai_fn(get = "is_zero", name = "is_zero")] - pub fn is_zero(x: $arg_type) -> bool { + pub const fn is_zero(x: $arg_type) -> bool { x == 0 } /// Return true if the number is odd. #[rhai_fn(get = "is_odd", name = "is_odd")] - pub fn is_odd(x: $arg_type) -> bool { + pub const fn is_odd(x: $arg_type) -> bool { x % 2 != 0 } /// Return true if the number is even. #[rhai_fn(get = "is_even", name = "is_even")] - pub fn is_even(x: $arg_type) -> bool { + pub const fn is_even(x: $arg_type) -> bool { x % 2 == 0 } } @@ -163,7 +163,7 @@ macro_rules! gen_signed_functions { } } #[rhai_fn(name = "+")] - pub fn plus(x: $arg_type) -> $arg_type { + pub const fn plus(x: $arg_type) -> $arg_type { x } /// Return the absolute value of the number. @@ -180,7 +180,7 @@ macro_rules! gen_signed_functions { /// * `0` if the number is zero /// * `1` if the number is positive /// * `-1` if the number is negative - pub fn sign(x: $arg_type) -> INT { + pub const fn sign(x: $arg_type) -> INT { x.signum() as INT } } @@ -232,17 +232,17 @@ def_package! { mod int_functions { /// Return true if the number is zero. #[rhai_fn(get = "is_zero", name = "is_zero")] - pub fn is_zero(x: INT) -> bool { + pub const fn is_zero(x: INT) -> bool { x == 0 } /// Return true if the number is odd. #[rhai_fn(get = "is_odd", name = "is_odd")] - pub fn is_odd(x: INT) -> bool { + pub const fn is_odd(x: INT) -> bool { x % 2 != 0 } /// Return true if the number is even. #[rhai_fn(get = "is_even", name = "is_even")] - pub fn is_even(x: INT) -> bool { + pub const fn is_even(x: INT) -> bool { x % 2 == 0 } } @@ -349,7 +349,7 @@ mod f32_functions { -x } #[rhai_fn(name = "+")] - pub fn plus(x: f32) -> f32 { + pub const fn plus(x: f32) -> f32 { x } /// Return the absolute value of the floating-point number. @@ -464,7 +464,7 @@ mod f64_functions { -x } #[rhai_fn(name = "+")] - pub fn plus(x: f64) -> f64 { + pub const fn plus(x: f64) -> f64 { x } /// Return the absolute value of the floating-point number. @@ -541,7 +541,7 @@ pub mod decimal_functions { -x } #[rhai_fn(name = "+")] - pub fn plus(x: Decimal) -> Decimal { + pub const fn plus(x: Decimal) -> Decimal { x } /// Return the absolute value of the decimal number. @@ -564,7 +564,7 @@ pub mod decimal_functions { } /// Return true if the decimal number is zero. #[rhai_fn(get = "is_zero", name = "is_zero")] - pub fn is_zero(x: Decimal) -> bool { + pub const fn is_zero(x: Decimal) -> bool { x.is_zero() } } diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index ca9490e7d..5f42a9fa9 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -315,9 +315,8 @@ pub mod array_functions { /// print(x); // prints "[3]" /// ``` pub fn remove(array: &mut Array, index: INT) -> Dynamic { - let index = match calc_index(array.len(), index, true, || Err(())) { - Ok(n) => n, - _ => return Dynamic::UNIT, + let Ok(index) = calc_index(array.len(), index, true, || Err(())) else { + return Dynamic::UNIT; }; array.remove(index) diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index c5343b8fe..9dc9e0608 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -457,9 +457,8 @@ pub mod blob_functions { /// print(x); // prints "[010305]" /// ``` pub fn remove(blob: &mut Blob, index: INT) -> INT { - let index = match calc_index(blob.len(), index, true, || Err(())) { - Ok(n) => n, - _ => return 0, + let Ok(index) = calc_index(blob.len(), index, true, || Err(())) else { + return 0; }; blob.remove(index) as INT diff --git a/src/packages/debugging.rs b/src/packages/debugging.rs index 68c32af16..c73b01a07 100644 --- a/src/packages/debugging.rs +++ b/src/packages/debugging.rs @@ -36,54 +36,53 @@ mod debugging_functions { pub fn back_trace(ctx: NativeCallContext) -> Array { use crate::debugger::CallStackFrame; - match ctx.global_runtime_state().debugger { - None => Array::new(), - Some(ref debugger) => debugger - .call_stack() - .iter() - .rev() - .filter(|CallStackFrame { fn_name, args, .. }| { - fn_name.as_str() != "back_trace" || !args.is_empty() - }) - .map( - |frame @ CallStackFrame { - fn_name: _fn_name, - args: _args, - source: _source, - pos: _pos, - }| { - let display = frame.to_string(); + ctx.global_runtime_state() + .debugger + .as_ref() + .map_or_else(Array::new, |debugger| { + debugger + .call_stack() + .iter() + .rev() + .filter(|CallStackFrame { fn_name, args, .. }| { + fn_name.as_str() != "back_trace" || !args.is_empty() + }) + .map( + |frame @ CallStackFrame { + fn_name: _fn_name, + args: _args, + source: _source, + pos: _pos, + }| { + let display = frame.to_string(); - #[cfg(not(feature = "no_object"))] - { - use crate::INT; + #[cfg(not(feature = "no_object"))] + { + use crate::INT; - let mut map = Map::new(); - map.insert("display".into(), display.into()); - map.insert("fn_name".into(), _fn_name.into()); - if !_args.is_empty() { - map.insert( - "args".into(), - Dynamic::from_array(_args.clone().to_vec()), - ); + let mut map = Map::new(); + map.insert("display".into(), display.into()); + map.insert("fn_name".into(), _fn_name.into()); + if !_args.is_empty() { + map.insert("args".into(), Dynamic::from_array(_args.clone())); + } + if let Some(source) = _source { + map.insert("source".into(), source.into()); + } + if !_pos.is_none() { + map.insert("line".into(), (_pos.line().unwrap() as INT).into()); + map.insert( + "position".into(), + (_pos.position().unwrap_or(0) as INT).into(), + ); + } + Dynamic::from_map(map) } - if let Some(source) = _source { - map.insert("source".into(), source.into()); - } - if !_pos.is_none() { - map.insert("line".into(), (_pos.line().unwrap() as INT).into()); - map.insert( - "position".into(), - (_pos.position().unwrap_or(0) as INT).into(), - ); - } - Dynamic::from_map(map) - } - #[cfg(feature = "no_object")] - display.into() - }, - ) - .collect(), - } + #[cfg(feature = "no_object")] + display.into() + }, + ) + .collect() + }) } } diff --git a/src/packages/lang_core.rs b/src/packages/lang_core.rs index 51e3f7958..940bba03a 100644 --- a/src/packages/lang_core.rs +++ b/src/packages/lang_core.rs @@ -356,7 +356,7 @@ fn collect_fn_metadata( use std::fmt::Write; let mut ns = SmartString::new_const(); - write!(&mut ns, "{namespace}{}{name}", NAMESPACE_SEPARATOR).unwrap(); + write!(&mut ns, "{namespace}{NAMESPACE_SEPARATOR}{name}").unwrap(); scan_module(engine, list, &ns, m, filter); } } diff --git a/src/packages/logic.rs b/src/packages/logic.rs index 9d3cc634e..b148512fc 100644 --- a/src/packages/logic.rs +++ b/src/packages/logic.rs @@ -14,6 +14,7 @@ macro_rules! gen_cmp_functions { use super::super::*; #[export_module] + #[allow(clippy::missing_const_for_fn)] pub mod functions { #[rhai_fn(name = "<")] pub fn lt(x: $arg_type, y: $arg_type) -> bool { x < y } #[rhai_fn(name = "<=")] pub fn lte(x: $arg_type, y: $arg_type) -> bool { x <= y } @@ -98,7 +99,7 @@ gen_cmp_functions!(float => f64); #[export_module] mod logic_functions { #[rhai_fn(name = "!")] - pub fn not(x: bool) -> bool { + pub const fn not(x: bool) -> bool { !x } } @@ -114,7 +115,7 @@ mod min_max_functions { /// ```rhai /// max(42, 123); // returns 132 /// ``` - pub fn max(x: INT, y: INT) -> INT { + pub const fn max(x: INT, y: INT) -> INT { if x >= y { x } else { @@ -128,7 +129,7 @@ mod min_max_functions { /// ```rhai /// min(42, 123); // returns 42 /// ``` - pub fn min(x: INT, y: INT) -> INT { + pub const fn min(x: INT, y: INT) -> INT { if x <= y { x } else { @@ -234,11 +235,19 @@ mod f32_functions { } #[rhai_fn(name = "!=")] pub fn neq_if(x: INT, y: f32) -> bool { - (x as f32) != (y as f32) + #[cfg(feature = "unchecked")] + return (x as f32) != (y as f32); + + #[cfg(not(feature = "unchecked"))] + return (x as f32 - y as f32).abs() > f32::EPSILON; } #[rhai_fn(name = "!=")] pub fn neq_fi(x: f32, y: INT) -> bool { - (x as f32) != (y as f32) + #[cfg(feature = "unchecked")] + return (x as f32) != (y as f32); + + #[cfg(not(feature = "unchecked"))] + return (x as f32 - y as f32).abs() > f32::EPSILON; } #[rhai_fn(name = ">")] pub fn gt_if(x: INT, y: f32) -> bool { diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index dc8bf591e..3f427f0b8 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -25,6 +25,7 @@ macro_rules! gen_conversion_as_functions { use super::super::*; #[export_fn] + #[allow(clippy::missing_const_for_fn)] pub fn $func_name(x: $arg_type) -> $result_type { x as $result_type } @@ -223,7 +224,7 @@ mod trig_functions { mod float_functions { /// Return the natural number _e_. #[rhai_fn(name = "E")] - pub fn e() -> FLOAT { + pub const fn e() -> FLOAT { #[cfg(not(feature = "f32_float"))] return std::f64::consts::E; #[cfg(feature = "f32_float")] @@ -231,7 +232,7 @@ mod float_functions { } /// Return the number π. #[rhai_fn(name = "PI")] - pub fn pi() -> FLOAT { + pub const fn pi() -> FLOAT { #[cfg(not(feature = "f32_float"))] return std::f64::consts::PI; #[cfg(feature = "f32_float")] @@ -557,6 +558,7 @@ mod decimal_functions { /// Convert the decimal number into an integer. #[rhai_fn(return_raw)] pub fn to_int(x: Decimal) -> RhaiResultOf { + #[allow(clippy::bind_instead_of_map)] x.to_i64() .and_then(|n| { #[cfg(feature = "only_i32")] diff --git a/src/packages/string_basic.rs b/src/packages/string_basic.rs index f33cc8022..f6d6b5163 100644 --- a/src/packages/string_basic.rs +++ b/src/packages/string_basic.rs @@ -90,7 +90,7 @@ mod print_debug_functions { /// Return the `string`. #[rhai_fn(name = "print", name = "to_string")] - pub fn print_string(string: ImmutableString) -> ImmutableString { + pub const fn print_string(string: ImmutableString) -> ImmutableString { string } /// Convert the string into debug format. diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index a2f423b36..5093d6ea8 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -87,12 +87,12 @@ mod string_functions { #[allow(unused_variables)] #[rhai_fn(name = "+")] - pub fn add_append_unit(string: ImmutableString, item: ()) -> ImmutableString { + pub const fn add_append_unit(string: ImmutableString, item: ()) -> ImmutableString { string } #[allow(unused_variables)] #[rhai_fn(name = "+")] - pub fn add_prepend_unit(item: (), string: ImmutableString) -> ImmutableString { + pub const fn add_prepend_unit(item: (), string: ImmutableString) -> ImmutableString { string } @@ -196,7 +196,7 @@ mod string_functions { } /// Return true if the string is empty. #[rhai_fn(name = "is_empty", get = "is_empty")] - pub fn is_empty(string: &str) -> bool { + pub const fn is_empty(string: &str) -> bool { string.len() == 0 } /// Return the length of the string, in number of bytes used to store it in UTF-8 encoding. @@ -209,7 +209,7 @@ mod string_functions { /// print(text.bytes); // prints 51 /// ``` #[rhai_fn(name = "bytes", get = "bytes")] - pub fn bytes(string: &str) -> INT { + pub const fn bytes(string: &str) -> INT { if string.is_empty() { return 0; } @@ -299,20 +299,17 @@ mod string_functions { /// print(text); // prints "hello" /// ``` pub fn trim(string: &mut ImmutableString) { - match string.get_mut() { - Some(s) => { - let trimmed = s.trim(); + if let Some(s) = string.get_mut() { + let trimmed = s.trim(); - if trimmed != s { - *s = trimmed.into(); - } + if trimmed != s { + *s = trimmed.into(); } - None => { - let trimmed = string.trim(); + } else { + let trimmed = string.trim(); - if trimmed != string { - *string = trimmed.into(); - } + if trimmed != string { + *string = trimmed.into(); } } } @@ -334,10 +331,7 @@ mod string_functions { return Dynamic::UNIT; } - match string.make_mut().pop() { - Some(c) => c.into(), - None => Dynamic::UNIT, - } + string.make_mut().pop().map_or(Dynamic::UNIT, Into::into) } /// Remove a specified number of characters from the end of the string and return it as a /// new string. @@ -409,7 +403,7 @@ mod string_functions { /// print(text); // prints "HELLO, WORLD!"; /// ``` pub fn make_upper(string: &mut ImmutableString) { - if string.is_empty() || string.chars().all(|ch| ch.is_uppercase()) { + if string.is_empty() || string.chars().all(char::is_uppercase) { return; } @@ -446,7 +440,7 @@ mod string_functions { /// print(text); // prints "hello, world!"; /// ``` pub fn make_lower(string: &mut ImmutableString) { - if string.is_empty() || string.chars().all(|ch| ch.is_lowercase()) { + if string.is_empty() || string.chars().all(char::is_lowercase) { return; } @@ -1425,7 +1419,7 @@ mod string_functions { /// max('h', 'w'); // returns 'w' /// ``` #[rhai_fn(name = "max")] - pub fn max_char(char1: char, char2: char) -> char { + pub const fn max_char(char1: char, char2: char) -> char { if char1 >= char2 { char1 } else { @@ -1440,7 +1434,7 @@ mod string_functions { /// max('h', 'w'); // returns 'h' /// ``` #[rhai_fn(name = "min")] - pub fn min_char(char1: char, char2: char) -> char { + pub const fn min_char(char1: char, char2: char) -> char { if char1 <= char2 { char1 } else { diff --git a/src/packages/time_basic.rs b/src/packages/time_basic.rs index b43136b82..abbd8e7b7 100644 --- a/src/packages/time_basic.rs +++ b/src/packages/time_basic.rs @@ -80,6 +80,7 @@ mod time_functions { /// Return the number of seconds between two timestamps. #[rhai_fn(return_raw, name = "-")] + #[allow(clippy::unnecessary_wraps)] pub fn time_diff(timestamp1: Instant, timestamp2: Instant) -> RhaiResult { #[cfg(not(feature = "no_float"))] return Ok(if timestamp2 > timestamp1 { @@ -205,8 +206,8 @@ mod time_functions { Ok(timestamp + Duration::from_secs(seconds as u64)) } } + #[allow(clippy::cast_sign_loss)] fn subtract_impl(timestamp: Instant, seconds: INT) -> RhaiResultOf { - #[allow(clippy::cast_sign_loss)] if seconds < 0 { return add_impl(timestamp, -seconds); } diff --git a/src/parser.rs b/src/parser.rs index ee3f12044..118b66506 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -289,6 +289,7 @@ bitflags! { bitflags! { /// Bit-flags containing all status for parsing property/indexing/namespace chains. + #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] struct ChainingFlags: u8 { /// Is the construct being parsed a property? const PROPERTY = 0b0000_0001; @@ -387,18 +388,18 @@ impl Expr { } } /// Raise an error if the expression can never yield a boolean value. - fn ensure_bool_expr(self) -> ParseResult { + fn ensure_bool_expr(self) -> ParseResult { let type_name = match self { - Expr::Unit(..) => "()", - Expr::DynamicConstant(ref v, ..) if !v.is_bool() => v.type_name(), - Expr::IntegerConstant(..) => "a number", + Self::Unit(..) => "()", + Self::DynamicConstant(ref v, ..) if !v.is_bool() => v.type_name(), + Self::IntegerConstant(..) => "a number", #[cfg(not(feature = "no_float"))] - Expr::FloatConstant(..) => "a floating-point number", - Expr::CharConstant(..) => "a character", - Expr::StringConstant(..) => "a string", - Expr::InterpolatedString(..) => "a string", - Expr::Array(..) => "an array", - Expr::Map(..) => "an object map", + Self::FloatConstant(..) => "a floating-point number", + Self::CharConstant(..) => "a character", + Self::StringConstant(..) => "a string", + Self::InterpolatedString(..) => "a string", + Self::Array(..) => "an array", + Self::Map(..) => "an object map", _ => return Ok(self), }; @@ -408,15 +409,15 @@ impl Expr { ) } /// Raise an error if the expression can never yield an iterable value. - fn ensure_iterable(self) -> ParseResult { + fn ensure_iterable(self) -> ParseResult { let type_name = match self { - Expr::Unit(..) => "()", - Expr::BoolConstant(..) => "a boolean", - Expr::IntegerConstant(..) => "a number", + Self::Unit(..) => "()", + Self::BoolConstant(..) => "a boolean", + Self::IntegerConstant(..) => "a number", #[cfg(not(feature = "no_float"))] - Expr::FloatConstant(..) => "a floating-point number", - Expr::CharConstant(..) => "a character", - Expr::Map(..) => "an object map", + Self::FloatConstant(..) => "a floating-point number", + Self::CharConstant(..) => "a character", + Self::Map(..) => "an object map", _ => return Ok(self), }; @@ -455,10 +456,10 @@ fn ensure_not_assignment(input: &mut TokenStream) -> ParseResult<()> { /// # Panics /// /// Panics if the next token is not the expected one, or either tokens is not a literal symbol. -fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position { +fn eat_token(input: &mut TokenStream, expected_token: &Token) -> Position { let (t, pos) = input.next().expect(NEVER_ENDS); - if t != expected_token { + if &t != expected_token { unreachable!( "{} expected but gets {} at {}", expected_token.literal_syntax(), @@ -470,9 +471,9 @@ fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position { } /// Match a particular [token][Token], consuming it if matched. -fn match_token(input: &mut TokenStream, token: Token) -> (bool, Position) { +fn match_token(input: &mut TokenStream, token: &Token) -> (bool, Position) { let (t, pos) = input.peek().expect(NEVER_ENDS); - if *t == token { + if t == token { (true, eat_token(input, token)) } else { (false, *pos) @@ -636,7 +637,7 @@ impl Engine { // id() Token::RightParen => { if !no_args { - eat_token(input, Token::RightParen); + eat_token(input, &Token::RightParen); } #[cfg(not(feature = "no_module"))] @@ -703,7 +704,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { // id(...args) (Token::RightParen, ..) => { - eat_token(input, Token::RightParen); + eat_token(input, &Token::RightParen); #[cfg(not(feature = "no_module"))] let hash = if _namespace.is_empty() { @@ -756,7 +757,7 @@ impl Engine { } // id(...args, (Token::Comma, ..) => { - eat_token(input, Token::Comma); + eat_token(input, &Token::Comma); } // id(...args (Token::EOF, pos) => { @@ -897,7 +898,7 @@ impl Engine { // Check if there is a closing bracket match input.peek().expect(NEVER_ENDS) { (Token::RightBracket, ..) => { - eat_token(input, Token::RightBracket); + eat_token(input, &Token::RightBracket); // Any more indexing following? match input.peek().expect(NEVER_ENDS) { @@ -951,7 +952,7 @@ impl Engine { ) -> ParseResult { // [ ... let mut settings = settings; - settings.pos = eat_token(input, Token::LeftBracket); + settings.pos = eat_token(input, &Token::LeftBracket); let mut array = FnArgsVec::new_const(); @@ -969,7 +970,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { (Token::RightBracket, ..) => { - eat_token(input, Token::RightBracket); + eat_token(input, &Token::RightBracket); break; } (Token::EOF, pos) => { @@ -984,7 +985,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { (Token::Comma, ..) => { - eat_token(input, Token::Comma); + eat_token(input, &Token::Comma); } (Token::RightBracket, ..) => (), (Token::EOF, pos) => { @@ -1021,7 +1022,7 @@ impl Engine { ) -> ParseResult { // #{ ... let mut settings = settings; - settings.pos = eat_token(input, Token::MapStart); + settings.pos = eat_token(input, &Token::MapStart); let mut map = StaticVec::<(Ident, Expr)>::new(); let mut template = std::collections::BTreeMap::::new(); @@ -1031,7 +1032,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { (Token::RightBrace, ..) => { - eat_token(input, Token::RightBrace); + eat_token(input, &Token::RightBrace); break; } (Token::EOF, pos) => { @@ -1108,7 +1109,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { (Token::Comma, ..) => { - eat_token(input, Token::Comma); + eat_token(input, &Token::Comma); } (Token::RightBrace, ..) => (), (Token::Identifier(..), pos) => { @@ -1143,7 +1144,7 @@ impl Engine { ) -> ParseResult { // switch ... let mut settings = settings.level_up()?; - settings.pos = eat_token(input, Token::Switch); + settings.pos = eat_token(input, &Token::Switch); let item = self.parse_expr(input, state, lib, settings)?; @@ -1170,7 +1171,7 @@ impl Engine { let (case_expr_list, condition) = match input.peek().expect(NEVER_ENDS) { (Token::RightBrace, ..) => { - eat_token(input, Token::RightBrace); + eat_token(input, &Token::RightBrace); break; } (Token::EOF, pos) => { @@ -1181,9 +1182,9 @@ impl Engine { } (Token::Underscore, pos) if def_case.is_none() => { def_case_pos = *pos; - eat_token(input, Token::Underscore); + eat_token(input, &Token::Underscore); - let (if_clause, if_pos) = match_token(input, Token::If); + let (if_clause, if_pos) = match_token(input, &Token::If); if if_clause { return Err(PERR::WrongSwitchCaseCondition.into_err(if_pos)); @@ -1214,12 +1215,12 @@ impl Engine { } } - if !match_token(input, Token::Pipe).0 { + if !match_token(input, &Token::Pipe).0 { break; } } - let condition = if match_token(input, Token::If).0 { + let condition = if match_token(input, &Token::If).0 { ensure_not_statement_expr(input, "a boolean")?; let guard = self .parse_expr(input, state, lib, settings)? @@ -1314,7 +1315,7 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { (Token::Comma, ..) => { - eat_token(input, Token::Comma); + eat_token(input, &Token::Comma); } (Token::RightBrace, ..) => (), (Token::EOF, pos) => { @@ -1412,7 +1413,7 @@ impl Engine { // ( - grouped expression Token::LeftParen => { - settings.pos = eat_token(input, Token::LeftParen); + settings.pos = eat_token(input, &Token::LeftParen); let expr = self.parse_expr(input, state, lib, settings.level_up()?)?; @@ -1517,7 +1518,7 @@ impl Engine { let (expr, fn_def) = result?; #[cfg(not(feature = "no_closure"))] - for Ident { name, pos } in new_state.external_vars.iter() { + for Ident { name, pos } in &new_state.external_vars { let (index, is_func) = state.access_var(name, lib, *pos); if !is_func @@ -1964,7 +1965,7 @@ impl Engine { // -expr Token::Minus | Token::UnaryMinus => { let token = token.clone(); - let pos = eat_token(input, token.clone()); + let pos = eat_token(input, &token); match self.parse_unary(input, state, lib, settings.level_up()?)? { // Negative integer @@ -1998,7 +1999,7 @@ impl Engine { // +expr Token::Plus | Token::UnaryPlus => { let token = token.clone(); - let pos = eat_token(input, token.clone()); + let pos = eat_token(input, &token); match self.parse_unary(input, state, lib, settings.level_up()?)? { expr @ Expr::IntegerConstant(..) => Ok(expr), @@ -2020,7 +2021,7 @@ impl Engine { // !expr Token::Bang => { let token = token.clone(); - let pos = eat_token(input, Token::Bang); + let pos = eat_token(input, &Token::Bang); Ok(FnCallExpr { namespace: Namespace::NONE, @@ -2075,10 +2076,10 @@ impl Engine { } } - let op_info = match op { - Some(op) => OpAssignment::new_op_assignment_from_token(op, op_pos), - None => OpAssignment::new_assignment(op_pos), - }; + let op_info = op.map_or_else( + || OpAssignment::new_assignment(op_pos), + |op| OpAssignment::new_op_assignment_from_token(op, op_pos), + ); match lhs { // this = rhs @@ -2117,20 +2118,19 @@ impl Engine { check_lvalue(&x.rhs, matches!(lhs, Expr::Dot(..))) }; - match valid_lvalue { - None => { - match x.lhs { - // var[???] = rhs, this[???] = rhs, var.??? = rhs, this.??? = rhs - Expr::Variable(..) | Expr::ThisPtr(..) => { - Ok(Stmt::Assignment((op_info, (lhs, rhs).into()).into())) - } - // expr[???] = rhs, expr.??? = rhs - ref expr => Err(PERR::AssignmentToInvalidLHS(String::new()) - .into_err(expr.position())), + if let Some(err_pos) = valid_lvalue { + Err(PERR::AssignmentToInvalidLHS(String::new()).into_err(err_pos)) + } else { + match x.lhs { + // var[???] = rhs, this[???] = rhs, var.??? = rhs, this.??? = rhs + Expr::Variable(..) | Expr::ThisPtr(..) => { + Ok(Stmt::Assignment((op_info, (lhs, rhs).into()).into())) + } + // expr[???] = rhs, expr.??? = rhs + ref expr => { + Err(PERR::AssignmentToInvalidLHS(String::new()) + .into_err(expr.position())) } - } - Some(err_pos) => { - Err(PERR::AssignmentToInvalidLHS(String::new()).into_err(err_pos)) } } } @@ -2692,7 +2692,7 @@ impl Engine { ) -> ParseResult { // if ... let mut settings = settings.level_up()?; - settings.pos = eat_token(input, Token::If); + settings.pos = eat_token(input, &Token::If); // if guard { if_body } ensure_not_statement_expr(input, "a boolean")?; @@ -2703,7 +2703,7 @@ impl Engine { let body = self.parse_block(input, state, lib, settings)?.into(); // if guard { if_body } else ... - let branch = if match_token(input, Token::Else).0 { + let branch = if match_token(input, &Token::Else).0 { match input.peek().expect(NEVER_ENDS) { // if guard { if_body } else if ... (Token::If, ..) => self.parse_if(input, state, lib, settings)?, @@ -2769,7 +2769,7 @@ impl Engine { let orig_breakable = settings.flags.contains(ParseSettingFlags::BREAKABLE); settings.flags |= ParseSettingFlags::BREAKABLE; - settings.pos = eat_token(input, Token::Do); + settings.pos = eat_token(input, &Token::Do); // do { body } [while|until] guard @@ -2815,14 +2815,14 @@ impl Engine { ) -> ParseResult { // for ... let mut settings = settings.level_up()?; - settings.pos = eat_token(input, Token::For); + settings.pos = eat_token(input, &Token::For); // for name ... - let (name, name_pos, counter_name, counter_pos) = if match_token(input, Token::LeftParen).0 + let (name, name_pos, counter_name, counter_pos) = if match_token(input, &Token::LeftParen).0 { // ( name, counter ) let (name, name_pos) = parse_var_name(input)?; - let (has_comma, pos) = match_token(input, Token::Comma); + let (has_comma, pos) = match_token(input, &Token::Comma); if !has_comma { return Err(PERR::MissingToken( Token::Comma.into(), @@ -2836,7 +2836,7 @@ impl Engine { return Err(PERR::DuplicatedVariable(counter_name.into()).into_err(counter_pos)); } - let (has_close_paren, pos) = match_token(input, Token::RightParen); + let (has_close_paren, pos) = match_token(input, &Token::RightParen); if !has_close_paren { return Err(PERR::MissingToken( Token::RightParen.into(), @@ -2958,7 +2958,7 @@ impl Engine { let name = state.get_interned_string(name); // let name = ... - let expr = if match_token(input, Token::Equals).0 { + let expr = if match_token(input, &Token::Equals).0 { // let name = expr self.parse_expr(input, state, lib, settings.level_up()?)? } else { @@ -2986,15 +2986,12 @@ impl Engine { None }; - let idx = match existing { - Some(n) => { - state.stack.get_mut_by_index(n).set_access_mode(access); - Some(NonZeroUsize::new(state.stack.len() - n).unwrap()) - } - None => { - state.stack.push_entry(name.clone(), access, Dynamic::UNIT); - None - } + let idx = if let Some(n) = existing { + state.stack.get_mut_by_index(n).set_access_mode(access); + Some(NonZeroUsize::new(state.stack.len() - n).unwrap()) + } else { + state.stack.push_entry(name.clone(), access, Dynamic::UNIT); + None }; #[cfg(not(feature = "no_module"))] @@ -3025,12 +3022,12 @@ impl Engine { ) -> ParseResult { // import ... let mut settings = settings.level_up()?; - settings.pos = eat_token(input, Token::Import); + settings.pos = eat_token(input, &Token::Import); // import expr ... let expr = self.parse_expr(input, state, lib, settings)?; - let export = if match_token(input, Token::As).0 { + let export = if match_token(input, &Token::As).0 { // import expr as name ... let (name, pos) = parse_var_name(input)?; Ident { @@ -3060,7 +3057,7 @@ impl Engine { settings: ParseSettings, ) -> ParseResult { let mut settings = settings; - settings.pos = eat_token(input, Token::Export); + settings.pos = eat_token(input, &Token::Export); match input.peek().expect(NEVER_ENDS) { (Token::Let, pos) => { @@ -3084,7 +3081,7 @@ impl Engine { let (id, id_pos) = parse_var_name(input)?; - let (alias, alias_pos) = if match_token(input, Token::As).0 { + let (alias, alias_pos) = if match_token(input, &Token::As).0 { parse_var_name(input).map(|(name, pos)| (state.get_interned_string(name), pos))? } else { (state.get_interned_string(""), Position::NONE) @@ -3161,7 +3158,7 @@ impl Engine { let end_pos = loop { // Terminated? match input.peek().expect(NEVER_ENDS) { - (Token::RightBrace, ..) => break eat_token(input, Token::RightBrace), + (Token::RightBrace, ..) => break eat_token(input, &Token::RightBrace), (Token::EOF, pos) => { return Err(PERR::MissingToken( Token::RightBrace.into(), @@ -3188,14 +3185,14 @@ impl Engine { match input.peek().expect(NEVER_ENDS) { // { ... stmt } - (Token::RightBrace, ..) => break eat_token(input, Token::RightBrace), + (Token::RightBrace, ..) => break eat_token(input, &Token::RightBrace), // { ... stmt; (Token::SemiColon, ..) if need_semicolon => { - eat_token(input, Token::SemiColon); + eat_token(input, &Token::SemiColon); } // { ... { stmt } ; (Token::SemiColon, ..) if !need_semicolon => { - eat_token(input, Token::SemiColon); + eat_token(input, &Token::SemiColon); } // { ... { stmt } ??? _ if !need_semicolon => (), @@ -3237,7 +3234,7 @@ impl Engine { let (op, pos) = match input.peek().expect(NEVER_ENDS) { // var = ... - (Token::Equals, ..) => (None, eat_token(input, Token::Equals)), + (Token::Equals, ..) => (None, eat_token(input, &Token::Equals)), // var op= ... (token, ..) if token.is_op_assignment() => input .next() @@ -3332,7 +3329,7 @@ impl Engine { match token { // ; - empty statement Token::SemiColon => { - eat_token(input, Token::SemiColon); + eat_token(input, &Token::SemiColon); Ok(Stmt::Noop(token_pos)) } @@ -3348,7 +3345,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] Token::Fn | Token::Private => { let access = if matches!(token, Token::Private) { - eat_token(input, Token::Private); + eat_token(input, &Token::Private); crate::FnAccess::Private } else { crate::FnAccess::Public @@ -3404,10 +3401,10 @@ impl Engine { let hash = calc_fn_hash(None, &f.name, f.params.len()); #[cfg(not(feature = "no_object"))] - let hash = match f.this_type { - Some(ref this_type) => crate::calc_typed_method_hash(hash, this_type), - None => hash, - }; + let hash = f + .this_type + .as_ref() + .map_or(hash, |typ| crate::calc_typed_method_hash(hash, typ)); if !lib.is_empty() && lib.contains_key(&hash) { return Err(PERR::FnDuplicatedDefinition( @@ -3445,13 +3442,13 @@ impl Engine { Token::Continue if self.allow_looping() && settings.has_flag(ParseSettingFlags::BREAKABLE) => { - let pos = eat_token(input, Token::Continue); + let pos = eat_token(input, &Token::Continue); Ok(Stmt::BreakLoop(None, ASTFlags::empty(), pos)) } Token::Break if self.allow_looping() && settings.has_flag(ParseSettingFlags::BREAKABLE) => { - let pos = eat_token(input, Token::Break); + let pos = eat_token(input, &Token::Break); let expr = match input.peek().expect(NEVER_ENDS) { // `break` at @@ -3540,13 +3537,13 @@ impl Engine { ) -> ParseResult { // try ... let mut settings = settings.level_up()?; - settings.pos = eat_token(input, Token::Try); + settings.pos = eat_token(input, &Token::Try); // try { try_block } let body = self.parse_block(input, state, lib, settings)?.into(); // try { try_block } catch - let (matched, catch_pos) = match_token(input, Token::Catch); + let (matched, catch_pos) = match_token(input, &Token::Catch); if !matched { return Err( @@ -3556,9 +3553,9 @@ impl Engine { } // try { try_block } catch ( - let catch_var = if match_token(input, Token::LeftParen).0 { + let catch_var = if match_token(input, &Token::LeftParen).0 { let (name, pos) = parse_var_name(input)?; - let (matched, err_pos) = match_token(input, Token::RightParen); + let (matched, err_pos) = match_token(input, &Token::RightParen); if !matched { return Err(PERR::MissingToken( @@ -3622,7 +3619,7 @@ impl Engine { match token { Token::StringConstant(s) if next_token == &Token::Period => { - eat_token(input, Token::Period); + eat_token(input, &Token::Period); let s = match s.as_str() { "int" => state.get_interned_string(std::any::type_name::()), #[cfg(not(feature = "no_float"))] @@ -3639,7 +3636,7 @@ impl Engine { .into_err(*next_pos)) } Token::Identifier(s) if next_token == &Token::Period => { - eat_token(input, Token::Period); + eat_token(input, &Token::Period); let s = match s.as_str() { "int" => state.get_interned_string(std::any::type_name::()), #[cfg(not(feature = "no_float"))] @@ -3660,11 +3657,11 @@ impl Engine { let no_params = match input.peek().expect(NEVER_ENDS) { (Token::LeftParen, ..) => { - eat_token(input, Token::LeftParen); - match_token(input, Token::RightParen).0 + eat_token(input, &Token::LeftParen); + match_token(input, &Token::RightParen).0 } (Token::Unit, ..) => { - eat_token(input, Token::Unit); + eat_token(input, &Token::Unit); true } (.., pos) => return Err(PERR::FnMissingParams(name.into()).into_err(*pos)), @@ -3756,8 +3753,7 @@ impl Engine { args.extend(externals.iter().cloned().map(|Ident { name, pos }| { let (index, is_func) = parent.access_var(&name, lib, pos); let idx = match index { - #[allow(clippy::cast_possible_truncation)] - Some(n) if !is_func && n.get() <= u8::MAX as usize => NonZeroU8::new(n.get() as u8), + Some(n) if !is_func => u8::try_from(n.get()).ok().and_then(NonZeroU8::new), _ => None, }; Expr::Variable((index, Namespace::default(), 0, name).into(), idx, pos) @@ -3807,7 +3803,7 @@ impl Engine { let settings = settings.level_up()?; let mut params_list = StaticVec::::new_const(); - if input.next().expect(NEVER_ENDS).0 != Token::Or && !match_token(input, Token::Pipe).0 { + if input.next().expect(NEVER_ENDS).0 != Token::Or && !match_token(input, &Token::Pipe).0 { loop { match input.next().expect(NEVER_ENDS) { (Token::Pipe, ..) => break, @@ -3996,7 +3992,7 @@ impl Engine { (Token::EOF, ..) => break, // stmt ; (Token::SemiColon, ..) if need_semicolon => { - eat_token(&mut input, Token::SemiColon); + eat_token(&mut input, &Token::SemiColon); } // stmt ; (Token::SemiColon, ..) if !need_semicolon => (), diff --git a/src/reify.rs b/src/reify.rs index 4c9506a88..aa5b28f79 100644 --- a/src/reify.rs +++ b/src/reify.rs @@ -51,6 +51,8 @@ macro_rules! reify { ($old:expr => !!! $t:ty) => {{ let old_value = $old; let new_value: $t = + // SAFETY: This is really dangerous (thus the exclamation marks). + // Make sure that the transmute is safe. unsafe { std::mem::transmute_copy(&std::mem::ManuallyDrop::new(old_value)) }; new_value }}; diff --git a/src/serde/metadata.rs b/src/serde/metadata.rs index 54d30e094..c8927e4f4 100644 --- a/src/serde/metadata.rs +++ b/src/serde/metadata.rs @@ -44,7 +44,7 @@ impl PartialOrd for CustomTypeMetadata<'_> { impl Ord for CustomTypeMetadata<'_> { fn cmp(&self, other: &Self) -> Ordering { match self.display_name.cmp(other.display_name) { - Ordering::Equal => self.display_name.cmp(&other.display_name), + Ordering::Equal => self.display_name.cmp(other.display_name), cmp => cmp, } } @@ -180,7 +180,7 @@ struct ModuleMetadata<'a> { impl ModuleMetadata<'_> { #[inline(always)] - pub fn new() -> Self { + pub const fn new() -> Self { Self { doc: "", modules: BTreeMap::new(), @@ -226,7 +226,7 @@ pub fn gen_metadata_to_json( let mut global = ModuleMetadata::new(); #[cfg(not(feature = "no_module"))] - for (name, m) in engine.global_sub_modules.iter() { + for (name, m) in &engine.global_sub_modules { global.modules.insert(name, m.as_ref().into()); } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index b1c311380..1b827d9f0 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -929,7 +929,7 @@ impl Token { } match KEYWORDS_LIST[hash_val] { - (_, Token::EOF) => None, + (_, Self::EOF) => None, // Fail early to avoid calling memcmp(). // Since we are already working with bytes, mind as well check the first one. (s, ref t) if s.len() == len && s.as_bytes()[0] == utf8[0] && s == syntax => { @@ -1180,7 +1180,10 @@ pub trait InputStream { /// Return error if the string is longer than the maximum length. #[inline] -fn ensure_string_len_within_limit(max: Option, value: &str) -> Result<(), LexError> { +const fn ensure_string_len_within_limit( + max: Option, + value: &str, +) -> Result<(), LexError> { match max { Some(max) if value.len() > max.get() => Err(LexError::StringTooLong(max.get())), _ => Ok(()), @@ -1258,7 +1261,7 @@ pub fn parse_string_literal( break; } None if allow_line_continuation && !escape.is_empty() => { - debug_assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); + debug_assert_eq!(escape, "\\", "unexpected escape {escape} at end of line"); pos.advance(); break; } @@ -1384,7 +1387,7 @@ pub fn parse_string_literal( // Line continuation '\n' if allow_line_continuation && !escape.is_empty() => { - debug_assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); + debug_assert_eq!(escape, "\\", "unexpected escape {escape} at end of line"); escape.clear(); pos.new_line(); @@ -1539,7 +1542,7 @@ fn get_next_token_inner( // Still inside a comment? if state.comment_level > 0 { let start_pos = *pos; - let mut comment = state.include_comments.then(|| String::new()); + let mut comment = state.include_comments.then(String::new); state.comment_level = scan_block_comment(stream, state.comment_level, pos, comment.as_mut()); @@ -2315,6 +2318,7 @@ pub fn is_valid_function_name(name: &str) -> bool { /// Is a character valid to start an identifier? #[inline(always)] #[must_use] +#[allow(clippy::missing_const_for_fn)] pub fn is_id_first_alphabetic(x: char) -> bool { #[cfg(feature = "unicode-xid-ident")] return unicode_xid::UnicodeXID::is_xid_start(x); @@ -2325,6 +2329,7 @@ pub fn is_id_first_alphabetic(x: char) -> bool { /// Is a character valid for an identifier? #[inline(always)] #[must_use] +#[allow(clippy::missing_const_for_fn)] pub fn is_id_continue(x: char) -> bool { #[cfg(feature = "unicode-xid-ident")] return unicode_xid::UnicodeXID::is_xid_continue(x); @@ -2418,7 +2423,7 @@ impl InputStream for MultiInputsStream<'_> { } loop { - if self.index >= self.extra_streams.len() + 1 { + if self.index > self.extra_streams.len() { // No more streams return None; } @@ -2443,7 +2448,7 @@ impl InputStream for MultiInputsStream<'_> { } loop { - if self.index >= self.extra_streams.len() + 1 { + if self.index > self.extra_streams.len() { // No more streams return None; } @@ -2513,7 +2518,7 @@ impl<'a> Iterator for TokenIterator<'a> { Some((Token::Reserved(s), pos)) => (match (s.as_str(), #[cfg(not(feature = "no_custom_syntax"))] - self.engine.is_custom_keyword(&*s), + self.engine.is_custom_keyword(&s), #[cfg(feature = "no_custom_syntax")] false ) @@ -2559,7 +2564,7 @@ impl<'a> Iterator for TokenIterator<'a> { }, pos), // Custom keyword #[cfg(not(feature = "no_custom_syntax"))] - Some((Token::Identifier(s), pos)) if self.engine.is_custom_keyword(&*s) => { + Some((Token::Identifier(s), pos)) if self.engine.is_custom_keyword(&s) => { (Token::Custom(s), pos) } // Custom keyword/symbol - must be disabled diff --git a/src/types/custom_types.rs b/src/types/custom_types.rs index 214c1249a..05bdbf156 100644 --- a/src/types/custom_types.rs +++ b/src/types/custom_types.rs @@ -45,7 +45,7 @@ impl CustomTypesCollection { CustomTypeInfo { display_name: name.into(), #[cfg(feature = "metadata")] - comments: Default::default(), + comments: <_>::default(), }, ); } @@ -75,7 +75,7 @@ impl CustomTypesCollection { CustomTypeInfo { display_name: name.into(), #[cfg(feature = "metadata")] - comments: Default::default(), + comments: <_>::default(), }, ); } @@ -106,7 +106,6 @@ impl CustomTypesCollection { } /// Iterate all the custom types. #[inline(always)] - #[must_use] pub fn iter(&self) -> impl Iterator { self.0.iter().map(|(k, v)| (k.as_str(), v)) } diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index c09a98b99..832db2c3e 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -1383,7 +1383,7 @@ impl Dynamic { Union::Shared(cell, ..) => crate::func::shared_try_take(cell).map_or_else( |ref cell| crate::func::locked_read(cell).clone(), #[cfg(not(feature = "sync"))] - |value| value.into_inner(), + crate::Locked::into_inner, #[cfg(feature = "sync")] |value| value.into_inner().unwrap(), ), @@ -1405,7 +1405,7 @@ impl Dynamic { *self = crate::func::shared_try_take(cell).map_or_else( |ref cell| crate::func::locked_read(cell).clone(), #[cfg(not(feature = "sync"))] - |value| value.into_inner(), + crate::Locked::into_inner, #[cfg(feature = "sync")] |value| value.into_inner().unwrap(), ); diff --git a/src/types/fn_ptr.rs b/src/types/fn_ptr.rs index 64e6d7468..c3904cd03 100644 --- a/src/types/fn_ptr.rs +++ b/src/types/fn_ptr.rs @@ -218,8 +218,8 @@ impl FnPtr { result.try_cast_raw().map_err(|r| { let result_type = engine.map_type_name(r.type_name()); let cast_type = match type_name::() { - typ @ _ if typ.contains("::") => engine.map_type_name(typ), - typ @ _ => typ, + typ if typ.contains("::") => engine.map_type_name(typ), + typ => typ, }; ERR::ErrorMismatchOutputType(cast_type.into(), result_type.into(), Position::NONE) .into() @@ -245,8 +245,8 @@ impl FnPtr { result.try_cast_raw().map_err(|r| { let result_type = context.engine().map_type_name(r.type_name()); let cast_type = match type_name::() { - typ @ _ if typ.contains("::") => context.engine().map_type_name(typ), - typ @ _ => typ, + typ if typ.contains("::") => context.engine().map_type_name(typ), + typ => typ, }; ERR::ErrorMismatchOutputType(cast_type.into(), result_type.into(), Position::NONE) .into() @@ -306,7 +306,7 @@ impl FnPtr { caches, &mut crate::Scope::new(), this_ptr, - self.encapsulated_environ().map(|r| r.as_ref()), + self.encapsulated_environ().map(AsRef::as_ref), fn_def, args, true, @@ -328,7 +328,7 @@ impl FnPtr { #[inline(always)] #[must_use] #[allow(dead_code)] - pub(crate) fn encapsulated_environ(&self) -> Option<&Shared> { + pub(crate) const fn encapsulated_environ(&self) -> Option<&Shared> { self.environ.as_ref() } /// Set a reference to the [encapsulated environment][EncapsulatedEnviron]. @@ -344,7 +344,7 @@ impl FnPtr { #[cfg(not(feature = "no_function"))] #[inline(always)] #[must_use] - pub(crate) fn fn_def(&self) -> Option<&Shared> { + pub(crate) const fn fn_def(&self) -> Option<&Shared> { self.fn_def.as_ref() } /// Set a reference to the linked [`ScriptFnDef`][crate::ast::ScriptFnDef]. @@ -437,32 +437,29 @@ impl FnPtr { if arity == N + self.curry().len() { return self.call_raw(ctx, this_ptr, args); } - if MOVE_PTR { - if this_ptr.is_some() { - if arity == N + 1 + self.curry().len() { - let mut args2 = FnArgsVec::with_capacity(args.len() + 1); - if move_this_ptr_to_args == 0 { - args2.push(this_ptr.as_mut().unwrap().clone()); - args2.extend(args); - } else { - args2.extend(args); - args2.insert(move_this_ptr_to_args, this_ptr.as_mut().unwrap().clone()); - } - return self.call_raw(ctx, None, args2); + if MOVE_PTR && this_ptr.is_some() { + if arity == N + 1 + self.curry().len() { + let mut args2 = FnArgsVec::with_capacity(args.len() + 1); + if move_this_ptr_to_args == 0 { + args2.push(this_ptr.as_mut().unwrap().clone()); + args2.extend(args); + } else { + args2.extend(args); + args2.insert(move_this_ptr_to_args, this_ptr.as_mut().unwrap().clone()); } - if arity == N + E + 1 + self.curry().len() { - let mut args2 = FnArgsVec::with_capacity(args.len() + extras.len() + 1); - if move_this_ptr_to_args == 0 { - args2.push(this_ptr.as_mut().unwrap().clone()); - args2.extend(args); - args2.extend(extras); - } else { - args2.extend(args); - args2.insert(move_this_ptr_to_args, this_ptr.as_mut().unwrap().clone()); - args2.extend(extras); - } - return self.call_raw(ctx, None, args2); + return self.call_raw(ctx, None, args2); + } + if arity == N + E + 1 + self.curry().len() { + let mut args2 = FnArgsVec::with_capacity(args.len() + extras.len() + 1); + if move_this_ptr_to_args == 0 { + args2.push(this_ptr.as_mut().unwrap().clone()); + args2.extend(args); + } else { + args2.extend(args); + args2.insert(move_this_ptr_to_args, this_ptr.as_mut().unwrap().clone()); } + args2.extend(extras); + return self.call_raw(ctx, None, args2); } } if arity == N + E + self.curry().len() { diff --git a/src/types/position.rs b/src/types/position.rs index 8bdaaab4f..dde988dd0 100644 --- a/src/types/position.rs +++ b/src/types/position.rs @@ -228,9 +228,9 @@ impl Span { /// Is this [`Span`] non-existent? /// /// Always returns `true` under `no_position`. - #[inline] + #[inline(always)] #[must_use] - pub const fn is_none(&self) -> bool { + pub const fn is_none(self) -> bool { self.start.is_none() && self.end.is_none() } /// Get the [`Span`]'s starting [position][Position]. @@ -238,7 +238,7 @@ impl Span { /// Always returns [`Position::NONE`] under `no_position`. #[inline(always)] #[must_use] - pub const fn start(&self) -> Position { + pub const fn start(self) -> Position { self.start } /// Get the [`Span`]'s ending [position][Position]. @@ -246,7 +246,7 @@ impl Span { /// Always returns [`Position::NONE`] under `no_position`. #[inline(always)] #[must_use] - pub const fn end(&self) -> Position { + pub const fn end(self) -> Position { self.end } } diff --git a/src/types/scope.rs b/src/types/scope.rs index e753cadd1..40f783c46 100644 --- a/src/types/scope.rs +++ b/src/types/scope.rs @@ -671,14 +671,13 @@ impl Scope<'_> { /// /// Panics if the index is out of bounds. #[inline(always)] - #[must_use] #[allow(dead_code)] pub(crate) fn get_entry_by_index( &mut self, index: usize, ) -> (&Identifier, &Dynamic, &[ImmutableString]) { if self.aliases.len() <= index { - self.aliases.resize(index + 1, Default::default()); + self.aliases.resize(index + 1, <_>::default()); } ( @@ -774,7 +773,7 @@ impl Scope<'_> { #[inline] pub(crate) fn add_alias_by_index(&mut self, index: usize, alias: ImmutableString) -> &mut Self { if self.aliases.len() <= index { - self.aliases.resize(index + 1, Default::default()); + self.aliases.resize(index + 1, <_>::default()); } let aliases = self.aliases.get_mut(index).unwrap(); if aliases.is_empty() || !aliases.contains(&alias) { @@ -829,7 +828,7 @@ impl Scope<'_> { scope.push_entry(name.clone(), v1.access_mode(), v1.clone()); if self.aliases.len() > index { - scope.aliases.resize(scope.len() - 1, Default::default()); + scope.aliases.resize(scope.len() - 1, <_>::default()); scope.aliases.push(self.aliases[index].clone()); } });