mlua icon indicating copy to clipboard operation
mlua copied to clipboard

Missing `impl IntoLuaMulti for Either<L: IntoLuaMulti, R: IntoLuaMulti>`

Open LunarLambda opened this issue 2 months ago • 1 comments

I wanted to use create_function with this function:

fn read(lua: &Lua, filename: PathBuf) -> LuaResult<Either<String, (LuaValue, String, Option<i32>)>> {
    match std::fs::read_to_string(&filename) {
        Ok(string) => Ok(Either::Left(string)),
        Err(error) => Ok(Either::Right((
            Nil, format!("{}: {error}", filename.display()), error.raw_os_error()
        )))
    }
}

String, LuaValue (mlua::Value), and Option<i32> all implement IntoLua, so the tuple (LuaValue, String, Option<i32>) implements IntoLuaMulti. Additionally String implements IntoLuaMulti via impl<T: IntoLua> IntoLuaMulti for T

However, unfortunately Either only has impl<L: IntoLua, R: IntoLua> IntoLua for Either<L, R>, not the equivalent using IntoLuaMulti.

More unfortunately, the blanket impl IntoLuaMulti for T where T: IntoLua prevents Either from implementing both traits. There is a IntoLuaMulti impl for Result<T, E> but it too uses T: IntoLua, E: IntoLua.

I'm not sure I can propose a concrete fix, but the current set of IntoLua/IntoLuaMulti impls makes it exceedingly to difficult to do multi-valued error returns in the style of io.open (which returns nil, string, number, with the last value being the errno/error code value)

LunarLambda avatar Nov 05 '25 13:11 LunarLambda

If you change return type to LuaResult<LuaMultiValue>, then any combination of values can be returned by:

    match std::fs::read_to_string(&filename) {
        Ok(string) => string.into_lua_multi(lua),
        Err(error) => (Nil, format!("{}: {error}", filename.display()), error.raw_os_error()).into_lua_multi(lua)
    }

khvzak avatar Nov 05 '25 16:11 khvzak