From 5dc6c3214b7b4ccda02b9743f4f9108e9fc0277e Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Tue, 6 May 2025 21:28:21 +0100 Subject: [PATCH] Prepare for 2024 edition --- mlua-sys/src/luau/lauxlib.rs | 2 +- src/function.rs | 36 +++++++++++++++++++++++++++++++----- src/lib.rs | 1 + src/util/error.rs | 2 +- tests/tests.rs | 8 +++++--- tests/thread.rs | 2 +- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/mlua-sys/src/luau/lauxlib.rs b/mlua-sys/src/luau/lauxlib.rs index 5aabf03..ab85089 100644 --- a/mlua-sys/src/luau/lauxlib.rs +++ b/mlua-sys/src/luau/lauxlib.rs @@ -3,7 +3,7 @@ use std::os::raw::{c_char, c_float, c_int, c_void}; use std::ptr; -use super::lua::{self, LUA_REGISTRYINDEX, lua_CFunction, lua_Number, lua_State, lua_Unsigned}; +use super::lua::{self, lua_CFunction, lua_Number, lua_State, lua_Unsigned, LUA_REGISTRYINDEX}; #[repr(C)] pub struct luaL_Reg { diff --git a/src/function.rs b/src/function.rs index 08dbc83..ef39b2c 100644 --- a/src/function.rs +++ b/src/function.rs @@ -14,9 +14,12 @@ use crate::value::Value; #[cfg(feature = "async")] use { + crate::thread::AsyncThread, crate::traits::LuaNativeAsyncFn, crate::types::AsyncCallback, std::future::{self, Future}, + std::pin::Pin, + std::task::{Context, Poll}, }; /// Handle to an internal Lua function. @@ -128,7 +131,8 @@ impl Function { /// Returns a future that, when polled, calls `self`, passing `args` as function arguments, /// and drives the execution. /// - /// Internally it wraps the function to an [`AsyncThread`]. + /// Internally it wraps the function to an [`AsyncThread`]. The returned type implements + /// `Future>` and can be awaited. /// /// Requires `feature = "async"` /// @@ -155,19 +159,18 @@ impl Function { /// [`AsyncThread`]: crate::AsyncThread #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] - pub fn call_async(&self, args: impl IntoLuaMulti) -> impl Future> + pub fn call_async(&self, args: impl IntoLuaMulti) -> AsyncCallFuture where R: FromLuaMulti, { let lua = self.0.lua.lock(); - let thread_res = unsafe { + AsyncCallFuture(unsafe { lua.create_recycled_thread(self).and_then(|th| { let mut th = th.into_async(args)?; th.set_recyclable(true); Ok(th) }) - }; - async move { thread_res?.await } + }) } /// Returns a function that, when called, calls `self`, passing `args` as the first set of @@ -644,6 +647,26 @@ impl LuaType for Function { const TYPE_ID: c_int = ffi::LUA_TFUNCTION; } +#[cfg(feature = "async")] +pub struct AsyncCallFuture(Result>); + +#[cfg(feature = "async")] +impl Future for AsyncCallFuture { + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // Safety: We're not moving any pinned data + let this = unsafe { self.get_unchecked_mut() }; + match &mut this.0 { + Ok(thread) => { + let pinned_thread = unsafe { Pin::new_unchecked(thread) }; + pinned_thread.poll(cx) + } + Err(err) => Poll::Ready(Err(err.clone())), + } + } +} + #[cfg(test)] mod assertions { use super::*; @@ -652,4 +675,7 @@ mod assertions { static_assertions::assert_not_impl_any!(Function: Send); #[cfg(feature = "send")] static_assertions::assert_impl_all!(Function: Send, Sync); + + #[cfg(all(feature = "async", feature = "send"))] + static_assertions::assert_impl_all!(AsyncCallFuture<()>: Send); } diff --git a/src/lib.rs b/src/lib.rs index 213a7ea..ae9c417 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,7 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(not(send), allow(clippy::arc_with_non_send_sync))] #![allow(clippy::ptr_eq)] +#![allow(unsafe_op_in_unsafe_fn)] #[macro_use] mod macros; diff --git a/src/util/error.rs b/src/util/error.rs index ef9184e..899522d 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -315,7 +315,7 @@ pub(crate) unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<( let _ = write!(&mut (*err_buf), "{error}"); Ok(err_buf) } - Some(WrappedFailure::Panic(Some(ref panic))) => { + Some(WrappedFailure::Panic(Some(panic))) => { let err_buf_key = &ERROR_PRINT_BUFFER_KEY as *const u8 as *const c_void; ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, err_buf_key); let err_buf = ffi::lua_touserdata(state, -1) as *mut String; diff --git a/tests/tests.rs b/tests/tests.rs index 61021ad..7bf40af 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -944,9 +944,11 @@ fn test_rust_function() -> Result<()> { fn test_c_function() -> Result<()> { let lua = Lua::new(); - unsafe extern "C-unwind" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int { - ffi::lua_pushboolean(state, 1); - ffi::lua_setglobal(state, b"c_function\0" as *const _ as *const _); + extern "C-unwind" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int { + unsafe { + ffi::lua_pushboolean(state, 1); + ffi::lua_setglobal(state, b"c_function\0" as *const _ as *const _); + } 0 } diff --git a/tests/thread.rs b/tests/thread.rs index 560dcd3..4cb6ab1 100644 --- a/tests/thread.rs +++ b/tests/thread.rs @@ -164,7 +164,7 @@ fn test_thread_reset() -> Result<()> { let result = thread.resume::<()>(()); assert!( matches!(result, Err(Error::CallbackError{ ref cause, ..}) - if matches!(cause.as_ref(), Error::RuntimeError(ref err) + if matches!(cause.as_ref(), Error::RuntimeError(err) if err == "cannot reset a running thread") ), "unexpected result: {result:?}",