Don't panic on mismatched `RegistryKey` use, instead return error
This commit is contained in:
parent
823c2deaca
commit
b056ed2c4e
|
@ -87,6 +87,8 @@ pub enum Error {
|
||||||
/// [`AnyUserData`]: struct.AnyUserData.html
|
/// [`AnyUserData`]: struct.AnyUserData.html
|
||||||
/// [`UserData`]: trait.UserData.html
|
/// [`UserData`]: trait.UserData.html
|
||||||
UserDataBorrowMutError,
|
UserDataBorrowMutError,
|
||||||
|
/// A `RegistryKey` produced from a different Lua state was used.
|
||||||
|
MismatchedRegistryKey,
|
||||||
/// A Rust callback returned `Err`, raising the contained `Error` as a Lua error.
|
/// A Rust callback returned `Err`, raising the contained `Error` as a Lua error.
|
||||||
CallbackError {
|
CallbackError {
|
||||||
/// Lua call stack backtrace.
|
/// Lua call stack backtrace.
|
||||||
|
@ -142,6 +144,9 @@ impl fmt::Display for Error {
|
||||||
Error::UserDataTypeMismatch => write!(fmt, "userdata is not expected type"),
|
Error::UserDataTypeMismatch => write!(fmt, "userdata is not expected type"),
|
||||||
Error::UserDataBorrowError => write!(fmt, "userdata already mutably borrowed"),
|
Error::UserDataBorrowError => write!(fmt, "userdata already mutably borrowed"),
|
||||||
Error::UserDataBorrowMutError => write!(fmt, "userdata already borrowed"),
|
Error::UserDataBorrowMutError => write!(fmt, "userdata already borrowed"),
|
||||||
|
Error::MismatchedRegistryKey => {
|
||||||
|
write!(fmt, "RegistryKey used from different Lua state")
|
||||||
|
}
|
||||||
Error::CallbackError { ref traceback, .. } => {
|
Error::CallbackError { ref traceback, .. } => {
|
||||||
write!(fmt, "callback error: {}", traceback)
|
write!(fmt, "callback error: {}", traceback)
|
||||||
}
|
}
|
||||||
|
|
24
src/lua.rs
24
src/lua.rs
|
@ -504,11 +504,9 @@ impl Lua {
|
||||||
/// value previously placed by `create_registry_value`.
|
/// value previously placed by `create_registry_value`.
|
||||||
pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result<T> {
|
pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
lua_assert!(
|
if !Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list) {
|
||||||
self.state,
|
return Err(Error::MismatchedRegistryKey);
|
||||||
Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list),
|
}
|
||||||
"Lua instance passed RegistryKey created from a different Lua"
|
|
||||||
);
|
|
||||||
|
|
||||||
stack_err_guard(self.state, 0, || {
|
stack_err_guard(self.state, 0, || {
|
||||||
check_stack(self.state, 1);
|
check_stack(self.state, 1);
|
||||||
|
@ -528,25 +526,25 @@ impl Lua {
|
||||||
/// `create_registry_value`. In addition to manual `RegistryKey` removal, you can also call
|
/// `create_registry_value`. In addition to manual `RegistryKey` removal, you can also call
|
||||||
/// `expire_registry_values` to automatically remove values from the registry whose
|
/// `expire_registry_values` to automatically remove values from the registry whose
|
||||||
/// `RegistryKey`s have been dropped.
|
/// `RegistryKey`s have been dropped.
|
||||||
pub fn remove_registry_value(&self, mut key: RegistryKey) {
|
pub fn remove_registry_value(&self, mut key: RegistryKey) -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
lua_assert!(
|
if !Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list) {
|
||||||
self.state,
|
return Err(Error::MismatchedRegistryKey);
|
||||||
Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list),
|
}
|
||||||
"Lua instance passed RegistryKey created from a different Lua"
|
|
||||||
);
|
|
||||||
|
|
||||||
ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, key.registry_id);
|
ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, key.registry_id);
|
||||||
// Don't adding to the registry drop list when dropping the key
|
// Don't adding to the registry drop list when dropping the key
|
||||||
key.registry_id = ffi::LUA_REFNIL;
|
key.registry_id = ffi::LUA_REFNIL;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the given `RegistryKey` was created by a `Lua` which shares the underlying
|
/// Returns true if the given `RegistryKey` was created by a `Lua` which shares the underlying
|
||||||
/// main state with this `Lua` instance.
|
/// main state with this `Lua` instance.
|
||||||
///
|
///
|
||||||
/// Other than this, methods that accept a `RegistryKey` will panic if passed a `RegistryKey`
|
/// Other than this, methods that accept a `RegistryKey` will return
|
||||||
/// that was not created with a matching `Lua` state.
|
/// `Error::MismatchedRegistryKey` if passed a `RegistryKey` that was not created with a
|
||||||
|
/// matching `Lua` state.
|
||||||
pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
|
pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
|
||||||
unsafe { Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list) }
|
unsafe { Arc::ptr_eq(&key.drop_list, &(*self.extra()).registry_drop_list) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,13 +586,15 @@ fn test_lua_registry_ownership() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
|
||||||
fn test_mismatched_registry_key() {
|
fn test_mismatched_registry_key() {
|
||||||
let lua1 = Lua::new();
|
let lua1 = Lua::new();
|
||||||
let lua2 = Lua::new();
|
let lua2 = Lua::new();
|
||||||
|
|
||||||
let r = lua1.create_registry_value("hello").unwrap();
|
let r = lua1.create_registry_value("hello").unwrap();
|
||||||
lua2.remove_registry_value(r);
|
match lua2.remove_registry_value(r) {
|
||||||
|
Err(Error::MismatchedRegistryKey) => {}
|
||||||
|
r => panic!("wrong result type for mismatched registry key, {:?}", r),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Need to use compiletest-rs or similar to make sure these don't compile.
|
// TODO: Need to use compiletest-rs or similar to make sure these don't compile.
|
||||||
|
|
Loading…
Reference in New Issue