-
-
Notifications
You must be signed in to change notification settings - Fork 196
add_method_mut does 2 different kinds of mutation #691
Description
Context:
I was implementing a Lua API using mlua and ran into the RecursiveMutCallback error.
This is because I want to call a method defined with add_method_mut recursively.
My code is traversing a tree and mutating the nodes along the way.
There is the issue: for my implementation, I do not need to mutate state, so the FnMut trait on add_method_mut is not needed for me. However, I do need mutable access to the object on which the method is called, so add_method is not an option.
Basically, I would need an API like this:
fn add_method_mut<M, A, R>(&mut self, name: impl Into<String>, method: M)
where
M: Fn(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static, // <-- notice the Fn instead of the FnMut, but &mut stays
A: FromLuaMulti,
R: IntoLuaMulti,Currently, a workaround is to wrap my T inside a RefCell which fix my issue, but it makes my code for verbose and adds a bit of overhead.
What would you think of adding on the UserDataMethods trait a function like this?
// It would need a better name obviously
fn add_method_self_mut<M, A, R>(&mut self, name: impl Into<String>, method: M)
where
M: Fn(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
A: FromLuaMulti,
R: IntoLuaMulti,One might think that we could make it so that, add_method could take a &mut T as input:
fn add_method<M, A, R>(&mut self, name: impl Into<String>, method: M)
where
M: Fn(&Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
A: FromLuaMulti,
R: IntoLuaMulti,
{
let name = name.into();
let callback = self.box_method(&name, method); // you'd need to update box_method to use `borrow_userdata_scoped_mut` for this to work.
self.raw.methods.push((name, callback));
}However, in that case if a method calls another method recusively on the same object, one would now get a UserDataBorrowMutError.
This is why a third method, in addition to add_method and add_method_mut is needed in my opinion.
If you agree, I am willing to implement it.