Don't panic with "rlua internal error" message on panics that are not internal

It is part of the contract that only LuaRef types constructed from the same
parent Lua state are passed into Lua, so generating a panic there is not an
internal error.
This commit is contained in:
kyren 2018-02-07 17:05:00 -05:00
parent b9d9bea28a
commit 164250b352
3 changed files with 37 additions and 31 deletions

View File

@ -6,48 +6,54 @@ macro_rules! cstr {
// A panic that clears the given lua stack before panicking
macro_rules! lua_panic {
($state:expr) => {
{
$crate::ffi::lua_settor($state, 0);
panic!("rlua internal error");
}
};
($state:expr, $msg:expr) => {
{
$crate::ffi::lua_settop($state, 0);
panic!(concat!("rlua internal error: ", $msg));
panic!($msg);
}
};
($state:expr, $fmt:expr, $($arg:tt)+) => {
($state:expr, $msg:expr, $($arg:tt)+) => {
{
$crate::ffi::lua_settop($state, 0);
panic!(concat!("rlua internal error: ", $fmt), $($arg)+);
panic!($msg, $($arg)+);
}
};
}
// An assert that clears the given lua stack before panicking
macro_rules! lua_assert {
($state:expr, $cond:expr) => {
if !$cond {
$crate::ffi::lua_settop($state, 0);
panic!("rlua internal error");
}
};
($state:expr, $cond:expr, $msg:expr) => {
if !$cond {
$crate::ffi::lua_settop($state, 0);
panic!(concat!("rlua internal error: ", $msg));
panic!($msg);
}
};
($state:expr, $cond:expr, $fmt:expr, $($arg:tt)+) => {
($state:expr, $cond:expr, $msg:expr, $($arg:tt)+) => {
if !$cond {
$crate::ffi::lua_settop($state, 0);
panic!(concat!("rlua internal error: ", $fmt), $($arg)+);
panic!($msg, $($arg)+);
}
};
}
macro_rules! lua_internal_panic {
($state:expr, $msg:expr) => {
lua_panic!($state, concat!("rlua internal error: ", $msg));
};
($state:expr, $msg:expr, $($arg:tt)+) => {
lua_panic!($state, concat!("rlua internal error: ", $msg), $($arg)+);
};
}
macro_rules! lua_internal_assert {
($state:expr, $cond:expr, $msg:expr) => {
lua_assert!($state, $cond, concat!("rlua internal error: ", $msg));
};
($state:expr, $cond:expr, $msg:expr, $($arg:tt)+) => {
lua_assert!($state, $cond, concat!("rlua internal error: ", $msg), $($arg)+);
};
}

View File

@ -370,7 +370,7 @@ impl<'lua> AnyUserData<'lua> {
lua.push_ref(lua.state, &self.0);
lua_assert!(
lua_internal_assert!(
lua.state,
ffi::lua_getmetatable(lua.state, -1) != 0,
"AnyUserData missing metatable"

View File

@ -11,7 +11,7 @@ use error::{Error, Result};
// Checks that Lua has enough free stack space for future stack operations.
// On failure, this will clear the stack and panic.
pub unsafe fn check_stack(state: *mut ffi::lua_State, amount: c_int) {
lua_assert!(
lua_internal_assert!(
state,
ffi::lua_checkstack(state, amount) != 0,
"out of stack space"
@ -25,7 +25,7 @@ where
F: FnOnce() -> R,
{
let expected = ffi::lua_gettop(state) + change;
lua_assert!(
lua_internal_assert!(
state,
expected >= 0,
"too many stack values would be popped"
@ -34,7 +34,7 @@ where
let res = op();
let top = ffi::lua_gettop(state);
lua_assert!(
lua_internal_assert!(
state,
ffi::lua_gettop(state) == expected,
"expected stack to be {}, got {}",
@ -59,7 +59,7 @@ where
F: FnOnce() -> Result<R>,
{
let expected = ffi::lua_gettop(state) + change;
lua_assert!(
lua_internal_assert!(
state,
expected >= 0,
"too many stack values would be popped"
@ -69,7 +69,7 @@ where
let top = ffi::lua_gettop(state);
if res.is_ok() {
lua_assert!(
lua_internal_assert!(
state,
ffi::lua_gettop(state) == expected,
"expected stack to be {}, got {}",
@ -77,7 +77,7 @@ where
top
);
} else {
lua_assert!(
lua_internal_assert!(
state,
top >= expected,
"{} too many stack values popped",
@ -171,7 +171,7 @@ where
// the current lua stack and continues the panic. If the error on the top of the stack is actually
// a WrappedError, just returns it. Otherwise, interprets the error as the appropriate lua error.
pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
lua_assert!(
lua_internal_assert!(
state,
err_code != ffi::LUA_OK && err_code != ffi::LUA_YIELD,
"pop_error called with non-error return code"
@ -185,7 +185,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
ffi::lua_settop(state, 0);
resume_unwind(p);
} else {
lua_panic!(state, "panic was resumed twice")
lua_internal_panic!(state, "panic was resumed twice")
}
} else {
let err_string = gc_guard(state, || {
@ -221,7 +221,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
process::abort()
}
ffi::LUA_ERRGCMM => Error::GarbageCollectorError(err_string),
_ => lua_panic!(state, "unrecognized lua error code"),
_ => lua_internal_panic!(state, "unrecognized lua error code"),
}
}
}
@ -244,7 +244,7 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
// Returns None in the case that the userdata has already been garbage collected.
pub unsafe fn get_userdata<T>(state: *mut ffi::lua_State, index: c_int) -> *mut T {
let ud = ffi::lua_touserdata(state, index) as *mut T;
lua_assert!(state, !ud.is_null(), "userdata pointer is null");
lua_internal_assert!(state, !ud.is_null(), "userdata pointer is null");
ud
}