summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--README.md2
-rw-r--r--src/function.rs60
-rw-r--r--src/hook.rs18
-rw-r--r--src/lua.rs653
-rw-r--r--src/luau.rs10
-rw-r--r--src/scope.rs62
-rw-r--r--src/serde/ser.rs13
-rw-r--r--src/string.rs7
-rw-r--r--src/table.rs140
-rw-r--r--src/thread.rs73
-rw-r--r--src/types.rs20
-rw-r--r--src/userdata.rs71
-rw-r--r--src/userdata_impl.rs52
-rw-r--r--src/value.rs8
15 files changed, 656 insertions, 534 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e471c0e..cffce2c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -73,6 +73,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
maplit = "1.0"
tempfile = "3"
+static_assertions = "1.0"
[[bench]]
name = "benchmark"
diff --git a/README.md b/README.md
index 211da8b..d6e946a 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[docs.rs]: https://docs.rs/mlua
[Coverage Status]: https://codecov.io/gh/khvzak/mlua/branch/master/graph/badge.svg?token=99339FS1CG
[codecov.io]: https://codecov.io/gh/khvzak/mlua
-[MSRV]: https://img.shields.io/badge/rust-1.56+-brightgreen.svg?&logo=rust
+[MSRV]: https://img.shields.io/badge/rust-1.63+-brightgreen.svg?&logo=rust
[Guided Tour] | [Benchmarks] | [FAQ]
diff --git a/src/function.rs b/src/function.rs
index a981007..d5edda4 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -95,31 +95,32 @@ impl<'lua> Function<'lua> {
/// ```
pub fn call<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(&self, args: A) -> Result<R> {
let lua = self.0.lua;
+ let state = lua.state();
let mut args = args.to_lua_multi(lua)?;
let nargs = args.len() as c_int;
let results = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, nargs + 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, nargs + 3)?;
- ffi::lua_pushcfunction(lua.state, error_traceback);
- let stack_start = ffi::lua_gettop(lua.state);
+ ffi::lua_pushcfunction(state, error_traceback);
+ let stack_start = ffi::lua_gettop(state);
lua.push_ref(&self.0);
for arg in args.drain_all() {
lua.push_value(arg)?;
}
- let ret = ffi::lua_pcall(lua.state, nargs, ffi::LUA_MULTRET, stack_start);
+ let ret = ffi::lua_pcall(state, nargs, ffi::LUA_MULTRET, stack_start);
if ret != ffi::LUA_OK {
- return Err(pop_error(lua.state, ret));
+ return Err(pop_error(state, ret));
}
- let nresults = ffi::lua_gettop(lua.state) - stack_start;
+ let nresults = ffi::lua_gettop(state) - stack_start;
let mut results = args; // Reuse MultiValue container
- assert_stack(lua.state, 2);
+ assert_stack(state, 2);
for _ in 0..nresults {
results.push_front(lua.pop_value());
}
- ffi::lua_pop(lua.state, 1);
+ ffi::lua_pop(state, 1);
results
};
R::from_lua_multi(results, lua)
@@ -217,6 +218,7 @@ impl<'lua> Function<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
let args = args.to_lua_multi(lua)?;
let nargs = args.len() as c_int;
@@ -230,14 +232,14 @@ impl<'lua> Function<'lua> {
}
let args_wrapper = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, nargs + 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, nargs + 3)?;
- ffi::lua_pushinteger(lua.state, nargs as ffi::lua_Integer);
+ ffi::lua_pushinteger(state, nargs as ffi::lua_Integer);
for arg in args {
lua.push_value(arg)?;
}
- protect_lua!(lua.state, nargs + 1, 1, fn(state) {
+ protect_lua!(state, nargs + 1, 1, fn(state) {
ffi::lua_pushcclosure(state, args_wrapper_impl, ffi::lua_gettop(state));
})?;
@@ -264,16 +266,17 @@ impl<'lua> Function<'lua> {
/// [`lua_getinfo`]: https://www.lua.org/manual/5.4/manual.html#lua_getinfo
pub fn info(&self) -> FunctionInfo {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 1);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 1);
let mut ar: ffi::lua_Debug = mem::zeroed();
lua.push_ref(&self.0);
#[cfg(not(feature = "luau"))]
- let res = ffi::lua_getinfo(lua.state, cstr!(">Sn"), &mut ar);
+ let res = ffi::lua_getinfo(state, cstr!(">Sn"), &mut ar);
#[cfg(feature = "luau")]
- let res = ffi::lua_getinfo(lua.state, -1, cstr!("sn"), &mut ar);
+ let res = ffi::lua_getinfo(state, -1, cstr!("sn"), &mut ar);
mlua_assert!(res != 0, "lua_getinfo failed with `>Sn`");
FunctionInfo {
@@ -319,15 +322,16 @@ impl<'lua> Function<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
let mut data: Vec<u8> = Vec::new();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 1);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 1);
lua.push_ref(&self.0);
let data_ptr = &mut data as *mut Vec<u8> as *mut c_void;
- ffi::lua_dump(lua.state, writer, data_ptr, strip as i32);
- ffi::lua_pop(lua.state, 1);
+ ffi::lua_dump(state, writer, data_ptr, strip as i32);
+ ffi::lua_pop(state, 1);
}
data
@@ -375,13 +379,14 @@ impl<'lua> Function<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 1);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 1);
lua.push_ref(&self.0);
let func_ptr = &mut func as *mut F as *mut c_void;
- ffi::lua_getcoverage(lua.state, -1, func_ptr, callback::<F>);
+ ffi::lua_getcoverage(state, -1, func_ptr, callback::<F>);
}
}
@@ -397,3 +402,10 @@ impl<'lua> PartialEq for Function<'lua> {
self.0 == other.0
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(Function: Send);
+}
diff --git a/src/hook.rs b/src/hook.rs
index f52fec3..6a0d233 100644
--- a/src/hook.rs
+++ b/src/hook.rs
@@ -67,12 +67,12 @@ impl<'lua> Debug<'lua> {
unsafe {
#[cfg(not(feature = "luau"))]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, cstr!("n"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), cstr!("n"), self.ar.get()) != 0,
"lua_getinfo failed with `n`"
);
#[cfg(feature = "luau")]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, self.level, cstr!("n"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), self.level, cstr!("n"), self.ar.get()) != 0,
"lua_getinfo failed with `n`"
);
@@ -91,12 +91,12 @@ impl<'lua> Debug<'lua> {
unsafe {
#[cfg(not(feature = "luau"))]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, cstr!("S"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), cstr!("S"), self.ar.get()) != 0,
"lua_getinfo failed with `S`"
);
#[cfg(feature = "luau")]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, self.level, cstr!("s"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), self.level, cstr!("s"), self.ar.get()) != 0,
"lua_getinfo failed with `s`"
);
@@ -119,12 +119,12 @@ impl<'lua> Debug<'lua> {
unsafe {
#[cfg(not(feature = "luau"))]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, cstr!("l"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), cstr!("l"), self.ar.get()) != 0,
"lua_getinfo failed with `l`"
);
#[cfg(feature = "luau")]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, self.level, cstr!("l"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), self.level, cstr!("l"), self.ar.get()) != 0,
"lua_getinfo failed with `l`"
);
@@ -139,7 +139,7 @@ impl<'lua> Debug<'lua> {
pub fn is_tail_call(&self) -> bool {
unsafe {
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, cstr!("t"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), cstr!("t"), self.ar.get()) != 0,
"lua_getinfo failed with `t`"
);
(*self.ar.get()).currentline != 0
@@ -151,12 +151,12 @@ impl<'lua> Debug<'lua> {
unsafe {
#[cfg(not(feature = "luau"))]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, cstr!("u"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), cstr!("u"), self.ar.get()) != 0,
"lua_getinfo failed with `u`"
);
#[cfg(feature = "luau")]
mlua_assert!(
- ffi::lua_getinfo(self.lua.state, self.level, cstr!("a"), self.ar.get()) != 0,
+ ffi::lua_getinfo(self.lua.state(), self.level, cstr!("a"), self.ar.get()) != 0,
"lua_getinfo failed with `a`"
);
diff --git a/src/lua.rs b/src/lua.rs
index 9fe9843..86473eb 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -5,10 +5,11 @@ use std::ffi::{CStr, CString};
use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
-use std::ops::{Deref, DerefMut};
+use std::ops::Deref;
use std::os::raw::{c_char, c_int, c_void};
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe, Location};
use std::ptr::NonNull;
+use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::{Arc, Mutex};
use std::{mem, ptr, str};
@@ -67,24 +68,20 @@ use serde::Serialize;
/// Top level Lua struct which represents an instance of Lua VM.
#[repr(transparent)]
-pub struct Lua(Arc<UnsafeCell<LuaInner>>);
+pub struct Lua(Arc<LuaInner>);
/// An inner Lua struct which holds a raw Lua state.
pub struct LuaInner {
- pub(crate) state: *mut ffi::lua_State,
+ // The state is dynamic and depends on context
+ state: AtomicPtr<ffi::lua_State>,
main_state: *mut ffi::lua_State,
extra: Arc<UnsafeCell<ExtraData>>,
- safe: bool,
- #[cfg(feature = "luau")]
- compiler: Option<Compiler>,
- // Lua has lots of interior mutability, should not be RefUnwindSafe
- _no_ref_unwind_safe: PhantomData<UnsafeCell<()>>,
}
// Data associated with the Lua.
pub(crate) struct ExtraData {
// Same layout as `Lua`
- inner: Option<ManuallyDrop<Arc<UnsafeCell<LuaInner>>>>,
+ inner: Option<ManuallyDrop<Arc<LuaInner>>>,
registered_userdata: FxHashMap<TypeId, c_int>,
registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
@@ -97,6 +94,7 @@ pub(crate) struct ExtraData {
#[cfg(feature = "send")]
app_data: RefCell<HashMap<TypeId, Box<dyn Any + Send>>>,
+ safe: bool,
libs: StdLib,
mem_info: Option<NonNull<MemoryInfo>>,
@@ -129,6 +127,8 @@ pub(crate) struct ExtraData {
#[cfg(feature = "luau")]
sandboxed: bool,
+ #[cfg(feature = "luau")]
+ compiler: Option<Compiler>,
}
#[derive(Default)]
@@ -256,10 +256,7 @@ impl Drop for LuaInner {
}
#[cfg(feature = "luau")]
{
- let callbacks = ffi::lua_callbacks(self.state);
- let extra_ptr = (*callbacks).userdata as *mut Arc<UnsafeCell<ExtraData>>;
- drop(Box::from_raw(extra_ptr));
- (*callbacks).userdata = ptr::null_mut();
+ (*ffi::lua_callbacks(self.state())).userdata = ptr::null_mut();
}
mlua_debug_assert!(
ffi::lua_gettop(extra.ref_thread) == extra.ref_stack_top
@@ -287,21 +284,16 @@ impl Drop for ExtraData {
impl fmt::Debug for Lua {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Lua({:p})", self.state)
+ write!(f, "Lua({:p})", self.state())
}
}
impl Deref for Lua {
type Target = LuaInner;
+ #[inline]
fn deref(&self) -> &Self::Target {
- unsafe { &*(*self.0).get() }
- }
-}
-
-impl DerefMut for Lua {
- fn deref_mut(&mut self) -> &mut Self::Target {
- unsafe { &mut *(*self.0).get() }
+ &self.0
}
}
@@ -319,7 +311,7 @@ impl Lua {
pub fn new() -> Lua {
mlua_expect!(
Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
- "can't create new safe Lua state"
+ "Cannot create new safe Lua state"
)
}
@@ -346,25 +338,23 @@ impl Lua {
#[cfg(not(feature = "luau"))]
if libs.contains(StdLib::DEBUG) {
return Err(Error::SafetyError(
- "the unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
+ "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
));
}
#[cfg(feature = "luajit")]
- {
- if libs.contains(StdLib::FFI) {
- return Err(Error::SafetyError(
- "the unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
- ));
- }
+ if libs.contains(StdLib::FFI) {
+ return Err(Error::SafetyError(
+ "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
+ ));
}
- let mut lua = unsafe { Self::inner_new(libs, options) };
+ let lua = unsafe { Self::inner_new(libs, options) };
#[cfg(not(feature = "luau"))]
if libs.contains(StdLib::PACKAGE) {
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
}
- lua.safe = true;
+ unsafe { (*lua.extra.get()).safe = true };
Ok(lua)
}
@@ -383,6 +373,7 @@ impl Lua {
Self::inner_new(libs, options)
}
+ /// Creates a new Lua state with required `libs` and `options`
unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
unsafe extern "C" fn allocator(
extra_data: *mut c_void,
@@ -464,30 +455,29 @@ impl Lua {
ffi::lua_pop(state, 1);
let lua = Lua::init_from_ptr(state);
- let extra = &mut *lua.extra.get();
- extra.mem_info = NonNull::new(mem_info);
+ (*lua.extra.get()).mem_info = NonNull::new(mem_info);
mlua_expect!(
load_from_std_lib(state, libs),
"Error during loading standard libraries"
);
- extra.libs |= libs;
+ (*lua.extra.get()).libs |= libs;
if !options.catch_rust_panics {
mlua_expect!(
(|| -> Result<()> {
- let _sg = StackGuard::new(lua.state);
+ let _sg = StackGuard::new(state);
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
- ffi::lua_rawgeti(lua.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
+ ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
- ffi::lua_pushvalue(lua.state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
- ffi::lua_pushcfunction(lua.state, safe_pcall);
- rawset_field(lua.state, -2, "pcall")?;
+ ffi::lua_pushcfunction(state, safe_pcall);
+ rawset_field(state, -2, "pcall")?;
- ffi::lua_pushcfunction(lua.state, safe_xpcall);
- rawset_field(lua.state, -2, "xpcall")?;
+ ffi::lua_pushcfunction(state, safe_xpcall);
+ rawset_field(state, -2, "xpcall")?;
Ok(())
})(),
@@ -497,7 +487,8 @@ impl Lua {
#[cfg(feature = "async")]
if options.thread_cache_size > 0 {
- extra.recycled_thread_cache = Vec::with_capacity(options.thread_cache_size);
+ (*lua.extra.get()).recycled_thread_cache =
+ Vec::with_capacity(options.thread_cache_size);
}
#[cfg(feature = "luau")]
@@ -513,13 +504,13 @@ impl Lua {
#[allow(clippy::missing_safety_doc)]
pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
assert!(!state.is_null(), "Lua state is NULL");
- let main_state = get_main_state(state).unwrap_or(state);
- let main_state_top = ffi::lua_gettop(main_state);
-
- if let Some(lua) = Lua::make_from_ptr(state) {
+ if let Some(lua) = Lua::try_from_ptr(state) {
return lua;
}
+ let main_state = get_main_state(state).unwrap_or(state);
+ let main_state_top = ffi::lua_gettop(main_state);
+
mlua_expect!(
(|state| {
init_error_registry(state)?;
@@ -550,7 +541,7 @@ impl Lua {
// Create ref stack thread and place it in the registry to prevent it from being garbage
// collected.
let ref_thread = mlua_expect!(
- protect_lua!(state, 0, 0, |state| {
+ protect_lua!(main_state, 0, 0, |state| {
let thread = ffi::lua_newthread(state);
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX);
thread
@@ -559,9 +550,9 @@ impl Lua {
);
let wrapped_failure_mt_ptr = {
- get_gc_metatable::<WrappedFailure>(state);
- let ptr = ffi::lua_topointer(state, -1);
- ffi::lua_pop(state, 1);
+ get_gc_metatable::<WrappedFailure>(main_state);
+ let ptr = ffi::lua_topointer(main_state, -1);
+ ffi::lua_pop(main_state, 1);
ptr
};
@@ -577,16 +568,16 @@ impl Lua {
let ref_stack_top = ffi::lua_gettop(ref_thread);
// Create ExtraData
-
let extra = Arc::new(UnsafeCell::new(ExtraData {
inner: None,
registered_userdata: FxHashMap::default(),
registered_userdata_mt: FxHashMap::default(),
registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),
app_data: RefCell::new(HashMap::new()),
- ref_thread,
+ safe: false,
libs: StdLib::NONE,
mem_info: None,
+ ref_thread,
// We need 1 extra stack space to move values in and out of the ref stack.
ref_stack_size: ffi::LUA_MINSTACK - 1,
ref_stack_top,
@@ -606,8 +597,11 @@ impl Lua {
interrupt_callback: None,
#[cfg(feature = "luau")]
sandboxed: false,
+ #[cfg(feature = "luau")]
+ compiler: None,
}));
+ // Store it in the registry
mlua_expect!(
(|state| {
push_gc_userdata(state, Arc::clone(&extra), true)?;
@@ -638,19 +632,14 @@ impl Lua {
// We can use global callbacks userdata since we don't allow C modules in Luau
#[cfg(feature = "luau")]
{
- let extra_raw = Box::into_raw(Box::new(Arc::clone(&extra)));
- (*ffi::lua_callbacks(main_state)).userdata = extra_raw as *mut c_void;
+ (*ffi::lua_callbacks(main_state)).userdata = extra.get() as *mut c_void;
}
- let inner = Arc::new(UnsafeCell::new(LuaInner {
- state,
+ let inner = Arc::new(LuaInner {
+ state: AtomicPtr::new(state),
main_state,
extra: Arc::clone(&extra),
- safe: false,
- #[cfg(feature = "luau")]
- compiler: None,
- _no_ref_unwind_safe: PhantomData,
- }));
+ });
(*extra.get()).inner = Some(ManuallyDrop::new(Arc::clone(&inner)));
#[cfg(not(feature = "module"))]
@@ -666,32 +655,32 @@ impl Lua {
/// [`StdLib`]: crate::StdLib
pub fn load_from_std_lib(&self, libs: StdLib) -> Result<()> {
#[cfg(not(feature = "luau"))]
- if self.safe && libs.contains(StdLib::DEBUG) {
+ let is_safe = unsafe { (*self.extra.get()).safe };
+
+ #[cfg(not(feature = "luau"))]
+ if is_safe && libs.contains(StdLib::DEBUG) {
return Err(Error::SafetyError(
"the unsafe `debug` module can't be loaded in safe mode".to_string(),
));
}
#[cfg(feature = "luajit")]
- {
- if self.safe && libs.contains(StdLib::FFI) {
- return Err(Error::SafetyError(
- "the unsafe `ffi` module can't be loaded in safe mode".to_string(),
- ));
- }
+ if is_safe && libs.contains(StdLib::FFI) {
+ return Err(Error::SafetyError(
+ "the unsafe `ffi` module can't be loaded in safe mode".to_string(),
+ ));
}
let res = unsafe { load_from_std_lib(self.main_state, libs) };
// If `package` library loaded into a safe lua state then disable C modules
- let extra = unsafe { &mut *self.extra.get() };
#[cfg(not(feature = "luau"))]
{
- let curr_libs = extra.libs;
- if self.safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
+ let curr_libs = unsafe { (*self.extra.get()).libs };
+ if is_safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
mlua_expect!(self.disable_c_modules(), "Error during disabling C modules");
}
}
- extra.libs |= libs;
+ unsafe { (*self.extra.get()).libs |= libs };
res
}
@@ -715,10 +704,11 @@ impl Lua {
where
T: FromLua<'lua>,
{
+ let state = self.state();
let loaded = unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 2)?;
- protect_lua!(self.state, 0, 1, fn(state) {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
+ protect_lua!(state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
Table(self.pop_ref())
@@ -747,10 +737,11 @@ impl Lua {
///
/// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
pub fn unload(&self, modname: &str) -> Result<()> {
+ let state = self.state();
let loaded = unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 2)?;
- protect_lua!(self.state, 0, 1, fn(state) {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
+ protect_lua!(state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
Table(self.pop_ref())
@@ -798,8 +789,9 @@ impl Lua {
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
{
let entrypoint_inner = |lua: &'lua Lua, func: F| {
- let nargs = ffi::lua_gettop(lua.state);
- check_stack(lua.state, 3)?;
+ let state = lua.state();
+ let nargs = ffi::lua_gettop(state);
+ check_stack(state, 3)?;
let mut args = MultiValue::new();
args.reserve(nargs as usize);
@@ -822,7 +814,7 @@ impl Lua {
}
Err(err) => {
self.push_value(Value::Error(err))?;
- let state = self.state;
+ let state = self.state();
// Lua (self) must be dropped before triggering longjmp
drop(self);
ffi::lua_error(state)
@@ -873,8 +865,7 @@ impl Lua {
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn sandbox(&self, enabled: bool) -> Result<()> {
unsafe {
- let extra = &mut *self.extra.get();
- if extra.sandboxed != enabled {
+ if (*self.extra.get()).sandboxed != enabled {
let state = self.main_state;
check_stack(state, 3)?;
protect_lua!(state, 0, 0, |state| {
@@ -888,7 +879,7 @@ impl Lua {
ffi::luaL_sandbox(state, 0);
}
})?;
- extra.sandboxed = enabled;
+ (*self.extra.get()).sandboxed = enabled;
}
Ok(())
}
@@ -934,14 +925,14 @@ impl Lua {
F: 'static + MaybeSend + Fn(&Lua, Debug) -> Result<()>,
{
unsafe extern "C" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
- let lua = match Lua::make_from_ptr(state) {
+ let lua = match Lua::try_from_ptr(state) {
Some(lua) => lua,
None => return,
};
let extra = lua.extra.get();
callback_error_ext(state, extra, move |_| {
let debug = Debug::new(&lua, ar);
- let hook_cb = (*lua.extra.get()).hook_callback.clone();
+ let hook_cb = (*extra).hook_callback.clone();
let hook_cb = mlua_expect!(hook_cb, "no hook callback set in hook_proc");
if Arc::strong_count(&hook_cb) > 2 {
return Ok(()); // Don't allow recursion
@@ -1028,10 +1019,10 @@ impl Lua {
// We don't support GC interrupts since they cannot survive Lua exceptions
return;
}
- let extra = match extra_data(state) {
- Some(e) => e.get(),
- None => return,
- };
+ let extra = extra_data(state);
+ if extra.is_null() {
+ return;
+ }
let result = callback_error_ext(state, extra, move |_| {
let interrupt_cb = (*extra).interrupt_callback.clone();
let interrupt_cb =
@@ -1077,15 +1068,11 @@ impl Lua {
F: 'static + MaybeSend + Fn(&Lua, &CStr, bool) -> Result<()>,
{
unsafe extern "C" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
- let state = ud as *mut ffi::lua_State;
- let lua = match Lua::make_from_ptr(state) {
- Some(lua) => lua,
- None => return,
- };
- let extra = lua.extra.get();
- callback_error_ext(state, extra, move |_| {
+ let extra = ud as *mut ExtraData;
+ let lua: &Lua = mem::transmute((*extra).inner.as_ref().unwrap());
+ callback_error_ext(lua.state(), extra, |_| {
let cb = mlua_expect!(
- (*lua.extra.get()).warn_callback.as_ref(),
+ (*extra).warn_callback.as_ref(),
"no warning callback set in warn_proc"
);
let msg = CStr::from_ptr(msg);
@@ -1096,7 +1083,7 @@ impl Lua {
let state = self.main_state;
unsafe {
(*self.extra.get()).warn_callback = Some(Box::new(callback));
- ffi::lua_setwarnf(state, Some(warn_proc), state as *mut c_void);
+ ffi::lua_setwarnf(state, Some(warn_proc), self.extra.get() as *mut c_void);
}
}
@@ -1123,7 +1110,7 @@ impl Lua {
#[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
pub fn warning<S: Into<Vec<u8>>>(&self, msg: S, tocont: bool) -> Result<()> {
let msg = CString::new(msg).map_err(|err| Error::RuntimeError(err.to_string()))?;
- unsafe { ffi::lua_warning(self.state, msg.as_ptr(), tocont as c_int) };
+ unsafe { ffi::lua_warning(self.state(), msg.as_ptr(), tocont as c_int) };
Ok(())
}
@@ -1139,11 +1126,11 @@ impl Lua {
let mut ar: ffi::lua_Debug = mem::zeroed();
let level = level as c_int;
#[cfg(not(feature = "luau"))]
- if ffi::lua_getstack(self.state, level, &mut ar) == 0 {
+ if ffi::lua_getstack(self.state(), level, &mut ar) == 0 {
return None;
}
#[cfg(feature = "luau")]
- if ffi::lua_getinfo(self.state, level, cstr!(""), &mut ar) == 0 {
+ if ffi::lua_getinfo(self.state(), level, cstr!(""), &mut ar) == 0 {
return None;
}
Some(Debug::new_owned(self, level, ar))
@@ -1350,7 +1337,7 @@ impl Lua {
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
pub fn set_compiler(&self, compiler: Compiler) {
- unsafe { (*self.0.get()).compiler = Some(compiler) };
+ unsafe { (*self.extra.get()).compiler = Some(compiler) };
}
/// Returns Lua source code as a `Chunk` builder type.
@@ -1375,7 +1362,7 @@ impl Lua {
env: chunk.env(self),
mode: chunk.mode(),
#[cfg(feature = "luau")]
- compiler: self.compiler.clone(),
+ compiler: unsafe { (*self.extra.get()).compiler.clone() },
}
}
@@ -1386,9 +1373,10 @@ impl Lua {
env: Option<Value<'lua>>,
mode: Option<ChunkMode>,
) -> Result<Function<'lua>> {
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 1)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1)?;
let mode_str = match mode {
Some(ChunkMode::Binary) => cstr!("b"),
@@ -1397,7 +1385,7 @@ impl Lua {
};
match ffi::luaL_loadbufferx(
- self.state,
+ state,
source.as_ptr() as *const c_char,
source.len(),
name.map(|n| n.as_ptr()).unwrap_or_else(ptr::null),
@@ -1407,13 +1395,13 @@ impl Lua {
if let Some(env) = env {
self.push_value(env)?;
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
- ffi::lua_setupvalue(self.state, -2, 1);
+ ffi::lua_setupvalue(state, -2, 1);
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
- ffi::lua_setfenv(self.state, -2);
+ ffi::lua_setfenv(state, -2);
}
Ok(Function(self.pop_ref()))
}
- err => Err(pop_error(self.state, err)),
+ err => Err(pop_error(state, err)),
}
}
}
@@ -1422,16 +1410,16 @@ impl Lua {
/// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]`
/// here.
pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
+ let state = self.state();
unsafe {
if self.unlikely_memory_error() {
push_string(self.ref_thread(), s.as_ref(), false)?;
return Ok(String(self.pop_ref_thread()));
}
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 3)?;
-
- push_string(self.state, s.as_ref(), true)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
+ push_string(state, s.as_ref(), true)?;
Ok(String(self.pop_ref()))
}
}
@@ -1446,16 +1434,16 @@ impl Lua {
/// `nrec` is a hint for how many other elements the table will have.
/// Lua may use these hints to preallocate memory for the new table.
pub fn create_table_with_capacity(&self, narr: c_int, nrec: c_int) -> Result<Table> {
+ let state = self.state();
unsafe {
if self.unlikely_memory_error() {
push_table(self.ref_thread(), narr, nrec, false)?;
return Ok(Table(self.pop_ref_thread()));
}
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 3)?;
-
- push_table(self.state, narr, nrec, true)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
+ push_table(state, narr, nrec, true)?;
Ok(Table(self.pop_ref()))
}
}
@@ -1467,21 +1455,22 @@ impl Lua {
V: ToLua<'lua>,
I: IntoIterator<Item = (K, V)>,
{
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 6)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 6)?;
let iter = iter.into_iter();
let lower_bound = iter.size_hint().0;
let protect = !self.unlikely_memory_error();
- push_table(self.state, 0, lower_bound as c_int, protect)?;
+ push_table(state, 0, lower_bound as c_int, protect)?;
for (k, v) in iter {
self.push_value(k.to_lua(self)?)?;
self.push_value(v.to_lua(self)?)?;
if protect {
- protect_lua!(self.state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
+ protect_lua!(state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
} else {
- ffi::lua_rawset(self.state, -3);
+ ffi::lua_rawset(state, -3);
}
}
@@ -1495,22 +1484,23 @@ impl Lua {
T: ToLua<'lua>,
I: IntoIterator<Item = T>,
{
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
let iter = iter.into_iter();
let lower_bound = iter.size_hint().0;
let protect = !self.unlikely_memory_error();
- push_table(self.state, lower_bound as c_int, 0, protect)?;
+ push_table(state, lower_bound as c_int, 0, protect)?;
for (i, v) in iter.enumerate() {
self.push_value(v.to_lua(self)?)?;
if protect {
- protect_lua!(self.state, 2, 1, |state| {
+ protect_lua!(state, 2, 1, |state| {
ffi::lua_rawseti(state, -2, (i + 1) as Integer);
})?;
} else {
- ffi::lua_rawseti(self.state, -2, (i + 1) as Integer);
+ ffi::lua_rawseti(state, -2, (i + 1) as Integer);
}
}
@@ -1599,8 +1589,9 @@ impl Lua {
/// # Safety
/// This function is unsafe because provides a way to execute unsafe C function.
pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
- check_stack(self.state, 1)?;
- ffi::lua_pushcfunction(self.state, func);
+ let state = self.state();
+ check_stack(state, 1)?;
+ ffi::lua_pushcfunction(state, func);
Ok(Function(self.pop_ref()))
}
@@ -1666,17 +1657,18 @@ impl Lua {
///
/// Equivalent to `coroutine.create`.
pub fn create_thread<'lua>(&'lua self, func: Function<'lua>) -> Result<Thread<'lua>> {
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
let thread_state = if self.unlikely_memory_error() {
- ffi::lua_newthread(self.state)
+ ffi::lua_newthread(state)
} else {
- protect_lua!(self.state, 0, 1, |state| ffi::lua_newthread(state))?
+ protect_lua!(state, 0, 1, |state| ffi::lua_newthread(state))?
};
self.push_ref(&func.0);
- ffi::lua_xmove(self.state, thread_state, 1);
+ ffi::lua_xmove(state, thread_state, 1);
Ok(Thread(self.pop_ref()))
}
@@ -1694,19 +1686,20 @@ impl Lua {
feature = "luau",
))]
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 1)?;
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1)?;
- let extra = &mut *self.extra.get();
- if let Some(index) = extra.recycled_thread_cache.pop() {
- let thread_state = ffi::lua_tothread(extra.ref_thread, index);
+ if let Some(index) = (*self.extra.get()).recycled_thread_cache.pop() {
+ let ref_thread = (*self.extra.get()).ref_thread;
+ let thread_state = ffi::lua_tothread(ref_thread, index);
self.push_ref(&func.0);
- ffi::lua_xmove(self.state, thread_state, 1);
+ ffi::lua_xmove(state, thread_state, 1);
#[cfg(feature = "luau")]
{
// Inherit `LUA_GLOBALSINDEX` from the caller
- ffi::lua_xpush(self.state, thread_state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
}
@@ -1735,7 +1728,7 @@ impl Lua {
ffi::lua_settop(thread_state, 0);
}
#[cfg(all(feature = "luajit", feature = "vendored"))]
- ffi::lua_resetthread(self.state, thread_state);
+ ffi::lua_resetthread(self.state(), thread_state);
#[cfg(feature = "luau")]
ffi::lua_resetthread(thread_state);
extra.recycled_thread_cache.push(thread.0.index);
@@ -1811,13 +1804,14 @@ impl Lua {
/// Returns a handle to the global environment.
pub fn globals(&self) -> Table {
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- assert_stack(self.state, 1);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 1);
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
- ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
+ ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
- ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
Table(self.pop_ref())
}
}
@@ -1825,10 +1819,11 @@ impl Lua {
/// Returns a handle to the active `Thread`. For calls to `Lua` this will be the main Lua thread,
/// for parameters given to a callback, this will be whatever Lua thread called the callback.
pub fn current_thread(&self) -> Thread {
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- assert_stack(self.state, 1);
- ffi::lua_pushthread(self.state);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 1);
+ ffi::lua_pushthread(state);
Thread(self.pop_ref())
}
}
@@ -1892,14 +1887,15 @@ impl Lua {
Ok(match v {
Value::String(s) => Some(s),
v => unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 4)?;
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
self.push_value(v)?;
let res = if self.unlikely_memory_error() {
- ffi::lua_tolstring(self.state, -1, ptr::null_mut())
+ ffi::lua_tolstring(state, -1, ptr::null_mut())
} else {
- protect_lua!(self.state, 1, 1, |state| {
+ protect_lua!(state, 1, 1, |state| {
ffi::lua_tolstring(state, -1, ptr::null_mut())
})?
};
@@ -1922,12 +1918,13 @@ impl Lua {
Ok(match v {
Value::Integer(i) => Some(i),
v => unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 2)?;
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
self.push_value(v)?;
let mut isint = 0;
- let i = ffi::lua_tointegerx(self.state, -1, &mut isint);
+ let i = ffi::lua_tointegerx(state, -1, &mut isint);
if isint == 0 {
None
} else {
@@ -1946,12 +1943,13 @@ impl Lua {
Ok(match v {
Value::Number(n) => Some(n),
v => unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 2)?;
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
self.push_value(v)?;
let mut isnum = 0;
- let n = ffi::lua_tonumberx(self.state, -1, &mut isnum);
+ let n = ffi::lua_tonumberx(state, -1, &mut isnum);
if isnum == 0 {
None
} else {
@@ -1992,13 +1990,14 @@ impl Lua {
where
T: ToLua<'lua>,
{
+ let state = self.state();
let t = t.to_lua(self)?;
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
self.push_value(t)?;
- rawset_field(self.state, ffi::LUA_REGISTRYINDEX, name)
+ rawset_field(state, ffi::LUA_REGISTRYINDEX, name)
}
}
@@ -2012,13 +2011,14 @@ impl Lua {
where
T: FromLua<'lua>,
{
+ let state = self.state();
let value = unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
let protect = !self.unlikely_memory_error();
- push_string(self.state, name.as_bytes(), protect)?;
- ffi::lua_rawget(self.state, ffi::LUA_REGISTRYINDEX);
+ push_string(state, name.as_bytes(), protect)?;
+ ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
self.pop_value()
};
@@ -2052,9 +2052,10 @@ impl Lua {
return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
}
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
let unref_list = (*self.extra.get()).registry_unref_list.clone();
self.push_value(t)?;
@@ -2064,12 +2065,12 @@ impl Lua {
let mut unref_list2 = mlua_expect!(unref_list2.lock(), "unref list poisoned");
if let Some(registry_id) = unref_list2.as_mut().and_then(|x| x.pop()) {
// It must be safe to replace the value without triggering memory error
- ffi::lua_rawseti(self.state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
+ ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
return Ok(RegistryKey::new(registry_id, unref_list));
}
// Allocate a new RegistryKey
- let registry_id = protect_lua!(self.state, 1, 0, |state| {
+ let registry_id = protect_lua!(state, 1, 0, |state| {
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
})?;
Ok(RegistryKey::new(registry_id, unref_list))
@@ -2087,14 +2088,15 @@ impl Lua {
return Err(Error::MismatchedRegistryKey);
}
+ let state = self.state();
let value = match key.is_nil() {
true => Value::Nil,
false => unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 1)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1)?;
let id = key.registry_id as Integer;
- ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, id);
+ ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, id);
self.pop_value()
},
};
@@ -2114,8 +2116,9 @@ impl Lua {
if !self.owns_registry_value(&key) {
return Err(Error::MismatchedRegistryKey);
}
+
unsafe {
- ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, key.take());
+ ffi::luaL_unref(self.state(), ffi::LUA_REGISTRYINDEX, key.take());
}
Ok(())
}
@@ -2144,9 +2147,10 @@ impl Lua {
return Err(Error::RuntimeError(err));
}
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let id = key.registry_id as Integer;
if t == Value::Nil {
@@ -2157,7 +2161,7 @@ impl Lua {
key.set_nil(false);
}
// It must be safe to replace the value without triggering memory error
- ffi::lua_rawseti(self.state, ffi::LUA_REGISTRYINDEX, id);
+ ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, id);
}
Ok(())
}
@@ -2179,6 +2183,7 @@ impl Lua {
/// but you can call this method to remove any unreachable registry values not manually removed
/// by `Lua::remove_registry_value`.
pub fn expire_registry_values(&self) {
+ let state = self.state();
unsafe {
let mut unref_list = mlua_expect!(
(*self.extra.get()).registry_unref_list.lock(),
@@ -2186,7 +2191,7 @@ impl Lua {
);
let unref_list = mem::replace(&mut *unref_list, Some(Vec::new()));
for id in mlua_expect!(unref_list, "unref list not set") {
- ffi::luaL_unref(self.state, ffi::LUA_REGISTRYINDEX, id);
+ ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
}
}
}
@@ -2219,7 +2224,7 @@ impl Lua {
/// ```
#[track_caller]
pub fn set_app_data<T: 'static + MaybeSend>(&self, data: T) {
- let extra = unsafe { &mut (*self.extra.get()) };
+ let extra = unsafe { &*self.extra.get() };
extra
.app_data
.try_borrow_mut()
@@ -2230,19 +2235,21 @@ impl Lua {
/// Gets a reference to an application data object stored by [`Lua::set_app_data()`] of type `T`.
#[track_caller]
pub fn app_data_ref<T: 'static>(&self) -> Option<Ref<T>> {
- let extra = unsafe { &(*self.extra.get()) };
+ let extra = unsafe { &*self.extra.get() };
let app_data = extra
.app_data
.try_borrow()
.expect("cannot borrow app data container");
- let value = app_data.get(&TypeId::of::<T>())?.downcast_ref::<T>()? as *const _;
- Some(Ref::map(app_data, |_| unsafe { &*value }))
+ Ref::filter_map(app_data, |data| {
+ data.get(&TypeId::of::<T>())?.downcast_ref::<T>()
+ })
+ .ok()
}
/// Gets a mutable reference to an application data object stored by [`Lua::set_app_data()`] of type `T`.
#[track_caller]
pub fn app_data_mut<T: 'static>(&self) -> Option<RefMut<T>> {
- let extra = unsafe { &(*self.extra.get()) };
+ let extra = unsafe { &*self.extra.get() };
let mut app_data = extra
.app_data
.try_borrow_mut()
@@ -2254,41 +2261,42 @@ impl Lua {
/// Removes an application data of type `T`.
#[track_caller]
pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
- let extra = unsafe { &mut (*self.extra.get()) };
+ let extra = unsafe { &*self.extra.get() };
extra
.app_data
.try_borrow_mut()
.expect("cannot mutably borrow app data container")
.remove(&TypeId::of::<T>())
- .and_then(|data| data.downcast().ok().map(|data| *data))
+ .and_then(|data| data.downcast().ok().map(|data: Box<T>| *data))
}
// Uses 2 stack spaces, does not call checkstack
pub(crate) unsafe fn push_value(&self, value: Value) -> Result<()> {
+ let state = self.state();
match value {
Value::Nil => {
- ffi::lua_pushnil(self.state);
+ ffi::lua_pushnil(state);
}
Value::Boolean(b) => {
- ffi::lua_pushboolean(self.state, b as c_int);
+ ffi::lua_pushboolean(state, b as c_int);
}
Value::LightUserData(ud) => {
- ffi::lua_pushlightuserdata(self.state, ud.0);
+ ffi::lua_pushlightuserdata(state, ud.0);
}
Value::Integer(i) => {
- ffi::lua_pushinteger(self.state, i);
+ ffi::lua_pushinteger(state, i);
}
Value::Number(n) => {
- ffi::lua_pushnumber(self.state, n);
+ ffi::lua_pushnumber(state, n);
}
#[cfg(feature = "luau")]
Value::Vector(x, y, z) => {
- ffi::lua_pushvector(self.state, x, y, z);
+ ffi::lua_pushvector(state, x, y, z);
}
Value::String(s) => {
@@ -2313,7 +2321,7 @@ impl Lua {
Value::Error(err) => {
let protect = !self.unlikely_memory_error();
- push_gc_userdata(self.state, WrappedFailure::Error(err), protect)?;
+ push_gc_userdata(state, WrappedFailure::Error(err), protect)?;
}
}
@@ -2322,9 +2330,7 @@ impl Lua {
// Uses 2 stack spaces, does not call checkstack
pub(crate) unsafe fn pop_value(&self) -> Value {
- let state = self.state;
- let extra = &mut *self.extra.get();
-
+ let state = self.state();
match ffi::lua_type(state, -1) {
ffi::LUA_TNIL => {
ffi::lua_pop(state, 1);
@@ -2385,7 +2391,7 @@ impl Lua {
ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
ffi::LUA_TUSERDATA => {
- let wrapped_failure_mt_ptr = extra.wrapped_failure_mt_ptr;
+ let wrapped_failure_mt_ptr = (*self.extra.get()).wrapped_failure_mt_ptr;
// We must prevent interaction with userdata types other than UserData OR a WrappedError.
// WrappedPanics are automatically resumed.
match get_gc_userdata::<WrappedFailure>(state, -1, wrapped_failure_mt_ptr).as_mut()
@@ -2427,8 +2433,7 @@ impl Lua {
Arc::ptr_eq(&lref.lua.0, &self.0),
"Lua instance passed Value created from a different main Lua state"
);
- let extra = &*self.extra.get();
- ffi::lua_xpush(extra.ref_thread, self.state, lref.index);
+ ffi::lua_xpush(self.ref_thread(), self.state(), lref.index);
}
// Pops the topmost element of the stack and stores a reference to it. This pins the object,
@@ -2441,34 +2446,31 @@ impl Lua {
// number of short term references being created, and `RegistryKey` being used for long term
// references.
pub(crate) unsafe fn pop_ref(&self) -> LuaRef {
- let extra = &mut *self.extra.get();
- ffi::lua_xmove(self.state, extra.ref_thread, 1);
- let index = ref_stack_pop(extra);
+ ffi::lua_xmove(self.state(), self.ref_thread(), 1);
+ let index = ref_stack_pop(&mut *self.extra.get());
LuaRef::new(self, index)
}
// Same as `pop_ref` but assumes the value is already on the reference thread
pub(crate) unsafe fn pop_ref_thread(&self) -> LuaRef {
- let extra = &mut *self.extra.get();
- let index = ref_stack_pop(extra);
+ let index = ref_stack_pop(&mut *self.extra.get());
LuaRef::new(self, index)
}
- pub(crate) fn clone_ref<'lua>(&'lua self, lref: &LuaRef<'lua>) -> LuaRef<'lua> {
+ pub(crate) fn clone_ref(&self, lref: &LuaRef) -> LuaRef {
unsafe {
- let extra = &mut *self.extra.get();
- ffi::lua_pushvalue(extra.ref_thread, lref.index);
- let index = ref_stack_pop(extra);
+ ffi::lua_pushvalue(self.ref_thread(), lref.index);
+ let index = ref_stack_pop(&mut *self.extra.get());
LuaRef::new(self, index)
}
}
pub(crate) fn drop_ref(&self, lref: &LuaRef) {
unsafe {
- let extra = &mut *self.extra.get();
- ffi::lua_pushnil(extra.ref_thread);
- ffi::lua_replace(extra.ref_thread, lref.index);
- extra.ref_free.push(lref.index);
+ let ref_thread = self.ref_thread();
+ ffi::lua_pushnil(ref_thread);
+ ffi::lua_replace(ref_thread, lref.index);
+ (*self.extra.get()).ref_free.push(lref.index);
}
}
@@ -2495,17 +2497,17 @@ impl Lua {
LuaRef::new(self, index)
}
- unsafe fn push_userdata_metatable<T: 'static + UserData>(&self) -> Result<()> {
- let extra = &mut *self.extra.get();
+ unsafe fn push_userdata_metatable<T: UserData + 'static>(&self) -> Result<()> {
+ let state = self.state();
let type_id = TypeId::of::<T>();
- if let Some(&table_id) = extra.registered_userdata.get(&type_id) {
- ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, table_id as Integer);
+ if let Some(&table_id) = (*self.extra.get()).registered_userdata.get(&type_id) {
+ ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, table_id as Integer);
return Ok(());
}
- let _sg = StackGuard::new_extra(self.state, 1);
- check_stack(self.state, 13)?;
+ let _sg = StackGuard::new_extra(state, 1);
+ check_stack(state, 13)?;
let mut fields = StaticUserDataFields::default();
let mut methods = StaticUserDataMethods::default();
@@ -2516,45 +2518,45 @@ impl Lua {
let metatable_nrec = methods.meta_methods.len() + fields.meta_fields.len();
#[cfg(feature = "async")]
let metatable_nrec = metatable_nrec + methods.async_meta_methods.len();
- push_table(self.state, 0, metatable_nrec as c_int, true)?;
+ push_table(state, 0, metatable_nrec as c_int, true)?;
for (k, m) in methods.meta_methods {
self.push_value(Value::Function(self.create_callback(m)?))?;
- rawset_field(self.state, -2, k.validate()?.name())?;
+ rawset_field(state, -2, k.validate()?.name())?;
}
#[cfg(feature = "async")]
for (k, m) in methods.async_meta_methods {
self.push_value(Value::Function(self.create_async_callback(m)?))?;
- rawset_field(self.state, -2, k.validate()?.name())?;
+ rawset_field(state, -2, k.validate()?.name())?;
}
for (k, f) in fields.meta_fields {
self.push_value(f(self)?)?;
- rawset_field(self.state, -2, k.validate()?.name())?;
+ rawset_field(state, -2, k.validate()?.name())?;
}
- let metatable_index = ffi::lua_absindex(self.state, -1);
+ let metatable_index = ffi::lua_absindex(state, -1);
let mut extra_tables_count = 0;
let mut field_getters_index = None;
let field_getters_nrec = fields.field_getters.len();
if field_getters_nrec > 0 {
- push_table(self.state, 0, field_getters_nrec as c_int, true)?;
+ push_table(state, 0, field_getters_nrec as c_int, true)?;
for (k, m) in fields.field_getters {
self.push_value(Value::Function(self.create_callback(m)?))?;
- rawset_field(self.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- field_getters_index = Some(ffi::lua_absindex(self.state, -1));
+ field_getters_index = Some(ffi::lua_absindex(state, -1));
extra_tables_count += 1;
}
let mut field_setters_index = None;
let field_setters_nrec = fields.field_setters.len();
if field_setters_nrec > 0 {
- push_table(self.state, 0, field_setters_nrec as c_int, true)?;
+ push_table(state, 0, field_setters_nrec as c_int, true)?;
for (k, m) in fields.field_setters {
self.push_value(Value::Function(self.create_callback(m)?))?;
- rawset_field(self.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- field_setters_index = Some(ffi::lua_absindex(self.state, -1));
+ field_setters_index = Some(ffi::lua_absindex(state, -1));
extra_tables_count += 1;
}
@@ -2563,22 +2565,22 @@ impl Lua {
#[cfg(feature = "async")]
let methods_nrec = methods_nrec + methods.async_methods.len();
if methods_nrec > 0 {
- push_table(self.state, 0, methods_nrec as c_int, true)?;
+ push_table(state, 0, methods_nrec as c_int, true)?;
for (k, m) in methods.methods {
self.push_value(Value::Function(self.create_callback(m)?))?;
- rawset_field(self.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
#[cfg(feature = "async")]
for (k, m) in methods.async_methods {
self.push_value(Value::Function(self.create_async_callback(m)?))?;
- rawset_field(self.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- methods_index = Some(ffi::lua_absindex(self.state, -1));
+ methods_index = Some(ffi::lua_absindex(state, -1));
extra_tables_count += 1;
}
init_userdata_metatable::<UserDataCell<T>>(
- self.state,
+ state,
metatable_index,
field_getters_index,
field_setters_index,
@@ -2586,29 +2588,34 @@ impl Lua {
)?;
// Pop extra tables to get metatable on top of the stack
- ffi::lua_pop(self.state, extra_tables_count);
+ ffi::lua_pop(state, extra_tables_count);
- let mt_ptr = ffi::lua_topointer(self.state, -1);
- ffi::lua_pushvalue(self.state, -1);
- let id = protect_lua!(self.state, 1, 0, |state| {
+ let mt_ptr = ffi::lua_topointer(state, -1);
+ ffi::lua_pushvalue(state, -1);
+ let id = protect_lua!(state, 1, 0, |state| {
ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
})?;
- extra.registered_userdata.insert(type_id, id);
- extra.registered_userdata_mt.insert(mt_ptr, Some(type_id));
+ (*self.extra.get()).registered_userdata.insert(type_id, id);
+ (*self.extra.get())
+ .registered_userdata_mt
+ .insert(mt_ptr, Some(type_id));
Ok(())
}
+ #[inline]
pub(crate) unsafe fn register_userdata_metatable(
&self,
ptr: *const c_void,
type_id: Option<TypeId>,
) {
- let extra = &mut *self.extra.get();
- extra.registered_userdata_mt.insert(ptr, type_id);
+ (*self.extra.get())
+ .registered_userdata_mt
+ .insert(ptr, type_id);
}
+ #[inline]
pub(crate) unsafe fn deregister_userdata_metatable(&self, ptr: *const c_void) {
(*self.extra.get()).registered_userdata_mt.remove(&ptr);
}
@@ -2617,16 +2624,16 @@ impl Lua {
// and not destructed UserData.
// Uses 2 stack spaces, does not call checkstack.
pub(crate) unsafe fn push_userdata_ref(&self, lref: &LuaRef) -> Result<Option<TypeId>> {
+ let state = self.state();
self.push_ref(lref);
- if ffi::lua_getmetatable(self.state, -1) == 0 {
- ffi::lua_pop(self.state, 1);
+ if ffi::lua_getmetatable(state, -1) == 0 {
+ ffi::lua_pop(state, 1);
return Err(Error::UserDataTypeMismatch);
}
- let mt_ptr = ffi::lua_topointer(self.state, -1);
- ffi::lua_pop(self.state, 1);
+ let mt_ptr = ffi::lua_topointer(state, -1);
+ ffi::lua_pop(state, 1);
- let extra = &*self.extra.get();
- match extra.registered_userdata_mt.get(&mt_ptr) {
+ match (*self.extra.get()).registered_userdata_mt.get(&mt_ptr) {
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdata>()) => {
Err(Error::UserDataDestructed)
}
@@ -2667,7 +2674,7 @@ impl Lua {
}
let lua: &Lua = mem::transmute((*extra).inner.as_ref().unwrap());
- let _guard = StateGuard::new(&mut *lua.0.get(), state);
+ let _guard = StateGuard::new(&lua.0, state);
let mut args = MultiValue::new_or_cached(lua);
args.reserve(nargs as usize);
@@ -2689,20 +2696,21 @@ impl Lua {
})
}
+ let state = self.state();
unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
let func = mem::transmute(func);
let extra = Arc::clone(&self.extra);
let protect = !self.unlikely_memory_error();
- push_gc_userdata(self.state, CallbackUpvalue { data: func, extra }, protect)?;
+ push_gc_userdata(state, CallbackUpvalue { data: func, extra }, protect)?;
if protect {
- protect_lua!(self.state, 1, 1, fn(state) {
+ protect_lua!(state, 1, 1, fn(state) {
ffi::lua_pushcclosure(state, call_callback, 1);
})?;
} else {
- ffi::lua_pushcclosure(self.state, call_callback, 1);
+ ffi::lua_pushcclosure(state, call_callback, 1);
}
Ok(Function(self.pop_ref()))
@@ -2721,9 +2729,9 @@ impl Lua {
feature = "luau"
))]
unsafe {
- let libs = (*self.extra.get()).libs;
- if !libs.contains(StdLib::COROUTINE) {
- self.load_from_std_lib(StdLib::COROUTINE)?;
+ if !(*self.extra.get()).libs.contains(StdLib::COROUTINE) {
+ load_from_std_lib(self.main_state, StdLib::COROUTINE)?;
+ (*self.extra.get()).libs |= StdLib::COROUTINE;
}
}
@@ -2748,7 +2756,7 @@ impl Lua {
}
let lua: &Lua = mem::transmute((*extra).inner.as_ref().unwrap());
- let _guard = StateGuard::new(&mut *lua.0.get(), state);
+ let _guard = StateGuard::new(&lua.0, state);
let mut args = MultiValue::new_or_cached(lua);
args.reserve(nargs as usize);
@@ -2793,7 +2801,7 @@ impl Lua {
}
let lua: &Lua = mem::transmute((*extra).inner.as_ref().unwrap());
- let _guard = StateGuard::new(&mut *lua.0.get(), state);
+ let _guard = StateGuard::new(&lua.0, state);
// Try to get an outer poll waker
let waker = lua.waker().unwrap_or_else(noop_waker);
@@ -2820,21 +2828,22 @@ impl Lua {
})
}
+ let state = self.state();
let get_poll = unsafe {
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
let func = mem::transmute(func);
let extra = Arc::clone(&self.extra);
let protect = !self.unlikely_memory_error();
let upvalue = AsyncCallbackUpvalue { data: func, extra };
- push_gc_userdata(self.state, upvalue, protect)?;
+ push_gc_userdata(state, upvalue, protect)?;
if protect {
- protect_lua!(self.state, 1, 1, fn(state) {
+ protect_lua!(state, 1, 1, fn(state) {
ffi::lua_pushcclosure(state, call_callback, 1);
})?;
} else {
- ffi::lua_pushcclosure(self.state, call_callback, 1);
+ ffi::lua_pushcclosure(state, call_callback, 1);
}
Function(self.pop_ref())
@@ -2901,32 +2910,33 @@ impl Lua {
pub(crate) unsafe fn make_userdata<T>(&self, data: UserDataCell<T>) -> Result<AnyUserData>
where
- T: 'static + UserData,
+ T: UserData + 'static,
{
- let _sg = StackGuard::new(self.state);
- check_stack(self.state, 3)?;
+ let state = self.state();
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
// We push metatable first to ensure having correct metatable with `__gc` method
- ffi::lua_pushnil(self.state);
+ ffi::lua_pushnil(state);
self.push_userdata_metatable::<T>()?;
let protect = !self.unlikely_memory_error();
#[cfg(not(feature = "lua54"))]
- push_userdata(self.state, data, protect)?;
+ push_userdata(state, data, protect)?;
#[cfg(feature = "lua54")]
- push_userdata_uv(self.state, data, USER_VALUE_MAXSLOT as c_int, protect)?;
- ffi::lua_replace(self.state, -3);
- ffi::lua_setmetatable(self.state, -2);
+ push_userdata_uv(state, data, USER_VALUE_MAXSLOT as c_int, protect)?;
+ ffi::lua_replace(state, -3);
+ ffi::lua_setmetatable(state, -2);
// Set empty environment for Lua 5.1
#[cfg(any(feature = "lua51", feature = "luajit"))]
if protect {
- protect_lua!(self.state, 1, 1, fn(state) {
+ protect_lua!(state, 1, 1, fn(state) {
ffi::lua_newtable(state);
ffi::lua_setuservalue(state, -2);
})?;
} else {
- ffi::lua_newtable(self.state);
- ffi::lua_setuservalue(self.state, -2);
+ ffi::lua_newtable(state);
+ ffi::lua_setuservalue(state, -2);
}
Ok(AnyUserData(self.pop_ref()))
@@ -2959,12 +2969,12 @@ impl Lua {
Ok(())
}
- pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
- let _sg = StackGuard::new(state);
- assert_stack(state, 1);
- let extra = extra_data(state)?;
- let inner = (*extra.get()).inner.as_ref().unwrap();
- Some(Lua(Arc::clone(inner)))
+ pub(crate) unsafe fn try_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
+ let extra = extra_data(state);
+ if extra.is_null() {
+ return None;
+ }
+ (*extra).inner.as_ref().map(|lua| Lua(Arc::clone(lua)))
}
#[inline]
@@ -2988,9 +2998,8 @@ impl Lua {
#[inline]
pub(crate) unsafe fn unlikely_memory_error(&self) -> bool {
- let extra = &mut *self.extra.get();
// MemoryInfo is empty in module mode so we cannot predict memory limits
- extra
+ (*self.extra.get())
.mem_info
.map(|x| x.as_ref().memory_limit == 0)
.unwrap_or_default()
@@ -2999,45 +3008,46 @@ impl Lua {
impl LuaInner {
#[inline(always)]
+ pub(crate) fn state(&self) -> *mut ffi::lua_State {
+ self.state.load(Ordering::Relaxed)
+ }
+
+ #[inline(always)]
pub(crate) fn ref_thread(&self) -> *mut ffi::lua_State {
unsafe { (*self.extra.get()).ref_thread }
}
}
-struct StateGuard<'a>(&'a mut LuaInner, *mut ffi::lua_State);
+struct StateGuard<'a>(&'a LuaInner, *mut ffi::lua_State);
impl<'a> StateGuard<'a> {
- fn new(inner: &'a mut LuaInner, mut state: *mut ffi::lua_State) -> Self {
- mem::swap(&mut inner.state, &mut state);
+ fn new(inner: &'a LuaInner, mut state: *mut ffi::lua_State) -> Self {
+ state = inner.state.swap(state, Ordering::Relaxed);
Self(inner, state)
}
}
impl<'a> Drop for StateGuard<'a> {
fn drop(&mut self) {
- mem::swap(&mut self.0.state, &mut self.1);
+ self.0.state.store(self.1, Ordering::Relaxed);
}
}
#[cfg(feature = "luau")]
-unsafe fn extra_data(state: *mut ffi::lua_State) -> Option<Arc<UnsafeCell<ExtraData>>> {
- let extra_ptr = (*ffi::lua_callbacks(state)).userdata as *mut Arc<UnsafeCell<ExtraData>>;
- if extra_ptr.is_null() {
- return None;
- }
- Some(Arc::clone(&*extra_ptr))
+unsafe fn extra_data(state: *mut ffi::lua_State) -> *mut ExtraData {
+ (*ffi::lua_callbacks(state)).userdata as *mut ExtraData
}
#[cfg(not(feature = "luau"))]
-unsafe fn extra_data(state: *mut ffi::lua_State) -> Option<Arc<UnsafeCell<ExtraData>>> {
+unsafe fn extra_data(state: *mut ffi::lua_State) -> *mut ExtraData {
let extra_key = &EXTRA_REGISTRY_KEY as *const u8 as *const c_void;
if ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, extra_key) != ffi::LUA_TUSERDATA {
- return None;
+ ffi::lua_pop(state, 1);
+ return ptr::null_mut();
}
let extra_ptr = ffi::lua_touserdata(state, -1) as *mut Arc<UnsafeCell<ExtraData>>;
- let extra = Arc::clone(&*extra_ptr);
ffi::lua_pop(state, 1);
- Some(extra)
+ (*extra_ptr).get()
}
// Creates required entries in the metatable cache (see `util::METATABLE_CACHE`)
@@ -3064,14 +3074,14 @@ where
if extra.is_null() {
return callback_error(state, f);
}
- let extra = &mut *extra;
+ let ref_thread = (*extra).ref_thread;
let nargs = ffi::lua_gettop(state);
// We need 2 extra stack spaces to store userdata and error/panic metatable.
// Luau workaround can be removed after solving https://github.com/Roblox/luau/issues/446
// Also see #142 and #153
- if !cfg!(feature = "luau") || extra.wrapped_failures_cache.is_empty() {
+ if !cfg!(feature = "luau") || (*extra).wrapped_failures_cache.is_empty() {
let extra_stack = if nargs < 2 { 2 - nargs } else { 1 };
ffi::luaL_checkstack(
state,
@@ -3087,7 +3097,7 @@ where
// We cannot shadow Rust errors with Lua ones, so we need to obtain pre-allocated memory
// to store a wrapped failure (error or panic) *before* we proceed.
- let prealloc_failure = match extra.wrapped_failures_cache.pop() {
+ let prealloc_failure = match (*extra).wrapped_failures_cache.pop() {
Some(index) => PreallocatedFailure::Cached(index),
None => {
let ud = WrappedFailure::new_userdata(state);
@@ -3096,7 +3106,7 @@ where
}
};
- let mut get_wrapped_failure = || match prealloc_failure {
+ let get_wrapped_failure = || match prealloc_failure {
PreallocatedFailure::New(ud) => {
ffi::lua_settop(state, 1);
ud
@@ -3105,11 +3115,11 @@ where
ffi::lua_settop(state, 0);
#[cfg(feature = "luau")]
assert_stack(state, 2);
- ffi::lua_pushvalue(extra.ref_thread, index);
- ffi::lua_xmove(extra.ref_thread, state, 1);
- ffi::lua_pushnil(extra.ref_thread);
- ffi::lua_replace(extra.ref_thread, index);
- extra.ref_free.push(index);
+ ffi::lua_pushvalue(ref_thread, index);
+ ffi::lua_xmove(ref_thread, state, 1);
+ ffi::lua_pushnil(ref_thread);
+ ffi::lua_replace(ref_thread, index);
+ (*extra).ref_free.push(index);
ffi::lua_touserdata(state, -1) as *mut WrappedFailure
}
};
@@ -3119,25 +3129,25 @@ where
// Return unused WrappedFailure to the cache
match prealloc_failure {
PreallocatedFailure::New(_)
- if extra.wrapped_failures_cache.len() < WRAPPED_FAILURES_CACHE_SIZE =>
+ if (*extra).wrapped_failures_cache.len() < WRAPPED_FAILURES_CACHE_SIZE =>
{
ffi::lua_rotate(state, 1, -1);
- ffi::lua_xmove(state, extra.ref_thread, 1);
- let index = ref_stack_pop(extra);
- extra.wrapped_failures_cache.push(index);
+ ffi::lua_xmove(state, ref_thread, 1);
+ let index = ref_stack_pop(&mut *extra);
+ (*extra).wrapped_failures_cache.push(index);
}
PreallocatedFailure::New(_) => {
ffi::lua_remove(state, 1);
}
PreallocatedFailure::Cached(index)
- if extra.wrapped_failures_cache.len() < WRAPPED_FAILURES_CACHE_SIZE =>
+ if (*extra).wrapped_failures_cache.len() < WRAPPED_FAILURES_CACHE_SIZE =>
{
- extra.wrapped_failures_cache.push(index);
+ (*extra).wrapped_failures_cache.push(index);
}
PreallocatedFailure::Cached(index) => {
- ffi::lua_pushnil(extra.ref_thread);
- ffi::lua_replace(extra.ref_thread, index);
- extra.ref_free.push(index);
+ ffi::lua_pushnil(ref_thread);
+ ffi::lua_replace(ref_thread, index);
+ (*extra).ref_free.push(index);
}
}
r
@@ -3331,3 +3341,16 @@ unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int {
extra.ref_stack_top += 1;
extra.ref_stack_top
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ // Lua has lots of interior mutability, should not be RefUnwindSafe
+ static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
+
+ #[cfg(not(feature = "send"))]
+ static_assertions::assert_not_impl_any!(Lua: Send);
+ #[cfg(feature = "send")]
+ static_assertions::assert_impl_all!(Lua: Send);
+}
diff --git a/src/luau.rs b/src/luau.rs
index e7f397b..7dab235 100644
--- a/src/luau.rs
+++ b/src/luau.rs
@@ -1,5 +1,6 @@
use std::ffi::CStr;
use std::os::raw::{c_float, c_int};
+use std::string::String as StdString;
use crate::chunk::ChunkMode;
use crate::error::{Error, Result};
@@ -69,14 +70,15 @@ unsafe extern "C" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_int {
}
}
-fn lua_require(lua: &Lua, name: Option<std::string::String>) -> Result<Value> {
+fn lua_require(lua: &Lua, name: Option<StdString>) -> Result<Value> {
let name = name.ok_or_else(|| Error::RuntimeError("invalid module name".into()))?;
// Find module in the cache
+ let state = lua.state();
let loaded = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
- protect_lua!(lua.state, 0, 1, fn(state) {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
+ protect_lua!(state, 0, 1, fn(state) {
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
})?;
Table(lua.pop_ref())
diff --git a/src/scope.rs b/src/scope.rs
index 69fc0a4..c47ded2 100644
--- a/src/scope.rs
+++ b/src/scope.rs
@@ -190,7 +190,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
#[cfg(any(feature = "lua51", feature = "luajit"))]
let newtable = self.lua.create_table()?;
let destructor: DestructorCallback = Box::new(move |ud| {
- let state = ud.lua.state;
+ let state = ud.lua.state();
let _sg = StackGuard::new(state);
assert_stack(state, 2);
@@ -275,11 +275,12 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
// first argument).
let check_ud_type = move |lua: &'callback Lua, value| {
if let Some(Value::UserData(ud)) = value {
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
lua.push_userdata_ref(&ud.0)?;
- if get_userdata(lua.state, -1) as *const _ == ud_ptr {
+ if get_userdata(state, -1) as *const _ == ud_ptr {
return Ok(());
}
}
@@ -330,14 +331,15 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
T::add_fields(&mut ud_fields);
T::add_methods(&mut ud_methods);
+ let lua = self.lua;
+ let state = lua.state();
unsafe {
- let lua = self.lua;
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 13)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 13)?;
#[cfg(not(feature = "luau"))]
#[allow(clippy::let_and_return)]
- let ud_ptr = protect_lua!(lua.state, 0, 1, |state| {
+ let ud_ptr = protect_lua!(state, 0, 1, |state| {
let ud =
ffi::lua_newuserdata(state, mem::size_of::<UserDataCell<Rc<RefCell<T>>>>());
@@ -353,67 +355,67 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
#[cfg(feature = "luau")]
let ud_ptr = {
crate::util::push_userdata::<UserDataCell<Rc<RefCell<T>>>>(
- lua.state,
+ state,
UserDataCell::new(data.clone()),
true,
)?;
- ffi::lua_touserdata(lua.state, -1)
+ ffi::lua_touserdata(state, -1)
};
// Prepare metatable, add meta methods first and then meta fields
let meta_methods_nrec = ud_methods.meta_methods.len() + ud_fields.meta_fields.len() + 1;
- push_table(lua.state, 0, meta_methods_nrec as c_int, true)?;
+ push_table(state, 0, meta_methods_nrec as c_int, true)?;
for (k, m) in ud_methods.meta_methods {
let data = data.clone();
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
- rawset_field(lua.state, -2, k.validate()?.name())?;
+ rawset_field(state, -2, k.validate()?.name())?;
}
for (k, f) in ud_fields.meta_fields {
lua.push_value(f(mem::transmute(lua))?)?;
- rawset_field(lua.state, -2, k.validate()?.name())?;
+ rawset_field(state, -2, k.validate()?.name())?;
}
- let metatable_index = ffi::lua_absindex(lua.state, -1);
+ let metatable_index = ffi::lua_absindex(state, -1);
let mut field_getters_index = None;
let field_getters_nrec = ud_fields.field_getters.len();
if field_getters_nrec > 0 {
- push_table(lua.state, 0, field_getters_nrec as c_int, true)?;
+ push_table(state, 0, field_getters_nrec as c_int, true)?;
for (k, m) in ud_fields.field_getters {
let data = data.clone();
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
- rawset_field(lua.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- field_getters_index = Some(ffi::lua_absindex(lua.state, -1));
+ field_getters_index = Some(ffi::lua_absindex(state, -1));
}
let mut field_setters_index = None;
let field_setters_nrec = ud_fields.field_setters.len();
if field_setters_nrec > 0 {
- push_table(lua.state, 0, field_setters_nrec as c_int, true)?;
+ push_table(state, 0, field_setters_nrec as c_int, true)?;
for (k, m) in ud_fields.field_setters {
let data = data.clone();
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
- rawset_field(lua.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- field_setters_index = Some(ffi::lua_absindex(lua.state, -1));
+ field_setters_index = Some(ffi::lua_absindex(state, -1));
}
let mut methods_index = None;
let methods_nrec = ud_methods.methods.len();
if methods_nrec > 0 {
// Create table used for methods lookup
- push_table(lua.state, 0, methods_nrec as c_int, true)?;
+ push_table(state, 0, methods_nrec as c_int, true)?;
for (k, m) in ud_methods.methods {
let data = data.clone();
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
- rawset_field(lua.state, -2, &k)?;
+ rawset_field(state, -2, &k)?;
}
- methods_index = Some(ffi::lua_absindex(lua.state, -1));
+ methods_index = Some(ffi::lua_absindex(state, -1));
}
init_userdata_metatable::<UserDataCell<Rc<RefCell<T>>>>(
- lua.state,
+ state,
metatable_index,
field_getters_index,
field_setters_index,
@@ -423,20 +425,20 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
let count = field_getters_index.map(|_| 1).unwrap_or(0)
+ field_setters_index.map(|_| 1).unwrap_or(0)
+ methods_index.map(|_| 1).unwrap_or(0);
- ffi::lua_pop(lua.state, count);
+ ffi::lua_pop(state, count);
- let mt_ptr = ffi::lua_topointer(lua.state, -1);
+ let mt_ptr = ffi::lua_topointer(state, -1);
// Write userdata just before attaching metatable with `__gc` metamethod
#[cfg(not(feature = "luau"))]
std::ptr::write(ud_ptr as _, UserDataCell::new(data));
- ffi::lua_setmetatable(lua.state, -2);
+ ffi::lua_setmetatable(state, -2);
let ud = AnyUserData(lua.pop_ref());
lua.register_userdata_metatable(mt_ptr, None);
#[cfg(any(feature = "lua51", feature = "luajit"))]
let newtable = lua.create_table()?;
let destructor: DestructorCallback = Box::new(move |ud| {
- let state = ud.lua.state;
+ let state = ud.lua.state();
let _sg = StackGuard::new(state);
assert_stack(state, 2);
@@ -498,7 +500,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
let f = self.lua.create_callback(f)?;
let destructor: DestructorCallback = Box::new(|f| {
- let state = f.lua.state;
+ let state = f.lua.state();
let _sg = StackGuard::new(state);
assert_stack(state, 3);
@@ -532,7 +534,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
let get_poll_str = self.lua.create_string("get_poll")?;
let poll_str = self.lua.create_string("poll")?;
let destructor: DestructorCallback = Box::new(move |f| {
- let state = f.lua.state;
+ let state = f.lua.state();
let _sg = StackGuard::new(state);
assert_stack(state, 5);
diff --git a/src/serde/ser.rs b/src/serde/ser.rs
index 7df27cd..2a0d691 100644
--- a/src/serde/ser.rs
+++ b/src/serde/ser.rs
@@ -320,20 +320,21 @@ impl<'lua> ser::SerializeSeq for SerializeVec<'lua> {
T: Serialize + ?Sized,
{
let lua = self.table.0.lua;
+ let state = lua.state();
let value = lua.to_value_with(value, self.options)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.table.0);
lua.push_value(value)?;
if lua.unlikely_memory_error() {
- let len = ffi::lua_rawlen(lua.state, -2) as Integer;
- ffi::lua_rawseti(lua.state, -2, len + 1);
- ffi::lua_pop(lua.state, 1);
+ let len = ffi::lua_rawlen(state, -2) as Integer;
+ ffi::lua_rawseti(state, -2, len + 1);
+ ffi::lua_pop(state, 1);
Ok(())
} else {
- protect_lua!(lua.state, 2, 0, fn(state) {
+ protect_lua!(state, 2, 0, fn(state) {
let len = ffi::lua_rawlen(state, -2) as Integer;
ffi::lua_rawseti(state, -2, len + 1);
})
diff --git a/src/string.rs b/src/string.rs
index 70e11d1..60732d8 100644
--- a/src/string.rs
+++ b/src/string.rs
@@ -190,3 +190,10 @@ impl<'lua> Serialize for String<'lua> {
}
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(String: Send);
+}
diff --git a/src/table.rs b/src/table.rs
index 2d9a889..0f0654e 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -78,14 +78,15 @@ impl<'lua> Table<'lua> {
let key = key.to_lua(lua)?;
let value = value.to_lua(lua)?;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_ref(&self.0);
lua.push_value(key)?;
lua.push_value(value)?;
- protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_settable(state, -3))
+ protect_lua!(state, 3, 0, fn(state) ffi::lua_settable(state, -3))
}
}
@@ -120,15 +121,16 @@ impl<'lua> Table<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
let key = key.to_lua(lua)?;
let value = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
lua.push_value(key)?;
- protect_lua!(lua.state, 2, 1, fn(state) ffi::lua_gettable(state, -2))?;
+ protect_lua!(state, 2, 1, fn(state) ffi::lua_gettable(state, -2))?;
lua.pop_value()
};
@@ -148,14 +150,15 @@ impl<'lua> Table<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
let value = value.to_lua(lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
lua.push_value(value)?;
- protect_lua!(lua.state, 2, 0, fn(state) {
+ protect_lua!(state, 2, 0, fn(state) {
let len = ffi::luaL_len(state, -2) as Integer;
ffi::lua_seti(state, -2, len + 1);
})?
@@ -171,12 +174,13 @@ impl<'lua> Table<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
let value = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
- protect_lua!(lua.state, 1, 1, fn(state) {
+ protect_lua!(state, 1, 1, fn(state) {
let len = ffi::luaL_len(state, -1) as Integer;
ffi::lua_geti(state, -1, len);
ffi::lua_pushnil(state);
@@ -249,23 +253,24 @@ impl<'lua> Table<'lua> {
self.check_readonly_write()?;
let lua = self.0.lua;
+ let state = lua.state();
let key = key.to_lua(lua)?;
let value = value.to_lua(lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_ref(&self.0);
lua.push_value(key)?;
lua.push_value(value)?;
if lua.unlikely_memory_error() {
- ffi::lua_rawset(lua.state, -3);
- ffi::lua_pop(lua.state, 1);
+ ffi::lua_rawset(state, -3);
+ ffi::lua_pop(state, 1);
Ok(())
} else {
- protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_rawset(state, -3))
+ protect_lua!(state, 3, 0, fn(state) ffi::lua_rawset(state, -3))
}
}
}
@@ -273,15 +278,16 @@ impl<'lua> Table<'lua> {
/// Gets the value associated to `key` without invoking metamethods.
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
let lua = self.0.lua;
+ let state = lua.state();
let key = key.to_lua(lua)?;
let value = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
lua.push_ref(&self.0);
lua.push_value(key)?;
- ffi::lua_rawget(lua.state, -2);
+ ffi::lua_rawget(state, -2);
lua.pop_value()
};
@@ -292,6 +298,8 @@ impl<'lua> Table<'lua> {
/// The worst case complexity is O(n), where n is the table length.
pub fn raw_insert<V: ToLua<'lua>>(&self, idx: Integer, value: V) -> Result<()> {
let lua = self.0.lua;
+ let state = lua.state();
+
let size = self.raw_len();
if idx < 1 || idx > size + 1 {
return Err(Error::RuntimeError("index out of bounds".to_string()));
@@ -299,12 +307,12 @@ impl<'lua> Table<'lua> {
let value = value.to_lua(lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_ref(&self.0);
lua.push_value(value)?;
- protect_lua!(lua.state, 2, 0, |state| {
+ protect_lua!(state, 2, 0, |state| {
for i in (idx..=size).rev() {
// table[i+1] = table[i]
ffi::lua_rawgeti(state, -2, i);
@@ -321,11 +329,12 @@ impl<'lua> Table<'lua> {
self.check_readonly_write()?;
let lua = self.0.lua;
+ let state = lua.state();
let value = value.to_lua(lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
lua.push_value(value)?;
@@ -336,9 +345,9 @@ impl<'lua> Table<'lua> {
}
if lua.unlikely_memory_error() {
- callback(lua.state);
+ callback(state);
} else {
- protect_lua!(lua.state, 2, 0, fn(state) callback(state))?;
+ protect_lua!(state, 2, 0, fn(state) callback(state))?;
}
}
Ok(())
@@ -350,16 +359,17 @@ impl<'lua> Table<'lua> {
self.check_readonly_write()?;
let lua = self.0.lua;
+ let state = lua.state();
let value = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
lua.push_ref(&self.0);
- let len = ffi::lua_rawlen(lua.state, -1) as Integer;
- ffi::lua_rawgeti(lua.state, -1, len);
+ let len = ffi::lua_rawlen(state, -1) as Integer;
+ ffi::lua_rawgeti(state, -1, len);
// Set slot to nil (it must be safe to do)
- ffi::lua_pushnil(lua.state);
- ffi::lua_rawseti(lua.state, -3, len);
+ ffi::lua_pushnil(state);
+ ffi::lua_rawseti(state, -3, len);
lua.pop_value()
};
V::from_lua(value, lua)
@@ -374,6 +384,7 @@ impl<'lua> Table<'lua> {
/// For other key types this is equivalent to setting `table[key] = nil`.
pub fn raw_remove<K: ToLua<'lua>>(&self, key: K) -> Result<()> {
let lua = self.0.lua;
+ let state = lua.state();
let key = key.to_lua(lua)?;
match key {
Value::Integer(idx) => {
@@ -382,11 +393,11 @@ impl<'lua> Table<'lua> {
return Err(Error::RuntimeError("index out of bounds".to_string()));
}
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
- protect_lua!(lua.state, 1, 0, |state| {
+ protect_lua!(state, 1, 0, |state| {
for i in idx..size {
ffi::lua_rawgeti(state, -1, i + 1);
ffi::lua_rawseti(state, -2, i);
@@ -412,12 +423,13 @@ impl<'lua> Table<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_ref(&self.0);
- protect_lua!(lua.state, 1, 0, |state| ffi::luaL_len(state, -1))
+ protect_lua!(state, 1, 0, |state| ffi::luaL_len(state, -1))
}
}
@@ -432,12 +444,13 @@ impl<'lua> Table<'lua> {
/// Unlike the `getmetatable` Lua function, this method ignores the `__metatable` field.
pub fn get_metatable(&self) -> Option<Table<'lua>> {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 2);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 2);
lua.push_ref(&self.0);
- if ffi::lua_getmetatable(lua.state, -1) == 0 {
+ if ffi::lua_getmetatable(state, -1) == 0 {
None
} else {
Some(Table(lua.pop_ref()))
@@ -457,17 +470,18 @@ impl<'lua> Table<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 2);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 2);
lua.push_ref(&self.0);
if let Some(metatable) = metatable {
lua.push_ref(&metatable.0);
} else {
- ffi::lua_pushnil(lua.state);
+ ffi::lua_pushnil(state);
}
- ffi::lua_setmetatable(lua.state, -2);
+ ffi::lua_setmetatable(state, -2);
}
}
@@ -654,16 +668,17 @@ impl<'lua> Table<'lua> {
#[cfg(feature = "serialize")]
pub(crate) fn is_array(&self) -> bool {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 3);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 3);
lua.push_ref(&self.0);
- if ffi::lua_getmetatable(lua.state, -1) == 0 {
+ if ffi::lua_getmetatable(state, -1) == 0 {
return false;
}
- crate::serde::push_array_metatable(lua.state);
- ffi::lua_rawequal(lua.state, -1, -2) != 0
+ crate::serde::push_array_metatable(state);
+ ffi::lua_rawequal(state, -1, -2) != 0
}
}
@@ -911,15 +926,16 @@ where
fn next(&mut self) -> Option<Self::Item> {
if let Some(prev_key) = self.key.take() {
let lua = self.table.lua;
+ let state = lua.state();
let res = (|| unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_ref(&self.table);
lua.push_value(prev_key)?;
- let next = protect_lua!(lua.state, 2, ffi::LUA_MULTRET, |state| {
+ let next = protect_lua!(state, 2, ffi::LUA_MULTRET, |state| {
ffi::lua_next(state, -2)
})?;
if next != 0 {
@@ -971,16 +987,17 @@ where
fn next(&mut self) -> Option<Self::Item> {
if let Some(index) = self.index.take() {
let lua = self.table.lua;
+ let state = lua.state();
let res = (|| unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 1 + if self.raw { 0 } else { 3 })?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 1 + if self.raw { 0 } else { 3 })?;
lua.push_ref(&self.table);
let res = if self.raw {
- ffi::lua_rawgeti(lua.state, -1, index)
+ ffi::lua_rawgeti(state, -1, index)
} else {
- protect_lua!(lua.state, 1, 1, |state| ffi::lua_geti(state, -1, index))?
+ protect_lua!(state, 1, 1, |state| ffi::lua_geti(state, -1, index))?
};
match res {
ffi::LUA_TNIL if index > self.len.unwrap_or(0) => Ok(None),
@@ -1001,3 +1018,10 @@ where
}
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(Table: Send);
+}
diff --git a/src/thread.rs b/src/thread.rs
index 811c056..4e5bd9e 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -22,7 +22,6 @@ use {
},
futures_core::{future::Future, stream::Stream},
std::{
- cell::RefCell,
marker::PhantomData,
pin::Pin,
task::{Context, Poll, Waker},
@@ -67,10 +66,9 @@ impl OwnedThread {
/// [`Stream`]: futures_core::stream::Stream
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
-#[derive(Debug)]
pub struct AsyncThread<'lua, R> {
thread: Thread<'lua>,
- args0: RefCell<Option<Result<MultiValue<'lua>>>>,
+ args0: Option<Result<MultiValue<'lua>>>,
ret: PhantomData<R>,
recycle: bool,
}
@@ -123,11 +121,13 @@ impl<'lua> Thread<'lua> {
R: FromLuaMulti<'lua>,
{
let lua = self.0.lua;
+ let state = lua.state();
+
let mut args = args.to_lua_multi(lua)?;
let nargs = args.len() as c_int;
let results = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, cmp::max(nargs + 1, 3))?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, cmp::max(nargs + 1, 3))?;
let thread_state = ffi::lua_tothread(lua.ref_thread(), self.0.index);
@@ -140,23 +140,23 @@ impl<'lua> Thread<'lua> {
for arg in args.drain_all() {
lua.push_value(arg)?;
}
- ffi::lua_xmove(lua.state, thread_state, nargs);
+ ffi::lua_xmove(state, thread_state, nargs);
let mut nresults = 0;
- let ret = ffi::lua_resume(thread_state, lua.state, nargs, &mut nresults as *mut c_int);
+ let ret = ffi::lua_resume(thread_state, state, nargs, &mut nresults as *mut c_int);
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
- check_stack(lua.state, 3)?;
- protect_lua!(lua.state, 0, 1, |state| error_traceback_thread(
+ check_stack(state, 3)?;
+ protect_lua!(state, 0, 1, |state| error_traceback_thread(
state,
thread_state
))?;
- return Err(pop_error(lua.state, ret));
+ return Err(pop_error(state, ret));
}
let mut results = args; // Reuse MultiValue container
- check_stack(lua.state, nresults + 2)?; // 2 is extra for `lua.pop_value()` below
- ffi::lua_xmove(thread_state, lua.state, nresults);
+ check_stack(state, nresults + 2)?; // 2 is extra for `lua.pop_value()` below
+ ffi::lua_xmove(thread_state, state, nresults);
for _ in 0..nresults {
results.push_front(lua.pop_value());
@@ -205,12 +205,13 @@ impl<'lua> Thread<'lua> {
))]
pub fn reset(&self, func: Function<'lua>) -> Result<()> {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
lua.push_ref(&self.0);
- let thread_state = ffi::lua_tothread(lua.state, -1);
+ let thread_state = ffi::lua_tothread(state, -1);
#[cfg(feature = "lua54")]
let status = ffi::lua_resetthread(thread_state);
@@ -219,17 +220,17 @@ impl<'lua> Thread<'lua> {
return Err(pop_error(thread_state, status));
}
#[cfg(all(feature = "luajit", feature = "vendored"))]
- ffi::lua_resetthread(lua.state, thread_state);
+ ffi::lua_resetthread(state, thread_state);
#[cfg(feature = "luau")]
ffi::lua_resetthread(thread_state);
lua.push_ref(&func.0);
- ffi::lua_xmove(lua.state, thread_state, 1);
+ ffi::lua_xmove(state, thread_state, 1);
#[cfg(feature = "luau")]
{
// Inherit `LUA_GLOBALSINDEX` from the caller
- ffi::lua_xpush(lua.state, thread_state, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
}
@@ -292,7 +293,7 @@ impl<'lua> Thread<'lua> {
let args = args.to_lua_multi(self.0.lua);
AsyncThread {
thread: self,
- args0: RefCell::new(Some(args)),
+ args0: Some(args),
ret: PhantomData,
recycle: false,
}
@@ -334,14 +335,15 @@ impl<'lua> Thread<'lua> {
#[doc(hidden)]
pub fn sandbox(&self) -> Result<()> {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
let thread = ffi::lua_tothread(lua.ref_thread(), self.0.index);
check_stack(thread, 1)?;
- check_stack(lua.state, 3)?;
+ check_stack(state, 3)?;
// Inherit `LUA_GLOBALSINDEX` from the caller
- ffi::lua_xpush(lua.state, thread, ffi::LUA_GLOBALSINDEX);
+ ffi::lua_xpush(state, thread, ffi::LUA_GLOBALSINDEX);
ffi::lua_replace(thread, ffi::LUA_GLOBALSINDEX);
- protect_lua!(lua.state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
+ protect_lua!(state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
}
}
@@ -406,10 +408,13 @@ where
};
let _wg = WakerGuard::new(lua, cx.waker().clone());
- let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() {
- self.thread.resume(args?)?
+
+ // This is safe as we are not moving the whole struct
+ let this = unsafe { self.get_unchecked_mut() };
+ let ret: MultiValue = if let Some(args) = this.args0.take() {
+ this.thread.resume(args?)?
} else {
- self.thread.resume(())?
+ this.thread.resume(())?
};
if is_poll_pending(&ret) {
@@ -437,17 +442,20 @@ where
};
let _wg = WakerGuard::new(lua, cx.waker().clone());
- let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() {
- self.thread.resume(args?)?
+
+ // This is safe as we are not moving the whole struct
+ let this = unsafe { self.get_unchecked_mut() };
+ let ret: MultiValue = if let Some(args) = this.args0.take() {
+ this.thread.resume(args?)?
} else {
- self.thread.resume(())?
+ this.thread.resume(())?
};
if is_poll_pending(&ret) {
return Poll::Pending;
}
- if let ThreadStatus::Resumable = self.thread.status() {
+ if let ThreadStatus::Resumable = this.thread.status() {
// Ignore value returned via yield()
cx.waker().wake_by_ref();
return Poll::Pending;
@@ -493,3 +501,10 @@ impl<'lua> Drop for WakerGuard<'lua> {
}
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(Thread: Send);
+}
diff --git a/src/types.rs b/src/types.rs
index d5a5413..a02c21a 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -192,6 +192,7 @@ impl<'lua> LuaRef<'lua> {
}
}
+ #[inline]
pub(crate) fn into_owned(self) -> LuaOwnedRef {
self.lua.make_owned_ref(self)
}
@@ -220,12 +221,13 @@ impl<'lua> Drop for LuaRef<'lua> {
impl<'lua> PartialEq for LuaRef<'lua> {
fn eq(&self, other: &Self) -> bool {
let lua = self.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- assert_stack(lua.state, 2);
+ let _sg = StackGuard::new(state);
+ assert_stack(state, 2);
lua.push_ref(self);
lua.push_ref(other);
- ffi::lua_rawequal(lua.state, -1, -2) == 1
+ ffi::lua_rawequal(state, -1, -2) == 1
}
}
}
@@ -249,10 +251,10 @@ impl Clone for LuaOwnedRef {
impl Drop for LuaOwnedRef {
fn drop(&mut self) {
- self.lua.drop_ref(&LuaRef {
+ drop(LuaRef {
lua: &self.lua,
index: self.index,
- drop: false,
+ drop: true,
});
}
}
@@ -266,3 +268,11 @@ impl LuaOwnedRef {
}
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_impl_all!(RegistryKey: Send, Sync);
+ static_assertions::assert_not_impl_any!(LuaRef: Send);
+}
diff --git a/src/userdata.rs b/src/userdata.rs
index eaf3800..48d731b 100644
--- a/src/userdata.rs
+++ b/src/userdata.rs
@@ -829,16 +829,17 @@ impl<'lua> AnyUserData<'lua> {
/// Keeps associated user values unchanged (they will be collected by Lua's GC).
pub fn take<T: 'static + UserData>(&self) -> Result<T> {
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let type_id = lua.push_userdata_ref(&self.0)?;
match type_id {
Some(type_id) if type_id == TypeId::of::<T>() => {
// Try to borrow userdata exclusively
- let _ = (*get_userdata::<UserDataCell<T>>(lua.state, -1)).try_borrow_mut()?;
- Ok(take_userdata::<UserDataCell<T>>(lua.state).into_inner())
+ let _ = (*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow_mut()?;
+ Ok(take_userdata::<UserDataCell<T>>(state).into_inner())
}
_ => Err(Error::UserDataTypeMismatch),
}
@@ -887,21 +888,22 @@ impl<'lua> AnyUserData<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_userdata_ref(&self.0)?;
lua.push_value(v.to_lua(lua)?)?;
#[cfg(feature = "lua54")]
if n < USER_VALUE_MAXSLOT {
- ffi::lua_setiuservalue(lua.state, -2, n as c_int);
+ ffi::lua_setiuservalue(state, -2, n as c_int);
return Ok(());
}
// Multiple (extra) user values are emulated by storing them in a table
- protect_lua!(lua.state, 2, 0, |state| {
+ protect_lua!(state, 2, 0, |state| {
if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
// Create a new table to use as uservalue
ffi::lua_pop(state, 1);
@@ -941,20 +943,21 @@ impl<'lua> AnyUserData<'lua> {
}
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_userdata_ref(&self.0)?;
#[cfg(feature = "lua54")]
if n < USER_VALUE_MAXSLOT {
- ffi::lua_getiuservalue(lua.state, -1, n as c_int);
+ ffi::lua_getiuservalue(state, -1, n as c_int);
return V::from_lua(lua.pop_value(), lua);
}
// Multiple (extra) user values are emulated by storing them in a table
- protect_lua!(lua.state, 1, 1, |state| {
+ protect_lua!(state, 1, 1, |state| {
if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
ffi::lua_pushnil(state);
return;
@@ -979,15 +982,16 @@ impl<'lua> AnyUserData<'lua> {
V: ToLua<'lua>,
{
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 5)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 5)?;
lua.push_userdata_ref(&self.0)?;
lua.push_value(v.to_lua(lua)?)?;
// Multiple (extra) user values are emulated by storing them in a table
- protect_lua!(lua.state, 2, 0, |state| {
+ protect_lua!(state, 2, 0, |state| {
if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
// Create a new table to use as uservalue
ffi::lua_pop(state, 1);
@@ -1016,14 +1020,15 @@ impl<'lua> AnyUserData<'lua> {
V: FromLua<'lua>,
{
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 4)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
lua.push_userdata_ref(&self.0)?;
// Multiple (extra) user values are emulated by storing them in a table
- protect_lua!(lua.state, 1, 1, |state| {
+ protect_lua!(state, 1, 1, |state| {
if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
ffi::lua_pushnil(state);
return;
@@ -1050,13 +1055,14 @@ impl<'lua> AnyUserData<'lua> {
}
fn get_raw_metatable(&self) -> Result<Table<'lua>> {
+ let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let lua = self.0.lua;
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 3)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3)?;
lua.push_userdata_ref(&self.0)?;
- ffi::lua_getmetatable(lua.state, -1); // Checked that non-empty on the previous call
+ ffi::lua_getmetatable(state, -1); // Checked that non-empty on the previous call
Ok(Table(lua.pop_ref()))
}
}
@@ -1093,14 +1099,15 @@ impl<'lua> AnyUserData<'lua> {
F: FnOnce(&'a UserDataCell<T>) -> Result<R>,
{
let lua = self.0.lua;
+ let state = lua.state();
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let type_id = lua.push_userdata_ref(&self.0)?;
match type_id {
Some(type_id) if type_id == TypeId::of::<T>() => {
- func(&*get_userdata::<UserDataCell<T>>(lua.state, -1))
+ func(&*get_userdata::<UserDataCell<T>>(state, -1))
}
_ => Err(Error::UserDataTypeMismatch),
}
@@ -1209,12 +1216,13 @@ impl<'lua> Serialize for AnyUserData<'lua> {
S: Serializer,
{
let lua = self.0.lua;
+ let state = lua.state();
let data = unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 3).map_err(ser::Error::custom)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 3).map_err(ser::Error::custom)?;
lua.push_userdata_ref(&self.0).map_err(ser::Error::custom)?;
- let ud = &*get_userdata::<UserDataCell<()>>(lua.state, -1);
+ let ud = &*get_userdata::<UserDataCell<()>>(state, -1);
ud.0.try_borrow()
.map_err(|_| ser::Error::custom(Error::UserDataBorrowError))?
};
@@ -1224,3 +1232,10 @@ impl<'lua> Serialize for AnyUserData<'lua> {
}
}
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(AnyUserData: Send);
+}
diff --git a/src/userdata_impl.rs b/src/userdata_impl.rs
index 3126b09..8853a90 100644
--- a/src/userdata_impl.rs
+++ b/src/userdata_impl.rs
@@ -211,42 +211,43 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
{
Box::new(move |lua, mut args| {
if let Some(front) = args.pop_front() {
+ let state = lua.state();
let userdata = AnyUserData::from_lua(front, lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let type_id = lua.push_userdata_ref(&userdata.0)?;
match type_id {
Some(id) if id == TypeId::of::<T>() => {
- let ud = get_userdata_ref::<T>(lua.state)?;
+ let ud = get_userdata_ref::<T>(state)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(not(feature = "send"))]
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud = get_userdata_ref::<Rc<RefCell<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Rc<RefCell<T>>>(state)?;
let ud = ud.try_borrow().map_err(|_| Error::UserDataBorrowError)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<Mutex<T>>>(state)?;
let ud = ud.try_lock().map_err(|_| Error::UserDataBorrowError)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state)?;
let ud = ud.try_lock().ok_or(Error::UserDataBorrowError)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud = get_userdata_ref::<Arc<RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<RwLock<T>>>(state)?;
let ud = ud.try_read().map_err(|_| Error::UserDataBorrowError)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state)?;
let ud = ud.try_read().ok_or(Error::UserDataBorrowError)?;
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
@@ -272,49 +273,50 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
let method = RefCell::new(method);
Box::new(move |lua, mut args| {
if let Some(front) = args.pop_front() {
+ let state = lua.state();
let userdata = AnyUserData::from_lua(front, lua)?;
let mut method = method
.try_borrow_mut()
.map_err(|_| Error::RecursiveMutCallback)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let type_id = lua.push_userdata_ref(&userdata.0)?;
match type_id {
Some(id) if id == TypeId::of::<T>() => {
- let mut ud = get_userdata_mut::<T>(lua.state)?;
+ let mut ud = get_userdata_mut::<T>(state)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(not(feature = "send"))]
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud = get_userdata_mut::<Rc<RefCell<T>>>(lua.state)?;
+ let ud = get_userdata_mut::<Rc<RefCell<T>>>(state)?;
let mut ud = ud
.try_borrow_mut()
.map_err(|_| Error::UserDataBorrowMutError)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud = get_userdata_mut::<Arc<Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_mut::<Arc<Mutex<T>>>(state)?;
let mut ud =
ud.try_lock().map_err(|_| Error::UserDataBorrowMutError)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(state)?;
let mut ud = ud.try_lock().ok_or(Error::UserDataBorrowMutError)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud = get_userdata_mut::<Arc<RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_mut::<Arc<RwLock<T>>>(state)?;
let mut ud =
ud.try_write().map_err(|_| Error::UserDataBorrowMutError)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(state)?;
let mut ud = ud.try_write().ok_or(Error::UserDataBorrowMutError)?;
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
}
@@ -343,43 +345,43 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
Box::new(move |lua, mut args| {
let fut_res = || {
if let Some(front) = args.pop_front() {
+ let state = lua.state();
let userdata = AnyUserData::from_lua(front, lua)?;
unsafe {
- let _sg = StackGuard::new(lua.state);
- check_stack(lua.state, 2)?;
+ let _sg = StackGuard::new(state);
+ check_stack(state, 2)?;
let type_id = lua.push_userdata_ref(&userdata.0)?;
match type_id {
Some(id) if id == TypeId::of::<T>() => {
- let ud = get_userdata_ref::<T>(lua.state)?;
+ let ud = get_userdata_ref::<T>(state)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
#[cfg(not(feature = "send"))]
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
- let ud = get_userdata_ref::<Rc<RefCell<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Rc<RefCell<T>>>(state)?;
let ud = ud.try_borrow().map_err(|_| Error::UserDataBorrowError)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<Mutex<T>>>(state)?;
let ud = ud.try_lock().map_err(|_| Error::UserDataBorrowError)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
- let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state)?;
let ud = ud.try_lock().ok_or(Error::UserDataBorrowError)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
- let ud = get_userdata_ref::<Arc<RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<RwLock<T>>>(state)?;
let ud = ud.try_read().map_err(|_| Error::UserDataBorrowError)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
#[cfg(feature = "parking_lot")]
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
- let ud =
- get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
+ let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state)?;
let ud = ud.try_read().ok_or(Error::UserDataBorrowError)?;
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
}
diff --git a/src/value.rs b/src/value.rs
index eb184d4..8d90b62 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -357,3 +357,11 @@ pub trait FromLuaMulti<'lua>: Sized {
/// any missing values are nil.
fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
}
+
+#[cfg(test)]
+mod assertions {
+ use super::*;
+
+ static_assertions::assert_not_impl_any!(Value: Send);
+ static_assertions::assert_not_impl_any!(MultiValue: Send);
+}