From 164250b352b5d08b94e107823ac0f53fded5d454 Mon Sep 17 00:00:00 2001 From: kyren Date: Wed, 7 Feb 2018 17:05:00 -0500 Subject: [PATCH] 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. --- src/macros.rs | 46 ++++++++++++++++++++++++++-------------------- src/userdata.rs | 2 +- src/util.rs | 20 ++++++++++---------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 1408384..929e2d7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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)+); + }; +} diff --git a/src/userdata.rs b/src/userdata.rs index 536c853..8c7a92f 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -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" diff --git a/src/util.rs b/src/util.rs index aba6ba6..9789d02 100644 --- a/src/util.rs +++ b/src/util.rs @@ -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, { 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(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(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 }