Skip to content

Commit 9931709

Browse files
committed
Remove explicit lifetime from UserDataMethods and UserDataFields traits.
Pass `'static` arguments to async functions and require `'static` Future. (in future we can use async closures to make it more elegant).
1 parent 8092f00 commit 9931709

18 files changed

+403
-361
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ luau-vector4 = ["luau", "ffi/luau-vector4"]
3838
vendored = ["ffi/vendored"]
3939
module = ["dep:mlua_derive", "ffi/module"]
4040
async = ["dep:futures-util"]
41-
send = []
41+
send = ["parking_lot/send_guard"]
4242
serialize = ["dep:serde", "dep:erased-serde", "dep:serde-value"]
4343
macros = ["mlua_derive/macros"]
4444
unstable = []

benches/benchmark.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ fn userdata_create(c: &mut Criterion) {
297297
fn userdata_call_index(c: &mut Criterion) {
298298
struct UserData(#[allow(unused)] i64);
299299
impl LuaUserData for UserData {
300-
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
300+
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
301301
methods.add_meta_method(LuaMetaMethod::Index, move |_, _, key: LuaString| Ok(key));
302302
}
303303
}
@@ -323,7 +323,7 @@ fn userdata_call_index(c: &mut Criterion) {
323323
fn userdata_call_method(c: &mut Criterion) {
324324
struct UserData(i64);
325325
impl LuaUserData for UserData {
326-
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
326+
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
327327
methods.add_method("add", |_, this, i: i64| Ok(this.0 + i));
328328
}
329329
}
@@ -353,7 +353,7 @@ fn userdata_call_method(c: &mut Criterion) {
353353
fn userdata_async_call_method(c: &mut Criterion) {
354354
struct UserData(i64);
355355
impl LuaUserData for UserData {
356-
fn add_methods<'a, M: LuaUserDataMethods<'a, Self>>(methods: &mut M) {
356+
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
357357
methods.add_async_method("add", |_, this, i: i64| async move {
358358
task::yield_now().await;
359359
Ok(this.0 + i)

examples/async_http_client.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use mlua::{chunk, ExternalResult, Lua, Result, UserData, UserDataMethods};
1010
struct BodyReader(Incoming);
1111

1212
impl UserData for BodyReader {
13-
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
13+
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1414
// Every call returns a next chunk
15-
methods.add_async_method_mut("read", |lua, reader, ()| async move {
15+
methods.add_async_method_mut("read", |lua, mut reader, ()| async move {
1616
if let Some(bytes) = reader.0.frame().await {
1717
if let Some(bytes) = bytes.into_lua_err()?.data_ref() {
1818
return Some(lua.create_string(&bytes)).transpose();

examples/async_http_server.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use mlua::{chunk, Error as LuaError, Function, Lua, String as LuaString, Table,
1717
struct LuaRequest(SocketAddr, Request<Incoming>);
1818

1919
impl UserData for LuaRequest {
20-
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
20+
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
2121
methods.add_method("remote_addr", |_, req, ()| Ok((req.0).to_string()));
2222
methods.add_method("method", |_, req, ()| Ok((req.1).method().to_string()));
2323
methods.add_method("path", |_, req, ()| Ok(req.1.uri().path().to_string()));

examples/async_tcp_server.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ use mlua::{chunk, BString, Function, Lua, UserData, UserDataMethods};
99
struct LuaTcpStream(TcpStream);
1010

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

15-
methods.add_async_method_mut("read", |lua, this, size| async move {
15+
methods.add_async_method_mut("read", |lua, mut this, size| async move {
1616
let mut buf = vec![0; size];
1717
let n = this.0.read(&mut buf).await?;
1818
buf.truncate(n);
1919
lua.create_string(&buf)
2020
});
2121

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

27-
methods.add_async_method_mut("close", |_, this, ()| async move {
27+
methods.add_async_method_mut("close", |_, mut this, ()| async move {
2828
this.0.shutdown().await?;
2929
Ok(())
3030
});

examples/guided_tour.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn main() -> Result<()> {
162162
}
163163

164164
impl UserData for Vec2 {
165-
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
165+
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
166166
methods.add_method("magnitude", |_, vec, ()| {
167167
let mag_squared = vec.0 * vec.0 + vec.1 * vec.1;
168168
Ok(mag_squared.sqrt())

examples/userdata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct Rectangle {
77
}
88

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

23-
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
23+
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
2424
methods.add_method("area", |_, this, ()| Ok(this.length * this.width));
2525
methods.add_method("diagonal", |_, this, ()| {
2626
Ok((this.length.pow(2) as f64 + this.width.pow(2) as f64).sqrt())

src/function.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -513,10 +513,10 @@ impl PartialEq for Function {
513513
}
514514
}
515515

516-
pub(crate) struct WrappedFunction(pub(crate) Callback<'static>);
516+
pub(crate) struct WrappedFunction(pub(crate) Callback);
517517

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

521521
impl Function {
522522
/// Wraps a Rust function or closure, returning an opaque type that implements [`IntoLua`]
@@ -558,15 +558,16 @@ impl Function {
558558
where
559559
A: FromLuaMulti,
560560
R: IntoLuaMulti,
561-
F: Fn(&Lua, A) -> FR + MaybeSend + 'static,
561+
F: Fn(Lua, A) -> FR + MaybeSend + 'static,
562562
FR: Future<Output = Result<R>> + MaybeSend + 'static,
563563
{
564-
WrappedAsyncFunction(Box::new(move |lua, args| unsafe {
565-
let args = match A::from_lua_args(args, 1, None, lua) {
564+
WrappedAsyncFunction(Box::new(move |rawlua, nargs| unsafe {
565+
let args = match A::from_stack_args(nargs, 1, None, rawlua) {
566566
Ok(args) => args,
567567
Err(e) => return Box::pin(future::ready(Err(e))),
568568
};
569-
let fut = func(lua, args);
569+
let lua = rawlua.lua().clone();
570+
let fut = func(lua.clone(), args);
570571
Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
571572
}))
572573
}

src/state.rs

+10-17
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,6 @@ impl LuaOptions {
137137
}
138138
}
139139

140-
#[cfg(not(feature = "module"))]
141-
impl Drop for Lua {
142-
fn drop(&mut self) {
143-
let _ = self.gc_collect();
144-
}
145-
}
146-
147140
impl fmt::Debug for Lua {
148141
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
149142
write!(f, "Lua({:p})", self.lock().state())
@@ -1138,7 +1131,7 @@ impl Lua {
11381131
/// use std::time::Duration;
11391132
/// use mlua::{Lua, Result};
11401133
///
1141-
/// async fn sleep(_lua: &Lua, n: u64) -> Result<&'static str> {
1134+
/// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
11421135
/// tokio::time::sleep(Duration::from_millis(n)).await;
11431136
/// Ok("done")
11441137
/// }
@@ -1157,20 +1150,20 @@ impl Lua {
11571150
/// [`AsyncThread`]: crate::AsyncThread
11581151
#[cfg(feature = "async")]
11591152
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1160-
pub fn create_async_function<'lua, 'a, F, A, FR, R>(&'lua self, func: F) -> Result<Function>
1153+
pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
11611154
where
1162-
'lua: 'a,
1163-
F: Fn(&'a Lua, A) -> FR + MaybeSend + 'static,
1155+
F: Fn(Lua, A) -> FR + MaybeSend + 'static,
11641156
A: FromLuaMulti,
1165-
FR: Future<Output = Result<R>> + MaybeSend + 'a,
1157+
FR: Future<Output = Result<R>> + MaybeSend + 'static,
11661158
R: IntoLuaMulti,
11671159
{
1168-
(self.lock()).create_async_callback(Box::new(move |lua, args| unsafe {
1169-
let args = match A::from_lua_args(args, 1, None, lua) {
1160+
(self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1161+
let args = match A::from_stack_args(nargs, 1, None, rawlua) {
11701162
Ok(args) => args,
11711163
Err(e) => return Box::pin(future::ready(Err(e))),
11721164
};
1173-
let fut = func(lua, args);
1165+
let lua = rawlua.lua().clone();
1166+
let fut = func(lua.clone(), args);
11741167
Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
11751168
}))
11761169
}
@@ -1274,11 +1267,11 @@ impl Lua {
12741267
/// struct MyUserData(i32);
12751268
///
12761269
/// impl UserData for MyUserData {
1277-
/// fn add_fields<'a, F: UserDataFields<'a, Self>>(fields: &mut F) {
1270+
/// fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
12781271
/// fields.add_field_method_get("val", |_, this| Ok(this.0));
12791272
/// }
12801273
///
1281-
/// fn add_methods<'a, M: UserDataMethods<'a, Self>>(methods: &mut M) {
1274+
/// fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
12821275
/// methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
12831276
/// }
12841277
/// }

src/state/raw.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,6 @@ impl RawLua {
10531053
let _sg = StackGuard::new(state);
10541054
check_stack(state, 4)?;
10551055

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

1093-
let args = MultiValue::from_stack_multi(nargs, rawlua)?;
10941092
let func = &*(*upvalue).data;
1095-
let fut = func(rawlua.lua(), args);
1093+
let fut = func(rawlua, nargs);
10961094
let extra = XRc::clone(&(*upvalue).extra);
10971095
let protect = !rawlua.unlikely_memory_error();
10981096
push_internal_userdata(state, AsyncPollUpvalue { data: fut, extra }, protect)?;
@@ -1152,7 +1150,6 @@ impl RawLua {
11521150
let _sg = StackGuard::new(state);
11531151
check_stack(state, 4)?;
11541152

1155-
let func = mem::transmute::<AsyncCallback, AsyncCallback<'static>>(func);
11561153
let extra = XRc::clone(&self.extra);
11571154
let protect = !self.unlikely_memory_error();
11581155
let upvalue = AsyncCallbackUpvalue { data: func, extra };

src/types.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ use crate::error::Result;
1212
use crate::hook::Debug;
1313
use crate::state::{ExtraData, Lua, RawLua, WeakLua};
1414

15-
#[cfg(feature = "async")]
16-
use crate::value::MultiValue;
17-
1815
#[cfg(all(feature = "async", feature = "send"))]
1916
pub(crate) type BoxFuture<'a, T> = futures_util::future::BoxFuture<'a, T>;
2017

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

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

5754
pub(crate) struct Upvalue<T> {
5855
pub(crate) data: T,
5956
pub(crate) extra: XRc<UnsafeCell<ExtraData>>,
6057
}
6158

62-
pub(crate) type CallbackUpvalue = Upvalue<Callback<'static>>;
59+
pub(crate) type CallbackUpvalue = Upvalue<Callback>;
6360

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

6864
#[cfg(feature = "async")]
69-
pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback<'static>>;
65+
pub(crate) type AsyncCallbackUpvalue = Upvalue<AsyncCallback>;
7066

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

0 commit comments

Comments
 (0)