Skip to content

Commit

Permalink
Remove explicit lifetime from UserDataMethods and UserDataFields
Browse files Browse the repository at this point in the history
…traits.

Pass `'static` arguments to async functions and require `'static` Future.
(in future we can use async closures to make it more elegant).
  • Loading branch information
khvzak committed Aug 22, 2024
1 parent 8092f00 commit 9931709
Show file tree
Hide file tree
Showing 18 changed files with 403 additions and 361 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ luau-vector4 = ["luau", "ffi/luau-vector4"]
vendored = ["ffi/vendored"]
module = ["dep:mlua_derive", "ffi/module"]
async = ["dep:futures-util"]
send = []
send = ["parking_lot/send_guard"]
serialize = ["dep:serde", "dep:erased-serde", "dep:serde-value"]
macros = ["mlua_derive/macros"]
unstable = []
Expand Down
6 changes: 3 additions & 3 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ fn userdata_create(c: &mut Criterion) {
fn userdata_call_index(c: &mut Criterion) {
struct UserData(#[allow(unused)] i64);
impl LuaUserData for UserData {
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method(LuaMetaMethod::Index, move |_, _, key: LuaString| Ok(key));
}
}
Expand All @@ -323,7 +323,7 @@ fn userdata_call_index(c: &mut Criterion) {
fn userdata_call_method(c: &mut Criterion) {
struct UserData(i64);
impl LuaUserData for UserData {
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method("add", |_, this, i: i64| Ok(this.0 + i));
}
}
Expand Down Expand Up @@ -353,7 +353,7 @@ fn userdata_call_method(c: &mut Criterion) {
fn userdata_async_call_method(c: &mut Criterion) {
struct UserData(i64);
impl LuaUserData for UserData {
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_async_method("add", |_, this, i: i64| async move {
task::yield_now().await;
Ok(this.0 + i)
Expand Down
4 changes: 2 additions & 2 deletions examples/async_http_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use mlua::{chunk, ExternalResult, Lua, Result, UserData, UserDataMethods};
struct BodyReader(Incoming);

impl UserData for BodyReader {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
// Every call returns a next chunk
methods.add_async_method_mut("read", |lua, reader, ()| async move {
methods.add_async_method_mut("read", |lua, mut reader, ()| async move {
if let Some(bytes) = reader.0.frame().await {
if let Some(bytes) = bytes.into_lua_err()?.data_ref() {
return Some(lua.create_string(&bytes)).transpose();
Expand Down
2 changes: 1 addition & 1 deletion examples/async_http_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use mlua::{chunk, Error as LuaError, Function, Lua, String as LuaString, Table,
struct LuaRequest(SocketAddr, Request<Incoming>);

impl UserData for LuaRequest {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("remote_addr", |_, req, ()| Ok((req.0).to_string()));
methods.add_method("method", |_, req, ()| Ok((req.1).method().to_string()));
methods.add_method("path", |_, req, ()| Ok(req.1.uri().path().to_string()));
Expand Down
8 changes: 4 additions & 4 deletions examples/async_tcp_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ use mlua::{chunk, BString, Function, Lua, UserData, UserDataMethods};
struct LuaTcpStream(TcpStream);

impl UserData for LuaTcpStream {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("peer_addr", |_, this, ()| Ok(this.0.peer_addr()?.to_string()));

methods.add_async_method_mut("read", |lua, this, size| async move {
methods.add_async_method_mut("read", |lua, mut this, size| async move {
let mut buf = vec![0; size];
let n = this.0.read(&mut buf).await?;
buf.truncate(n);
lua.create_string(&buf)
});

methods.add_async_method_mut("write", |_, this, data: BString| async move {
methods.add_async_method_mut("write", |_, mut this, data: BString| async move {
let n = this.0.write(&data).await?;
Ok(n)
});

methods.add_async_method_mut("close", |_, this, ()| async move {
methods.add_async_method_mut("close", |_, mut this, ()| async move {
this.0.shutdown().await?;
Ok(())
});
Expand Down
2 changes: 1 addition & 1 deletion examples/guided_tour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn main() -> Result<()> {
}

impl UserData for Vec2 {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("magnitude", |_, vec, ()| {
let mag_squared = vec.0 * vec.0 + vec.1 * vec.1;
Ok(mag_squared.sqrt())
Expand Down
4 changes: 2 additions & 2 deletions examples/userdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Rectangle {
}

impl UserData for Rectangle {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("length", |_, this| Ok(this.length));
fields.add_field_method_set("length", |_, this, val| {
this.length = val;
Expand All @@ -20,7 +20,7 @@ impl UserData for Rectangle {
});
}

fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("area", |_, this, ()| Ok(this.length * this.width));
methods.add_method("diagonal", |_, this, ()| {
Ok((this.length.pow(2) as f64 + this.width.pow(2) as f64).sqrt())
Expand Down
13 changes: 7 additions & 6 deletions src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,10 +513,10 @@ impl PartialEq for Function {
}
}

pub(crate) struct WrappedFunction(pub(crate) Callback<'static>);
pub(crate) struct WrappedFunction(pub(crate) Callback);

#[cfg(feature = "async")]
pub(crate) struct WrappedAsyncFunction(pub(crate) AsyncCallback<'static>);
pub(crate) struct WrappedAsyncFunction(pub(crate) AsyncCallback);

impl Function {
/// Wraps a Rust function or closure, returning an opaque type that implements [`IntoLua`]
Expand Down Expand Up @@ -558,15 +558,16 @@ impl Function {
where
A: FromLuaMulti,
R: IntoLuaMulti,
F: Fn(&Lua, A) -> FR + MaybeSend + 'static,
F: Fn(Lua, A) -> FR + MaybeSend + 'static,
FR: Future<Output = Result<R>> + MaybeSend + 'static,
{
WrappedAsyncFunction(Box::new(move |lua, args| unsafe {
let args = match A::from_lua_args(args, 1, None, lua) {
WrappedAsyncFunction(Box::new(move |rawlua, nargs| unsafe {
let args = match A::from_stack_args(nargs, 1, None, rawlua) {
Ok(args) => args,
Err(e) => return Box::pin(future::ready(Err(e))),
};
let fut = func(lua, args);
let lua = rawlua.lua().clone();
let fut = func(lua.clone(), args);
Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
}))
}
Expand Down
27 changes: 10 additions & 17 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,6 @@ impl LuaOptions {
}
}

#[cfg(not(feature = "module"))]
impl Drop for Lua {
fn drop(&mut self) {
let _ = self.gc_collect();
}
}

impl fmt::Debug for Lua {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Lua({:p})", self.lock().state())
Expand Down Expand Up @@ -1138,7 +1131,7 @@ impl Lua {
/// use std::time::Duration;
/// use mlua::{Lua, Result};
///
/// async fn sleep(_lua: &Lua, n: u64) -> Result<&'static str> {
/// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
/// tokio::time::sleep(Duration::from_millis(n)).await;
/// Ok("done")
/// }
Expand All @@ -1157,20 +1150,20 @@ impl Lua {
/// [`AsyncThread`]: crate::AsyncThread
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn create_async_function<'lua, 'a, F, A, FR, R>(&'lua self, func: F) -> Result<Function>
pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
where
'lua: 'a,
F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
F: Fn(Lua, A) -> FR + MaybeSend + 'static,
A: FromLuaMulti,
FR: Future<Output = Result<R>> + MaybeSend + 'a,
FR: Future<Output = Result<R>> + MaybeSend + 'static,
R: IntoLuaMulti,
{
(self.lock()).create_async_callback(Box::new(move |lua, args| unsafe {
let args = match A::from_lua_args(args, 1, None, lua) {
(self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
let args = match A::from_stack_args(nargs, 1, None, rawlua) {
Ok(args) => args,
Err(e) => return Box::pin(future::ready(Err(e))),
};
let fut = func(lua, args);
let lua = rawlua.lua().clone();
let fut = func(lua.clone(), args);
Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
}))
}
Expand Down Expand Up @@ -1274,11 +1267,11 @@ impl Lua {
/// struct MyUserData(i32);
///
/// impl UserData for MyUserData {
/// fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
/// fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
/// fields.add_field_method_get("val", |_, this| Ok(this.0));
/// }
///
/// fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
/// fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
/// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
/// }
/// }
Expand Down
5 changes: 1 addition & 4 deletions src/state/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,6 @@ impl RawLua {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;

let func = mem::transmute::<Callback, Callback<'static>>(func);
let extra = XRc::clone(&self.extra);
let protect = !self.unlikely_memory_error();
push_internal_userdata(state, CallbackUpvalue { data: func, extra }, protect)?;
Expand Down Expand Up @@ -1090,9 +1089,8 @@ impl RawLua {
let rawlua = (*extra).raw_lua();
let _guard = StateGuard::new(rawlua, state);

let args = MultiValue::from_stack_multi(nargs, rawlua)?;
let func = &*(*upvalue).data;
let fut = func(rawlua.lua(), args);
let fut = func(rawlua, nargs);
let extra = XRc::clone(&(*upvalue).extra);
let protect = !rawlua.unlikely_memory_error();
push_internal_userdata(state, AsyncPollUpvalue { data: fut, extra }, protect)?;
Expand Down Expand Up @@ -1152,7 +1150,6 @@ impl RawLua {
let _sg = StackGuard::new(state);
check_stack(state, 4)?;

let func = mem::transmute::<AsyncCallback, AsyncCallback<'static>>(func);
let extra = XRc::clone(&self.extra);
let protect = !self.unlikely_memory_error();
let upvalue = AsyncCallbackUpvalue { data: func, extra };
Expand Down
12 changes: 4 additions & 8 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ use crate::error::Result;
use crate::hook::Debug;
use crate::state::{ExtraData, Lua, RawLua, WeakLua};

#[cfg(feature = "async")]
use crate::value::MultiValue;

#[cfg(all(feature = "async", feature = "send"))]
pub(crate) type BoxFuture<'a, T> = futures_util::future::BoxFuture<'a, T>;

Expand Down Expand Up @@ -52,21 +49,20 @@ unsafe impl Send for LightUserData {}
#[cfg(feature = "send")]
unsafe impl Sync for LightUserData {}

pub(crate) type Callback<'a> = Box<dyn Fn(&'a RawLua, c_int) -> Result<c_int> + 'static>;
pub(crate) type Callback = Box<dyn Fn(&RawLua, c_int) -> Result<c_int> + 'static>;

pub(crate) struct Upvalue<T> {
pub(crate) data: T,
pub(crate) extra: XRc<UnsafeCell<ExtraData>>,
}

pub(crate) type CallbackUpvalue = Upvalue<Callback<'static>>;
pub(crate) type CallbackUpvalue = Upvalue<Callback>;

#[cfg(feature = "async")]
pub(crate) type AsyncCallback<'a> =
Box<dyn Fn(&'a Lua, MultiValue) -> BoxFuture<'a, Result<c_int>> + 'static>;
pub(crate) type AsyncCallback = Box<dyn Fn(&RawLua, c_int) -> BoxFuture<'static, Result<c_int>> + 'static>;

#[cfg(feature = "async")]
pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback<'static>>;
pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback>;

#[cfg(feature = "async")]
pub(crate) type AsyncPollUpvalue = Upvalue<BoxFuture<'static, Result<c_int>>>;
Expand Down
Loading

0 comments on commit 9931709

Please sign in to comment.