lua_types/closure.rs
1//! `LuaClosure` — the function variant of `LuaValue`. Three sub-kinds:
2//! Lua closure (compiled Proto + upvalues), C closure (function pointer +
3//! upvalues), light C function (function pointer, no upvalues).
4
5use std::cell::Cell;
6
7use crate::gc::GcRef;
8use crate::proto::LuaProto;
9use crate::upval::UpVal;
10use crate::value::LuaValue;
11
12/// Opaque registry index into `GlobalState.c_functions`, where the real
13/// `lua_CFunction` (`fn(&mut LuaState) -> Result<usize, LuaError>`) is stored.
14/// Lua-types can't reference `LuaState` without a circular dep, so we keep
15/// the closure variant type-erased here and resolve through the registry at
16/// call time.
17pub type LuaCFnPtr = usize;
18
19#[derive(Debug, Clone, Copy)]
20pub enum LuaClosure {
21 Lua(GcRef<LuaLClosure>),
22 C(GcRef<LuaCClosure>),
23 LightC(LuaCFnPtr),
24}
25
26#[derive(Debug)]
27pub struct LuaLClosure {
28 pub proto: GcRef<LuaProto>,
29 /// Each upvalue slot is held in a `Cell` so that `debug.upvaluejoin`
30 /// can replace an entry with another closure's slot without rebuilding
31 /// the (shared) closure. `GcRef<UpVal>` is `Copy` (thin wrapper over
32 /// `Gc<UpVal>`), so a plain `Cell` is sufficient and skips RefCell
33 /// borrow tracking on every upvalue read — critical for the
34 /// `upvalue_get` hot path.
35 pub upvals: Vec<Cell<GcRef<UpVal>>>,
36}
37
38#[derive(Debug)]
39pub struct LuaCClosure {
40 pub func: LuaCFnPtr,
41 pub upvalues: Vec<LuaValue>,
42}
43
44impl LuaLClosure {
45 pub fn placeholder() -> Self {
46 LuaLClosure {
47 proto: GcRef::new(LuaProto::placeholder()),
48 upvals: Vec::new(),
49 }
50 }
51
52 /// Returns the upvalue slot at index `i`. Cheap (Copy of a one-pointer
53 /// `GcRef<UpVal>`).
54 #[inline(always)]
55 pub fn upval(&self, i: usize) -> GcRef<UpVal> {
56 self.upvals[i].get()
57 }
58
59 /// Replaces the upvalue slot at index `i` with `new`. Used by
60 /// `debug.upvaluejoin` to share an upvalue between two closures.
61 pub fn set_upval(&self, i: usize, new: GcRef<UpVal>) {
62 self.upvals[i].set(new);
63 }
64}
65
66// ──────────────────────────────────────────────────────────────────────────────
67// PORT STATUS
68// source: src/lobject.h (CClosure / LClosure / Closure union)
69// target_crate: lua-types
70// confidence: high
71// todos: 0
72// port_notes: 0
73// unsafe_blocks: 0
74// notes: LuaClosure enum covering the C-Lua C/LightC/Lua closure variants.
75// C uses a union with a common header; we use a tagged enum.
76// LuaLClosure.upvals uses Cell<GcRef<UpVal>> (not RefCell) so per-
77// upvalue reads avoid borrow-tracking; GcRef<UpVal> is Copy.
78// ──────────────────────────────────────────────────────────────────────────────