Refine expect messages.

This commit is contained in:
Stephen Chung 2021-08-26 23:58:41 +08:00
parent 2a760eb44b
commit aec4417bd5
21 changed files with 328 additions and 334 deletions

View File

@ -1490,8 +1490,7 @@ impl Stmt {
_ => (), _ => (),
} }
path.pop() path.pop().expect("`path` contains current node");
.expect("never fails because `path` always contains the current node");
true true
} }
@ -1566,7 +1565,7 @@ impl OpAssignment<'_> {
pub fn new(op: Token) -> Self { pub fn new(op: Token) -> Self {
let op_raw = op let op_raw = op
.map_op_assignment() .map_op_assignment()
.expect("never fails because token must be an op-assignment operator") .expect("token is op-assignment operator")
.literal_syntax(); .literal_syntax();
let op_assignment = op.literal_syntax(); let op_assignment = op.literal_syntax();
@ -2018,7 +2017,7 @@ impl Expr {
let mut arr = Array::with_capacity(x.len()); let mut arr = Array::with_capacity(x.len());
arr.extend(x.iter().map(|v| { arr.extend(x.iter().map(|v| {
v.get_literal_value() v.get_literal_value()
.expect("never fails because a constant array always has a constant value") .expect("constant array has constant value")
})); }));
Dynamic::from_array(arr) Dynamic::from_array(arr)
} }
@ -2028,9 +2027,9 @@ impl Expr {
let mut map = x.1.clone(); let mut map = x.1.clone();
x.0.iter().for_each(|(k, v)| { x.0.iter().for_each(|(k, v)| {
*map.get_mut(k.name.as_str()) *map.get_mut(k.name.as_str())
.expect("never fails because the template should contain all the keys") = v .expect("template contains all keys") = v
.get_literal_value() .get_literal_value()
.expect("never fails because a constant map always has a constant value") .expect("constant map has constant value")
}); });
Dynamic::from_map(map) Dynamic::from_map(map)
} }
@ -2309,8 +2308,7 @@ impl Expr {
_ => (), _ => (),
} }
path.pop() path.pop().expect("`path` contains current node");
.expect("never fails because `path` always contains the current node");
true true
} }

View File

@ -154,8 +154,8 @@ impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_> {
/// Definition of a custom syntax definition. /// Definition of a custom syntax definition.
pub struct CustomSyntax { pub struct CustomSyntax {
/// A parsing function to return the next keyword in a custom syntax based on the /// A parsing function to return the next token in a custom syntax based on the
/// keywords parsed so far. /// symbols parsed so far.
pub parse: Box<FnCustomSyntaxParse>, pub parse: Box<FnCustomSyntaxParse>,
/// Custom syntax implementation function. /// Custom syntax implementation function.
pub func: Shared<FnCustomSyntaxEval>, pub func: Shared<FnCustomSyntaxEval>,
@ -166,10 +166,17 @@ pub struct CustomSyntax {
impl Engine { impl Engine {
/// Register a custom syntax with the [`Engine`]. /// Register a custom syntax with the [`Engine`].
/// ///
/// * `keywords` holds a slice of strings that define the custom syntax. /// * `symbols` holds a slice of strings that define the custom syntax.
/// * `scope_may_be_changed` specifies variables _may_ be added/removed by this custom syntax. /// * `scope_may_be_changed` specifies variables _may_ be added/removed by this custom syntax.
/// * `func` is the implementation function. /// * `func` is the implementation function.
/// ///
/// ## Note on `symbols`
///
/// * Whitespaces around symbols are stripped.
/// * Symbols that are all-whitespace or empty are ignored.
/// * If `symbols` does not contain at least one valid token, then the custom syntax registration
/// is simply ignored.
///
/// ## Note on `scope_may_be_changed` /// ## Note on `scope_may_be_changed`
/// ///
/// If `scope_may_be_changed` is `true`, then _size_ of the current [`Scope`][crate::Scope] /// If `scope_may_be_changed` is `true`, then _size_ of the current [`Scope`][crate::Scope]
@ -185,7 +192,7 @@ impl Engine {
/// does NOT count, so `false` should be passed. /// does NOT count, so `false` should be passed.
pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>( pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>(
&mut self, &mut self,
keywords: &[S], symbols: &[S],
scope_may_be_changed: bool, scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static, func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static,
) -> Result<&mut Self, ParseError> { ) -> Result<&mut Self, ParseError> {
@ -193,10 +200,10 @@ impl Engine {
let mut segments: StaticVec<ImmutableString> = Default::default(); let mut segments: StaticVec<ImmutableString> = Default::default();
for s in keywords { for s in symbols {
let s = s.as_ref().trim(); let s = s.as_ref().trim();
// Skip empty keywords // Skip empty symbols
if s.is_empty() { if s.is_empty() {
continue; continue;
} }
@ -220,10 +227,10 @@ impl Engine {
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(), CUSTOM_SYNTAX_MARKER_FLOAT if !segments.is_empty() => s.into(),
// Standard or reserved keyword/symbol not in first position // Standard or reserved keyword/symbol not in first position
s if !segments.is_empty() && token.is_some() => { _ if !segments.is_empty() && token.is_some() => {
// Make it a custom keyword/symbol if it is disabled or reserved // Make it a custom keyword/symbol if it is disabled or reserved
if (self.disabled_symbols.contains(s) if (self.disabled_symbols.contains(s)
|| matches!(token, Some(Token::Reserved(_)))) || token.map_or(false, |v| v.is_reserved()))
&& !self.custom_keywords.contains_key(s) && !self.custom_keywords.contains_key(s)
{ {
self.custom_keywords.insert(s.into(), None); self.custom_keywords.insert(s.into(), None);
@ -273,7 +280,7 @@ impl Engine {
segments.push(seg); segments.push(seg);
} }
// If the syntax has no keywords, just ignore the registration // If the syntax has no symbols, just ignore the registration
if segments.is_empty() { if segments.is_empty() {
return Ok(self); return Ok(self);
} }
@ -307,8 +314,8 @@ impl Engine {
/// * `parse` is the parsing function. /// * `parse` is the parsing function.
/// * `func` is the implementation function. /// * `func` is the implementation function.
/// ///
/// All custom keywords must be manually registered via [`Engine::register_custom_operator`]. /// All custom keywords used as symbols must be manually registered via [`Engine::register_custom_operator`].
/// Otherwise, custom keywords won't be recognized. /// Otherwise, they won't be recognized.
pub fn register_custom_syntax_raw( pub fn register_custom_syntax_raw(
&mut self, &mut self,
key: impl Into<Identifier>, key: impl Into<Identifier>,

View File

@ -34,8 +34,8 @@ use fmt::Debug;
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
use instant::Instant; use instant::Instant;
/// The message: never fails because the type was checked /// The message: data type was checked
const CHECKED: &str = "never fails because the type was checked"; const CHECKED: &str = "data type was checked";
mod private { mod private {
use crate::fn_native::SendSync; use crate::fn_native::SendSync;
@ -259,9 +259,7 @@ impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
match self.0 { match self.0 {
DynamicReadLockInner::Reference(ref reference) => *reference, DynamicReadLockInner::Reference(ref reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().expect( DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().expect(CHECKED),
"never fails because the read guard was created after checking the data type",
),
} }
} }
} }
@ -302,9 +300,7 @@ impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
match self.0 { match self.0 {
DynamicWriteLockInner::Reference(ref reference) => *reference, DynamicWriteLockInner::Reference(ref reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().expect( DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().expect(CHECKED),
"never fails because the write guard was created after checking the data type",
),
} }
} }
} }
@ -315,9 +311,7 @@ impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
match self.0 { match self.0 {
DynamicWriteLockInner::Reference(ref mut reference) => *reference, DynamicWriteLockInner::Reference(ref mut reference) => *reference,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().expect( DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().expect(CHECKED),
"never fails because the write guard was created after checking the data type",
),
} }
} }
} }
@ -1261,7 +1255,7 @@ impl Dynamic {
/// ///
/// let x = Dynamic::from(42_u32); /// let x = Dynamic::from(42_u32);
/// ///
/// assert_eq!(x.try_cast::<u32>().unwrap(), 42); /// assert_eq!(x.try_cast::<u32>().expect("x should be u32"), 42);
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]

View File

@ -501,7 +501,7 @@ impl<'a> Target<'a> {
let value = &mut *value let value = &mut *value
.write_lock::<crate::INT>() .write_lock::<crate::INT>()
.expect("never fails because `BitField` always holds an `INT`"); .expect("`BitField` holds `INT`");
let index = *index; let index = *index;
@ -529,7 +529,7 @@ impl<'a> Target<'a> {
let s = &mut *s let s = &mut *s
.write_lock::<ImmutableString>() .write_lock::<ImmutableString>()
.expect("never fails because `StringChar` always holds an `ImmutableString`"); .expect("`StringChar` holds `ImmutableString`");
let index = *index; let index = *index;
@ -553,9 +553,7 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
// Cloning is cheap for a shared value // Cloning is cheap for a shared value
let container = value.clone(); let container = value.clone();
return Self::LockGuard(( return Self::LockGuard((
value value.write_lock::<Dynamic>().expect("cast to `Dynamic`"),
.write_lock::<Dynamic>()
.expect("never fails when casting to `Dynamic`"),
container, container,
)); ));
} }
@ -701,9 +699,9 @@ impl EvalState {
// Push a new function resolution cache if the stack is empty // Push a new function resolution cache if the stack is empty
self.fn_resolution_caches.push(Default::default()); self.fn_resolution_caches.push(Default::default());
} }
self.fn_resolution_caches.last_mut().expect( self.fn_resolution_caches
"never fails because there is at least one function resolution cache by this point", .last_mut()
) .expect("at least one function resolution cache")
} }
/// Push an empty function resolution cache onto the stack and make it current. /// Push an empty function resolution cache onto the stack and make it current.
#[allow(dead_code)] #[allow(dead_code)]
@ -720,7 +718,7 @@ impl EvalState {
pub fn pop_fn_resolution_cache(&mut self) { pub fn pop_fn_resolution_cache(&mut self) {
self.fn_resolution_caches self.fn_resolution_caches
.pop() .pop()
.expect("there should be at least one function resolution cache"); .expect("at least one function resolution cache");
} }
} }
@ -1088,16 +1086,10 @@ impl Engine {
if let Some(index) = index { if let Some(index) = index {
let offset = mods.len() - index.get(); let offset = mods.len() - index.get();
Some( Some(mods.get(offset).expect("offset within range"))
mods.get(offset)
.expect("never fails because offset should be within range"),
)
} else { } else {
mods.find(root) mods.find(root)
.map(|n| { .map(|n| mods.get(n).expect("index is valid"))
mods.get(n)
.expect("never fails because the index came from `find`")
})
.or_else(|| self.global_sub_modules.get(root).cloned()) .or_else(|| self.global_sub_modules.get(root).cloned())
} }
} }
@ -1191,8 +1183,7 @@ impl Engine {
level: 0, level: 0,
}; };
match resolve_var( match resolve_var(
expr.get_variable_name(true) expr.get_variable_name(true).expect("`expr` is `Variable`"),
.expect("`expr` should be `Variable`"),
index, index,
&context, &context,
) { ) {
@ -1209,9 +1200,7 @@ impl Engine {
scope.len() - index scope.len() - index
} else { } else {
// Find the variable in the scope // Find the variable in the scope
let var_name = expr let var_name = expr.get_variable_name(true).expect("`expr` is `Variable`");
.get_variable_name(true)
.expect("`expr` should be `Variable`");
scope scope
.get_index(var_name) .get_index(var_name)
.ok_or_else(|| EvalAltResult::ErrorVariableNotFound(var_name.to_string(), var_pos))? .ok_or_else(|| EvalAltResult::ErrorVariableNotFound(var_name.to_string(), var_pos))?
@ -1245,9 +1234,7 @@ impl Engine {
let _terminate_chaining = terminate_chaining; let _terminate_chaining = terminate_chaining;
// Pop the last index value // Pop the last index value
let idx_val = idx_values let idx_val = idx_values.pop().expect("index chain is never empty");
.pop()
.expect("never fails because an index chain is never empty");
match chain_type { match chain_type {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -1255,7 +1242,7 @@ impl Engine {
let pos = rhs.position(); let pos = rhs.position();
let idx_val = idx_val let idx_val = idx_val
.into_index_value() .into_index_value()
.expect("never fails because `chain_type` is `ChainType::Index`"); .expect("`chain_type` is `ChainType::Index`");
match rhs { match rhs {
// xxx[idx].expr... | xxx[idx][expr]... // xxx[idx].expr... | xxx[idx][expr]...
@ -1277,7 +1264,7 @@ impl Engine {
// xxx[rhs] op= new_val // xxx[rhs] op= new_val
_ if new_val.is_some() => { _ if new_val.is_some() => {
let ((new_val, new_pos), (op_info, op_pos)) = let ((new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`"); new_val.expect("`new_val` is `Some`");
let mut idx_val_for_setter = idx_val.clone(); let mut idx_val_for_setter = idx_val.clone();
let try_setter = match self.get_indexed_mut( let try_setter = match self.get_indexed_mut(
@ -1333,7 +1320,7 @@ impl Engine {
let FnCallExpr { name, hashes, .. } = x.as_ref(); let FnCallExpr { name, hashes, .. } = x.as_ref();
let call_args = &mut idx_val let call_args = &mut idx_val
.into_fn_call_args() .into_fn_call_args()
.expect("never fails because `chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`"); .expect("`chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`");
self.make_method_call( self.make_method_call(
mods, state, lib, name, *hashes, target, call_args, *pos, level, mods, state, lib, name, *hashes, target, call_args, *pos, level,
) )
@ -1350,7 +1337,7 @@ impl Engine {
Expr::Property(x) if target.is::<Map>() && new_val.is_some() => { Expr::Property(x) if target.is::<Map>() && new_val.is_some() => {
let (name, pos) = &x.2; let (name, pos) = &x.2;
let ((new_val, new_pos), (op_info, op_pos)) = let ((new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`"); new_val.expect("`new_val` is `Some`");
let index = name.into(); let index = name.into();
{ {
let val_target = &mut self.get_indexed_mut( let val_target = &mut self.get_indexed_mut(
@ -1378,7 +1365,7 @@ impl Engine {
Expr::Property(x) if new_val.is_some() => { Expr::Property(x) if new_val.is_some() => {
let ((getter, hash_get), (setter, hash_set), (name, pos)) = x.as_ref(); let ((getter, hash_get), (setter, hash_set), (name, pos)) = x.as_ref();
let ((mut new_val, new_pos), (op_info, op_pos)) = let ((mut new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`"); new_val.expect("`new_val` is `Some`");
if op_info.is_some() { if op_info.is_some() {
let hash = FnCallHashes::from_native(*hash_get); let hash = FnCallHashes::from_native(*hash_get);
@ -1498,9 +1485,9 @@ impl Engine {
// {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr // {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
Expr::FnCall(ref x, pos) if !x.is_qualified() => { Expr::FnCall(ref x, pos) if !x.is_qualified() => {
let FnCallExpr { name, hashes, .. } = x.as_ref(); let FnCallExpr { name, hashes, .. } = x.as_ref();
let call_args = &mut idx_val let call_args = &mut idx_val.into_fn_call_args().expect(
.into_fn_call_args() "`chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`",
.expect("never fails because `chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`"); );
let (val, _) = self.make_method_call( let (val, _) = self.make_method_call(
mods, state, lib, name, *hashes, target, call_args, pos, level, mods, state, lib, name, *hashes, target, call_args, pos, level,
)?; )?;
@ -1620,9 +1607,9 @@ impl Engine {
Expr::FnCall(ref f, pos) if !f.is_qualified() => { Expr::FnCall(ref f, pos) if !f.is_qualified() => {
let FnCallExpr { name, hashes, .. } = f.as_ref(); let FnCallExpr { name, hashes, .. } = f.as_ref();
let rhs_chain = match_chaining_type(rhs); let rhs_chain = match_chaining_type(rhs);
let args = &mut idx_val let args = &mut idx_val.into_fn_call_args().expect(
.into_fn_call_args() "`chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`",
.expect("never fails because `chain_type` is `ChainType::Dot` with `Expr::FnCallExpr`"); );
let (mut val, _) = self.make_method_call( let (mut val, _) = self.make_method_call(
mods, state, lib, name, *hashes, target, args, pos, level, mods, state, lib, name, *hashes, target, args, pos, level,
)?; )?;
@ -2117,7 +2104,7 @@ impl Engine {
for (Ident { name: key, .. }, expr) in &x.0 { for (Ident { name: key, .. }, expr) in &x.0 {
let value_ref = map let value_ref = map
.get_mut(key.as_str()) .get_mut(key.as_str())
.expect("never fails because the template should contain all the keys"); .expect("template contains all keys");
*value_ref = self *value_ref = self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? .eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.flatten(); .flatten();
@ -2135,9 +2122,7 @@ impl Engine {
constants, constants,
.. ..
} = x.as_ref(); } = x.as_ref();
let namespace = namespace let namespace = namespace.as_ref().expect("qualified function call");
.as_ref()
.expect("never fails because function call is qualified");
let hash = hashes.native; let hash = hashes.native;
self.make_qualified_function_call( self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash, scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash,
@ -2192,12 +2177,14 @@ impl Engine {
Expr::Custom(custom, _) => { Expr::Custom(custom, _) => {
let expressions: StaticVec<_> = custom.keywords.iter().map(Into::into).collect(); let expressions: StaticVec<_> = custom.keywords.iter().map(Into::into).collect();
let key_token = custom.tokens.first().expect( let key_token = custom
"never fails because a custom syntax stream must contain at least one token", .tokens
); .first()
.expect("custom syntax stream contains at least one token");
let custom_def = self let custom_def = self
.custom_syntax.get(key_token) .custom_syntax
.expect("never fails because the custom syntax leading token should match with definition"); .get(key_token)
.expect("custom syntax leading token matches with definition");
let mut context = EvalContext { let mut context = EvalContext {
engine: self, engine: self,
scope, scope,
@ -2329,9 +2316,7 @@ impl Engine {
let target_is_shared = false; let target_is_shared = false;
if target_is_shared { if target_is_shared {
lock_guard = target lock_guard = target.write_lock::<Dynamic>().expect("cast to `Dynamic`");
.write_lock::<Dynamic>()
.expect("never fails when casting to `Dynamic`");
lhs_ptr_inner = &mut *lock_guard; lhs_ptr_inner = &mut *lock_guard;
} else { } else {
lhs_ptr_inner = &mut *target; lhs_ptr_inner = &mut *target;
@ -2403,7 +2388,7 @@ impl Engine {
let var_name = lhs_expr let var_name = lhs_expr
.get_variable_name(false) .get_variable_name(false)
.expect("never fails because `lhs_ptr` is a `Variable`s"); .expect("`lhs_ptr` is `Variable`");
if !lhs_ptr.is_ref() { if !lhs_ptr.is_ref() {
return EvalAltResult::ErrorAssignmentToConstant(var_name.to_string(), pos) return EvalAltResult::ErrorAssignmentToConstant(var_name.to_string(), pos)
@ -2667,10 +2652,7 @@ impl Engine {
if x > INT::MAX as usize { if x > INT::MAX as usize {
return EvalAltResult::ErrorArithmetic( return EvalAltResult::ErrorArithmetic(
format!("for-loop counter overflow: {}", x), format!("for-loop counter overflow: {}", x),
counter counter.as_ref().expect("`counter` is `Some`").pos,
.as_ref()
.expect("never fails because `counter` is `Some`")
.pos,
) )
.into(); .into();
} }
@ -2678,7 +2660,7 @@ impl Engine {
let mut counter_var = scope let mut counter_var = scope
.get_mut_by_index(c) .get_mut_by_index(c)
.write_lock::<INT>() .write_lock::<INT>()
.expect("never fails because the counter always holds an `INT`"); .expect("counter holds `INT`");
*counter_var = x as INT; *counter_var = x as INT;
} }
@ -2691,9 +2673,7 @@ impl Engine {
let loop_var_is_shared = false; let loop_var_is_shared = false;
if loop_var_is_shared { if loop_var_is_shared {
let mut value_ref = loop_var let mut value_ref = loop_var.write_lock().expect("cast to `Dynamic`");
.write_lock()
.expect("never fails when casting to `Dynamic`");
*value_ref = value; *value_ref = value;
} else { } else {
*loop_var = value; *loop_var = value;
@ -2744,9 +2724,7 @@ impl Engine {
constants, constants,
.. ..
} = x.as_ref(); } = x.as_ref();
let namespace = namespace let namespace = namespace.as_ref().expect("qualified function call");
.as_ref()
.expect("never fails because function call is qualified");
let hash = hashes.native; let hash = hashes.native;
self.make_qualified_function_call( self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash, scope, mods, state, lib, this_ptr, namespace, name, args, constants, hash,
@ -2805,11 +2783,16 @@ impl Engine {
if err_pos.is_none() { if err_pos.is_none() {
// No position info // No position info
} else { } else {
let line = err_pos.line().expect("never fails because a non-NONE `Position` always has a line number") as INT; let line = err_pos
.line()
.expect("non-NONE `Position` has line number")
as INT;
let position = if err_pos.is_beginning_of_line() { let position = if err_pos.is_beginning_of_line() {
0 0
} else { } else {
err_pos.position().expect("never fails because a non-NONE `Position` always has a character position") err_pos
.position()
.expect("non-NONE `Position` has character position")
} as INT; } as INT;
err_map.insert("line".into(), line.into()); err_map.insert("line".into(), line.into());
err_map.insert("position".into(), position.into()); err_map.insert("position".into(), position.into());
@ -2893,10 +2876,7 @@ impl Engine {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) { if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) { let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
match mods match mods.get_mut(index).expect("index is valid") {
.get_mut(index)
.expect("never fails because the index came from `find`")
{
m if m.internal => Some(m), m if m.internal => Some(m),
_ => None, _ => None,
} }
@ -2905,15 +2885,12 @@ impl Engine {
let mut global = Module::new(); let mut global = Module::new();
global.internal = true; global.internal = true;
mods.push(KEYWORD_GLOBAL, global); mods.push(KEYWORD_GLOBAL, global);
Some( Some(mods.get_mut(mods.len() - 1).expect("global module exists"))
mods.get_mut(mods.len() - 1)
.expect("never fails because the global module was just added"),
)
}; };
if let Some(global) = global { if let Some(global) = global {
Shared::get_mut(global) Shared::get_mut(global)
.expect("never fails because the global module is never shared") .expect("global module is not shared")
.set_var(name.clone(), value.clone()); .set_var(name.clone(), value.clone());
} }
} }

View File

@ -937,14 +937,8 @@ impl Engine {
} }
} else { } else {
let mut iter = name.as_ref().splitn(2, separator.as_ref()); let mut iter = name.as_ref().splitn(2, separator.as_ref());
let sub_module = iter let sub_module = iter.next().expect("name contains separator").trim();
.next() let remainder = iter.next().expect("name contains separator").trim();
.expect("never fails because the name contains a separator")
.trim();
let remainder = iter
.next()
.expect("never fails because the name contains a separator")
.trim();
if !root.contains_key(sub_module) { if !root.contains_key(sub_module) {
let mut m: Module = Default::default(); let mut m: Module = Default::default();
@ -954,7 +948,7 @@ impl Engine {
} else { } else {
let m = root let m = root
.remove(sub_module) .remove(sub_module)
.expect("never fails because the root contains the sub-module"); .expect("root contains the sub-module");
let mut m = crate::fn_native::shared_take_or_clone(m); let mut m = crate::fn_native::shared_take_or_clone(m);
register_static_module_raw(m.sub_modules_mut(), remainder, module); register_static_module_raw(m.sub_modules_mut(), remainder, module);
m.build_index(); m.build_index();
@ -1059,10 +1053,8 @@ impl Engine {
resolver: &StaticModuleResolver, resolver: &StaticModuleResolver,
imports: &mut BTreeSet<Identifier>, imports: &mut BTreeSet<Identifier>,
) { ) {
ast.walk(&mut |path| match path ast.walk(
.last() &mut |path| match path.last().expect("`path` contains the current node") {
.expect("never fails because `path` always contains the current node")
{
// Collect all `import` statements with a string constant path // Collect all `import` statements with a string constant path
ASTNode::Stmt(Stmt::Import(Expr::StringConstant(s, _), _, _)) ASTNode::Stmt(Stmt::Import(Expr::StringConstant(s, _), _, _))
if !resolver.contains_path(s) && !imports.contains(s.as_str()) => if !resolver.contains_path(s) && !imports.contains(s.as_str()) =>
@ -1071,7 +1063,8 @@ impl Engine {
true true
} }
_ => true, _ => true,
}); },
);
} }
let mut ast = self.compile_scripts_with_scope(scope, &[script])?; let mut ast = self.compile_scripts_with_scope(scope, &[script])?;
@ -1315,12 +1308,12 @@ impl Engine {
/// true)?; /// true)?;
/// ///
/// assert_eq!(map.len(), 4); /// assert_eq!(map.len(), 4);
/// assert_eq!(map["a"].as_int().unwrap(), 123); /// assert_eq!(map["a"].as_int().expect("a should exist"), 123);
/// assert_eq!(map["b"].as_int().unwrap(), 42); /// assert_eq!(map["b"].as_int().expect("b should exist"), 42);
/// assert!(map["d"].is::<()>()); /// assert!(map["d"].is::<()>());
/// ///
/// let c = map["c"].read_lock::<Map>().unwrap(); /// let c = map["c"].read_lock::<Map>().expect("c should exist");
/// assert_eq!(c["x"].as_bool().unwrap(), false); /// assert_eq!(c["x"].as_bool().expect("x should be bool"), false);
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
@ -1913,7 +1906,7 @@ impl Engine {
/// let mut value: Dynamic = 1_i64.into(); /// let mut value: Dynamic = 1_i64.into();
/// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "action", Some(&mut value), [ 41_i64.into() ])?; /// let result = engine.call_fn_dynamic(&mut scope, &ast, true, "action", Some(&mut value), [ 41_i64.into() ])?;
/// // ^^^^^^^^^^^^^^^^ binding the 'this' pointer /// // ^^^^^^^^^^^^^^^^ binding the 'this' pointer
/// assert_eq!(value.as_int().unwrap(), 42); /// assert_eq!(value.as_int().expect("value should be INT"), 42);
/// # } /// # }
/// # Ok(()) /// # Ok(())
/// # } /// # }
@ -2018,7 +2011,7 @@ impl Engine {
.map(|f| { .map(|f| {
f.func f.func
.get_script_fn_def() .get_script_fn_def()
.expect("never fails because the function is scripted") .expect("scripted function")
.clone() .clone()
}) })
.collect(); .collect();

View File

@ -279,7 +279,7 @@ impl Engine {
/// ///
/// // Register a custom operator called 'foo' and give it /// // Register a custom operator called 'foo' and give it
/// // a precedence of 160 (i.e. between +|- and *|/). /// // a precedence of 160 (i.e. between +|- and *|/).
/// engine.register_custom_operator("foo", 160).unwrap(); /// engine.register_custom_operator("foo", 160).expect("should succeed");
/// ///
/// // Register a binary function named 'foo' /// // Register a binary function named 'foo'
/// engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y)); /// engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));

View File

@ -303,7 +303,7 @@ impl EvalAltResult {
format!("{:?}", self) format!("{:?}", self)
.split('(') .split('(')
.next() .next()
.expect("never fails because the debug format of an error is `ErrorXXX(...)`") .expect("debug format of error is `ErrorXXX(...)`")
.into(), .into(),
); );

View File

@ -14,8 +14,8 @@ use crate::FLOAT;
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
use rust_decimal::Decimal; use rust_decimal::Decimal;
/// The message: never fails because this is built-in code and the type is already checked /// The message: data type was checked
const BUILTIN: &str = "never fails because this is built-in code and the type is already checked"; const BUILTIN: &str = "data type was checked";
/// Is the type a numeric type? /// Is the type a numeric type?
#[inline] #[inline]

View File

@ -190,17 +190,45 @@ impl Engine {
let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic` let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic`
loop { loop {
let func = lib.iter().find_map(|m| m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { let func = lib
func, source: m.id_raw().cloned() .iter()
})).or_else(|| self.global_namespace.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { .find_map(|m| {
func, source: None m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
})).or_else(|| self.global_modules.iter().find_map(|m| m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { func,
func, source: m.id_raw().cloned() source: m.id_raw().cloned(),
}))).or_else(|| mods.get_fn(hash).map(|(func, source)| FnResolutionCacheEntry { })
func: func.clone(), source: source.cloned() })
})).or_else(|| self.global_sub_modules.values().find_map(|m| m.get_qualified_fn(hash).cloned().map(|func| FnResolutionCacheEntry { .or_else(|| {
func, source: m.id_raw().cloned() self.global_namespace
}))); .get_fn(hash)
.cloned()
.map(|func| FnResolutionCacheEntry { func, source: None })
})
.or_else(|| {
self.global_modules.iter().find_map(|m| {
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
func,
source: m.id_raw().cloned(),
})
})
})
.or_else(|| {
mods.get_fn(hash)
.map(|(func, source)| FnResolutionCacheEntry {
func: func.clone(),
source: source.cloned(),
})
})
.or_else(|| {
self.global_sub_modules.values().find_map(|m| {
m.get_qualified_fn(hash).cloned().map(|func| {
FnResolutionCacheEntry {
func,
source: m.id_raw().cloned(),
}
})
})
});
match func { match func {
// Specific version found // Specific version found
@ -215,17 +243,26 @@ 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| { get_builtin_binary_op_fn(fn_name, &args[0], &args[1]).map(|f| {
FnResolutionCacheEntry { func: CallableFunction::from_method( FnResolutionCacheEntry {
func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), source: None } ),
source: None,
}
}) })
} else { } else {
let (first, second) = args.split_first() let (first, second) = args
.expect("never fails because an op-assignment must have two arguments"); .split_first()
.expect("op-assignment has two arguments");
get_builtin_op_assignment_fn(fn_name, *first, second[0]).map(|f| FnResolutionCacheEntry { get_builtin_op_assignment_fn(fn_name, *first, second[0]).map(
func: CallableFunction::from_method(Box::new(f) as Box<FnAny>), source: None |f| FnResolutionCacheEntry {
}) func: CallableFunction::from_method(
Box::new(f) as Box<FnAny>
),
source: None,
},
)
} }
.map(Box::new) .map(Box::new)
}); });
@ -234,9 +271,11 @@ impl Engine {
// Try all permutations with `Dynamic` wildcards // Try all permutations with `Dynamic` wildcards
None => { None => {
let hash_params = calc_fn_params_hash( let hash_params = calc_fn_params_hash(
args.as_ref().expect("never fails because there are no permutations if there are no arguments") args.as_ref()
.iter().enumerate().map(|(i, a)| .expect("no permutations if no arguments")
{ .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 {
// Replace with `Dynamic` // Replace with `Dynamic`
@ -290,7 +329,10 @@ impl Engine {
let mut backup: Option<ArgBackup> = None; let mut backup: Option<ArgBackup> = None;
if is_method_call && func.is_pure() && !args.is_empty() { if is_method_call && func.is_pure() && !args.is_empty() {
backup = Some(Default::default()); backup = Some(Default::default());
backup.as_mut().unwrap().change_first_arg_to_copy(args); backup
.as_mut()
.expect("`backup` is `Some`")
.change_first_arg_to_copy(args);
} }
// Run external function // Run external function
@ -301,12 +343,10 @@ impl Engine {
let result = if func.is_plugin_fn() { let result = if func.is_plugin_fn() {
func.get_plugin_fn() func.get_plugin_fn()
.expect("never fails because the function is a plugin") .expect("plugin function")
.call((self, name, source, mods, lib).into(), args) .call((self, name, source, mods, lib).into(), args)
} else { } else {
let func = func let func = func.get_native_fn().expect("native function");
.get_native_fn()
.expect("never fails because the function is native");
func((self, name, source, mods, lib).into(), args) func((self, name, source, mods, lib).into(), args)
}; };
@ -644,10 +684,8 @@ impl Engine {
{ {
let fn_name = args[0] let fn_name = args[0]
.read_lock::<ImmutableString>() .read_lock::<ImmutableString>()
.expect("never fails because `args[0]` is `FnPtr`"); .expect("`args[0]` is `FnPtr`");
let num_params = args[1] let num_params = args[1].as_int().expect("`args[1]` is `INT`");
.as_int()
.expect("never fails because `args[1]` is `INT`");
return Ok(( return Ok((
if num_params < 0 { if num_params < 0 {
@ -691,9 +729,7 @@ impl Engine {
// Script function call // Script function call
assert!(func.is_script()); assert!(func.is_script());
let func = func let func = func.get_script_fn_def().expect("scripted function");
.get_script_fn_def()
.expect("never fails because the function is scripted");
if func.body.is_empty() { if func.body.is_empty() {
return Ok((Dynamic::UNIT, false)); return Ok((Dynamic::UNIT, false));
@ -719,7 +755,7 @@ impl Engine {
// Method call of script function - map first argument to `this` // Method call of script function - map first argument to `this`
let (first, rest) = args let (first, rest) = args
.split_first_mut() .split_first_mut()
.expect("never fails because a method call always has a first parameter"); .expect("method call has first parameter");
let orig_source = state.source.take(); let orig_source = state.source.take();
state.source = source; state.source = source;
@ -748,7 +784,10 @@ impl Engine {
let mut backup: Option<ArgBackup> = None; let mut backup: Option<ArgBackup> = None;
if is_ref_mut && !args.is_empty() { if is_ref_mut && !args.is_empty() {
backup = Some(Default::default()); backup = Some(Default::default());
backup.as_mut().unwrap().change_first_arg_to_copy(args); backup
.as_mut()
.expect("`backup` is `Some`")
.change_first_arg_to_copy(args);
} }
let orig_source = state.source.take(); let orig_source = state.source.take();
@ -871,9 +910,7 @@ impl Engine {
let (result, updated) = match fn_name { let (result, updated) = match fn_name {
KEYWORD_FN_PTR_CALL if target.is::<FnPtr>() => { KEYWORD_FN_PTR_CALL if target.is::<FnPtr>() => {
// FnPtr call // FnPtr call
let fn_ptr = target let fn_ptr = target.read_lock::<FnPtr>().expect("`obj` is `FnPtr`");
.read_lock::<FnPtr>()
.expect("never fails because `obj` is `FnPtr`");
// Redirect function name // Redirect function name
let fn_name = fn_ptr.fn_name(); let fn_name = fn_ptr.fn_name();
let args_len = call_args.len() + fn_ptr.curry().len(); let args_len = call_args.len() + fn_ptr.curry().len();
@ -938,9 +975,7 @@ impl Engine {
)); ));
} }
let fn_ptr = target let fn_ptr = target.read_lock::<FnPtr>().expect("`obj` is `FnPtr`");
.read_lock::<FnPtr>()
.expect("never fails because `obj` is `FnPtr`");
// Curry call // Curry call
Ok(( Ok((
@ -1264,7 +1299,7 @@ impl Engine {
} 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;
let obj_ref = target.take_ref().expect("never fails because `target` is a reference if it is not a value and not shared"); let obj_ref = target.take_ref().expect("`target` is reference");
args.push(obj_ref); args.push(obj_ref);
args.extend(arg_values.iter_mut()); args.extend(arg_values.iter_mut());
} }
@ -1345,9 +1380,9 @@ impl Engine {
// 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
let (first, rest) = arg_values let (first, rest) = arg_values
.split_first_mut() .split_first_mut()
.expect("never fails because the arguments list is not empty"); .expect("arguments list is not empty");
first_arg_value = Some(first); first_arg_value = Some(first);
let obj_ref = target.take_ref().expect("never fails because `target` is a reference if it is not a value and not shared"); let obj_ref = target.take_ref().expect("`target` is reference");
args.push(obj_ref); args.push(obj_ref);
args.extend(rest.iter_mut()); args.extend(rest.iter_mut());
} }
@ -1393,9 +1428,7 @@ impl Engine {
match func { match func {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Some(f) if f.is_script() => { Some(f) if f.is_script() => {
let fn_def = f let fn_def = f.get_script_fn_def().expect("scripted function");
.get_script_fn_def()
.expect("never fails because the function is scripted");
if fn_def.body.is_empty() { if fn_def.body.is_empty() {
Ok(Dynamic::UNIT) Ok(Dynamic::UNIT)
@ -1419,15 +1452,13 @@ impl Engine {
Some(f) if f.is_plugin_fn() => f Some(f) if f.is_plugin_fn() => f
.get_plugin_fn() .get_plugin_fn()
.expect("never fails because the function is a plugin") .expect("plugin function")
.clone() .clone()
.call((self, fn_name, module.id(), &*mods, lib).into(), &mut args) .call((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
.map_err(|err| err.fill_position(pos)), .map_err(|err| err.fill_position(pos)),
Some(f) if f.is_native() => { Some(f) if f.is_native() => {
let func = f let func = f.get_native_fn().expect("native function");
.get_native_fn()
.expect("never fails because the function is native");
func((self, fn_name, module.id(), &*mods, lib).into(), &mut args) func((self, fn_name, module.id(), &*mods, lib).into(), &mut args)
.map_err(|err| err.fill_position(pos)) .map_err(|err| err.fill_position(pos))
} }

View File

@ -259,7 +259,7 @@ pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
pub fn shared_take<T>(value: Shared<T>) -> T { pub fn shared_take<T>(value: Shared<T>) -> T {
shared_try_take(value) shared_try_take(value)
.ok() .ok()
.expect("resource should have no outstanding references") .expect("no outstanding references")
} }
/// A general function trail object. /// A general function trail object.

View File

@ -34,8 +34,7 @@ pub struct Mut<T>(T);
#[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> {
// Directly cast the &mut Dynamic into DynamicWriteLock to access the underlying data. // Directly cast the &mut Dynamic into DynamicWriteLock to access the underlying data.
data.write_lock::<T>() data.write_lock::<T>().expect("data type was checked")
.expect("never fails because the type was checked")
} }
/// Dereference into value. /// Dereference into value.
@ -47,15 +46,15 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
data.flatten_in_place(); data.flatten_in_place();
let ref_str = data let ref_str = data
.as_str_ref() .as_str_ref()
.expect("never fails because argument passed by value should not be shared"); .expect("argument passed by value is not shared");
let ref_t = unsafe { mem::transmute::<_, &T>(&ref_str) }; let ref_t = unsafe { mem::transmute::<_, &T>(&ref_str) };
ref_t.clone() ref_t.clone()
} else if TypeId::of::<T>() == TypeId::of::<String>() { } else if TypeId::of::<T>() == TypeId::of::<String>() {
// If T is `String`, data must be `ImmutableString`, so map directly to it // If T is `String`, data must be `ImmutableString`, so map directly to it
let value = mem::take(data) let value = mem::take(data)
.into_string() .into_string()
.expect("never fails because the type was checked"); .expect("data type was checked");
unsafe_try_cast(value).expect("never fails because the type was checked") unsafe_try_cast(value).expect("data type was checked")
} else { } else {
// We consume the argument and then replace it with () - the argument is not supposed to be used again. // We consume the argument and then replace it with () - the argument is not supposed to be used again.
// This way, we avoid having to clone the argument again, because it is already a clone when passed here. // This way, we avoid having to clone the argument again, because it is already a clone when passed here.
@ -131,7 +130,7 @@ macro_rules! def_register {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect("never fails because arguments list is fixed")); )* $($let $par = ($clone)(_drain.next().expect("arguments list is fixed")); )*
// Call the function with each argument value // Call the function with each argument value
let r = self($($arg),*); let r = self($($arg),*);
@ -159,7 +158,7 @@ macro_rules! def_register {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect("never fails because arguments list is fixed")); )* $($let $par = ($clone)(_drain.next().expect("arguments list is fixed")); )*
// Call the function with each argument value // Call the function with each argument value
let r = self(ctx, $($arg),*); let r = self(ctx, $($arg),*);
@ -187,7 +186,7 @@ macro_rules! def_register {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect("never fails because arguments list is fixed")); )* $($let $par = ($clone)(_drain.next().expect("arguments list is fixed")); )*
// Call the function with each argument value // Call the function with each argument value
self($($arg),*).map(Dynamic::from) self($($arg),*).map(Dynamic::from)
@ -212,7 +211,7 @@ macro_rules! def_register {
// The arguments are assumed to be of the correct number and types! // The arguments are assumed to be of the correct number and types!
let mut _drain = args.iter_mut(); let mut _drain = args.iter_mut();
$($let $par = ($clone)(_drain.next().expect("never fails because arguments list is fixed")); )* $($let $par = ($clone)(_drain.next().expect("arguments list is fixed")); )*
// Call the function with each argument value // Call the function with each argument value
self(ctx, $($arg),*).map(Dynamic::from) self(ctx, $($arg),*).map(Dynamic::from)

View File

@ -238,7 +238,7 @@ impl Module {
/// # use rhai::Module; /// # use rhai::Module;
/// let mut module = Module::new(); /// let mut module = Module::new();
/// module.set_var("answer", 42_i64); /// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42); /// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -400,7 +400,7 @@ impl Module {
/// # use rhai::Module; /// # use rhai::Module;
/// let mut module = Module::new(); /// let mut module = Module::new();
/// module.set_var("answer", 42_i64); /// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42); /// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -416,7 +416,7 @@ impl Module {
/// # use rhai::Module; /// # use rhai::Module;
/// let mut module = Module::new(); /// let mut module = Module::new();
/// module.set_var("answer", 42_i64); /// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var("answer").unwrap().cast::<i64>(), 42); /// assert_eq!(module.get_var("answer").expect("answer should exist").cast::<i64>(), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -434,7 +434,7 @@ impl Module {
/// # use rhai::Module; /// # use rhai::Module;
/// let mut module = Module::new(); /// let mut module = Module::new();
/// module.set_var("answer", 42_i64); /// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42); /// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
/// ``` /// ```
#[inline] #[inline]
pub fn set_var( pub fn set_var(
@ -1337,9 +1337,7 @@ impl Module {
f.access, f.access,
f.name.as_str(), f.name.as_str(),
f.params, f.params,
f.func f.func.get_script_fn_def().expect("scripted function"),
.get_script_fn_def()
.expect("never fails because the function is scripted"),
) )
}) })
} }
@ -1407,7 +1405,7 @@ impl Module {
/// let ast = engine.compile("let answer = 42; export answer;")?; /// let ast = engine.compile("let answer = 42; export answer;")?;
/// let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?; /// let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
/// assert!(module.contains_var("answer")); /// assert!(module.contains_var("answer"));
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42); /// assert_eq!(module.get_var_value::<i64>("answer").expect("answer should exist"), 42);
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
@ -1431,9 +1429,7 @@ impl Module {
match aliases.len() { match aliases.len() {
0 => (), 0 => (),
1 => { 1 => {
let alias = aliases let alias = aliases.pop().expect("list has one item");
.pop()
.expect("never fails because the list has one item");
module.set_var(alias, value); module.set_var(alias, value);
} }
_ => aliases.into_iter().for_each(|alias| { _ => aliases.into_iter().for_each(|alias| {
@ -1465,7 +1461,7 @@ impl Module {
let mut func = f let mut func = f
.func .func
.get_script_fn_def() .get_script_fn_def()
.expect("never fails because the function is scripted") .expect("scripted function")
.as_ref() .as_ref()
.clone(); .clone();
func.lib = Some(ast.shared_lib()); func.lib = Some(ast.shared_lib());

View File

@ -282,14 +282,19 @@ fn optimize_stmt_block(
if reduce_return && !last_stmt.returns_value() => if reduce_return && !last_stmt.returns_value() =>
{ {
state.set_dirty(); state.set_dirty();
statements.pop().unwrap(); statements
.pop()
.expect("`statements` contains at least two elements");
} }
// { ...; return val; } -> { ...; val } // { ...; return val; } -> { ...; val }
[.., Stmt::Return(crate::ast::ReturnType::Return, ref mut expr, pos)] [.., Stmt::Return(crate::ast::ReturnType::Return, ref mut expr, pos)]
if reduce_return => if reduce_return =>
{ {
state.set_dirty(); state.set_dirty();
*statements.last_mut().unwrap() = if let Some(expr) = expr { *statements
.last_mut()
.expect("`statements` contains at least two elements") =
if let Some(expr) = expr {
Stmt::Expr(mem::take(expr)) Stmt::Expr(mem::take(expr))
} else { } else {
Stmt::Noop(pos) Stmt::Noop(pos)
@ -308,9 +313,14 @@ fn optimize_stmt_block(
{ {
state.set_dirty(); state.set_dirty();
if second_last_stmt.returns_value() { if second_last_stmt.returns_value() {
*statements.last_mut().unwrap() = Stmt::Noop(last_stmt.position()); *statements
.last_mut()
.expect("`statements` contains at least two elements") =
Stmt::Noop(last_stmt.position());
} else { } else {
statements.pop().unwrap(); statements
.pop()
.expect("`statements` contains at least two elements");
} }
} }
_ => break, _ => break,
@ -328,18 +338,24 @@ fn optimize_stmt_block(
if reduce_return => if reduce_return =>
{ {
state.set_dirty(); state.set_dirty();
statements.pop().unwrap(); statements
.pop()
.expect("`statements` contains at least two elements");
} }
// { ...; return pure_val; } -> { ... } // { ...; return pure_val; } -> { ... }
[.., Stmt::Return(crate::ast::ReturnType::Return, Some(ref expr), _)] [.., Stmt::Return(crate::ast::ReturnType::Return, Some(ref expr), _)]
if reduce_return && expr.is_pure() => if reduce_return && expr.is_pure() =>
{ {
state.set_dirty(); state.set_dirty();
statements.pop().unwrap(); statements
.pop()
.expect("`statements` contains at least two elements");
} }
[.., ref last_stmt] if is_pure(last_stmt) => { [.., ref last_stmt] if is_pure(last_stmt) => {
state.set_dirty(); state.set_dirty();
statements.pop().unwrap(); statements
.pop()
.expect("`statements` contains at least one element");
} }
_ => break, _ => break,
} }
@ -381,14 +397,18 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
match x.2 { match x.2 {
Expr::FnCall(ref mut x2, _) => { Expr::FnCall(ref mut x2, _) => {
state.set_dirty(); state.set_dirty();
let op = Token::lookup_from_syntax(&x2.name).unwrap(); let op = Token::lookup_from_syntax(&x2.name).expect("`x2` is operator");
let op_assignment = op.make_op_assignment().unwrap(); let op_assignment = op.make_op_assignment().expect("`op` is operator");
x.1 = Some(OpAssignment::new(op_assignment)); x.1 = Some(OpAssignment::new(op_assignment));
let value = mem::take(&mut x2.args[1]); let value = mem::take(&mut x2.args[1]);
if let Expr::Stack(slot, pos) = value { if let Expr::Stack(slot, pos) = value {
let value = mem::take(x2.constants.get_mut(slot).unwrap()); let value = mem::take(
x2.constants
.get_mut(slot)
.expect("`constants[slot]` is valid"),
);
x.2 = Expr::from_dynamic(value, pos); x.2 = Expr::from_dynamic(value, pos);
} else { } else {
x.2 = value; x.2 = value;
@ -459,7 +479,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
// switch const { ... } // switch const { ... }
Stmt::Switch(match_expr, x, pos) if match_expr.is_constant() => { Stmt::Switch(match_expr, x, pos) if match_expr.is_constant() => {
let value = match_expr.get_literal_value().unwrap(); let value = match_expr
.get_literal_value()
.expect("`match_expr` is constant");
let hasher = &mut get_hasher(); let hasher = &mut get_hasher();
value.hash(hasher); value.hash(hasher);
let hash = hasher.finish(); let hash = hasher.finish();
@ -782,13 +804,13 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _)) if *i >= 0 && (*i as usize) < s.chars().count() => { (Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _)) if *i >= 0 && (*i as usize) < s.chars().count() => {
// String literal indexing - get the character // String literal indexing - get the character
state.set_dirty(); state.set_dirty();
*expr = Expr::CharConstant(s.chars().nth(*i as usize).unwrap(), *pos); *expr = Expr::CharConstant(s.chars().nth(*i as usize).expect("character position is valid"), *pos);
} }
// string[-int] // string[-int]
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _)) if *i < 0 && i.checked_abs().map(|n| n as usize <= s.chars().count()).unwrap_or(false) => { (Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _)) if *i < 0 && i.checked_abs().map(|n| n as usize <= s.chars().count()).unwrap_or(false) => {
// String literal indexing - get the character // String literal indexing - get the character
state.set_dirty(); state.set_dirty();
*expr = Expr::CharConstant(s.chars().rev().nth(i.abs() as usize - 1).unwrap(), *pos); *expr = Expr::CharConstant(s.chars().rev().nth(i.abs() as usize - 1).expect("character position is valid"), *pos);
} }
// var[rhs] // var[rhs]
(Expr::Variable(_, _, _), rhs) => optimize_expr(rhs, state, true), (Expr::Variable(_, _, _), rhs) => optimize_expr(rhs, state, true),
@ -855,7 +877,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Array(_, _) if expr.is_constant() => { Expr::Array(_, _) if expr.is_constant() => {
state.set_dirty(); state.set_dirty();
*expr = Expr::DynamicConstant(expr.get_literal_value().unwrap().into(), expr.position()); *expr = Expr::DynamicConstant(expr.get_literal_value().expect("`expr` is constant").into(), expr.position());
} }
// [ items .. ] // [ items .. ]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -864,7 +886,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Map(_, _) if expr.is_constant() => { Expr::Map(_, _) if expr.is_constant() => {
state.set_dirty(); state.set_dirty();
*expr = Expr::DynamicConstant(expr.get_literal_value().unwrap().into(), expr.position()); *expr = Expr::DynamicConstant(expr.get_literal_value().expect("`expr` is constant").into(), expr.position());
} }
// #{ key:value, .. } // #{ key:value, .. }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
@ -935,7 +957,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
if let Some(fn_name) = fn_name { if let Some(fn_name) = fn_name {
if fn_name.is::<ImmutableString>() { if fn_name.is::<ImmutableString>() {
state.set_dirty(); state.set_dirty();
let fn_ptr = FnPtr::new_unchecked(fn_name.as_str_ref().unwrap().into(), Default::default()); let fn_ptr = FnPtr::new_unchecked(
fn_name.as_str_ref().expect("`fn_name` is `ImmutableString`").into(),
Default::default()
);
*expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos); *expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos);
} }
} }
@ -955,7 +980,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
=> { => {
let arg_values = &mut x.args.iter().map(|e| match e { let arg_values = &mut x.args.iter().map(|e| match e {
Expr::Stack(slot, _) => x.constants[*slot].clone(), Expr::Stack(slot, _) => x.constants[*slot].clone(),
_ => e.get_literal_value().unwrap() _ => e.get_literal_value().expect("`e` is constant")
}).collect::<StaticVec<_>>(); }).collect::<StaticVec<_>>();
let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect(); let arg_types: StaticVec<_> = arg_values.iter().map(Dynamic::type_id).collect();
@ -969,7 +994,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1]) get_builtin_binary_op_fn(x.name.as_ref(), &arg_values[0], &arg_values[1])
.and_then(|f| { .and_then(|f| {
let ctx = (state.engine, x.name.as_ref(), state.lib).into(); let ctx = (state.engine, x.name.as_ref(), state.lib).into();
let (first, second) = arg_values.split_first_mut().unwrap(); let (first, second) = arg_values.split_first_mut().expect("`arg_values` is not empty");
(f)(ctx, &mut [ first, &mut second[0] ]).ok() (f)(ctx, &mut [ first, &mut second[0] ]).ok()
}) })
} }
@ -1009,7 +1034,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
if !has_script_fn { if !has_script_fn {
let arg_values = &mut x.args.iter().map(|e| match e { let arg_values = &mut x.args.iter().map(|e| match e {
Expr::Stack(slot, _) => x.constants[*slot].clone(), Expr::Stack(slot, _) => x.constants[*slot].clone(),
_ => e.get_literal_value().unwrap() _ => e.get_literal_value().expect("`e` is constant")
}).collect::<StaticVec<_>>(); }).collect::<StaticVec<_>>();
let result = match x.name.as_str() { let result = match x.name.as_str() {
@ -1044,7 +1069,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
// constant-name // constant-name
Expr::Variable(_, pos, x) if x.1.is_none() && state.find_constant(&x.2).is_some() => { Expr::Variable(_, pos, x) if x.1.is_none() && state.find_constant(&x.2).is_some() => {
// Replace constant with value // Replace constant with value
*expr = Expr::from_dynamic(state.find_constant(&x.2).unwrap().clone(), *pos); *expr = Expr::from_dynamic(state.find_constant(&x.2).expect("constant exists").clone(), *pos);
state.set_dirty(); state.set_dirty();
} }

View File

@ -45,7 +45,7 @@ fn collect_fn_metadata(ctx: NativeCallContext) -> crate::Array {
namespace: Option<Identifier>, namespace: Option<Identifier>,
f: &ScriptFnDef, f: &ScriptFnDef,
) -> Map { ) -> Map {
const DICT: &str = "never fails because the dictionary is pre-filled with all the keys"; const DICT: &str = "key exists";
let mut map = Map::new(); let mut map = Map::new();

View File

@ -31,7 +31,7 @@ pub fn print_with_func(
match ctx.call_fn_dynamic_raw(fn_name, true, &mut [value]) { match ctx.call_fn_dynamic_raw(fn_name, true, &mut [value]) {
Ok(result) if result.is::<crate::ImmutableString>() => result Ok(result) if result.is::<crate::ImmutableString>() => result
.into_immutable_string() .into_immutable_string()
.expect("never fails as the result is `ImmutableString`"), .expect("result is `ImmutableString`"),
Ok(result) => ctx.engine().map_type_name(result.type_name()).into(), Ok(result) => ctx.engine().map_type_name(result.type_name()).into(),
Err(_) => ctx.engine().map_type_name(value.type_name()).into(), Err(_) => ctx.engine().map_type_name(value.type_name()).into(),
} }

View File

@ -116,9 +116,7 @@ mod string_functions {
#[rhai_fn(name = "to_upper")] #[rhai_fn(name = "to_upper")]
pub fn to_upper_char(character: char) -> char { pub fn to_upper_char(character: char) -> char {
let mut stream = character.to_uppercase(); let mut stream = character.to_uppercase();
let ch = stream let ch = stream.next().expect("at least one character");
.next()
.expect("never fails because there should be at least one character");
if stream.next().is_some() { if stream.next().is_some() {
character character
} else { } else {
@ -134,7 +132,7 @@ mod string_functions {
let mut stream = character.to_lowercase(); let mut stream = character.to_lowercase();
let ch = stream let ch = stream
.next() .next()
.expect("never fails because there should be at least one character"); .expect("there should be at least one character");
if stream.next().is_some() { if stream.next().is_some() {
character character
} else { } else {

View File

@ -38,8 +38,8 @@ type FunctionsLib = BTreeMap<u64, Shared<ScriptFnDef>>;
/// Invalid variable name that acts as a search barrier in a [`Scope`]. /// Invalid variable name that acts as a search barrier in a [`Scope`].
const SCOPE_SEARCH_BARRIER_MARKER: &str = "$BARRIER$"; const SCOPE_SEARCH_BARRIER_MARKER: &str = "$BARRIER$";
/// The message: never fails because `TokenStream` never ends /// The message: `TokenStream` never ends
const NEVER_ENDS: &str = "never fails because `TokenStream` never ends"; const NEVER_ENDS: &str = "`TokenStream` never ends";
/// A factory of identifiers from text strings. /// A factory of identifiers from text strings.
/// ///
@ -1602,9 +1602,7 @@ fn make_assignment_stmt(
let index = i.map_or_else( let index = i.map_or_else(
|| { || {
index index
.expect( .expect("the long index is `Some` when the short index is `None`")
"never fails because the long index is `Some` when the short index is `None`",
)
.get() .get()
}, },
|n| n.get() as usize, |n| n.get() as usize,
@ -1695,8 +1693,9 @@ fn make_dot_expr(
} }
// lhs.module::id - syntax error // lhs.module::id - syntax error
(_, Expr::Variable(_, _, x)) => { (_, Expr::Variable(_, _, x)) => {
return Err(PERR::PropertyExpected return Err(
.into_err(x.1.expect("never fails because the namespace is `Some`").0[0].pos)) PERR::PropertyExpected.into_err(x.1.expect("the namespace is `Some`").0[0].pos)
)
} }
// lhs.prop // lhs.prop
(lhs, prop @ Expr::Property(_)) => { (lhs, prop @ Expr::Property(_)) => {
@ -1901,12 +1900,8 @@ fn parse_binary_op(
| Token::GreaterThanEqualsTo => FnCallExpr { args, ..op_base }.into_fn_call_expr(pos), | Token::GreaterThanEqualsTo => FnCallExpr { args, ..op_base }.into_fn_call_expr(pos),
Token::Or => { Token::Or => {
let rhs = args let rhs = args.pop().expect("`||` has two arguments");
.pop() let current_lhs = args.pop().expect("`||` has two arguments");
.expect("never fails because `||` has two arguments");
let current_lhs = args
.pop()
.expect("never fails because `||` has two arguments");
Expr::Or( Expr::Or(
BinaryExpr { BinaryExpr {
lhs: current_lhs.ensure_bool_expr()?, lhs: current_lhs.ensure_bool_expr()?,
@ -1917,12 +1912,8 @@ fn parse_binary_op(
) )
} }
Token::And => { Token::And => {
let rhs = args let rhs = args.pop().expect("`&&` has two arguments");
.pop() let current_lhs = args.pop().expect("`&&` has two arguments");
.expect("never fails because `&&` has two arguments");
let current_lhs = args
.pop()
.expect("never fails because `&&` has two arguments");
Expr::And( Expr::And(
BinaryExpr { BinaryExpr {
lhs: current_lhs.ensure_bool_expr()?, lhs: current_lhs.ensure_bool_expr()?,
@ -2391,7 +2382,7 @@ fn parse_for(
}, },
counter_var.map(|name| Ident { counter_var.map(|name| Ident {
name, name,
pos: counter_pos.expect("never fails because `counter_var` is `Some`"), pos: counter_pos.expect("`counter_var` is `Some`"),
}), }),
body.into(), body.into(),
)), )),

View File

@ -32,8 +32,8 @@ const SCOPE_ENTRIES_INLINED: usize = 8;
/// ///
/// assert_eq!(engine.eval_with_scope::<i64>(&mut my_scope, "x + 1")?, 42); /// assert_eq!(engine.eval_with_scope::<i64>(&mut my_scope, "x + 1")?, 42);
/// ///
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 41); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 41);
/// assert_eq!(my_scope.get_value::<i64>("z").unwrap(), 0); /// assert_eq!(my_scope.get_value::<i64>("z").expect("z should exist"), 0);
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
@ -85,7 +85,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push("x", 42_i64); /// my_scope.push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -163,7 +163,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push("x", 42_i64); /// my_scope.push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn push( pub fn push(
@ -183,7 +183,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push_dynamic("x", Dynamic::from(42_i64)); /// my_scope.push_dynamic("x", Dynamic::from(42_i64));
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn push_dynamic(&mut self, name: impl Into<Cow<'a, str>>, value: Dynamic) -> &mut Self { pub fn push_dynamic(&mut self, name: impl Into<Cow<'a, str>>, value: Dynamic) -> &mut Self {
@ -202,7 +202,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push_constant("x", 42_i64); /// my_scope.push_constant("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn push_constant( pub fn push_constant(
@ -225,7 +225,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push_constant_dynamic("x", Dynamic::from(42_i64)); /// my_scope.push_constant_dynamic("x", Dynamic::from(42_i64));
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn push_constant_dynamic( pub fn push_constant_dynamic(
@ -327,7 +327,7 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push("x", 42_i64); /// my_scope.push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]
@ -377,15 +377,15 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.set_or_push("x", 42_i64); /// my_scope.set_or_push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// assert_eq!(my_scope.len(), 1); /// assert_eq!(my_scope.len(), 1);
/// ///
/// my_scope.set_or_push("x", 0_i64); /// my_scope.set_or_push("x", 0_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 0); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 0);
/// assert_eq!(my_scope.len(), 1); /// assert_eq!(my_scope.len(), 1);
/// ///
/// my_scope.set_or_push("y", 123_i64); /// my_scope.set_or_push("y", 123_i64);
/// assert_eq!(my_scope.get_value::<i64>("y").unwrap(), 123); /// assert_eq!(my_scope.get_value::<i64>("y").expect("y should exist"), 123);
/// assert_eq!(my_scope.len(), 2); /// assert_eq!(my_scope.len(), 2);
/// ``` /// ```
#[inline] #[inline]
@ -399,10 +399,7 @@ impl<'a> Scope<'a> {
self.push(name, value); self.push(name, value);
} }
Some((index, AccessMode::ReadWrite)) => { Some((index, AccessMode::ReadWrite)) => {
let value_ref = self let value_ref = self.values.get_mut(index).expect("index is valid");
.values
.get_mut(index)
.expect("never fails because the index is returned by `get_index`");
*value_ref = Dynamic::from(value); *value_ref = Dynamic::from(value);
} }
} }
@ -425,10 +422,10 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push("x", 42_i64); /// my_scope.push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ///
/// my_scope.set_value("x", 0_i64); /// my_scope.set_value("x", 0_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 0); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 0);
/// ``` /// ```
#[inline] #[inline]
pub fn set_value( pub fn set_value(
@ -442,10 +439,7 @@ impl<'a> Scope<'a> {
} }
Some((_, AccessMode::ReadOnly)) => panic!("variable {} is constant", name.as_ref()), Some((_, AccessMode::ReadOnly)) => panic!("variable {} is constant", name.as_ref()),
Some((index, AccessMode::ReadWrite)) => { Some((index, AccessMode::ReadWrite)) => {
let value_ref = self let value_ref = self.values.get_mut(index).expect("index is valid");
.values
.get_mut(index)
.expect("never fails because the index is returned by `get_index`");
*value_ref = Dynamic::from(value); *value_ref = Dynamic::from(value);
} }
} }
@ -464,12 +458,12 @@ impl<'a> Scope<'a> {
/// let mut my_scope = Scope::new(); /// let mut my_scope = Scope::new();
/// ///
/// my_scope.push("x", 42_i64); /// my_scope.push("x", 42_i64);
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 42); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 42);
/// ///
/// let ptr = my_scope.get_mut("x").unwrap(); /// let ptr = my_scope.get_mut("x").expect("x should exist");
/// *ptr = 123_i64.into(); /// *ptr = 123_i64.into();
/// ///
/// assert_eq!(my_scope.get_value::<i64>("x").unwrap(), 123); /// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 123);
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]
@ -488,9 +482,7 @@ impl<'a> Scope<'a> {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub(crate) fn get_mut_by_index(&mut self, index: usize) -> &mut Dynamic { pub(crate) fn get_mut_by_index(&mut self, index: usize) -> &mut Dynamic {
self.values self.values.get_mut(index).expect("index is out of bounds")
.get_mut(index)
.expect("never fails unless the index is out of bounds")
} }
/// Update the access type of an entry in the [`Scope`]. /// Update the access type of an entry in the [`Scope`].
/// ///
@ -500,10 +492,7 @@ impl<'a> Scope<'a> {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[inline] #[inline]
pub(crate) fn add_entry_alias(&mut self, index: usize, alias: Identifier) -> &mut Self { pub(crate) fn add_entry_alias(&mut self, index: usize, alias: Identifier) -> &mut Self {
let (_, aliases) = self let (_, aliases) = self.names.get_mut(index).expect("index is out of bounds");
.names
.get_mut(index)
.expect("never fails unless the index is out of bounds");
match aliases { match aliases {
None => { None => {
let mut list = StaticVec::new(); let mut list = StaticVec::new();
@ -563,12 +552,12 @@ impl<'a> Scope<'a> {
/// ///
/// let mut iter = my_scope.iter(); /// let mut iter = my_scope.iter();
/// ///
/// let (name, is_constant, value) = iter.next().unwrap(); /// let (name, is_constant, value) = iter.next().expect("value should exist");
/// assert_eq!(name, "x"); /// assert_eq!(name, "x");
/// assert!(!is_constant); /// assert!(!is_constant);
/// assert_eq!(value.cast::<i64>(), 42); /// assert_eq!(value.cast::<i64>(), 42);
/// ///
/// let (name, is_constant, value) = iter.next().unwrap(); /// let (name, is_constant, value) = iter.next().expect("value should exist");
/// assert_eq!(name, "foo"); /// assert_eq!(name, "foo");
/// assert!(is_constant); /// assert!(is_constant);
/// assert_eq!(value.cast::<String>(), "hello"); /// assert_eq!(value.cast::<String>(), "hello");

View File

@ -568,7 +568,7 @@ where
) -> Result<V::Value, Box<EvalAltResult>> { ) -> Result<V::Value, Box<EvalAltResult>> {
// Deserialize each value item coming out of the iterator. // Deserialize each value item coming out of the iterator.
seed.deserialize(&mut DynamicDeserializer::from_dynamic( seed.deserialize(&mut DynamicDeserializer::from_dynamic(
self.values.next().unwrap(), self.values.next().expect("value should exist"),
)) ))
} }
} }

View File

@ -53,7 +53,12 @@ struct FnParam {
impl PartialOrd for FnParam { impl PartialOrd for FnParam {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(match self.name.partial_cmp(&other.name).unwrap() { Some(
match self
.name
.partial_cmp(&other.name)
.expect("String::partial_cmp should succeed")
{
Ordering::Less => Ordering::Less, Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater, Ordering::Greater => Ordering::Greater,
Ordering::Equal => match (self.typ.is_none(), other.typ.is_none()) { Ordering::Equal => match (self.typ.is_none(), other.typ.is_none()) {
@ -63,11 +68,12 @@ impl PartialOrd for FnParam {
(false, false) => self (false, false) => self
.typ .typ
.as_ref() .as_ref()
.unwrap() .expect("`typ` is not `None`")
.partial_cmp(other.typ.as_ref().unwrap()) .partial_cmp(other.typ.as_ref().expect("`typ` is not `None`"))
.unwrap(), .expect("String::partial_cmp should succeed"),
}, },
}) },
)
} }
} }
@ -157,7 +163,7 @@ impl From<&crate::module::FuncInfo> for FnMetadata {
{ {
info.func info.func
.get_script_fn_def() .get_script_fn_def()
.expect("never fails because the function is scripted") .expect("scripted function")
.comments .comments
.to_vec() .to_vec()
} }

View File

@ -1207,7 +1207,7 @@ pub fn parse_string_literal(
{ {
let start_position = start let start_position = start
.position() .position()
.expect("never fails because the string must have a starting position"); .expect("string must have starting position");
skip_whitespace_until = start_position + 1; skip_whitespace_until = start_position + 1;
} }
} }
@ -1229,9 +1229,7 @@ pub fn parse_string_literal(
// Whitespace to skip // Whitespace to skip
#[cfg(not(feature = "no_position"))] #[cfg(not(feature = "no_position"))]
_ if next_char.is_whitespace() _ if next_char.is_whitespace()
&& pos && pos.position().expect("character must have position")
.position()
.expect("never fails because a character must have a position")
< skip_whitespace_until => {} < skip_whitespace_until => {}
// All other characters // All other characters
@ -1379,16 +1377,12 @@ fn get_next_token_inner(
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let return_comment = return_comment let return_comment =
|| is_doc_comment( return_comment || is_doc_comment(comment.as_ref().expect("`include_comments` is true"));
comment
.as_ref()
.expect("never fails because `include_comments` is true"),
);
if return_comment { if return_comment {
return Some(( return Some((
Token::Comment(comment.expect("never fails because `return_comment` is true")), Token::Comment(comment.expect("`return_comment` is true")),
start_pos, start_pos,
)); ));
} }
@ -1440,7 +1434,7 @@ fn get_next_token_inner(
} }
#[cfg(any(not(feature = "no_float"), feature = "decimal"))] #[cfg(any(not(feature = "no_float"), feature = "decimal"))]
'.' => { '.' => {
stream.get_next().expect("never fails because it is `.`"); stream.get_next().expect("it is `.`");
// Check if followed by digits or something that cannot start a property name // Check if followed by digits or something that cannot start a property name
match stream.peek_next().unwrap_or('\0') { match stream.peek_next().unwrap_or('\0') {
@ -1474,7 +1468,7 @@ fn get_next_token_inner(
} }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
'e' => { 'e' => {
stream.get_next().expect("never fails it is `e`"); stream.get_next().expect("it is `e`");
// Check if followed by digits or +/- // Check if followed by digits or +/-
match stream.peek_next().unwrap_or('\0') { match stream.peek_next().unwrap_or('\0') {
@ -1487,11 +1481,7 @@ fn get_next_token_inner(
'+' | '-' => { '+' | '-' => {
result.push(next_char); result.push(next_char);
pos.advance(); pos.advance();
result.push( result.push(stream.get_next().expect("it is `+` or `-`"));
stream
.get_next()
.expect("never fails because it is `+` or `-`"),
);
pos.advance(); pos.advance();
} }
// Not a floating-point number // Not a floating-point number
@ -1639,7 +1629,7 @@ fn get_next_token_inner(
|(err, err_pos)| (Token::LexError(err), err_pos), |(err, err_pos)| (Token::LexError(err), err_pos),
|(result, _)| { |(result, _)| {
let mut chars = result.chars(); let mut chars = result.chars();
let first = chars.next().unwrap(); let first = chars.next().expect("`chars` is not empty");
if chars.next().is_some() { if chars.next().is_some() {
(Token::LexError(LERR::MalformedChar(result)), start_pos) (Token::LexError(LERR::MalformedChar(result)), start_pos)