Better error messages.

This commit is contained in:
Stephen Chung 2021-12-30 12:19:41 +08:00
parent 1fd242ed2c
commit 64bf2eef5c
9 changed files with 74 additions and 64 deletions

View File

@ -469,7 +469,10 @@ impl fmt::Debug for Expr {
Self::Dot(_, _, _) => "Dot", Self::Dot(_, _, _) => "Dot",
Self::And(_, _) => "And", Self::And(_, _) => "And",
Self::Or(_, _) => "Or", Self::Or(_, _) => "Or",
_ => unreachable!(), expr => unreachable!(
"Self::Dot or Self::And or Self::Or expected but gets {:?}",
expr
),
}; };
display_pos = *pos; display_pos = *pos;

View File

@ -480,7 +480,11 @@ impl Stmt {
match self { match self {
Self::Var(_, _, _, _) => true, Self::Var(_, _, _, _) => true,
Self::FnCall(x, _) if x.name == KEYWORD_EVAL => true, Self::Expr(Expr::Stmt(s)) => s.iter().all(Stmt::is_block_dependent),
Self::FnCall(x, _) | Self::Expr(Expr::FnCall(x, _)) => {
x.namespace.is_none() && x.name == KEYWORD_EVAL
}
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Self::Import(_, _, _) | Self::Export(_, _) => true, Self::Import(_, _, _) | Self::Export(_, _) => true,
@ -500,6 +504,8 @@ impl Stmt {
match self { match self {
Self::Var(expr, _, _, _) => expr.is_pure(), Self::Var(expr, _, _, _) => expr.is_pure(),
Self::Expr(Expr::Stmt(s)) => s.iter().all(Stmt::is_internally_pure),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Self::Import(expr, _, _) => expr.is_pure(), Self::Import(expr, _, _) => expr.is_pure(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]

View File

@ -129,7 +129,7 @@ impl ChainArgument {
Self::MethodCallArgs(Some(mut values), pos) => { Self::MethodCallArgs(Some(mut values), pos) => {
(values.iter_mut().map(std::mem::take).collect(), pos) (values.iter_mut().map(std::mem::take).collect(), pos)
} }
_ => unreachable!("`MethodCallArgs` expected"), x => unreachable!("ChainArgument::MethodCallArgs expected but gets {:?}", x),
} }
} }
/// Return the [position][Position]. /// Return the [position][Position].
@ -174,7 +174,7 @@ fn match_chaining_type(expr: &Expr) -> ChainType {
Expr::Index(_, _, _) => ChainType::Indexing, Expr::Index(_, _, _) => ChainType::Indexing,
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Dot(_, _, _) => ChainType::Dotting, Expr::Dot(_, _, _) => ChainType::Dotting,
_ => unreachable!("`expr` should only be `Index` or `Dot`, but got {:?}", expr), expr => unreachable!("Expr::Index or Expr::Dot expected but gets {:?}", expr),
} }
} }
@ -1226,7 +1226,7 @@ impl Engine {
#[cfg(feature = "no_module")] #[cfg(feature = "no_module")]
(_, Some((_, _)), _) => unreachable!("qualified access under no_module"), (_, Some((_, _)), _) => unreachable!("qualified access under no_module"),
}, },
_ => unreachable!("Expr::Variable expected, but gets {:?}", expr), _ => unreachable!("Expr::Variable expected but gets {:?}", expr),
} }
} }
@ -1258,7 +1258,7 @@ impl Engine {
_ if state.always_search_scope => (0, expr.position()), _ if state.always_search_scope => (0, expr.position()),
Expr::Variable(Some(i), pos, _) => (i.get() as usize, *pos), Expr::Variable(Some(i), pos, _) => (i.get() as usize, *pos),
Expr::Variable(None, pos, v) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos), Expr::Variable(None, pos, v) => (v.0.map(NonZeroUsize::get).unwrap_or(0), *pos),
_ => unreachable!("Expr::Variable expected, but gets {:?}", expr), _ => unreachable!("Expr::Variable expected but gets {:?}", expr),
}; };
// Check the variable resolver, if any // Check the variable resolver, if any
@ -1774,7 +1774,7 @@ impl Engine {
Expr::Index(x, term, pos) => (x.as_ref(), ChainType::Indexing, *term, *pos), Expr::Index(x, term, pos) => (x.as_ref(), ChainType::Indexing, *term, *pos),
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Dot(x, term, pos) => (x.as_ref(), ChainType::Dotting, *term, *pos), Expr::Dot(x, term, pos) => (x.as_ref(), ChainType::Dotting, *term, *pos),
_ => unreachable!("index or dot chain expected, but gets {:?}", expr), expr => unreachable!("Expr::Index or Expr::Dot expected but gets {:?}", expr),
}; };
let idx_values = &mut StaticVec::new_const(); let idx_values = &mut StaticVec::new_const();
@ -2123,7 +2123,7 @@ impl Engine {
) )
} }
} else { } else {
unreachable!("`Range` or `RangeInclusive`"); unreachable!("Range or RangeInclusive expected but gets {:?}", idx);
}; };
let field_value = (*value & mask) >> shift; let field_value = (*value & mask) >> shift;
@ -2655,7 +2655,7 @@ impl Engine {
match lhs_expr { match lhs_expr {
// name op= rhs (handled above) // name op= rhs (handled above)
Expr::Variable(_, _, _) => { Expr::Variable(_, _, _) => {
unreachable!("Expr::Variable case should already been handled") unreachable!("Expr::Variable case is already handled")
} }
// idx_lhs[idx_expr] op= rhs // idx_lhs[idx_expr] op= rhs
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]

View File

@ -1334,7 +1334,7 @@ impl Module {
self.all_type_iterators.clear(); self.all_type_iterators.clear();
self.indexed = false; self.indexed = false;
self.contains_indexed_global_functions = false; self.contains_indexed_global_functions = false;
self.interner.merge(&other.interner); self.interner += &other.interner;
self self
} }
@ -1384,7 +1384,7 @@ impl Module {
self.all_type_iterators.clear(); self.all_type_iterators.clear();
self.indexed = false; self.indexed = false;
self.contains_indexed_global_functions = false; self.contains_indexed_global_functions = false;
self.interner.merge(&other.interner); self.interner += &other.interner;
self self
} }

View File

@ -199,7 +199,7 @@ fn optimize_stmt_block(
let stmt = mem::take(&mut second[0]); let stmt = mem::take(&mut second[0]);
let mut stmts = match stmt { let mut stmts = match stmt {
Stmt::Block(block, _) => block, Stmt::Block(block, _) => block,
_ => unreachable!("Stmt::Block expected but gets {:?}", stmt), stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
}; };
statements = first statements = first
.iter_mut() .iter_mut()

View File

@ -771,7 +771,7 @@ pub mod array_functions {
v if v > 0 => Ordering::Greater, v if v > 0 => Ordering::Greater,
v if v < 0 => Ordering::Less, v if v < 0 => Ordering::Less,
0 => Ordering::Equal, 0 => Ordering::Equal,
_ => unreachable!(), _ => unreachable!("v is {}", v),
}) })
.unwrap_or_else(|| x.type_id().cmp(&y.type_id())) .unwrap_or_else(|| x.type_id().cmp(&y.type_id()))
}); });

View File

@ -349,7 +349,7 @@ fn eat_token(input: &mut TokenStream, expected_token: Token) -> Position {
if t != expected_token { if t != expected_token {
unreachable!( unreachable!(
"expecting {} (found {}) at {}", "{} expected but gets {} at {}",
expected_token.syntax(), expected_token.syntax(),
t.syntax(), t.syntax(),
pos pos
@ -1098,7 +1098,7 @@ fn parse_switch(
None None
} }
(None, None) => Some(stmt.into()), (None, None) => Some(stmt.into()),
_ => unreachable!("both hash and range in `switch` statement case"), _ => unreachable!("both hash and range in switch statement case"),
}; };
match input.peek().expect(NEVER_ENDS) { match input.peek().expect(NEVER_ENDS) {
@ -1163,7 +1163,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!(), token => unreachable!("token is {:?}", token),
}, },
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Token::FloatConstant(x) => { Token::FloatConstant(x) => {
@ -1182,7 +1182,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())? {
block @ Stmt::Block(_, _) => Expr::Stmt(Box::new(block.into())), block @ Stmt::Block(_, _) => Expr::Stmt(Box::new(block.into())),
stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt), stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
} }
} }
// ( - grouped expression // ( - grouped expression
@ -1253,16 +1253,17 @@ fn parse_primary(
Token::InterpolatedString(_) => { Token::InterpolatedString(_) => {
let mut segments = StaticVec::<Expr>::new(); let mut segments = StaticVec::<Expr>::new();
if let (Token::InterpolatedString(s), pos) = input.next().expect(NEVER_ENDS) { match input.next().expect(NEVER_ENDS) {
(Token::InterpolatedString(s), pos) => {
segments.push(Expr::StringConstant(s.into(), pos)); segments.push(Expr::StringConstant(s.into(), pos));
} else { }
unreachable!(); token => unreachable!("Token::InterpolatedString expected but gets {:?}", token),
} }
loop { loop {
let expr = match parse_block(input, state, lib, settings.level_up())? { let expr = match parse_block(input, state, lib, settings.level_up())? {
block @ Stmt::Block(_, _) => Expr::Stmt(Box::new(block.into())), block @ Stmt::Block(_, _) => Expr::Stmt(Box::new(block.into())),
stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt), stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
}; };
segments.push(expr); segments.push(expr);
@ -1288,7 +1289,7 @@ fn parse_primary(
return Err(err.into_err(pos)) return Err(err.into_err(pos))
} }
(token, _) => unreachable!( (token, _) => unreachable!(
"expected a string within an interpolated string literal, but gets {:?}", "string within an interpolated string literal expected but gets {:?}",
token token
), ),
} }
@ -1324,7 +1325,7 @@ fn parse_primary(
Token::Identifier(_) => { Token::Identifier(_) => {
let s = match input.next().expect(NEVER_ENDS) { let s = match input.next().expect(NEVER_ENDS) {
(Token::Identifier(s), _) => s, (Token::Identifier(s), _) => s,
_ => unreachable!(), token => unreachable!("Token::Identifier expected but gets {:?}", token),
}; };
match input.peek().expect(NEVER_ENDS).0 { match input.peek().expect(NEVER_ENDS).0 {
@ -1383,7 +1384,7 @@ fn parse_primary(
Token::Reserved(_) => { Token::Reserved(_) => {
let s = match input.next().expect(NEVER_ENDS) { let s = match input.next().expect(NEVER_ENDS) {
(Token::Reserved(s), _) => s, (Token::Reserved(s), _) => s,
_ => unreachable!(), token => unreachable!("Token::Reserved expected but gets {:?}", token),
}; };
match input.peek().expect(NEVER_ENDS).0 { match input.peek().expect(NEVER_ENDS).0 {
@ -1411,7 +1412,7 @@ fn parse_primary(
Token::LexError(_) => match input.next().expect(NEVER_ENDS) { Token::LexError(_) => match input.next().expect(NEVER_ENDS) {
(Token::LexError(err), _) => return Err(err.into_err(settings.pos)), (Token::LexError(err), _) => return Err(err.into_err(settings.pos)),
_ => unreachable!(), token => unreachable!("Token::LexError expected but gets {:?}", token),
}, },
_ => { _ => {
@ -1694,12 +1695,12 @@ fn make_assignment_stmt(
ref e => Some(e.position()), ref e => Some(e.position()),
}, },
Expr::Index(x, term, _) | Expr::Dot(x, term, _) => match x.lhs { Expr::Index(x, term, _) | Expr::Dot(x, term, _) => match x.lhs {
Expr::Property(_) => unreachable!("unexpected `Expr::Property` in indexing"), Expr::Property(_) => unreachable!("unexpected Expr::Property in indexing"),
_ if !term => check_lvalue(&x.rhs, matches!(expr, Expr::Dot(_, _, _))), _ if !term => check_lvalue(&x.rhs, matches!(expr, Expr::Dot(_, _, _))),
_ => None, _ => None,
}, },
Expr::Property(_) if parent_is_dot => None, Expr::Property(_) if parent_is_dot => None,
Expr::Property(_) => unreachable!("unexpected `Expr::Property` in indexing"), Expr::Property(_) => unreachable!("unexpected Expr::Property in indexing"),
e if parent_is_dot => Some(e.position()), e if parent_is_dot => Some(e.position()),
_ => None, _ => None,
} }
@ -1838,7 +1839,7 @@ fn make_dot_expr(
let (x, term, pos, is_dot) = match rhs { let (x, term, pos, is_dot) = match rhs {
Expr::Dot(x, term, pos) => (x, term, pos, true), Expr::Dot(x, term, pos) => (x, term, pos, true),
Expr::Index(x, term, pos) => (x, term, pos, false), Expr::Index(x, term, pos) => (x, term, pos, false),
_ => unreachable!(), expr => unreachable!("Expr::Dot or Expr::Index expected but gets {:?}", expr),
}; };
match x.lhs { match x.lhs {
@ -1877,7 +1878,7 @@ fn make_dot_expr(
}; };
Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)) Ok(Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos))
} }
_ => unreachable!("invalid dot expression: {:?}", x.lhs), expr => unreachable!("invalid dot expression: {:?}", expr),
} }
} }
// lhs.nnn::func(...) // lhs.nnn::func(...)
@ -2162,7 +2163,7 @@ fn parse_custom_syntax(
segments.push(keyword.clone().into()); segments.push(keyword.clone().into());
tokens.push(keyword); tokens.push(keyword);
} }
stmt => unreachable!("expecting Stmt::Block, but gets {:?}", stmt), stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
}, },
CUSTOM_SYNTAX_MARKER_BOOL => match input.next().expect(NEVER_ENDS) { CUSTOM_SYNTAX_MARKER_BOOL => match input.next().expect(NEVER_ENDS) {
(b @ Token::True, pos) | (b @ Token::False, pos) => { (b @ Token::True, pos) | (b @ Token::False, pos) => {
@ -2338,7 +2339,7 @@ fn parse_while_loop(
(expr, pos) (expr, pos)
} }
(Token::Loop, pos) => (Expr::Unit(Position::NONE), pos), (Token::Loop, pos) => (Expr::Unit(Position::NONE), pos),
_ => unreachable!(), token => unreachable!("Token::While or Token::Loop expected but gets {:?}", token),
}; };
settings.pos = token_pos; settings.pos = token_pos;
settings.is_breakable = true; settings.is_breakable = true;
@ -2789,7 +2790,7 @@ fn parse_stmt(
} }
if !crate::tokenizer::is_doc_comment(comment) { if !crate::tokenizer::is_doc_comment(comment) {
unreachable!("expecting doc-comment, but gets {:?}", comment); unreachable!("doc-comment expected but gets {:?}", comment);
} }
if !settings.is_global { if !settings.is_global {
@ -2806,7 +2807,7 @@ fn parse_stmt(
_ => return Err(PERR::WrongDocComment.into_err(comments_pos)), _ => return Err(PERR::WrongDocComment.into_err(comments_pos)),
} }
} }
_ => unreachable!(), token => unreachable!("Token::Comment expected but gets {:?}", token),
} }
} }
@ -2933,14 +2934,15 @@ fn parse_stmt(
let (return_type, token_pos) = input let (return_type, token_pos) = input
.next() .next()
.map(|(token, pos)| { .map(|(token, pos)| {
( let flags = match token {
match token {
Token::Return => AST_OPTION_NONE, Token::Return => AST_OPTION_NONE,
Token::Throw => AST_OPTION_BREAK_OUT, Token::Throw => AST_OPTION_BREAK_OUT,
_ => unreachable!(), token => unreachable!(
}, "Token::Return or Token::Throw expected but gets {:?}",
pos, token
) ),
};
(flags, pos)
}) })
.expect(NEVER_ENDS); .expect(NEVER_ENDS);

View File

@ -250,7 +250,7 @@ impl fmt::Display for Position {
#[cfg(not(feature = "no_position"))] #[cfg(not(feature = "no_position"))]
write!(f, "line {}, position {}", self.line, self.pos)?; write!(f, "line {}, position {}", self.line, self.pos)?;
#[cfg(feature = "no_position")] #[cfg(feature = "no_position")]
unreachable!(); unreachable!("no position");
} }
Ok(()) Ok(())
@ -285,7 +285,7 @@ impl Add for Position {
}, },
}; };
#[cfg(feature = "no_position")] #[cfg(feature = "no_position")]
unreachable!(); unreachable!("no position");
} }
} }
} }
@ -1159,7 +1159,7 @@ pub fn parse_string_literal(
'x' => 2, 'x' => 2,
'u' => 4, 'u' => 4,
'U' => 8, 'U' => 8,
_ => unreachable!(), c => unreachable!("x or u or U expected but gets '{}'", c),
}; };
for _ in 0..len { for _ in 0..len {
@ -1506,14 +1506,14 @@ fn get_next_token_inner(
'x' | 'X' => is_hex_digit, 'x' | 'X' => is_hex_digit,
'o' | 'O' => is_numeric_digit, 'o' | 'O' => is_numeric_digit,
'b' | 'B' => is_numeric_digit, 'b' | 'B' => is_numeric_digit,
_ => unreachable!(), c => unreachable!("x/X or o/O or b/B expected but gets '{}'", c),
}; };
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!(), c => unreachable!("x/X or o/O or b/B expected but gets '{}'", c),
}); });
} }
@ -2238,7 +2238,7 @@ impl<'a> Iterator for TokenIterator<'a> {
(Token::Custom(token.syntax().into()), pos) (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!("`{:?}` is an active keyword", token) unreachable!("{:?} is an active keyword", token)
} }
} }
// Disabled symbol // Disabled symbol

View File

@ -9,6 +9,7 @@ use std::{
any::{type_name, Any, TypeId}, any::{type_name, Any, TypeId},
fmt, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
mem,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
str::FromStr, str::FromStr,
}; };
@ -472,7 +473,7 @@ impl Hash for Dynamic {
/// ///
/// Panics if the [`Dynamic`] value contains an unrecognized trait object. /// Panics if the [`Dynamic`] value contains an unrecognized trait object.
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(&self.0).hash(state); mem::discriminant(&self.0).hash(state);
match self.0 { match self.0 {
Union::Unit(_, _, _) => ().hash(state), Union::Unit(_, _, _) => ().hash(state),
@ -1614,8 +1615,8 @@ impl Dynamic {
pub(crate) fn flatten_in_place(&mut self) -> &mut Self { pub(crate) fn flatten_in_place(&mut self) -> &mut Self {
match self.0 { match self.0 {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Union::Shared(_, _, _) => match std::mem::take(self).0 { Union::Shared(ref mut cell, _, _) => {
Union::Shared(cell, _, _) => { let cell = mem::take(cell);
*self = crate::func::native::shared_try_take(cell).map_or_else( *self = crate::func::native::shared_try_take(cell).map_or_else(
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
|cell| cell.borrow().clone(), |cell| cell.borrow().clone(),
@ -1627,8 +1628,6 @@ impl Dynamic {
|value| value.into_inner().unwrap(), |value| value.into_inner().unwrap(),
); );
} }
_ => unreachable!(),
},
_ => (), _ => (),
} }
self self