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 // A panic that clears the given lua stack before panicking
macro_rules! lua_panic { macro_rules! lua_panic {
($state:expr) => {
{
$crate::ffi::lua_settor($state, 0);
panic!("rlua internal error");
}
};
($state:expr, $msg:expr) => { ($state:expr, $msg:expr) => {
{ {
$crate::ffi::lua_settop($state, 0); $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); $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 // An assert that clears the given lua stack before panicking
macro_rules! lua_assert { 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) => { ($state:expr, $cond:expr, $msg:expr) => {
if !$cond { if !$cond {
$crate::ffi::lua_settop($state, 0); $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 { if !$cond {
$crate::ffi::lua_settop($state, 0); $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.push_ref(lua.state, &self.0);
lua_assert!( lua_internal_assert!(
lua.state, lua.state,
ffi::lua_getmetatable(lua.state, -1) != 0, ffi::lua_getmetatable(lua.state, -1) != 0,
"AnyUserData missing metatable" "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. // Checks that Lua has enough free stack space for future stack operations.
// On failure, this will clear the stack and panic. // On failure, this will clear the stack and panic.
pub unsafe fn check_stack(state: *mut ffi::lua_State, amount: c_int) { pub unsafe fn check_stack(state: *mut ffi::lua_State, amount: c_int) {
lua_assert!( lua_internal_assert!(
state, state,
ffi::lua_checkstack(state, amount) != 0, ffi::lua_checkstack(state, amount) != 0,
"out of stack space" "out of stack space"
@ -25,7 +25,7 @@ where
F: FnOnce() -> R, F: FnOnce() -> R,
{ {
let expected = ffi::lua_gettop(state) + change; let expected = ffi::lua_gettop(state) + change;
lua_assert!( lua_internal_assert!(
state, state,
expected >= 0, expected >= 0,
"too many stack values would be popped" "too many stack values would be popped"
@ -34,7 +34,7 @@ where
let res = op(); let res = op();
let top = ffi::lua_gettop(state); let top = ffi::lua_gettop(state);
lua_assert!( lua_internal_assert!(
state, state,
ffi::lua_gettop(state) == expected, ffi::lua_gettop(state) == expected,
"expected stack to be {}, got {}", "expected stack to be {}, got {}",
@ -59,7 +59,7 @@ where
F: FnOnce() -> Result<R>, F: FnOnce() -> Result<R>,
{ {
let expected = ffi::lua_gettop(state) + change; let expected = ffi::lua_gettop(state) + change;
lua_assert!( lua_internal_assert!(
state, state,
expected >= 0, expected >= 0,
"too many stack values would be popped" "too many stack values would be popped"
@ -69,7 +69,7 @@ where
let top = ffi::lua_gettop(state); let top = ffi::lua_gettop(state);
if res.is_ok() { if res.is_ok() {
lua_assert!( lua_internal_assert!(
state, state,
ffi::lua_gettop(state) == expected, ffi::lua_gettop(state) == expected,
"expected stack to be {}, got {}", "expected stack to be {}, got {}",
@ -77,7 +77,7 @@ where
top top
); );
} else { } else {
lua_assert!( lua_internal_assert!(
state, state,
top >= expected, top >= expected,
"{} too many stack values popped", "{} 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 // 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. // 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 { pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
lua_assert!( lua_internal_assert!(
state, state,
err_code != ffi::LUA_OK && err_code != ffi::LUA_YIELD, err_code != ffi::LUA_OK && err_code != ffi::LUA_YIELD,
"pop_error called with non-error return code" "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); ffi::lua_settop(state, 0);
resume_unwind(p); resume_unwind(p);
} else { } else {
lua_panic!(state, "panic was resumed twice") lua_internal_panic!(state, "panic was resumed twice")
} }
} else { } else {
let err_string = gc_guard(state, || { 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() process::abort()
} }
ffi::LUA_ERRGCMM => Error::GarbageCollectorError(err_string), 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. // 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 { 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; 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 ud
} }