Use MaybeUninit instead of hack in protect_lua_closure

This commit is contained in:
Alex Orlenko 2022-07-17 11:33:51 +01:00
parent f75af6d75f
commit f9ff6116db
No known key found for this signature in database
GPG key ID: 4C150C250863B96D

View file

@ -1,6 +1,7 @@
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt::Write; use std::fmt::Write;
use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int, c_void}; use std::os::raw::{c_char, c_int, c_void};
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
use std::sync::Arc; use std::sync::Arc;
@ -136,26 +137,21 @@ where
F: Fn(*mut ffi::lua_State) -> R, F: Fn(*mut ffi::lua_State) -> R,
R: Copy, R: Copy,
{ {
union URes<R: Copy> {
uninit: (),
init: R,
}
struct Params<F, R: Copy> { struct Params<F, R: Copy> {
function: F, function: F,
result: URes<R>, result: MaybeUninit<R>,
nresults: c_int, nresults: c_int,
} }
unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
where where
R: Copy,
F: Fn(*mut ffi::lua_State) -> R, F: Fn(*mut ffi::lua_State) -> R,
R: Copy,
{ {
let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>; let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
ffi::lua_pop(state, 1); ffi::lua_pop(state, 1);
(*params).result.init = ((*params).function)(state); (*params).result.write(((*params).function)(state));
if (*params).nresults == ffi::LUA_MULTRET { if (*params).nresults == ffi::LUA_MULTRET {
ffi::lua_gettop(state) ffi::lua_gettop(state)
@ -174,7 +170,7 @@ where
let mut params = Params { let mut params = Params {
function: f, function: f,
result: URes { uninit: () }, result: MaybeUninit::uninit(),
nresults, nresults,
}; };
@ -185,7 +181,7 @@ where
if ret == ffi::LUA_OK { if ret == ffi::LUA_OK {
// `LUA_OK` is only returned when the `do_call` function has completed successfully, so // `LUA_OK` is only returned when the `do_call` function has completed successfully, so
// `params.result` is definitely initialized. // `params.result` is definitely initialized.
Ok(params.result.init) Ok(params.result.assume_init())
} else { } else {
Err(pop_error(state, ret)) Err(pop_error(state, ret))
} }