Skip to content

Expose a public method to retrieve the Lua runtime (or WeakLua) from values #714

Description

@Renderthegreat

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:

  1. Callback Constraints: We don't control the top-level callback signatures, meaning we cannot pass &Lua or a thread context down through standard arguments.
  2. 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:

  1. Direct Accessors: Implement pub fn lua(&self) -> Option<&Lua> directly on String, Table, Function, and other types wrapping ValueRef.
  2. 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions