diff --git a/CHANGELOG.md b/CHANGELOG.md index 571ec17e..ba6d5d2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Bug fixes * Off-by-one error in character positions after a comment line is now fixed. * Globally-defined constants are now encapsulated correctly inside a loaded module and no longer spill across call boundaries. * Type names display is fixed. +* Exceptions thrown inside function calls now unwrap correctly when `catch`-ed. Script-breaking changes ----------------------- @@ -40,6 +41,7 @@ Enhancements * `AST` position display is improved: * `Expr::start_position` is added to give the beginning of the expression (not the operator's position). * `StmtBlock` and `Stmt::Block` now keep the position of the closing `}` as well. +* `EvalAltResult::unwrap_inner` is added to access the base error inside multiple layers of wrappings (e.g. `EvalAltResult::ErrorInFunction`). REPL tool changes ----------------- diff --git a/src/bin/rhai-dbg.rs b/src/bin/rhai-dbg.rs index d5b9de06..4b289985 100644 --- a/src/bin/rhai-dbg.rs +++ b/src/bin/rhai-dbg.rs @@ -1,5 +1,5 @@ use rhai::debugger::{BreakPoint, DebuggerCommand, DebuggerEvent}; -use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString, Position, Scope}; +use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString, Position, Scope, INT}; use std::{ env, @@ -553,7 +553,16 @@ fn main() { ["throw"] => { break Err(EvalAltResult::ErrorRuntime(Dynamic::UNIT, pos).into()) } - ["throw", _msg, ..] => { + ["throw", num] if num.trim().parse::().is_ok() => { + let value = num.trim().parse::().unwrap().into(); + break Err(EvalAltResult::ErrorRuntime(value, pos).into()); + } + #[cfg(not(feature = "no_float"))] + ["throw", num] if num.trim().parse::().is_ok() => { + let value = num.trim().parse::().unwrap().into(); + break Err(EvalAltResult::ErrorRuntime(value, pos).into()); + } + ["throw", ..] => { let msg = input.trim().splitn(2, ' ').skip(1).next().unwrap_or(""); break Err(EvalAltResult::ErrorRuntime(msg.trim().into(), pos).into()); } diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index d81fc5e0..a06bb742 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -715,8 +715,8 @@ impl Engine { Err(err) if err.is_pseudo_error() => Err(err), Err(err) if !err.is_catchable() => Err(err), Err(mut err) => { - let err_value = match *err { - ERR::ErrorRuntime(ref x, ..) => x.clone(), + let err_value = match err.unwrap_inner() { + ERR::ErrorRuntime(x, ..) => x.clone(), #[cfg(feature = "no_object")] _ => { diff --git a/src/types/error.rs b/src/types/error.rs index e79d7ec8..32d3195b 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -403,6 +403,16 @@ impl EvalAltResult { } }; } + /// Unwrap this error and get the very base error. + #[must_use] + pub fn unwrap_inner(&self) -> &Self { + match self { + Self::ErrorInFunctionCall(.., err, _) | Self::ErrorInModule(.., err, _) => { + err.unwrap_inner() + } + _ => self, + } + } /// Get the [position][Position] of this error. #[must_use] pub const fn position(&self) -> Position {