Summary
In embedded architectures or standalone plugin middleware where callbacks are driven externally, it is often difficult or impossible to pass a root Lua context handle down through execution arguments.
Because mlua values (like mlua::String and mlua::Table) already hold internal references back to the core Lua registry via ValueRef, the state is technically already present inside the values. I would like to request a public, safe API method to upgrade or retrieve this handle—such as a pub fn lua(&self) -> Option(&Lua) or pub fn weak_lua(&self) -> Option<WeakLua> method on standard value types.
The Problem / Motivation
When writing libraries or plugins that hook into an orchestrator, we frequently face the following constraints:
- Callback Constraints: We don't control the top-level callback signatures, meaning we cannot pass
&Lua or a thread context down through standard arguments.
- Concurrency Bottlenecks: Attempting to store the Lua engine in a global
Mutex or RwLock to share it across simultaneous function invocations creates major performance bottlenecks and can easily introduce deadlocks if a script execution yields while holding the lock.
Because mlua relies on internal reference counting tied back to the root registry, the objects themselves are already holding onto the state we desperately need to query.
Proof of Concept
To illustrate the severity of this limitation, it is currently possible to bypass crate privacy boundaries via type-inference manipulation and memory layout transmutation to get the handle anyway.
While this works, it relies entirely on undefined behavior and structural layout symmetry that could break at any time:
use ::core::mem::transmute;
use ::mlua::{self, ObjectLike as _};
/// Uses type inference tricks and layout transmutations to force-extract
/// the Lua instance from an opaque mlua::String.
pub(crate) fn extract_lua_from_string(string: mlua::String) -> mlua::Result<mlua::Lua> {
let value_ref = if false {
// Forces type inference to match the pub(crate) ValueRef
match mlua::Value::String(string.clone()) {
mlua::Value::Other(vref) => vref,
_ => unsafe { std::hint::unreachable_unchecked() },
}
} else {
unsafe { transmute(string) }
};
// Transmute the inferred reference into a Table layout to invoke weak_lua()
let table: mlua::Table = unsafe { transmute([value_ref]) };
let weak_lua = table.weak_lua();
weak_lua.try_upgrade().ok_or(mlua::Error::external("Could not upgrade `WeakLua`."))
}
Proposed Solutions
To eliminate the need for dangerous, fragile transmute workarounds in the community, I would love to see one of the following official additions:
- Direct Accessors: Implement
pub fn lua(&self) -> Option<&Lua> directly on String, Table, Function, and other types wrapping ValueRef.
- Weak Handle Leakage: Expose a public
pub fn weak_lua(&self) -> Option<WeakLua> method (or expose it via a shared trait) so developers can safely upgrade to a concrete context handle when absolutely required by standalone architectures.
I am more than happy to open a Pull Request implementing this if the core design changes are acceptable to the maintainers!
Summary
In embedded architectures or standalone plugin middleware where callbacks are driven externally, it is often difficult or impossible to pass a root Lua context handle down through execution arguments.
Because
mluavalues (likemlua::Stringandmlua::Table) already hold internal references back to the core Lua registry via ValueRef, the state is technically already present inside the values. I would like to request a public, safe API method to upgrade or retrieve this handle—such as apub fn lua(&self) -> Option(&Lua)orpub fn weak_lua(&self) -> Option<WeakLua>method on standard value types.The Problem / Motivation
When writing libraries or plugins that hook into an orchestrator, we frequently face the following constraints:
&Luaor a thread context down through standard arguments.MutexorRwLockto share it across simultaneous function invocations creates major performance bottlenecks and can easily introduce deadlocks if a script execution yields while holding the lock.Because
mluarelies on internal reference counting tied back to the root registry, the objects themselves are already holding onto the state we desperately need to query.Proof of Concept
To illustrate the severity of this limitation, it is currently possible to bypass crate privacy boundaries via type-inference manipulation and memory layout transmutation to get the handle anyway.
While this works, it relies entirely on undefined behavior and structural layout symmetry that could break at any time:
Proposed Solutions
To eliminate the need for dangerous, fragile transmute workarounds in the community, I would love to see one of the following official additions:
pub fn lua(&self) -> Option<&Lua>directly onString,Table,Function, and other types wrappingValueRef.pub fn weak_lua(&self) -> Option<WeakLua>method (or expose it via a shared trait) so developers can safely upgrade to a concrete context handle when absolutely required by standalone architectures.I am more than happy to open a Pull Request implementing this if the core design changes are acceptable to the maintainers!