Hide Lua "Send" capability under the optional "send" feature flag

This commit is contained in:
Alex Orlenko 2020-05-06 13:18:04 +01:00
parent 7b0e4b4280
commit 2bd5c2f6ca
6 changed files with 71 additions and 45 deletions

View File

@ -35,6 +35,7 @@ lua51 = []
luajit = []
vendored = ["lua-src", "luajit-src"]
async = ["futures-core", "futures-task", "futures-util"]
send = []
[dependencies]
bstr = { version = "0.2", features = ["std"], default_features = false }

View File

@ -12,7 +12,7 @@ use crate::lua::Lua;
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
use crate::types::{LightUserData, Number};
use crate::types::{LightUserData, Number, MaybeSend};
use crate::userdata::{AnyUserData, UserData};
use crate::value::{FromLua, Nil, ToLua, Value};
@ -122,7 +122,7 @@ impl<'lua> FromLua<'lua> for AnyUserData<'lua> {
}
}
impl<'lua, T: 'static + Send + UserData> ToLua<'lua> for T {
impl<'lua, T: 'static + MaybeSend + UserData> ToLua<'lua> for T {
fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
Ok(Value::UserData(lua.create_userdata(self)?))
}

View File

@ -127,7 +127,10 @@ pub enum Error {
/// Returning `Err(ExternalError(...))` from a Rust callback will raise the error as a Lua
/// error. The Rust code that originally invoked the Lua code then receives a `CallbackError`,
/// from which the original error (and a stack traceback) can be recovered.
#[cfg(feature = "send")]
ExternalError(Arc<dyn StdError + Send + Sync>),
#[cfg(not(feature = "send"))]
ExternalError(Arc<dyn StdError>),
}
/// A specialized `Result` type used by `mlua`'s API.
@ -206,19 +209,30 @@ impl StdError for Error {
}
impl Error {
#[cfg(feature = "send")]
pub fn external<T: Into<Box<dyn StdError + Send + Sync>>>(err: T) -> Error {
Error::ExternalError(err.into().into())
}
#[cfg(not(feature = "send"))]
pub fn external<T: Into<Box<dyn StdError>>>(err: T) -> Error {
Error::ExternalError(err.into().into())
}
}
pub trait ExternalError {
fn to_lua_err(self) -> Error;
}
impl<E> ExternalError for E
where
E: Into<Box<dyn StdError + Send + Sync>>,
{
#[cfg(feature = "send")]
impl<E: Into<Box<dyn StdError + Send + Sync>>> ExternalError for E {
fn to_lua_err(self) -> Error {
Error::external(self)
}
}
#[cfg(not(feature = "send"))]
impl<E: Into<Box<dyn StdError>>> ExternalError for E {
fn to_lua_err(self) -> Error {
Error::external(self)
}

View File

@ -14,7 +14,7 @@ use crate::stdlib::StdLib;
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
use crate::types::{Callback, Integer, LightUserData, LuaRef, Number, RegistryKey};
use crate::types::{Callback, Integer, LightUserData, LuaRef, Number, RegistryKey, MaybeSend};
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
use crate::util::{
assert_stack, callback_error, check_stack, get_gc_userdata, get_main_state,
@ -56,6 +56,7 @@ struct ExtraData {
ref_free: Vec<c_int>,
}
#[cfg(feature = "send")]
unsafe impl Send for Lua {}
#[cfg(feature = "async")]
@ -215,7 +216,7 @@ impl Lua {
where
'lua: 'callback,
R: ToLua<'callback>,
F: 'static + Send + Fn(&'callback Lua) -> Result<R>,
F: 'static + MaybeSend + Fn(&'callback Lua) -> Result<R>,
{
let cb = self.create_callback(Box::new(move |lua, _| func(lua)?.to_lua_multi(lua)))?;
unsafe { self.push_value(cb.call(())?).map(|_| 1) }
@ -473,7 +474,7 @@ impl Lua {
'lua: 'callback,
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'static + Send + Fn(&'callback Lua, A) -> Result<R>,
F: 'static + MaybeSend + Fn(&'callback Lua, A) -> Result<R>,
{
self.create_callback(Box::new(move |lua, args| {
func(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
@ -494,7 +495,7 @@ impl Lua {
'lua: 'callback,
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'static + Send + FnMut(&'callback Lua, A) -> Result<R>,
F: 'static + MaybeSend + FnMut(&'callback Lua, A) -> Result<R>,
{
let func = RefCell::new(func);
self.create_function(move |lua, args| {
@ -551,7 +552,7 @@ impl Lua {
'lua: 'callback,
A: FromLuaMulti<'callback>,
R: ToLuaMulti<'callback>,
F: 'static + Send + Fn(&'callback Lua, A) -> FR,
F: 'static + MaybeSend + Fn(&'callback Lua, A) -> FR,
FR: 'lua + Future<Output = Result<R>>,
{
self.create_async_callback(Box::new(move |lua, args| {
@ -583,7 +584,7 @@ impl Lua {
/// Create a Lua userdata object from a custom userdata type.
pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
where
T: 'static + Send + UserData,
T: 'static + MaybeSend + UserData,
{
unsafe { self.make_userdata(data) }
}
@ -1607,10 +1608,10 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> {
impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> {
fn add_method<S, A, R, M>(&mut self, name: &S, method: M)
where
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, &T, A) -> Result<R>,
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
{
self.methods
.push((name.as_ref().to_vec(), Self::box_method(method)));
@ -1618,10 +1619,10 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
fn add_method_mut<S, A, R, M>(&mut self, name: &S, method: M)
where
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
{
self.methods
.push((name.as_ref().to_vec(), Self::box_method_mut(method)));
@ -1631,10 +1632,10 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
fn add_async_method<S, A, R, M, MR>(&mut self, name: &S, method: M)
where
T: Clone,
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, T, A) -> MR,
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
MR: 'lua + Future<Output = Result<R>>,
{
self.async_methods
@ -1643,10 +1644,10 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
fn add_function<S, A, R, F>(&mut self, name: &S, function: F)
where
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
{
self.methods
.push((name.as_ref().to_vec(), Self::box_function(function)));
@ -1654,10 +1655,10 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
fn add_function_mut<S, A, R, F>(&mut self, name: &S, function: F)
where
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + FnMut(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
{
self.methods
.push((name.as_ref().to_vec(), Self::box_function_mut(function)));
@ -1667,10 +1668,10 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
fn add_async_function<S, A, R, F, FR>(&mut self, name: &S, function: F)
where
T: Clone,
S: ?Sized + AsRef<[u8]>,
S: AsRef<[u8]> + ?Sized,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> FR,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
FR: 'lua + Future<Output = Result<R>>,
{
self.async_methods
@ -1681,7 +1682,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, &T, A) -> Result<R>,
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
{
self.meta_methods.push((meta, Self::box_method(method)));
}
@ -1690,7 +1691,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
{
self.meta_methods.push((meta, Self::box_method_mut(method)));
}
@ -1699,7 +1700,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
{
self.meta_methods.push((meta, Self::box_function(function)));
}
@ -1708,7 +1709,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + FnMut(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
{
self.meta_methods
.push((meta, Self::box_function_mut(function)));
@ -1720,7 +1721,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, &T, A) -> Result<R>,
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
{
Box::new(move |lua, mut args| {
if let Some(front) = args.pop_front() {
@ -1741,7 +1742,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
{
let method = RefCell::new(method);
Box::new(move |lua, mut args| {
@ -1768,7 +1769,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
T: Clone,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, T, A) -> MR,
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
MR: 'lua + Future<Output = Result<R>>,
{
Box::new(move |lua, mut args| {
@ -1796,7 +1797,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
{
Box::new(move |lua, args| function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua))
}
@ -1805,7 +1806,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + FnMut(&'lua Lua, A) -> Result<R>,
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
{
let function = RefCell::new(function);
Box::new(move |lua, args| {
@ -1821,7 +1822,7 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> FR,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
FR: 'lua + Future<Output = Result<R>>,
{
Box::new(move |lua, args| {

View File

@ -27,6 +27,16 @@ pub(crate) type Callback<'lua, 'a> =
pub(crate) type AsyncCallback<'lua, 'a> =
Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> LocalBoxFuture<'lua, Result<MultiValue<'lua>>> + 'a>;
#[cfg(feature = "send")]
pub trait MaybeSend: Send {}
#[cfg(feature = "send")]
impl<T: Send> MaybeSend for T {}
#[cfg(not(feature = "send"))]
pub trait MaybeSend {}
#[cfg(not(feature = "send"))]
impl<T> MaybeSend for T {}
/// An auto generated key into the Lua registry.
///
/// This is a handle to a value stored inside the Lua registry. It is not automatically

View File

@ -8,7 +8,7 @@ use crate::ffi;
use crate::function::Function;
use crate::lua::Lua;
use crate::table::Table;
use crate::types::LuaRef;
use crate::types::{LuaRef, MaybeSend};
use crate::util::{assert_stack, get_userdata, StackGuard};
use crate::value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
@ -137,7 +137,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, &T, A) -> Result<R>;
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
/// Add a regular method which accepts a `&mut T` as the first parameter.
///
@ -149,7 +149,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
/// Add an async method which accepts a `T` as the first parameter and returns Future.
/// The passed `T` is cloned from the original value.
@ -164,7 +164,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, T, A) -> MR,
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
MR: 'lua + Future<Output = Result<R>>;
/// Add a regular method as a function which accepts generic arguments, the first argument will
@ -181,7 +181,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> Result<R>;
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
/// Add a regular method as a mutable function which accepts generic arguments.
///
@ -193,7 +193,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + FnMut(&'lua Lua, A) -> Result<R>;
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
/// Add a regular method as an async function which accepts generic arguments
/// and returns Future.
@ -208,7 +208,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
S: ?Sized + AsRef<[u8]>,
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> FR,
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
FR: 'lua + Future<Output = Result<R>>;
/// Add a metamethod which accepts a `&T` as the first parameter.
@ -223,7 +223,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + Fn(&'lua Lua, &T, A) -> Result<R>;
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
/// Add a metamethod as a function which accepts a `&mut T` as the first parameter.
///
@ -237,7 +237,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
M: 'static + Send + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
/// Add a metamethod which accepts generic arguments.
///
@ -248,7 +248,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + Fn(&'lua Lua, A) -> Result<R>;
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
/// Add a metamethod as a mutable function which accepts generic arguments.
///
@ -259,7 +259,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
where
A: FromLuaMulti<'lua>,
R: ToLuaMulti<'lua>,
F: 'static + Send + FnMut(&'lua Lua, A) -> Result<R>;
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
}
/// Trait for custom userdata types.