Replace unwrap with expect.

This commit is contained in:
Stephen Chung
2021-05-22 19:14:24 +08:00
parent 1545b602a7
commit cc3e2d79a5
18 changed files with 600 additions and 323 deletions

View File

@@ -429,15 +429,15 @@ impl<'a> Target<'a> {
/// This has no effect except for string indexing.
#[cfg(not(feature = "no_object"))]
#[inline(always)]
pub fn propagate_changed_value(&mut self) {
pub fn propagate_changed_value(&mut self) -> Result<(), Box<EvalAltResult>> {
match self {
Self::Ref(_) | Self::Value(_) => (),
Self::Ref(_) | Self::Value(_) => Ok(()),
#[cfg(not(feature = "no_closure"))]
Self::LockGuard(_) => (),
Self::LockGuard(_) => Ok(()),
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, ch) => {
let char_value = ch.clone();
self.set_value(char_value, Position::NONE).unwrap();
self.set_value(char_value, Position::NONE)
}
}
}
@@ -455,7 +455,9 @@ impl<'a> Target<'a> {
Self::Value(_) => panic!("cannot update a value"),
#[cfg(not(feature = "no_index"))]
Self::StringChar(s, index, _) => {
let s = &mut *s.write_lock::<ImmutableString>().unwrap();
let s = &mut *s
.write_lock::<ImmutableString>()
.expect("never fails because `StringChar` always holds an `ImmutableString`");
// Replace the character at the specified index position
let new_ch = new_val.as_char().map_err(|err| {
@@ -488,7 +490,12 @@ impl<'a> From<&'a mut Dynamic> for Target<'a> {
if value.is_shared() {
// Cloning is cheap for a shared value
let container = value.clone();
return Self::LockGuard((value.write_lock::<Dynamic>().unwrap(), container));
return Self::LockGuard((
value
.write_lock::<Dynamic>()
.expect("never fails when casting to `Dynamic`"),
container,
));
}
Self::Ref(value)
@@ -598,9 +605,12 @@ impl State {
#[inline(always)]
pub fn fn_resolution_cache_mut(&mut self) -> &mut FnResolutionCache {
if self.fn_resolution_caches.0.is_empty() {
// Push a new function resolution cache if the stack is empty
self.fn_resolution_caches.0.push(BTreeMap::new());
}
self.fn_resolution_caches.0.last_mut().unwrap()
self.fn_resolution_caches.0.last_mut().expect(
"never fails because there is at least one function resolution cache by this point",
)
}
/// Push an empty function resolution cache onto the stack and make it current.
#[allow(dead_code)]
@@ -617,7 +627,11 @@ impl State {
/// Panics if there are no more function resolution cache in the stack.
#[inline(always)]
pub fn pop_fn_resolution_cache(&mut self) {
let mut cache = self.fn_resolution_caches.0.pop().unwrap();
let mut cache = self
.fn_resolution_caches
.0
.pop()
.expect("there should be at least one function resolution cache");
cache.clear();
self.fn_resolution_caches.1.push(cache);
}
@@ -996,10 +1010,16 @@ impl Engine {
if let Some(index) = index {
let offset = mods.len() - index.get();
Some(mods.get(offset).expect("invalid index in Imports"))
Some(
mods.get(offset)
.expect("never fails because offset should be within range"),
)
} else {
mods.find(root)
.map(|n| mods.get(n).expect("invalid index in Imports"))
.map(|n| {
mods.get(n)
.expect("never fails because the index came from `find`")
})
.or_else(|| self.global_sub_modules.get(root).cloned())
}
}
@@ -1051,6 +1071,10 @@ impl Engine {
}
/// Search for a variable within the scope
///
/// # Panics
///
/// Panics if `expr` is not [`Expr::Variable`].
pub(crate) fn search_scope_only<'s>(
&self,
scope: &'s mut Scope,
@@ -1088,9 +1112,13 @@ impl Engine {
this_ptr,
level: 0,
};
if let Some(mut result) =
resolve_var(expr.get_variable_name(true).unwrap(), index, &context)
.map_err(|err| err.fill_position(var_pos))?
if let Some(mut result) = resolve_var(
expr.get_variable_name(true)
.expect("`expr` should be `Variable`"),
index,
&context,
)
.map_err(|err| err.fill_position(var_pos))?
{
result.set_access_mode(AccessMode::ReadOnly);
return Ok((result.into(), var_pos));
@@ -1101,7 +1129,9 @@ impl Engine {
scope.len() - index
} else {
// Find the variable in the scope
let var_name = expr.get_variable_name(true).unwrap();
let var_name = expr
.get_variable_name(true)
.expect("`expr` should be `Variable`");
scope
.get_index(var_name)
.ok_or_else(|| EvalAltResult::ErrorVariableNotFound(var_name.to_string(), var_pos))?
@@ -1130,18 +1160,22 @@ impl Engine {
level: usize,
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
fn match_chain_type(expr: &Expr) -> ChainType {
match expr {
#[cfg(not(feature = "no_index"))]
Expr::Index(_, _) => ChainType::Index,
#[cfg(not(feature = "no_object"))]
Expr::Dot(_, _) => ChainType::Dot,
_ => unreachable!("`expr` should only be `Index` or `Dot`, but got {:?}", expr),
}
}
let is_ref = target.is_ref();
let rhs_chain = match rhs {
#[cfg(not(feature = "no_index"))]
Expr::Index(_, _) => Some(ChainType::Index),
#[cfg(not(feature = "no_object"))]
Expr::Dot(_, _) => Some(ChainType::Dot),
_ => None,
};
// Pop the last index value
let idx_val = idx_values.pop().unwrap();
let idx_val = idx_values
.pop()
.expect("never fails because an index chain is never empty");
match chain_type {
#[cfg(not(feature = "no_index"))]
@@ -1156,7 +1190,7 @@ impl Engine {
let obj_ptr = &mut self.get_indexed_mut(
mods, state, lib, target, idx_val, idx_pos, false, true, level,
)?;
let rhs_chain = rhs_chain.unwrap();
let rhs_chain = match_chain_type(rhs);
self.eval_dot_index_chain_helper(
mods, state, lib, this_ptr, obj_ptr, root, &x.rhs, idx_values,
@@ -1166,7 +1200,8 @@ impl Engine {
}
// xxx[rhs] op= new_val
_ if new_val.is_some() => {
let ((mut new_val, new_pos), (op_info, op_pos)) = new_val.unwrap();
let ((mut new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`");
let idx_val = idx_val.as_index_value();
#[cfg(not(feature = "no_index"))]
@@ -1239,7 +1274,8 @@ impl Engine {
let val = self.get_indexed_mut(
mods, state, lib, target, index, *pos, true, false, level,
)?;
let ((new_val, new_pos), (op_info, op_pos)) = new_val.unwrap();
let ((new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`");
self.eval_op_assignment(
mods, state, lib, op_info, op_pos, val, root, new_val, new_pos,
)?;
@@ -1258,7 +1294,8 @@ impl Engine {
// xxx.id op= ???
Expr::Property(x) if new_val.is_some() => {
let ((getter, hash_get), (setter, hash_set), (name, pos)) = x.as_ref();
let ((mut new_val, new_pos), (op_info, op_pos)) = new_val.unwrap();
let ((mut new_val, new_pos), (op_info, op_pos)) =
new_val.expect("never fails because `new_val` is `Some`");
if op_info.is_some() {
let hash = FnCallHashes::from_native(*hash_get);
@@ -1376,7 +1413,7 @@ impl Engine {
// Others - syntax error
expr => unreachable!("invalid dot expression: {:?}", expr),
};
let rhs_chain = rhs_chain.unwrap();
let rhs_chain = match_chain_type(rhs);
self.eval_dot_index_chain_helper(
mods, state, lib, this_ptr, &mut val, root, &x.rhs, idx_values,
@@ -1391,7 +1428,7 @@ impl Engine {
Expr::Property(p) => {
let ((getter, hash_get), (setter, hash_set), (name, pos)) =
p.as_ref();
let rhs_chain = rhs_chain.unwrap();
let rhs_chain = match_chain_type(rhs);
let hash_get = FnCallHashes::from_native(*hash_get);
let hash_set = FnCallHashes::from_native(*hash_set);
let mut arg_values = [target.as_mut(), &mut Default::default()];
@@ -1479,7 +1516,7 @@ impl Engine {
// xxx.fn_name(arg_expr_list)[expr] | xxx.fn_name(arg_expr_list).expr
Expr::FnCall(f, pos) if !f.is_qualified() => {
let FnCallExpr { name, hashes, .. } = f.as_ref();
let rhs_chain = rhs_chain.unwrap();
let rhs_chain = match_chain_type(rhs);
let mut args = idx_val.as_fn_call_args();
let (mut val, _) = self.make_method_call(
mods, state, lib, name, *hashes, target, &mut args, *pos, level,
@@ -1924,7 +1961,10 @@ impl Engine {
Expr::Map(x, _) => {
let mut map = x.1.clone();
for (Ident { name: key, .. }, expr) in &x.0 {
*map.get_mut(key.as_str()).unwrap() = self
let value_ref = map
.get_mut(key.as_str())
.expect("never fails because the template should contain all the keys");
*value_ref = self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.flatten();
}
@@ -1941,7 +1981,9 @@ impl Engine {
literal_args: c_args,
..
} = x.as_ref();
let namespace = namespace.as_ref();
let namespace = namespace
.as_ref()
.expect("never fails because function call is qualified");
let hash = hashes.native_hash();
self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, c_args, hash, *pos,
@@ -2000,10 +2042,12 @@ impl Engine {
.iter()
.map(Into::into)
.collect::<StaticVec<_>>();
let key_token = custom.tokens.first().expect(
"never fails because a custom syntax stream must contain at least one token",
);
let custom_def = self
.custom_syntax
.get(custom.tokens.first().unwrap())
.unwrap();
.custom_syntax.get(key_token)
.expect("never fails because the custom syntax leading token should match with definition");
let mut context = EvalContext {
engine: self,
scope,
@@ -2134,7 +2178,9 @@ impl Engine {
let target_is_shared = false;
if target_is_shared {
lock_guard = target.write_lock::<Dynamic>().unwrap();
lock_guard = target
.write_lock::<Dynamic>()
.expect("never fails when casting to `Dynamic`");
lhs_ptr_inner = &mut *lock_guard;
} else {
lhs_ptr_inner = &mut *target;
@@ -2204,12 +2250,13 @@ impl Engine {
let (lhs_ptr, pos) =
self.search_namespace(scope, mods, state, lib, this_ptr, lhs_expr)?;
let var_name = lhs_expr
.get_variable_name(false)
.expect("never fails because `lhs_ptr` is a `Variable`s");
if !lhs_ptr.is_ref() {
return EvalAltResult::ErrorAssignmentToConstant(
lhs_expr.get_variable_name(false).unwrap().to_string(),
pos,
)
.into();
return EvalAltResult::ErrorAssignmentToConstant(var_name.to_string(), pos)
.into();
}
#[cfg(not(feature = "unchecked"))]
@@ -2222,7 +2269,7 @@ impl Engine {
op_info.clone(),
*op_pos,
lhs_ptr,
(lhs_expr.get_variable_name(false).unwrap(), pos),
(var_name, pos),
rhs_val,
rhs_expr.position(),
)?;
@@ -2447,7 +2494,10 @@ impl Engine {
let loop_var_is_shared = false;
if loop_var_is_shared {
*loop_var.write_lock().unwrap() = value;
let mut value_ref = loop_var
.write_lock()
.expect("never fails when casting to `Dynamic`");
*value_ref = value;
} else {
*loop_var = value;
}
@@ -2497,7 +2547,9 @@ impl Engine {
literal_args: c_args,
..
} = x.as_ref();
let namespace = namespace.as_ref();
let namespace = namespace
.as_ref()
.expect("never fails because function call is qualified");
let hash = hashes.native_hash();
self.make_qualified_function_call(
scope, mods, state, lib, this_ptr, namespace, name, args, c_args, hash, *pos,
@@ -2558,19 +2610,14 @@ impl Engine {
if err_pos.is_none() {
// No position info
} else {
err_map.insert(
"line".into(),
(err_pos.line().unwrap() as INT).into(),
);
err_map.insert(
"position".into(),
if err_pos.is_beginning_of_line() {
0
} else {
err_pos.position().unwrap() as INT
}
.into(),
);
let line = err_pos.line().expect("never fails because a non-NONE `Position` always has a line number") as INT;
let position = if err_pos.is_beginning_of_line() {
0
} else {
err_pos.position().expect("never fails because a non-NONE `Position` always has a character position")
} as INT;
err_map.insert("line".into(), line.into());
err_map.insert("position".into(), position.into());
}
err.dump_fields(&mut err_map);
@@ -2650,7 +2697,10 @@ impl Engine {
#[cfg(not(feature = "no_function"))]
if entry_type == AccessMode::ReadOnly && lib.iter().any(|&m| !m.is_empty()) {
let global = if let Some(index) = mods.find(KEYWORD_GLOBAL) {
match mods.get_mut(index).unwrap() {
match mods
.get_mut(index)
.expect("never fails because the index came from `find`")
{
m if m.internal => Some(m),
_ => None,
}
@@ -2659,11 +2709,15 @@ impl Engine {
let mut global = Module::new();
global.internal = true;
mods.push(KEYWORD_GLOBAL, global);
Some(mods.get_mut(mods.len() - 1).unwrap())
Some(
mods.get_mut(mods.len() - 1)
.expect("never fails because the global module was just added"),
)
};
if let Some(global) = global {
let global = Shared::get_mut(global).unwrap();
let global = Shared::get_mut(global)
.expect("never fails because the global module is never shared");
global.set_var(name.clone(), value.clone());
}
}
@@ -2778,9 +2832,10 @@ impl Engine {
/// Check a result to ensure that the data size is within allowable limit.
#[cfg(not(feature = "unchecked"))]
fn check_data_size(&self, result: &RhaiResult) -> Result<(), Box<EvalAltResult>> {
if result.is_err() {
return Ok(());
}
let result = match result {
Err(_) => return Ok(()),
Ok(r) => r,
};
// If no data size limits, just return
let mut _has_limit = self.limits.max_string_size.is_some();
@@ -2849,7 +2904,7 @@ impl Engine {
}
}
let (_arr, _map, s) = calc_size(result.as_ref().unwrap());
let (_arr, _map, s) = calc_size(result);
if s > self
.limits