Simplify code and better error messages.

This commit is contained in:
Stephen Chung 2020-12-28 14:21:13 +08:00
parent 5c813ca7c0
commit e481a8019d
11 changed files with 224 additions and 157 deletions

View File

@ -13,7 +13,8 @@ by unifying the terminology and API under the global umbrella of _modules_.
Bug fixes Bug fixes
--------- ---------
* Bug when accessing properties in closures is fixed. * Fix bug when accessing properties in closures.
* Fix bug when accessing a deep index with a function call.
Breaking changes Breaking changes
---------------- ----------------

View File

@ -830,7 +830,7 @@ impl Stmt {
Self::Import(_, _, _) | Self::Export(_, _) => false, Self::Import(_, _, _) | Self::Export(_, _) => false,
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Self::Share(_) => unreachable!(), Self::Share(_) => unreachable!("Stmt::Share should not be parsed"),
} }
} }
/// Is this statement _pure_? /// Is this statement _pure_?
@ -979,8 +979,6 @@ pub enum Expr {
Property(Box<(ImmutableString, ImmutableString, Ident)>), Property(Box<(ImmutableString, ImmutableString, Ident)>),
/// { [statement][Stmt] } /// { [statement][Stmt] }
Stmt(Box<StaticVec<Stmt>>, Position), Stmt(Box<StaticVec<Stmt>>, Position),
/// Wrapped [expression][Expr] - should not be optimized away.
Expr(Box<Expr>),
/// func `(` expr `,` ... `)` /// func `(` expr `,` ... `)`
FnCall(Box<FnCallExpr>, Position), FnCall(Box<FnCallExpr>, Position),
/// lhs `.` rhs /// lhs `.` rhs
@ -1010,8 +1008,6 @@ impl Expr {
/// Returns [`None`] if the expression is not constant. /// Returns [`None`] if the expression is not constant.
pub fn get_constant_value(&self) -> Option<Dynamic> { pub fn get_constant_value(&self) -> Option<Dynamic> {
Some(match self { Some(match self {
Self::Expr(x) => return x.get_constant_value(),
Self::DynamicConstant(x, _) => x.as_ref().clone(), Self::DynamicConstant(x, _) => x.as_ref().clone(),
Self::IntegerConstant(x, _) => (*x).into(), Self::IntegerConstant(x, _) => (*x).into(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -1061,8 +1057,6 @@ impl Expr {
/// Get the [position][Position] of the expression. /// Get the [position][Position] of the expression.
pub fn position(&self) -> Position { pub fn position(&self) -> Position {
match self { match self {
Self::Expr(x) => x.position(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Self::FloatConstant(_, pos) => *pos, Self::FloatConstant(_, pos) => *pos,
@ -1091,10 +1085,6 @@ impl Expr {
/// Override the [position][Position] of the expression. /// Override the [position][Position] of the expression.
pub fn set_position(&mut self, new_pos: Position) -> &mut Self { pub fn set_position(&mut self, new_pos: Position) -> &mut Self {
match self { match self {
Self::Expr(x) => {
x.set_position(new_pos);
}
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Self::FloatConstant(_, pos) => *pos = new_pos, Self::FloatConstant(_, pos) => *pos = new_pos,
@ -1123,8 +1113,6 @@ impl Expr {
/// A pure expression has no side effects. /// A pure expression has no side effects.
pub fn is_pure(&self) -> bool { pub fn is_pure(&self) -> bool {
match self { match self {
Self::Expr(x) => x.is_pure(),
Self::Array(x, _) => x.iter().all(Self::is_pure), Self::Array(x, _) => x.iter().all(Self::is_pure),
Self::Map(x, _) => x.iter().map(|(_, v)| v).all(Self::is_pure), Self::Map(x, _) => x.iter().map(|(_, v)| v).all(Self::is_pure),
@ -1151,8 +1139,6 @@ impl Expr {
/// Is the expression a constant? /// Is the expression a constant?
pub fn is_constant(&self) -> bool { pub fn is_constant(&self) -> bool {
match self { match self {
Self::Expr(x) => x.is_constant(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Self::FloatConstant(_, _) => true, Self::FloatConstant(_, _) => true,
@ -1189,8 +1175,6 @@ impl Expr {
} }
match self { match self {
Self::Expr(x) => x.is_valid_postfix(token),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Self::FloatConstant(_, _) => false, Self::FloatConstant(_, _) => false,

View File

@ -812,6 +812,7 @@ impl Dynamic {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
Union::Shared(cell, _) => return cell.read().unwrap().clone().try_cast(), Union::Shared(cell, _) => return cell.read().unwrap().clone().try_cast(),
_ => (), _ => (),
} }
@ -903,7 +904,7 @@ impl Dynamic {
match self.0 { match self.0 {
Union::Variant(value, _) => (*value).as_box_any().downcast().map(|x| *x).ok(), Union::Variant(value, _) => (*value).as_box_any().downcast().map(|x| *x).ok(),
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, _) => unreachable!(), Union::Shared(_, _) => unreachable!("Union::Shared case should be already handled"),
_ => None, _ => None,
} }
} }

View File

@ -225,7 +225,7 @@ impl IndexChainValue {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
pub fn as_value(self) -> Dynamic { pub fn as_value(self) -> Dynamic {
match self { match self {
Self::None | Self::FnCallArgs(_) => unreachable!("expecting IndexChainValue::Value"), Self::None | Self::FnCallArgs(_) => panic!("expecting IndexChainValue::Value"),
Self::Value(value) => value, Self::Value(value) => value,
} }
} }
@ -237,7 +237,7 @@ impl IndexChainValue {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
pub fn as_fn_call_args(self) -> StaticVec<Dynamic> { pub fn as_fn_call_args(self) -> StaticVec<Dynamic> {
match self { match self {
Self::None | Self::Value(_) => unreachable!("expecting IndexChainValue::FnCallArgs"), Self::None | Self::Value(_) => panic!("expecting IndexChainValue::FnCallArgs"),
Self::FnCallArgs(value) => value, Self::FnCallArgs(value) => value,
} }
} }
@ -382,7 +382,7 @@ impl<'a> Target<'a> {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Self::LockGuard((r, _)) => **r = new_val, Self::LockGuard((r, _)) => **r = new_val,
Self::Value(_) => unreachable!(), Self::Value(_) => panic!("cannot update a value"),
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Self::StringChar(string, index, _) if string.is::<ImmutableString>() => { Self::StringChar(string, index, _) if string.is::<ImmutableString>() => {
let mut s = string.write_lock::<ImmutableString>().unwrap(); let mut s = string.write_lock::<ImmutableString>().unwrap();
@ -896,7 +896,7 @@ impl Engine {
// Normal variable access // Normal variable access
_ => self.search_scope_only(scope, mods, state, lib, this_ptr, expr), _ => self.search_scope_only(scope, mods, state, lib, this_ptr, expr),
}, },
_ => unreachable!(), _ => unreachable!("Expr::Variable expected, but gets {:?}", expr),
} }
} }
@ -912,7 +912,7 @@ impl Engine {
) -> Result<(Target<'s>, Position), Box<EvalAltResult>> { ) -> Result<(Target<'s>, Position), Box<EvalAltResult>> {
let (index, _, Ident { name, pos }) = match expr { let (index, _, Ident { name, pos }) = match expr {
Expr::Variable(v) => v.as_ref(), Expr::Variable(v) => v.as_ref(),
_ => unreachable!(), _ => unreachable!("Expr::Variable expected, but gets {:?}", expr),
}; };
// Check if the variable is `this` // Check if the variable is `this`
@ -988,7 +988,7 @@ impl Engine {
new_val: Option<(Dynamic, Position)>, new_val: Option<(Dynamic, Position)>,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
if chain_type == ChainType::None { if chain_type == ChainType::None {
unreachable!(); unreachable!("should not be ChainType::None");
} }
let is_ref = target.is_ref(); let is_ref = target.is_ref();
@ -1103,7 +1103,9 @@ impl Engine {
) )
} }
// xxx.module::fn_name(...) - syntax error // xxx.module::fn_name(...) - syntax error
Expr::FnCall(_, _) => unreachable!(), Expr::FnCall(_, _) => {
unreachable!("function call in dot chain should not be namespace-qualified")
}
// {xxx:map}.id = ??? // {xxx:map}.id = ???
Expr::Property(x) if target_val.is::<Map>() && new_val.is_some() => { Expr::Property(x) if target_val.is::<Map>() && new_val.is_some() => {
let Ident { name, pos } = &x.2; let Ident { name, pos } = &x.2;
@ -1178,9 +1180,11 @@ impl Engine {
val.into() val.into()
} }
// {xxx:map}.module::fn_name(...) - syntax error // {xxx:map}.module::fn_name(...) - syntax error
Expr::FnCall(_, _) => unreachable!(), Expr::FnCall(_, _) => unreachable!(
"function call in dot chain should not be namespace-qualified"
),
// Others - syntax error // Others - syntax error
_ => unreachable!(), expr => unreachable!("invalid dot expression: {:?}", expr),
}; };
self.eval_dot_index_chain_helper( self.eval_dot_index_chain_helper(
@ -1266,9 +1270,11 @@ impl Engine {
.map_err(|err| err.fill_position(*pos)) .map_err(|err| err.fill_position(*pos))
} }
// xxx.module::fn_name(...) - syntax error // xxx.module::fn_name(...) - syntax error
Expr::FnCall(_, _) => unreachable!(), Expr::FnCall(_, _) => unreachable!(
"function call in dot chain should not be namespace-qualified"
),
// Others - syntax error // Others - syntax error
_ => unreachable!(), expr => unreachable!("invalid dot expression: {:?}", expr),
} }
} }
// Syntax error // Syntax error
@ -1276,7 +1282,7 @@ impl Engine {
} }
} }
_ => unreachable!(), chain_type => unreachable!("invalid ChainType: {:?}", chain_type),
} }
} }
@ -1296,7 +1302,7 @@ impl Engine {
let (crate::ast::BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr { let (crate::ast::BinaryExpr { lhs, rhs }, chain_type, op_pos) = match expr {
Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos), Expr::Index(x, pos) => (x.as_ref(), ChainType::Index, *pos),
Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos), Expr::Dot(x, pos) => (x.as_ref(), ChainType::Dot, *pos),
_ => unreachable!(), _ => unreachable!("index or dot chain expected, but gets {:?}", expr),
}; };
let idx_values = &mut Default::default(); let idx_values = &mut Default::default();
@ -1333,7 +1339,7 @@ impl Engine {
.map_err(|err| err.fill_position(op_pos)) .map_err(|err| err.fill_position(op_pos))
} }
// {expr}.??? = ??? or {expr}[???] = ??? // {expr}.??? = ??? or {expr}[???] = ???
_ if new_val.is_some() => unreachable!(), _ if new_val.is_some() => unreachable!("cannot assign to an expression"),
// {expr}.??? or {expr}[???] // {expr}.??? or {expr}[???]
expr => { expr => {
let val = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?; let val = self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?;
@ -1359,7 +1365,7 @@ impl Engine {
lib: &[&Module], lib: &[&Module],
this_ptr: &mut Option<&mut Dynamic>, this_ptr: &mut Option<&mut Dynamic>,
expr: &Expr, expr: &Expr,
chain_type: ChainType, parent_chain_type: ChainType,
idx_values: &mut StaticVec<IndexChainValue>, idx_values: &mut StaticVec<IndexChainValue>,
size: usize, size: usize,
level: usize, level: usize,
@ -1367,7 +1373,7 @@ impl Engine {
self.inc_operations(state, expr.position())?; self.inc_operations(state, expr.position())?;
match expr { match expr {
Expr::FnCall(x, _) if x.namespace.is_none() => { Expr::FnCall(x, _) if parent_chain_type == ChainType::Dot && x.namespace.is_none() => {
let arg_values = x let arg_values = x
.args .args
.iter() .iter()
@ -1378,15 +1384,27 @@ impl Engine {
idx_values.push(arg_values.into()); idx_values.push(arg_values.into());
} }
Expr::FnCall(_, _) => unreachable!(), Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
Expr::Property(_) => idx_values.push(IndexChainValue::None), unreachable!("function call in dot chain should not be namespace-qualified")
}
Expr::Property(_) if parent_chain_type == ChainType::Dot => {
idx_values.push(IndexChainValue::None)
}
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
Expr::Index(x, _) | Expr::Dot(x, _) => { Expr::Index(x, _) | Expr::Dot(x, _) => {
let crate::ast::BinaryExpr { lhs, rhs, .. } = x.as_ref(); let crate::ast::BinaryExpr { lhs, rhs, .. } = x.as_ref();
// Evaluate in left-to-right order // Evaluate in left-to-right order
let lhs_val = match lhs { let lhs_val = match lhs {
Expr::Property(_) => IndexChainValue::None, Expr::Property(_) if parent_chain_type == ChainType::Dot => {
Expr::FnCall(x, _) if chain_type == ChainType::Dot && x.namespace.is_none() => { IndexChainValue::None
}
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
Expr::FnCall(x, _)
if parent_chain_type == ChainType::Dot && x.namespace.is_none() =>
{
x.args x.args
.iter() .iter()
.map(|arg_expr| { .map(|arg_expr| {
@ -1395,7 +1413,9 @@ impl Engine {
.collect::<Result<StaticVec<Dynamic>, _>>()? .collect::<Result<StaticVec<Dynamic>, _>>()?
.into() .into()
} }
Expr::FnCall(_, _) => unreachable!(), Expr::FnCall(_, _) if parent_chain_type == ChainType::Dot => {
unreachable!("function call in dot chain should not be namespace-qualified")
}
_ => self _ => self
.eval_expr(scope, mods, state, lib, this_ptr, lhs, level)? .eval_expr(scope, mods, state, lib, this_ptr, lhs, level)?
.into(), .into(),
@ -1405,7 +1425,7 @@ impl Engine {
let chain_type = match expr { let chain_type = match expr {
Expr::Index(_, _) => ChainType::Index, Expr::Index(_, _) => ChainType::Index,
Expr::Dot(_, _) => ChainType::Dot, Expr::Dot(_, _) => ChainType::Dot,
_ => unreachable!(), _ => unreachable!("index or dot chain expected, but gets {:?}", expr),
}; };
self.eval_indexed_chain( self.eval_indexed_chain(
scope, mods, state, lib, this_ptr, rhs, chain_type, idx_values, size, level, scope, mods, state, lib, this_ptr, rhs, chain_type, idx_values, size, level,
@ -1413,6 +1433,7 @@ impl Engine {
idx_values.push(lhs_val); idx_values.push(lhs_val);
} }
_ => idx_values.push( _ => idx_values.push(
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
.into(), .into(),
@ -1622,7 +1643,7 @@ impl Engine {
// var[...] // var[...]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Index(x, _) if x.lhs.get_variable_access(false).is_some() => match x.rhs { Expr::Index(x, _) if x.lhs.get_variable_access(false).is_some() => match x.rhs {
Expr::Property(_) => unreachable!(), Expr::Property(_) => unreachable!("unexpected Expr::Property in indexing"),
// var[...]... // var[...]...
Expr::FnCall(_, _) | Expr::Index(_, _) | Expr::Dot(_, _) => self Expr::FnCall(_, _) | Expr::Index(_, _) | Expr::Dot(_, _) => self
.eval_expr(scope, mods, state, lib, this_ptr, expr, level) .eval_expr(scope, mods, state, lib, this_ptr, expr, level)
@ -1655,7 +1676,9 @@ impl Engine {
// var.prop // var.prop
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Dot(x, _) if x.lhs.get_variable_access(false).is_some() => match x.rhs { Expr::Dot(x, _) if x.lhs.get_variable_access(false).is_some() => match x.rhs {
Expr::Variable(_) => unreachable!(), Expr::Variable(_) => unreachable!(
"unexpected Expr::Variable in dot access (should be Expr::Property)"
),
// var.prop // var.prop
Expr::Property(ref p) => { Expr::Property(ref p) => {
let (mut target, _) = self.eval_expr_as_target( let (mut target, _) = self.eval_expr_as_target(
@ -1718,8 +1741,6 @@ impl Engine {
self.inc_operations(state, expr.position())?; self.inc_operations(state, expr.position())?;
let result = match expr { let result = match expr {
Expr::Expr(x) => self.eval_expr(scope, mods, state, lib, this_ptr, x, level),
Expr::DynamicConstant(x, _) => Ok(x.as_ref().clone()), Expr::DynamicConstant(x, _) => Ok(x.as_ref().clone()),
Expr::IntegerConstant(x, _) => Ok((*x).into()), Expr::IntegerConstant(x, _) => Ok((*x).into()),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -1738,7 +1759,6 @@ impl Engine {
let (val, _) = self.search_namespace(scope, mods, state, lib, this_ptr, expr)?; let (val, _) = self.search_namespace(scope, mods, state, lib, this_ptr, expr)?;
Ok(val.take_or_clone()) Ok(val.take_or_clone())
} }
Expr::Property(_) => unreachable!(),
// Statement block // Statement block
Expr::Stmt(x, _) => { Expr::Stmt(x, _) => {
@ -1867,7 +1887,7 @@ impl Engine {
(custom.func)(&mut context, &expressions) (custom.func)(&mut context, &expressions)
} }
_ => unreachable!(), _ => unreachable!("expression cannot be evaluated: {:?}", expr),
}; };
self.check_data_size(result, expr.position()) self.check_data_size(result, expr.position())
@ -2072,7 +2092,9 @@ impl Engine {
// Must be either `var[index] op= val` or `var.prop op= val` // Must be either `var[index] op= val` or `var.prop op= val`
match lhs_expr { match lhs_expr {
// name op= rhs (handled above) // name op= rhs (handled above)
Expr::Variable(_) => unreachable!(), Expr::Variable(_) => {
unreachable!("Expr::Variable case should already been handled")
}
// idx_lhs[idx_expr] op= rhs // idx_lhs[idx_expr] op= rhs
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Index(_, _) => { Expr::Index(_, _) => {
@ -2090,7 +2112,7 @@ impl Engine {
Ok(Dynamic::UNIT) Ok(Dynamic::UNIT)
} }
// Non-lvalue expression (should be caught during parsing) // Non-lvalue expression (should be caught during parsing)
_ => unreachable!(), _ => unreachable!("cannot assign to expression: {:?}", lhs_expr),
} }
} }
@ -2334,7 +2356,7 @@ impl Engine {
let entry_type = match stmt { let entry_type = match stmt {
Stmt::Let(_, _, _, _) => AccessMode::ReadWrite, Stmt::Let(_, _, _, _) => AccessMode::ReadWrite,
Stmt::Const(_, _, _, _) => AccessMode::ReadOnly, Stmt::Const(_, _, _, _) => AccessMode::ReadOnly,
_ => unreachable!(), _ => unreachable!("should be Stmt::Let or Stmt::Const, but gets {:?}", stmt),
}; };
let val = if let Some(expr) = expr { let val = if let Some(expr) = expr {
@ -2353,7 +2375,7 @@ impl Engine {
}, },
) )
} else if *export { } else if *export {
unreachable!(); unreachable!("exported variable not on global level");
} else { } else {
(unsafe_cast_var_name_to_lifetime(&var_def.name).into(), None) (unsafe_cast_var_name_to_lifetime(&var_def.name).into(), None)
}; };

View File

@ -118,7 +118,7 @@ impl Drop for ArgBackup<'_> {
// Panic if the shorter lifetime leaks. // Panic if the shorter lifetime leaks.
assert!( assert!(
self.orig_mut.is_none(), self.orig_mut.is_none(),
"MutBackup::restore has not been called prior to existing this scope" "ArgBackup::restore_first_arg has not been called prior to existing this scope"
); );
} }
} }
@ -672,7 +672,9 @@ impl Engine {
}) })
.or_else(|err| match *err { .or_else(|err| match *err {
EvalAltResult::Return(out, _) => Ok(out), EvalAltResult::Return(out, _) => Ok(out),
EvalAltResult::LoopBreak(_, _) => unreachable!(), EvalAltResult::LoopBreak(_, _) => {
unreachable!("no outer loop scope to break out of")
}
_ => Err(err), _ => Err(err),
}) })
} }
@ -1227,7 +1229,7 @@ impl Engine {
f.get_native_fn()((self, module.id_raw(), &*mods, lib).into(), args.as_mut()) f.get_native_fn()((self, module.id_raw(), &*mods, lib).into(), args.as_mut())
} }
Some(_) => unreachable!(), Some(f) => unreachable!("unknown function type: {:?}", f),
None if def_val.is_some() => Ok(def_val.unwrap().clone()), None if def_val.is_some() => Ok(def_val.unwrap().clone()),
None => EvalAltResult::ErrorFunctionNotFound( None => EvalAltResult::ErrorFunctionNotFound(
format!( format!(

View File

@ -535,10 +535,10 @@ impl CallableFunction {
pub fn get_native_fn(&self) -> &FnAny { pub fn get_native_fn(&self) -> &FnAny {
match self { match self {
Self::Pure(f) | Self::Method(f) => f.as_ref(), Self::Pure(f) | Self::Method(f) => f.as_ref(),
Self::Iterator(_) | Self::Plugin(_) => unreachable!(), Self::Iterator(_) | Self::Plugin(_) => panic!("function should be native"),
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Self::Script(_) => unreachable!(), Self::Script(_) => panic!("function should be native"),
} }
} }
/// Get a shared reference to a script-defined function definition. /// Get a shared reference to a script-defined function definition.
@ -549,7 +549,9 @@ impl CallableFunction {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
pub fn get_fn_def(&self) -> &ScriptFnDef { pub fn get_fn_def(&self) -> &ScriptFnDef {
match self { match self {
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => unreachable!(), Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => {
panic!("function should be scripted")
}
Self::Script(f) => f.as_ref(), Self::Script(f) => f.as_ref(),
} }
} }
@ -561,10 +563,12 @@ impl CallableFunction {
pub fn get_iter_fn(&self) -> IteratorFn { pub fn get_iter_fn(&self) -> IteratorFn {
match self { match self {
Self::Iterator(f) => *f, Self::Iterator(f) => *f,
Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => unreachable!(), Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => {
panic!("function should an iterator")
}
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Self::Script(_) => unreachable!(), Self::Script(_) => panic!("function should be an iterator"),
} }
} }
/// Get a shared reference to a plugin function. /// Get a shared reference to a plugin function.
@ -575,10 +579,12 @@ impl CallableFunction {
pub fn get_plugin_fn<'s>(&'s self) -> &FnPlugin { pub fn get_plugin_fn<'s>(&'s self) -> &FnPlugin {
match self { match self {
Self::Plugin(f) => f.as_ref(), Self::Plugin(f) => f.as_ref(),
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => unreachable!(), Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => {
panic!("function should a plugin")
}
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Self::Script(_) => unreachable!(), Self::Script(_) => panic!("function should a plugin"),
} }
} }
/// Create a new [`CallableFunction::Pure`]. /// Create a new [`CallableFunction::Pure`].
@ -609,7 +615,7 @@ impl From<ScriptFnDef> for CallableFunction {
#[inline(always)] #[inline(always)]
fn from(_func: ScriptFnDef) -> Self { fn from(_func: ScriptFnDef) -> Self {
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
unreachable!(); unreachable!("no_function active");
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Self::Script(_func.into()) Self::Script(_func.into())
@ -620,7 +626,7 @@ impl From<Shared<ScriptFnDef>> for CallableFunction {
#[inline(always)] #[inline(always)]
fn from(_func: Shared<ScriptFnDef>) -> Self { fn from(_func: Shared<ScriptFnDef>) -> Self {
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
unreachable!(); unreachable!("no_function active");
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
Self::Script(_func) Self::Script(_func)

View File

@ -483,8 +483,6 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
]; ];
match expr { match expr {
// expr - do not promote because there is a reason it is wrapped in an `Expr::Expr`
Expr::Expr(x) => optimize_expr(x, state),
// {} // {}
Expr::Stmt(x, pos) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(*pos) } Expr::Stmt(x, pos) if x.is_empty() => { state.set_dirty(); *expr = Expr::Unit(*pos) }
// { stmt; ... } - do not count promotion as dirty because it gets turned back into an array // { stmt; ... } - do not count promotion as dirty because it gets turned back into an array

View File

@ -603,28 +603,12 @@ fn parse_index_chain(
)) ))
} }
// Otherwise terminate the indexing chain // Otherwise terminate the indexing chain
_ => {
match idx_expr {
// Terminate with an `Expr::Expr` wrapper to prevent the last index expression
// inside brackets to be mis-parsed as another level of indexing, or a
// dot expression/function call to be mis-parsed as following the indexing chain.
Expr::Index(_, _) | Expr::Dot(_, _) | Expr::FnCall(_, _) => {
Ok(Expr::Index(
Box::new(BinaryExpr {
lhs,
rhs: Expr::Expr(Box::new(idx_expr)),
}),
settings.pos,
))
}
_ => Ok(Expr::Index( _ => Ok(Expr::Index(
Box::new(BinaryExpr { lhs, rhs: idx_expr }), Box::new(BinaryExpr { lhs, rhs: idx_expr }),
settings.pos, settings.pos,
)), )),
} }
} }
}
}
(Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)), (Token::LexError(err), pos) => return Err(err.clone().into_err(*pos)),
(_, pos) => Err(PERR::MissingToken( (_, pos) => Err(PERR::MissingToken(
Token::RightBracket.into(), Token::RightBracket.into(),
@ -970,7 +954,7 @@ fn parse_primary(
} }
Token::True => Expr::BoolConstant(true, settings.pos), Token::True => Expr::BoolConstant(true, settings.pos),
Token::False => Expr::BoolConstant(false, settings.pos), Token::False => Expr::BoolConstant(false, settings.pos),
_ => unreachable!(), t => unreachable!("unexpected token: {:?}", t),
}, },
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Token::FloatConstant(x) => { Token::FloatConstant(x) => {
@ -983,7 +967,7 @@ fn parse_primary(
Token::LeftBrace if settings.allow_stmt_expr => { Token::LeftBrace if settings.allow_stmt_expr => {
match parse_block(input, state, lib, settings.level_up())? { match parse_block(input, state, lib, settings.level_up())? {
Stmt::Block(statements, pos) => Expr::Stmt(Box::new(statements.into()), pos), Stmt::Block(statements, pos) => Expr::Stmt(Box::new(statements.into()), pos),
_ => unreachable!(), stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt),
} }
} }
// ( - grouped expression // ( - grouped expression
@ -1050,7 +1034,7 @@ fn parse_primary(
Token::Identifier(_) => { Token::Identifier(_) => {
let s = match input.next().unwrap().0 { let s = match input.next().unwrap().0 {
Token::Identifier(s) => s, Token::Identifier(s) => s,
_ => unreachable!(), t => unreachable!("expecting Token::Identifier, but gets {:?}", t),
}; };
match input.peek().unwrap().0 { match input.peek().unwrap().0 {
@ -1097,7 +1081,7 @@ fn parse_primary(
Token::Reserved(_) => { Token::Reserved(_) => {
let s = match input.next().unwrap().0 { let s = match input.next().unwrap().0 {
Token::Reserved(s) => s, Token::Reserved(s) => s,
_ => unreachable!(), t => unreachable!("expecting Token::Reserved, but gets {:?}", t),
}; };
match input.peek().unwrap().0 { match input.peek().unwrap().0 {
@ -1140,7 +1124,7 @@ fn parse_primary(
Token::LexError(_) => { Token::LexError(_) => {
let err = match input.next().unwrap().0 { let err = match input.next().unwrap().0 {
Token::LexError(err) => err, Token::LexError(err) => err,
_ => unreachable!(), t => unreachable!("expecting Token::LexError, but gets {:?}", t),
}; };
return Err(err.into_err(settings.pos)); return Err(err.into_err(settings.pos));
@ -1200,7 +1184,6 @@ fn parse_primary(
let ns = namespace.map(|(_, ns)| ns); let ns = namespace.map(|(_, ns)| ns);
parse_fn_call(input, state, lib, name, false, ns, settings.level_up())? parse_fn_call(input, state, lib, name, false, ns, settings.level_up())?
} }
(Expr::Property(_), _) => unreachable!(),
// module access // module access
(Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() { (Expr::Variable(x), Token::DoubleColon) => match input.next().unwrap() {
(Token::Identifier(id2), pos2) => { (Token::Identifier(id2), pos2) => {
@ -1270,7 +1253,7 @@ fn parse_primary(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
namespace.set_index(state.find_module(&namespace[0].name)); namespace.set_index(state.find_module(&namespace[0].name));
} }
_ => unreachable!(), _ => unreachable!("expecting namespace-qualified variable access"),
}); });
// Make sure identifiers are valid // Make sure identifiers are valid
@ -1973,7 +1956,7 @@ fn parse_custom_syntax(
segments.push(keyword.clone()); segments.push(keyword.clone());
tokens.push(keyword); tokens.push(keyword);
} }
_ => unreachable!(), stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt),
}, },
s => match input.next().unwrap() { s => match input.next().unwrap() {
(Token::LexError(err), pos) => return Err(err.into_err(pos)), (Token::LexError(err), pos) => return Err(err.into_err(pos)),
@ -2136,7 +2119,7 @@ fn parse_while_loop(
(parse_expr(input, state, lib, settings.level_up())?, pos) (parse_expr(input, state, lib, settings.level_up())?, pos)
} }
(Token::Loop, pos) => (Expr::BoolConstant(true, pos), pos), (Token::Loop, pos) => (Expr::BoolConstant(true, pos), pos),
_ => unreachable!(), (t, _) => unreachable!("expecting Token::While or Token::Loop, but gets {:?}", t),
}; };
settings.pos = token_pos; settings.pos = token_pos;
@ -2533,14 +2516,15 @@ fn parse_stmt(
} }
if !is_doc_comment(comment) { if !is_doc_comment(comment) {
unreachable!(); unreachable!("expecting doc-comment, but gets {:?}", comment);
} }
if !settings.is_global { if !settings.is_global {
return Err(PERR::WrongDocComment.into_err(comments_pos)); return Err(PERR::WrongDocComment.into_err(comments_pos));
} }
if let Token::Comment(comment) = input.next().unwrap().0 { match input.next().unwrap().0 {
Token::Comment(comment) => {
comments.push(comment); comments.push(comment);
match input.peek().unwrap() { match input.peek().unwrap() {
@ -2548,8 +2532,8 @@ fn parse_stmt(
(Token::Comment(_), _) => (), (Token::Comment(_), _) => (),
_ => return Err(PERR::WrongDocComment.into_err(comments_pos)), _ => return Err(PERR::WrongDocComment.into_err(comments_pos)),
} }
} else { }
unreachable!(); t => unreachable!("expecting Token::Comment, but gets {:?}", t),
} }
} }
@ -2649,7 +2633,10 @@ fn parse_stmt(
match token { match token {
Token::Return => ReturnType::Return, Token::Return => ReturnType::Return,
Token::Throw => ReturnType::Exception, Token::Throw => ReturnType::Exception,
_ => unreachable!(), t => unreachable!(
"expecting Token::Return or Token::Throw, but gets {:?}",
t
),
}, },
pos, pos,
) )

View File

@ -190,13 +190,16 @@ impl fmt::Display for EvalAltResult {
Self::ErrorAssignmentToConstant(s, _) => { Self::ErrorAssignmentToConstant(s, _) => {
write!(f, "Cannot assign to constant '{}'", s)? write!(f, "Cannot assign to constant '{}'", s)?
} }
Self::ErrorMismatchOutputType(r, s, _) => { Self::ErrorMismatchOutputType(s, r, _) => {
write!(f, "Output type is incorrect: {} (expecting {})", r, s)? write!(f, "Output type is incorrect: {} (expecting {})", r, s)?
} }
Self::ErrorMismatchDataType(r, s, _) if r.is_empty() => { Self::ErrorMismatchDataType(s, r, _) if r.is_empty() => {
write!(f, "Data type is incorrect, expecting {}", s)? write!(f, "Data type is incorrect, expecting {}", s)?
} }
Self::ErrorMismatchDataType(r, s, _) => { Self::ErrorMismatchDataType(s, r, _) if s.is_empty() => {
write!(f, "Data type is incorrect: {}", r)?
}
Self::ErrorMismatchDataType(s, r, _) => {
write!(f, "Data type is incorrect: {} (expecting {})", r, s)? write!(f, "Data type is incorrect: {} (expecting {})", r, s)?
} }
Self::ErrorArithmetic(s, _) => f.write_str(s)?, Self::ErrorArithmetic(s, _) => f.write_str(s)?,
@ -263,10 +266,14 @@ impl<T: AsRef<str>> From<T> for Box<EvalAltResult> {
impl EvalAltResult { impl EvalAltResult {
/// Can this error be caught? /// Can this error be caught?
///
/// # Panics
///
/// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return].
pub fn is_catchable(&self) -> bool { pub fn is_catchable(&self) -> bool {
match self { match self {
Self::ErrorSystem(_, _) => false, Self::ErrorSystem(_, _) => false,
Self::ErrorParsing(_, _) => unreachable!(), Self::ErrorParsing(_, _) => false,
Self::ErrorFunctionNotFound(_, _) Self::ErrorFunctionNotFound(_, _)
| Self::ErrorInFunctionCall(_, _, _) | Self::ErrorInFunctionCall(_, _, _)
@ -293,14 +300,19 @@ impl EvalAltResult {
| Self::ErrorDataTooLarge(_, _) | Self::ErrorDataTooLarge(_, _)
| Self::ErrorTerminated(_, _) => false, | Self::ErrorTerminated(_, _) => false,
Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(), Self::LoopBreak(_, _) => panic!("EvalAltResult::LoopBreak should not occur naturally"),
Self::Return(_, _) => panic!("EvalAltResult::Return should not occur naturally"),
} }
} }
/// Is this error a system exception? /// Is this error a system exception?
///
/// # Panics
///
/// Panics when [`LoopBreak`][EvalAltResult::LoopBreak] or [`Return`][EvalAltResult::Return].
pub fn is_system_exception(&self) -> bool { pub fn is_system_exception(&self) -> bool {
match self { match self {
Self::ErrorSystem(_, _) => true, Self::ErrorSystem(_, _) => true,
Self::ErrorParsing(_, _) => unreachable!(), Self::ErrorParsing(_, _) => true,
Self::ErrorTooManyOperations(_) Self::ErrorTooManyOperations(_)
| Self::ErrorTooManyModules(_) | Self::ErrorTooManyModules(_)
@ -309,7 +321,8 @@ impl EvalAltResult {
Self::ErrorTerminated(_, _) => true, Self::ErrorTerminated(_, _) => true,
Self::LoopBreak(_, _) | Self::Return(_, _) => unreachable!(), Self::LoopBreak(_, _) => panic!("EvalAltResult::LoopBreak should not occur naturally"),
Self::Return(_, _) => panic!("EvalAltResult::Return should not occur naturally"),
_ => false, _ => false,
} }

View File

@ -283,9 +283,9 @@ impl Serializer for &mut DynamicSerializer {
make_variant(_variant, content) make_variant(_variant, content)
} }
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType( return EvalAltResult::ErrorMismatchDataType(
"Dynamic".into(), "".into(),
"map".into(), "object maps are not supported with 'no_object'".into(),
Position::NONE, Position::NONE,
) )
.into(); .into();
@ -295,9 +295,9 @@ impl Serializer for &mut DynamicSerializer {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
return Ok(DynamicSerializer::new(Array::new().into())); return Ok(DynamicSerializer::new(Array::new().into()));
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
return EvalAltResult::ErrorMismatchOutputType( return EvalAltResult::ErrorMismatchDataType(
"Dynamic".into(), "".into(),
"array".into(), "arrays are not supported with 'no_index'".into(),
Position::NONE, Position::NONE,
) )
.into(); .into();
@ -322,33 +322,28 @@ impl Serializer for &mut DynamicSerializer {
_variant: &'static str, _variant: &'static str,
_len: usize, _len: usize,
) -> Result<Self::SerializeTupleVariant, Box<EvalAltResult>> { ) -> Result<Self::SerializeTupleVariant, Box<EvalAltResult>> {
#[cfg(not(any(feature = "no_object", feature = "no_index")))] #[cfg(not(feature = "no_object"))]
#[cfg(not(feature = "no_index"))]
return Ok(TupleVariantSerializer { return Ok(TupleVariantSerializer {
variant: _variant, variant: _variant,
array: Array::with_capacity(_len), array: Array::with_capacity(_len),
}); });
#[cfg(any(feature = "no_object", feature = "no_index"))] #[cfg(any(feature = "no_object", feature = "no_index"))]
{ return EvalAltResult::ErrorMismatchDataType(
#[cfg(feature = "no_object")] "".into(),
let err_type = "map"; "tuples are not supported with 'no_index' or 'no_object'".into(),
#[cfg(not(feature = "no_object"))]
let err_type = "array";
EvalAltResult::ErrorMismatchOutputType(
"Dynamic".into(),
err_type.into(),
Position::NONE, Position::NONE,
) )
.into() .into();
}
} }
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Box<EvalAltResult>> { fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
return Ok(DynamicSerializer::new(Map::new().into())); return Ok(DynamicSerializer::new(Map::new().into()));
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType( return EvalAltResult::ErrorMismatchDataType(
"Dynamic".into(), "".into(),
"map".into(), "object maps are not supported with 'no_object'".into(),
Position::NONE, Position::NONE,
) )
.into(); .into();
@ -375,9 +370,9 @@ impl Serializer for &mut DynamicSerializer {
map: Map::with_capacity(_len), map: Map::with_capacity(_len),
}); });
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
return EvalAltResult::ErrorMismatchOutputType( return EvalAltResult::ErrorMismatchDataType(
"Dynamic".into(), "".into(),
"map".into(), "object maps are not supported with 'no_object'".into(),
Position::NONE, Position::NONE,
) )
.into(); .into();
@ -400,7 +395,12 @@ impl SerializeSeq for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"arrays are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
// Close the sequence. // Close the sequence.
@ -408,7 +408,12 @@ impl SerializeSeq for DynamicSerializer {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
return Ok(self._value); return Ok(self._value);
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"arrays are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
} }
@ -428,14 +433,24 @@ impl SerializeTuple for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"tuples are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> { fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
return Ok(self._value); return Ok(self._value);
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"tuples are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
} }
@ -455,14 +470,24 @@ impl SerializeTupleStruct for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"tuples are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> { fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
return Ok(self._value); return Ok(self._value);
#[cfg(feature = "no_index")] #[cfg(feature = "no_index")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"tuples are not supported with 'no_index'".into(),
Position::NONE,
)
.into();
} }
} }
@ -477,7 +502,12 @@ impl SerializeMap for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
fn serialize_value<T: ?Sized + Serialize>( fn serialize_value<T: ?Sized + Serialize>(
@ -489,7 +519,7 @@ impl SerializeMap for DynamicSerializer {
let key = crate::stdlib::mem::take(&mut self._key) let key = crate::stdlib::mem::take(&mut self._key)
.take_immutable_string() .take_immutable_string()
.map_err(|typ| { .map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType( EvalAltResult::ErrorMismatchDataType(
"string".into(), "string".into(),
typ.into(), typ.into(),
Position::NONE, Position::NONE,
@ -501,7 +531,12 @@ impl SerializeMap for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
fn serialize_entry<K: ?Sized + Serialize, T: ?Sized + Serialize>( fn serialize_entry<K: ?Sized + Serialize, T: ?Sized + Serialize>(
@ -513,7 +548,7 @@ impl SerializeMap for DynamicSerializer {
{ {
let _key: Dynamic = _key.serialize(&mut *self)?; let _key: Dynamic = _key.serialize(&mut *self)?;
let _key = _key.take_immutable_string().map_err(|typ| { let _key = _key.take_immutable_string().map_err(|typ| {
EvalAltResult::ErrorMismatchOutputType("string".into(), typ.into(), Position::NONE) EvalAltResult::ErrorMismatchDataType("string".into(), typ.into(), Position::NONE)
})?; })?;
let _value = _value.serialize(&mut *self)?; let _value = _value.serialize(&mut *self)?;
let map = self._value.downcast_mut::<Map>().unwrap(); let map = self._value.downcast_mut::<Map>().unwrap();
@ -521,14 +556,24 @@ impl SerializeMap for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> { fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
return Ok(self._value); return Ok(self._value);
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
} }
@ -549,14 +594,24 @@ impl SerializeStruct for DynamicSerializer {
Ok(()) Ok(())
} }
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> { fn end(self) -> Result<Self::Ok, Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
return Ok(self._value); return Ok(self._value);
#[cfg(feature = "no_object")] #[cfg(feature = "no_object")]
unreachable!() return EvalAltResult::ErrorMismatchDataType(
"".into(),
"object maps are not supported with 'no_object'".into(),
Position::NONE,
)
.into();
} }
} }

View File

@ -437,7 +437,7 @@ impl Token {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
As => "as", As => "as",
EOF => "{EOF}", EOF => "{EOF}",
_ => unreachable!("operator should be match in outer scope"), _ => unreachable!("operator should be matched in outer scope"),
} }
.into(), .into(),
} }
@ -837,7 +837,7 @@ pub fn parse_string_literal(
'x' => 2, 'x' => 2,
'u' => 4, 'u' => 4,
'U' => 8, 'U' => 8,
_ => unreachable!(), _ => unreachable!("expecting 'x', 'u' or 'U', but gets {}", ch),
}; };
for _ in 0..len { for _ in 0..len {
@ -1126,14 +1126,14 @@ fn get_next_token_inner(
'x' | 'X' => is_hex_char, 'x' | 'X' => is_hex_char,
'o' | 'O' => is_octal_char, 'o' | 'O' => is_octal_char,
'b' | 'B' => is_binary_char, 'b' | 'B' => is_binary_char,
_ => unreachable!(), _ => unreachable!("expecting 'x', 'o' or 'B', but gets {}", ch),
}; };
radix_base = Some(match ch { radix_base = Some(match ch {
'x' | 'X' => 16, 'x' | 'X' => 16,
'o' | 'O' => 8, 'o' | 'O' => 8,
'b' | 'B' => 2, 'b' | 'B' => 2,
_ => unreachable!(), _ => unreachable!("expecting 'x', 'o' or 'B', but gets {}", ch),
}); });
while let Some(next_char_in_escape_seq) = stream.peek_next() { while let Some(next_char_in_escape_seq) = stream.peek_next() {
@ -1494,8 +1494,6 @@ fn get_next_token_inner(
('$', _) => return Some((Token::Reserved("$".into()), start_pos)), ('$', _) => return Some((Token::Reserved("$".into()), start_pos)),
('\0', _) => unreachable!(),
(ch, _) if ch.is_whitespace() => (), (ch, _) if ch.is_whitespace() => (),
#[cfg(feature = "unicode-xid-ident")] #[cfg(feature = "unicode-xid-ident")]
(ch, _) if unicode_xid::UnicodeXID::is_xid_start(ch) => { (ch, _) if unicode_xid::UnicodeXID::is_xid_start(ch) => {
@ -1749,7 +1747,7 @@ impl<'a> Iterator for TokenIterator<'a, '_> {
Some((Token::Custom(token.syntax().into()), pos)) Some((Token::Custom(token.syntax().into()), pos))
} else { } else {
// Active standard keyword - should never be a custom keyword! // Active standard keyword - should never be a custom keyword!
unreachable!("{:?}", token) unreachable!("{:?} is an active keyword", token)
} }
} }
// Disabled symbol // Disabled symbol