This commit is contained in:
2025-06-22 15:11:37 +10:00
parent 5be3f2970c
commit 0667f79ff5
14 changed files with 508 additions and 319 deletions

View File

@@ -1,6 +1,6 @@
use crate::{
__internal::{display, type_id},
CDef, CDefBuilder, Metatype, MetatypeBuilder, ToFfi, Type, TypeBuilder,
CDef, CDefBuilder, FfiReturnConvention, Metatype, MetatypeBuilder, ToFfi, Type, TypeBuilder,
};
use luaify::luaify;
use std::{
@@ -94,12 +94,9 @@ impl<F: Future<Output: ToFfi>> lua_future<F> {
}
unsafe extern "C" fn take(&mut self) -> <F::Output as ToFfi>::To {
// `fut:__take()` returns the fulfilled value by-value because it is the lowest common
// denominator for supported return conventions (all `ToFfi` impls support return by-value;
// primitives e.g. don't support return by out-param because they get boxed in cdata).
//
// Plus, if we preallocate a cdata for out-param and the thread for some reason gets dropped
// and never resumed, GC could call the destructor on an uninitialised cdata.
// `fut:__take()` returns the fulfilled value by-value (not by out-param) because if we
// preallocate a cdata for the out-param and the thread for some reason gets dropped and
// never resumed, the GC could call the destructor on an uninitialised cdata.
match self.state {
State::Fulfilled(_) => match mem::replace(&mut self.state, State::Complete) {
State::Fulfilled(value) => value.convert(),
@@ -170,7 +167,7 @@ unsafe impl<F: Future<Output: ToFfi> + 'static> ToFfi for lua_future<F> {
self
}
fn postlude(ret: &str) -> impl Display {
fn postlude(ret: &str, _conv: FfiReturnConvention) -> impl Display {
// When returning a future from Rust to Lua, yield it immediately to the runtime which will
// poll it to completion in the background, then take the fulfilled value once the thread
// gets resumed. Lua user code should never to worry about awaiting futures.
@@ -181,7 +178,7 @@ unsafe impl<F: Future<Output: ToFfi> + 'static> ToFfi for lua_future<F> {
// `coroutine.yield` is cached as `yield` and `ffi.gc` as `gc` in locals (see lib.rs)
display!(
"yield({ret}); {ret} = gc({ret}, nil):__take(); {}",
<F::Output as ToFfi>::postlude(ret)
<F::Output as ToFfi>::postlude(ret, FfiReturnConvention::ByValue)
)
}
}