Skip to main content

mlua/
state.rs

1//! Lua state management.
2//!
3//! This module provides the main [`Lua`] state handle together with state-specific
4//! configuration and garbage collector controls.
5
6use std::any::TypeId;
7use std::cell::{BorrowError, BorrowMutError, RefCell};
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::os::raw::{c_char, c_int};
11use std::panic::Location;
12use std::result::Result as StdResult;
13use std::{fmt, mem, ptr};
14
15use crate::chunk::{AsChunk, Chunk};
16use crate::debug::Debug;
17use crate::error::{Error, Result};
18use crate::function::Function;
19use crate::memory::MemoryState;
20use crate::multi::MultiValue;
21use crate::scope::Scope;
22use crate::stdlib::StdLib;
23use crate::string::LuaString;
24use crate::table::Table;
25use crate::thread::{Thread, ThreadEvent, ThreadTriggers};
26use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
27use crate::types::{
28    AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LuaType, MaybeSend, MaybeSync, Number,
29    ReentrantMutex, ReentrantMutexGuard, RegistryKey, VmState, XRc, XWeak,
30};
31use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataStorage};
32use crate::util::{StackGuard, assert_stack, check_stack, protect_lua_closure, push_string, rawset_field};
33use crate::value::{Nil, Value};
34
35#[cfg(not(feature = "luau"))]
36use crate::{debug::HookTriggers, types::HookKind};
37
38#[cfg(any(feature = "luau", doc))]
39use crate::{buffer::Buffer, chunk::Compiler};
40
41#[cfg(feature = "async")]
42use {
43    crate::types::LightUserData,
44    std::future::{self, Future},
45    std::task::Poll,
46};
47
48#[cfg(feature = "serde")]
49use serde::Serialize;
50
51pub(crate) use extra::ExtraData;
52#[doc(hidden)]
53pub use raw::RawLua;
54pub(crate) use util::callback_error_ext;
55
56/// Top level Lua struct which represents an instance of Lua VM.
57pub struct Lua {
58    pub(self) raw: XRc<ReentrantMutex<RawLua>>,
59    // Controls whether garbage collection should be run on drop
60    pub(self) collect_garbage: bool,
61}
62
63/// Weak reference to Lua instance.
64///
65/// This can used to prevent circular references between Lua and Rust objects.
66#[derive(Clone)]
67pub struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
68
69pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
70
71/// Tuning parameters for the incremental GC collector.
72///
73/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
74/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the Lua reference manual
75/// for details.
76#[non_exhaustive]
77#[derive(Clone, Copy, Debug, Default)]
78pub struct GcIncParams {
79    /// Pause between successive GC cycles, expressed as a percentage of live memory.
80    #[cfg(not(feature = "luau"))]
81    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
82    pub pause: Option<c_int>,
83
84    /// Target heap size as a percentage of live data, controlling how aggressively
85    /// the GC reclaims memory (`LUA_GCSETGOAL`).
86    #[cfg(any(feature = "luau", doc))]
87    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
88    pub goal: Option<c_int>,
89
90    /// GC work performed per unit of memory allocated.
91    pub step_multiplier: Option<c_int>,
92
93    /// Granularity of each GC step.
94    ///
95    /// The unit is version-dependent, check the Lua reference manual for details.
96    #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
97    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
98    pub step_size: Option<c_int>,
99}
100
101impl GcIncParams {
102    /// Sets the `pause` parameter.
103    #[cfg(not(feature = "luau"))]
104    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
105    #[must_use]
106    pub fn pause(mut self, v: c_int) -> Self {
107        self.pause = Some(v);
108        self
109    }
110
111    /// Sets the `goal` parameter.
112    #[cfg(any(feature = "luau", doc))]
113    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
114    #[must_use]
115    pub fn goal(mut self, v: c_int) -> Self {
116        self.goal = Some(v);
117        self
118    }
119
120    /// Sets the `step_multiplier` parameter.
121    #[must_use]
122    pub fn step_multiplier(mut self, v: c_int) -> Self {
123        self.step_multiplier = Some(v);
124        self
125    }
126
127    /// Sets the `step_size` parameter.
128    #[cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))]
129    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54", feature = "luau"))))]
130    #[must_use]
131    pub fn step_size(mut self, v: c_int) -> Self {
132        self.step_size = Some(v);
133        self
134    }
135}
136
137/// Tuning parameters for the generational GC collector (Lua 5.4+).
138///
139/// Each field is an [`Option`]: `None` leaves the corresponding parameter unchanged, while
140/// `Some(v)` sets it. Units and ranges depend on the Lua version, check the reference manual
141/// for details.
142#[cfg(any(feature = "lua55", feature = "lua54"))]
143#[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
144#[non_exhaustive]
145#[derive(Clone, Copy, Debug, Default)]
146pub struct GcGenParams {
147    /// Frequency of minor (young-generation) collection steps.
148    pub minor_multiplier: Option<c_int>,
149
150    /// Threshold controlling how large the young generation can grow before triggering
151    /// a shift from minor to major collection.
152    pub minor_to_major: Option<c_int>,
153
154    /// Threshold controlling how much the major collection must shrink the heap before
155    /// switching back to minor (young-generation) collection.
156    #[cfg(feature = "lua55")]
157    #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
158    pub major_to_minor: Option<c_int>,
159}
160
161#[cfg(any(feature = "lua55", feature = "lua54"))]
162impl GcGenParams {
163    /// Sets the `minor_multiplier` parameter.
164    #[must_use]
165    pub fn minor_multiplier(mut self, v: c_int) -> Self {
166        self.minor_multiplier = Some(v);
167        self
168    }
169
170    /// Sets the `minor_to_major` threshold.
171    #[must_use]
172    pub fn minor_to_major(mut self, v: c_int) -> Self {
173        self.minor_to_major = Some(v);
174        self
175    }
176
177    /// Sets the `major_to_minor` parameter.
178    #[cfg(feature = "lua55")]
179    #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
180    #[must_use]
181    pub fn major_to_minor(mut self, v: c_int) -> Self {
182        self.major_to_minor = Some(v);
183        self
184    }
185}
186
187/// Lua garbage collector (GC) operating mode.
188///
189/// Use [`Lua::gc_set_mode`] to switch the collector mode and/or tune its parameters.
190#[non_exhaustive]
191#[derive(Clone, Debug)]
192pub enum GcMode {
193    /// Incremental mark-and-sweep
194    Incremental(GcIncParams),
195
196    /// Generational
197    #[cfg(any(feature = "lua55", feature = "lua54"))]
198    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
199    Generational(GcGenParams),
200}
201
202/// Controls Lua interpreter behavior such as Rust panics handling.
203#[derive(Clone, Debug)]
204#[non_exhaustive]
205pub struct LuaOptions {
206    /// Catch Rust panics when using [`pcall`]/[`xpcall`].
207    ///
208    /// If disabled, wraps these functions and automatically resumes panic if found.
209    /// Also in Lua 5.1 adds ability to provide arguments to [`xpcall`] similar to Lua >= 5.2.
210    ///
211    /// If enabled, keeps [`pcall`]/[`xpcall`] unmodified.
212    /// Panics are still automatically resumed if returned to the Rust side.
213    ///
214    /// Default: **true**
215    ///
216    /// [`pcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-pcall
217    /// [`xpcall`]: https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
218    pub catch_rust_panics: bool,
219
220    /// Max size of thread (coroutine) object pool used to execute asynchronous functions.
221    ///
222    /// Default: **0** (disabled)
223    ///
224    /// [`lua_resetthread`]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
225    #[cfg(feature = "async")]
226    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
227    pub thread_pool_size: usize,
228}
229
230impl Default for LuaOptions {
231    fn default() -> Self {
232        const { LuaOptions::new() }
233    }
234}
235
236impl LuaOptions {
237    /// Returns a new instance of `LuaOptions` with default parameters.
238    pub const fn new() -> Self {
239        LuaOptions {
240            catch_rust_panics: true,
241            #[cfg(feature = "async")]
242            thread_pool_size: 0,
243        }
244    }
245
246    /// Sets [`catch_rust_panics`] option.
247    ///
248    /// [`catch_rust_panics`]: #structfield.catch_rust_panics
249    #[must_use]
250    pub const fn catch_rust_panics(mut self, enabled: bool) -> Self {
251        self.catch_rust_panics = enabled;
252        self
253    }
254
255    /// Sets [`thread_pool_size`] option.
256    ///
257    /// [`thread_pool_size`]: #structfield.thread_pool_size
258    #[cfg(feature = "async")]
259    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
260    #[must_use]
261    pub const fn thread_pool_size(mut self, size: usize) -> Self {
262        self.thread_pool_size = size;
263        self
264    }
265}
266
267/// Luau JIT options
268#[cfg(any(feature = "luau-jit", doc))]
269#[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
270#[derive(Clone, Copy, Debug, PartialEq, Eq)]
271pub struct JitOptions {
272    inliner: bool,
273}
274
275#[cfg(any(feature = "luau-jit", doc))]
276impl Default for JitOptions {
277    fn default() -> Self {
278        const { Self::new() }
279    }
280}
281
282#[cfg(any(feature = "luau-jit", doc))]
283impl JitOptions {
284    /// Creates default JIT options.
285    pub const fn new() -> Self {
286        JitOptions { inliner: false }
287    }
288
289    /// Toggles the runtime bytecode inliner.
290    ///
291    /// Disabled by default. Enable before compiling and executing code.
292    #[must_use]
293    pub const fn inliner(mut self, enabled: bool) -> Self {
294        self.inliner = enabled;
295        self
296    }
297}
298
299impl Drop for Lua {
300    fn drop(&mut self) {
301        if self.collect_garbage {
302            let _ = self.gc_collect();
303        }
304    }
305}
306
307impl Clone for Lua {
308    #[inline]
309    fn clone(&self) -> Self {
310        Lua {
311            raw: XRc::clone(&self.raw),
312            collect_garbage: false,
313        }
314    }
315}
316
317impl fmt::Debug for Lua {
318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319        write!(f, "Lua({:p})", self.state())
320    }
321}
322
323impl Default for Lua {
324    #[inline]
325    fn default() -> Self {
326        Lua::new()
327    }
328}
329
330impl Lua {
331    /// Creates a new Lua state and loads the **safe** subset of the standard libraries.
332    ///
333    /// # Safety
334    /// The created Lua state will have _some_ safety guarantees and will not allow to load unsafe
335    /// standard libraries or C modules.
336    ///
337    /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
338    pub fn new() -> Lua {
339        mlua_expect!(
340            Self::new_with(StdLib::ALL_SAFE, LuaOptions::default()),
341            "Cannot create a Lua state"
342        )
343    }
344
345    /// Creates a new Lua state and loads all the standard libraries.
346    ///
347    /// # Safety
348    /// The created Lua state will not have safety guarantees and will allow to load C modules.
349    pub unsafe fn unsafe_new() -> Lua {
350        Self::unsafe_new_with(StdLib::ALL, LuaOptions::default())
351    }
352
353    /// Creates a new Lua state and loads the specified safe subset of the standard libraries.
354    ///
355    /// Use the [`StdLib`] flags to specify the libraries you want to load.
356    ///
357    /// # Safety
358    /// The created Lua state will have _some_ safety guarantees and will not allow to load unsafe
359    /// standard libraries or C modules.
360    ///
361    /// See [`StdLib`] documentation for a list of unsafe modules that cannot be loaded.
362    pub fn new_with(libs: StdLib, options: LuaOptions) -> Result<Lua> {
363        #[cfg(not(feature = "luau"))]
364        if libs.contains(StdLib::DEBUG) {
365            return Err(Error::SafetyError(
366                "The unsafe `debug` module can't be loaded using safe `new_with`".to_string(),
367            ));
368        }
369        #[cfg(feature = "luajit")]
370        if libs.contains(StdLib::FFI) {
371            return Err(Error::SafetyError(
372                "The unsafe `ffi` module can't be loaded using safe `new_with`".to_string(),
373            ));
374        }
375
376        let lua = unsafe { Self::inner_new(libs, options) };
377
378        #[cfg(not(feature = "luau"))]
379        if libs.contains(StdLib::PACKAGE) {
380            mlua_expect!(lua.disable_c_modules(), "Error disabling C modules");
381        }
382        lua.lock().mark_safe();
383
384        Ok(lua)
385    }
386
387    /// Creates a new Lua state and loads the specified subset of the standard libraries.
388    ///
389    /// Use the [`StdLib`] flags to specify the libraries you want to load.
390    ///
391    /// # Safety
392    /// The created Lua state will not have safety guarantees and allow to load C modules.
393    pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
394        // Workaround to avoid stripping a few unused Lua symbols that could be imported
395        // by C modules in unsafe mode
396        let mut _symbols: Vec<*const extern "C-unwind" fn()> =
397            vec![ffi::lua_isuserdata as _, ffi::lua_tocfunction as _];
398
399        #[cfg(not(feature = "luau"))]
400        _symbols.extend_from_slice(&[
401            ffi::lua_atpanic as _,
402            ffi::luaL_loadstring as _,
403            ffi::luaL_openlibs as _,
404        ]);
405        #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
406        {
407            _symbols.push(ffi::lua_getglobal as _);
408            _symbols.push(ffi::lua_setglobal as _);
409            _symbols.push(ffi::luaL_setfuncs as _);
410        }
411
412        Self::inner_new(libs, options)
413    }
414
415    /// Creates a new Lua state with required `libs` and `options`
416    unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
417        let lua = Lua {
418            raw: RawLua::new(libs, &options),
419            collect_garbage: true,
420        };
421
422        #[cfg(feature = "luau")]
423        mlua_expect!(lua.configure_luau(), "Error configuring Luau");
424
425        lua
426    }
427
428    /// Returns or constructs Lua instance from a raw state.
429    ///
430    /// Once initialized, the returned Lua instance is cached in the registry and can be retrieved
431    /// by calling this function again.
432    ///
433    /// # Safety
434    /// The `Lua` must outlive the chosen lifetime `'a`.
435    #[inline]
436    pub unsafe fn get_or_init_from_ptr<'a>(state: *mut ffi::lua_State) -> &'a Lua {
437        debug_assert!(!state.is_null(), "Lua state is null");
438        match ExtraData::get(state) {
439            extra if !extra.is_null() => (*extra).lua(),
440            _ => {
441                // The `owned` flag is set to `false` as we don't own the Lua state.
442                RawLua::init_from_ptr(state, false);
443                (*ExtraData::get(state)).lua()
444            }
445        }
446    }
447
448    /// Calls provided function passing a raw lua state.
449    ///
450    /// The arguments will be pushed onto the stack before calling the function.
451    ///
452    /// This method ensures that the Lua instance is locked while the function is called
453    /// and restores Lua stack after the function returns.
454    ///
455    /// # Example
456    /// ```
457    /// # use mlua::{Lua, Result};
458    /// # fn main() -> Result<()> {
459    /// let lua = Lua::new();
460    /// let n: i32 = unsafe {
461    ///     let nums = (3, 4, 5);
462    ///     lua.exec_raw(nums, |state| {
463    ///         let n = ffi::lua_gettop(state);
464    ///         let mut sum = 0;
465    ///         for i in 1..=n {
466    ///             sum += ffi::lua_tointeger(state, i);
467    ///         }
468    ///         ffi::lua_pop(state, n);
469    ///         ffi::lua_pushinteger(state, sum);
470    ///     })
471    /// }?;
472    /// assert_eq!(n, 12);
473    /// # Ok(())
474    /// # }
475    /// ```
476    #[allow(clippy::missing_safety_doc)]
477    pub unsafe fn exec_raw<R: FromLuaMulti>(
478        &self,
479        args: impl IntoLuaMulti,
480        f: impl FnOnce(*mut ffi::lua_State),
481    ) -> Result<R> {
482        let lua = self.lock();
483        let state = lua.state();
484        let _sg = StackGuard::new(state);
485        let stack_start = ffi::lua_gettop(state);
486        let nargs = args.push_into_stack_multi(&lua)?;
487        check_stack(state, 3)?;
488        protect_lua_closure::<_, ()>(state, nargs, ffi::LUA_MULTRET, f)?;
489        let nresults = ffi::lua_gettop(state) - stack_start;
490        R::from_stack_multi(nresults, &lua)
491    }
492
493    /// Calls provided function passing a reference to the [`RawLua`] handle.
494    ///
495    /// Provided [`RawLua`] handle can be used to manually pushing/popping values to/from the stack.
496    ///
497    /// # Example
498    /// ```
499    /// # use mlua::{Lua, Result, FromLua, IntoLua, IntoLuaMulti};
500    /// # fn main() -> Result<()> {
501    /// let lua = Lua::new();
502    /// let n: i32 = {
503    ///     let nums = (3, 4, 5);
504    ///     lua.exec_raw_lua(|rawlua| unsafe {
505    ///         nums.push_into_stack_multi(rawlua)?;
506    ///         let mut sum = 0;
507    ///         for _ in 0..3 {
508    ///             sum += rawlua.pop::<i32>()?;
509    ///         }
510    ///         Result::Ok(sum)
511    ///     })
512    /// }?;
513    /// assert_eq!(n, 12);
514    /// # Ok(())
515    /// # }
516    /// ```
517    #[doc(hidden)]
518    pub fn exec_raw_lua<R>(&self, f: impl FnOnce(&RawLua) -> R) -> R {
519        let lua = self.lock();
520        f(&lua)
521    }
522
523    /// Loads the specified subset of the standard libraries into an existing Lua state.
524    ///
525    /// Use the [`StdLib`] flags to specify the libraries you want to load.
526    pub fn load_std_libs(&self, libs: StdLib) -> Result<()> {
527        unsafe { self.lock().load_std_libs(libs) }
528    }
529
530    /// Registers module into an existing Lua state using the specified value.
531    ///
532    /// After registration, the given value will always be immediately returned when the
533    /// given module is [required].
534    ///
535    /// [required]: https://www.lua.org/manual/5.4/manual.html#pdf-require
536    pub fn register_module(&self, modname: &str, value: impl IntoLua) -> Result<()> {
537        #[cfg(not(feature = "luau"))]
538        const LOADED_MODULES_KEY: *const c_char = ffi::LUA_LOADED_TABLE;
539        #[cfg(feature = "luau")]
540        const LOADED_MODULES_KEY: *const c_char = ffi::LUA_REGISTERED_MODULES_TABLE;
541
542        if cfg!(feature = "luau") && !modname.starts_with('@') {
543            return Err(Error::runtime("module name must begin with '@'"));
544        }
545        #[cfg(feature = "luau")]
546        let modname = modname.to_ascii_lowercase();
547        unsafe {
548            self.exec_raw::<()>(value, |state| {
549                ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, LOADED_MODULES_KEY);
550                ffi::lua_pushlstring(state, modname.as_ptr() as *const c_char, modname.len() as _);
551                ffi::lua_pushvalue(state, -3);
552                ffi::lua_rawset(state, -3);
553            })
554        }
555    }
556
557    /// Preloads module into an existing Lua state using the specified loader function.
558    ///
559    /// When the module is required, the loader function will be called with module name as the
560    /// first argument.
561    ///
562    /// This is similar to setting the [`package.preload[modname]`] field.
563    ///
564    /// [`package.preload[modname]`]: <https://www.lua.org/manual/5.4/manual.html#pdf-package.preload>
565    #[cfg(not(feature = "luau"))]
566    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
567    pub fn preload_module(&self, modname: &str, func: Function) -> Result<()> {
568        #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
569        let preload = unsafe {
570            self.exec_raw::<Option<Table>>((), |state| {
571                ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_PRELOAD_TABLE);
572            })?
573        };
574        #[cfg(any(feature = "lua51", feature = "luajit"))]
575        let preload = unsafe {
576            self.exec_raw::<Option<Table>>((), |state| {
577                if ffi::lua_getfield(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_LOADED_TABLE) != ffi::LUA_TNIL {
578                    ffi::luaL_getsubtable(state, -1, ffi::LUA_LOADLIBNAME);
579                    ffi::luaL_getsubtable(state, -1, cstr!("preload"));
580                    ffi::lua_rotate(state, 1, 1);
581                }
582            })?
583        };
584        if let Some(preload) = preload {
585            preload.raw_set(modname, func)?;
586        }
587        Ok(())
588    }
589
590    /// Unloads module `modname`.
591    ///
592    /// This method does not support unloading binary Lua modules since they are internally cached
593    /// and can be unloaded only by closing Lua state.
594    ///
595    /// This is similar to calling [`Lua::register_module`] with `Nil` value.
596    ///
597    /// [`package.loaded`]: https://www.lua.org/manual/5.4/manual.html#pdf-package.loaded
598    pub fn unload_module(&self, modname: &str) -> Result<()> {
599        self.register_module(modname, Nil)
600    }
601
602    // Executes module entrypoint function, which returns only one Value.
603    // The returned value then pushed onto the stack.
604    #[doc(hidden)]
605    #[cfg(not(tarpaulin_include))]
606    pub unsafe fn entrypoint<F, A, R>(state: *mut ffi::lua_State, func: F) -> c_int
607    where
608        F: FnOnce(&Lua, A) -> Result<R>,
609        A: FromLuaMulti,
610        R: IntoLua,
611    {
612        // Make sure that Lua is initialized
613        let _ = Self::get_or_init_from_ptr(state);
614
615        callback_error_ext(state, ptr::null_mut(), true, move |extra, nargs| {
616            let rawlua = (*extra).raw_lua();
617            let args = A::from_stack_args(nargs, 1, None, rawlua)?;
618            func(rawlua.lua(), args)?.push_into_stack(rawlua)?;
619            Ok(1)
620        })
621    }
622
623    // A simple module entrypoint without arguments
624    #[doc(hidden)]
625    #[cfg(not(tarpaulin_include))]
626    pub unsafe fn entrypoint1<F, R>(state: *mut ffi::lua_State, func: F) -> c_int
627    where
628        F: FnOnce(&Lua) -> Result<R>,
629        R: IntoLua,
630    {
631        Self::entrypoint(state, move |lua, _: ()| func(lua))
632    }
633
634    /// Skips memory checks for some operations.
635    #[doc(hidden)]
636    #[cfg(feature = "module")]
637    pub fn skip_memory_check(&self, skip: bool) {
638        let lua = self.lock();
639        unsafe {
640            (*lua.extra.get()).skip_memory_check = skip;
641            if MemoryState::get(lua.state()).is_null() {
642                (*lua.extra.get()).unlikely_memory_error = skip;
643            }
644        }
645    }
646
647    /// Enables (or disables) sandbox mode on this Lua instance.
648    ///
649    /// This method, in particular:
650    /// - Set all libraries to read-only
651    /// - Set all builtin metatables to read-only
652    /// - Set globals to read-only (and activates safeenv)
653    /// - Setup local environment table that performs writes locally and proxies reads to the global
654    ///   environment.
655    /// - Allow only `count` mode in `collectgarbage` function.
656    ///
657    /// # Examples
658    ///
659    /// ```
660    /// # use mlua::{Lua, Result};
661    /// # #[cfg(feature = "luau")]
662    /// # fn main() -> Result<()> {
663    /// let lua = Lua::new();
664    ///
665    /// lua.sandbox(true)?;
666    /// lua.load("var = 123").exec()?;
667    /// assert_eq!(lua.globals().get::<u32>("var")?, 123);
668    ///
669    /// // Restore the global environment (clear changes made in sandbox)
670    /// lua.sandbox(false)?;
671    /// assert_eq!(lua.globals().get::<Option<u32>>("var")?, None);
672    /// # Ok(())
673    /// # }
674    ///
675    /// # #[cfg(not(feature = "luau"))]
676    /// # fn main() {}
677    /// ```
678    #[cfg(any(feature = "luau", doc))]
679    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
680    pub fn sandbox(&self, enabled: bool) -> Result<()> {
681        let lua = self.lock();
682        unsafe {
683            if (*lua.extra.get()).sandboxed != enabled {
684                let state = lua.main_state();
685                check_stack(state, 3)?;
686                protect_lua!(state, 0, 0, |state| {
687                    if enabled {
688                        ffi::luaL_sandbox(state, 1);
689                        ffi::luaL_sandboxthread(state);
690                    } else {
691                        // Restore original `LUA_GLOBALSINDEX`
692                        ffi::lua_xpush(lua.ref_thread(), state, ffi::LUA_GLOBALSINDEX);
693                        ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
694                        ffi::luaL_sandbox(state, 0);
695                    }
696                })?;
697                (*lua.extra.get()).sandboxed = enabled;
698            }
699            Ok(())
700        }
701    }
702
703    /// Sets or replaces a global hook function that will periodically be called as Lua code
704    /// executes.
705    ///
706    /// All new threads created (by mlua) after this call will use the global hook function.
707    ///
708    /// For more information see [`Lua::set_hook`].
709    #[cfg(not(feature = "luau"))]
710    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
711    pub fn set_global_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
712    where
713        F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
714    {
715        let lua = self.lock();
716        unsafe {
717            let _old_callback = (*lua.extra.get()).hook_callback.replace(XRc::new(callback));
718            (*lua.extra.get()).hook_triggers = triggers;
719            lua.set_thread_hook(lua.state(), HookKind::Global)
720        }
721    }
722
723    /// Sets a hook function that will periodically be called as Lua code executes.
724    ///
725    /// When exactly the hook function is called depends on the contents of the `triggers`
726    /// parameter, see [`HookTriggers`] for more details.
727    ///
728    /// The provided hook function can error, and this error will be propagated through the Lua code
729    /// that was executing at the time the hook was triggered. This can be used to implement a
730    /// limited form of execution limits by setting [`HookTriggers.every_nth_instruction`] and
731    /// erroring once an instruction limit has been reached.
732    ///
733    /// This method sets a hook function for the *current* thread of this Lua instance.
734    /// If you want to set a hook function for another thread (coroutine), use
735    /// [`Thread::set_hook`] instead.
736    ///
737    /// # Example
738    ///
739    /// Shows each line number of code being executed by the Lua interpreter.
740    ///
741    /// ```
742    /// # use mlua::{Lua, HookTriggers, Result, VmState};
743    /// # fn main() -> Result<()> {
744    /// let lua = Lua::new();
745    /// lua.set_hook(HookTriggers::EVERY_LINE, |_lua, debug| {
746    ///     println!("line {:?}", debug.current_line());
747    ///     Ok(VmState::Continue)
748    /// });
749    ///
750    /// lua.load(r#"
751    ///     local x = 2 + 3
752    ///     local y = x * 63
753    ///     local z = string.len(x..", "..y)
754    /// "#).exec()
755    /// # }
756    /// ```
757    ///
758    /// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
759    #[cfg(not(feature = "luau"))]
760    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
761    pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
762    where
763        F: Fn(&Lua, &Debug) -> Result<VmState> + MaybeSend + 'static,
764    {
765        let lua = self.lock();
766        unsafe { lua.set_thread_hook(lua.state(), HookKind::Thread(triggers, XRc::new(callback))) }
767    }
768
769    /// Removes a global hook previously set by [`Lua::set_global_hook`].
770    ///
771    /// This function has no effect if a hook was not previously set.
772    #[cfg(not(feature = "luau"))]
773    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
774    pub fn remove_global_hook(&self) {
775        let lua = self.lock();
776        unsafe {
777            let _old_callback = (*lua.extra.get()).hook_callback.take();
778            (*lua.extra.get()).hook_triggers = HookTriggers::default();
779        }
780    }
781
782    /// Removes any hook from the current thread.
783    ///
784    /// This function has no effect if a hook was not previously set.
785    #[cfg(not(feature = "luau"))]
786    #[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
787    pub fn remove_hook(&self) {
788        let lua = self.lock();
789        unsafe {
790            lua.remove_thread_hook(lua.state());
791        }
792    }
793
794    /// Sets an interrupt function that will periodically be called by Luau VM.
795    ///
796    /// Any Luau code is guaranteed to call this handler "eventually"
797    /// (in practice this can happen at any function call or at any loop iteration).
798    /// This is similar to `Lua::set_hook` but in more simplified form.
799    ///
800    /// The provided interrupt function can error, and this error will be propagated through
801    /// the Luau code that was executing at the time the interrupt was triggered.
802    /// Also this can be used to implement continuous execution limits by instructing Luau VM to
803    /// yield by returning [`VmState::Yield`]. The yield will happen only at yieldable points
804    /// of execution (not across metamethod/C-call boundaries).
805    ///
806    /// # Example
807    ///
808    /// Periodically yield Luau VM to suspend execution.
809    ///
810    /// ```
811    /// # use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
812    /// # use mlua::thread::ThreadStatus;
813    /// # use mlua::{Lua, Result, VmState};
814    /// # #[cfg(feature = "luau")]
815    /// # fn main() -> Result<()> {
816    /// let lua = Lua::new();
817    /// let count = Arc::new(AtomicU64::new(0));
818    /// lua.set_interrupt(move |_| {
819    ///     if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
820    ///         return Ok(VmState::Yield);
821    ///     }
822    ///     Ok(VmState::Continue)
823    /// });
824    ///
825    /// let co = lua.create_thread(
826    ///     lua.load(r#"
827    ///         local b = 0
828    ///         for _, x in ipairs({1, 2, 3}) do b += x end
829    ///     "#)
830    ///     .into_function()?,
831    /// )?;
832    /// while co.status() == ThreadStatus::Resumable {
833    ///     co.resume::<()>(())?;
834    /// }
835    /// # Ok(())
836    /// # }
837    ///
838    /// # #[cfg(not(feature = "luau"))]
839    /// # fn main() {}
840    /// ```
841    #[cfg(any(feature = "luau", doc))]
842    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
843    pub fn set_interrupt<F>(&self, callback: F)
844    where
845        F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
846    {
847        unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
848            if gc >= 0 {
849                // We don't support GC interrupts since they cannot survive Lua exceptions
850                return;
851            }
852            let result = callback_error_ext(state, ptr::null_mut(), false, move |extra, _| {
853                let interrupt_cb = (*extra).interrupt_callback.clone();
854                let interrupt_cb = mlua_expect!(interrupt_cb, "no interrupt callback set in interrupt_proc");
855                if XRc::strong_count(&interrupt_cb) > 2 {
856                    return Ok(VmState::Continue); // Don't allow recursion
857                }
858                interrupt_cb((*extra).lua())
859            });
860            match result {
861                VmState::Continue => {}
862                VmState::Yield => {
863                    // We can yield only at yieldable points, otherwise ignore and continue
864                    if ffi::lua_isyieldable(state) != 0 {
865                        ffi::lua_yield(state, 0);
866                    }
867                }
868            }
869        }
870
871        // Set interrupt callback
872        let lua = self.lock();
873        unsafe {
874            let _old_callback = (*lua.extra.get()).interrupt_callback.replace(XRc::new(callback));
875            (*ffi::lua_callbacks(lua.main_state())).interrupt = Some(interrupt_proc);
876        }
877    }
878
879    /// Removes any interrupt function previously set by `set_interrupt`.
880    ///
881    /// This function has no effect if an 'interrupt' was not previously set.
882    #[cfg(any(feature = "luau", doc))]
883    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
884    pub fn remove_interrupt(&self) {
885        let lua = self.lock();
886        unsafe {
887            let _old_callback = (*lua.extra.get()).interrupt_callback.take();
888            (*ffi::lua_callbacks(lua.main_state())).interrupt = None;
889        }
890    }
891
892    /// Sets a callback invoked when thread lifecycle events occur.
893    ///
894    /// `triggers` controls which events trigger the callback, see [`ThreadTriggers`] for more
895    /// details.
896    ///
897    /// Only one callback can be registered at a time. Calling this again replaces the previous
898    /// callback and its triggers.
899    ///
900    /// If the callback returns an error, it's propagated out of the operation that triggered the
901    /// event. For a [`ThreadEvent::Yield`], the yielded values are discarded.
902    ///
903    /// # Example
904    ///
905    /// Subscribe only to yield events:
906    ///
907    /// ```
908    /// # use mlua::thread::{ThreadTriggers, ThreadEvent};
909    /// # use mlua::{Lua, Result};
910    /// # fn main() -> Result<()> {
911    /// let lua = Lua::new();
912    /// lua.set_thread_event_callback(
913    ///     ThreadTriggers::ON_YIELD,
914    ///     |_lua, event| {
915    ///         if let ThreadEvent::Yield(thread) = event {
916    ///             println!("thread yielded");
917    ///         }
918    ///         Ok(())
919    ///     },
920    /// );
921    /// # Ok(())
922    /// # }
923    /// ```
924    pub fn set_thread_event_callback<F>(&self, triggers: ThreadTriggers, callback: F)
925    where
926        F: Fn(&Lua, ThreadEvent) -> Result<()> + MaybeSend + 'static,
927    {
928        let lua = self.lock();
929        unsafe {
930            let _old_callback = ((*lua.extra.get()).thread_event_callback).replace(XRc::new(callback));
931            (*lua.extra.get()).thread_triggers = triggers;
932            #[cfg(feature = "luau")]
933            {
934                let proc = Self::userthread_proc as _;
935                (*ffi::lua_callbacks(lua.main_state())).userthread = triggers.on_create.then_some(proc);
936            }
937        }
938    }
939
940    /// Removes the thread event callback previously set by [`Lua::set_thread_event_callback`].
941    ///
942    /// This function has no effect if a callback was not previously set.
943    pub fn remove_thread_event_callback(&self) {
944        let lua = self.lock();
945        let extra = lua.extra.get();
946        unsafe {
947            let _old_callback = (*extra).thread_event_callback.take();
948            (*extra).thread_triggers = ThreadTriggers::new();
949            #[cfg(feature = "luau")]
950            {
951                (*ffi::lua_callbacks(lua.main_state())).userthread = None;
952            }
953        }
954    }
955
956    #[cfg(feature = "luau")]
957    unsafe extern "C-unwind" fn userthread_proc(parent: *mut ffi::lua_State, child: *mut ffi::lua_State) {
958        // Only handle thread creation
959        if parent.is_null() {
960            return;
961        }
962
963        let extra = ExtraData::get(child);
964        if !(*extra).thread_triggers.on_create || !(*extra).thread_event_state.is_null() {
965            return;
966        }
967        let Some(callback) = (*extra).thread_event_callback.clone() else {
968            return;
969        };
970        ffi::lua_pushthread(child);
971        ffi::lua_xmove(child, (*extra).ref_thread, 1);
972        let Ok(thread) = ((*extra).raw_lua().try_pop_ref_thread()).map(|vref| Thread(vref, child)) else {
973            return;
974        };
975        callback_error_ext(parent, extra, false, move |extra, _| {
976            let _guard = crate::thread::ThreadEventGuard::new((*extra).raw_lua(), child);
977            callback((*extra).lua(), ThreadEvent::Create(thread))
978        })
979    }
980
981    /// Sets the warning function to be used by Lua to emit warnings.
982    #[cfg(any(feature = "lua55", feature = "lua54"))]
983    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
984    pub fn set_warning_function<F>(&self, callback: F)
985    where
986        F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
987    {
988        use std::ffi::CStr;
989        use std::os::raw::{c_char, c_void};
990
991        unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
992            let extra = ud as *mut ExtraData;
993            callback_error_ext((*extra).raw_lua().state(), extra, false, |extra, _| {
994                let warn_callback = (*extra).warn_callback.clone();
995                let warn_callback = mlua_expect!(warn_callback, "no warning callback set in warn_proc");
996                if XRc::strong_count(&warn_callback) > 2 {
997                    return Ok(());
998                }
999                let msg = String::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
1000                warn_callback((*extra).lua(), &msg, tocont != 0)
1001            });
1002        }
1003
1004        let lua = self.lock();
1005        unsafe {
1006            let _old_callback = (*lua.extra.get()).warn_callback.replace(XRc::new(callback));
1007            ffi::lua_setwarnf(lua.state(), Some(warn_proc), lua.extra.get() as *mut c_void);
1008        }
1009    }
1010
1011    /// Removes warning function previously set by `set_warning_function`.
1012    ///
1013    /// This function has no effect if a warning function was not previously set.
1014    #[cfg(any(feature = "lua55", feature = "lua54"))]
1015    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1016    pub fn remove_warning_function(&self) {
1017        let lua = self.lock();
1018        unsafe {
1019            let _old_callback = (*lua.extra.get()).warn_callback.take();
1020            ffi::lua_setwarnf(lua.state(), None, ptr::null_mut());
1021        }
1022    }
1023
1024    /// Emits a warning with the given message.
1025    ///
1026    /// A message in a call with `incomplete` set to `true` should be continued in
1027    /// another call to this function.
1028    #[cfg(any(feature = "lua55", feature = "lua54"))]
1029    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
1030    pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
1031        let msg = msg.as_ref().as_bytes();
1032        let end = msg.iter().position(|&c| c == 0).unwrap_or(msg.len());
1033        let mut bytes = Vec::with_capacity(end + 1);
1034        bytes.extend_from_slice(&msg[..end]);
1035        bytes.push(0);
1036        let lua = self.lock();
1037        unsafe {
1038            ffi::lua_warning(lua.state(), bytes.as_ptr() as *const _, incomplete as c_int);
1039        }
1040    }
1041
1042    /// Gets information about the interpreter runtime stack at the given level.
1043    ///
1044    /// This function calls callback `f`, passing the [`struct@Debug`] structure that can be used to
1045    /// get information about the function executing at a given level.
1046    /// Level `0` is the current running function, whereas level `n+1` is the function that has
1047    /// called level `n` (except for tail calls, which do not count in the stack).
1048    pub fn inspect_stack<R>(&self, level: usize, f: impl FnOnce(&Debug) -> R) -> Option<R> {
1049        let level = c_int::try_from(level).ok()?;
1050        let lua = self.lock();
1051        unsafe {
1052            let mut ar = mem::zeroed::<ffi::lua_Debug>();
1053            #[cfg(not(feature = "luau"))]
1054            if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
1055                return None;
1056            }
1057            #[cfg(feature = "luau")]
1058            if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
1059                return None;
1060            }
1061
1062            Some(f(&Debug::new(&lua, level, &mut ar)))
1063        }
1064    }
1065
1066    /// Creates a traceback of the call stack at the given level.
1067    ///
1068    /// The `msg` parameter, if provided, is added at the beginning of the traceback.
1069    /// The `level` parameter works the same way as in [`Lua::inspect_stack`].
1070    pub fn traceback(&self, msg: Option<&str>, level: usize) -> Result<LuaString> {
1071        let lua = self.lock();
1072        unsafe {
1073            check_stack(lua.state(), 3)?;
1074            protect_lua!(lua.state(), 0, 1, |state| {
1075                let msg = match msg {
1076                    Some(s) => ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len()),
1077                    None => ptr::null(),
1078                };
1079                // `protect_lua` adds its own call frame, leave room for Lua's internal increment.
1080                let level = level.saturating_add(1).min((c_int::MAX - 1) as usize) as c_int;
1081                ffi::luaL_traceback(state, state, msg, level);
1082            })?;
1083            Ok(LuaString(lua.try_pop_ref()?))
1084        }
1085    }
1086
1087    /// Returns the amount of memory (in bytes) currently used inside this Lua state.
1088    pub fn used_memory(&self) -> usize {
1089        let lua = self.lock();
1090        let state = lua.main_state();
1091        unsafe {
1092            match MemoryState::get(state) {
1093                mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
1094                _ => {
1095                    // Get data from the Lua GC
1096                    let used_kbytes = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0);
1097                    let used_kbytes_rem = ffi::lua_gc(state, ffi::LUA_GCCOUNTB, 0);
1098                    (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
1099                }
1100            }
1101        }
1102    }
1103
1104    /// Sets a memory limit (in bytes) on this Lua state.
1105    ///
1106    /// Once an allocation occurs that would pass this memory limit, a `Error::MemoryError` is
1107    /// generated instead.
1108    /// Returns previous limit (zero means no limit).
1109    ///
1110    /// Does not work in module mode where Lua state is managed externally.
1111    pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
1112        let lua = self.lock();
1113        unsafe {
1114            match MemoryState::get(lua.state()) {
1115                mem_state if !mem_state.is_null() => {
1116                    let prev_limit = (*mem_state).set_memory_limit(limit);
1117                    (*lua.extra.get()).unlikely_memory_error = (*mem_state).memory_limit() == 0;
1118                    Ok(prev_limit)
1119                }
1120                _ => Err(Error::MemoryControlNotAvailable),
1121            }
1122        }
1123    }
1124
1125    /// Returns `true` if the garbage collector is currently running automatically.
1126    #[cfg(any(
1127        feature = "lua55",
1128        feature = "lua54",
1129        feature = "lua53",
1130        feature = "lua52",
1131        feature = "luau"
1132    ))]
1133    #[cfg_attr(
1134        docsrs,
1135        doc(cfg(any(
1136            feature = "lua55",
1137            feature = "lua54",
1138            feature = "lua53",
1139            feature = "lua52",
1140            feature = "luau"
1141        )))
1142    )]
1143    pub fn gc_is_running(&self) -> bool {
1144        let lua = self.lock();
1145        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCISRUNNING, 0) != 0 }
1146    }
1147
1148    /// Stops the Lua GC from running.
1149    pub fn gc_stop(&self) {
1150        let lua = self.lock();
1151        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCSTOP, 0) };
1152    }
1153
1154    /// Restarts the Lua GC if it is not running.
1155    pub fn gc_restart(&self) {
1156        let lua = self.lock();
1157        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCRESTART, 0) };
1158    }
1159
1160    /// Performs a full garbage-collection cycle.
1161    ///
1162    /// It may be necessary to call this function twice to collect all currently unreachable
1163    /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
1164    pub fn gc_collect(&self) -> Result<()> {
1165        let lua = self.lock();
1166        let state = lua.main_state();
1167        unsafe {
1168            check_stack(state, 2)?;
1169            protect_lua!(state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
1170        }
1171    }
1172
1173    /// Performs a basic step of garbage collection.
1174    ///
1175    /// In incremental mode, a basic step corresponds to the current step size. In generational
1176    /// mode, a basic step performs a full minor collection or an incremental step, if the collector
1177    /// has scheduled one.
1178    ///
1179    /// In incremental mode, returns `true` if this step has finished a collection cycle.
1180    /// In generational mode, returns `true` if the step finished a major collection.
1181    pub fn gc_step(&self) -> Result<bool> {
1182        let lua = self.lock();
1183        let state = lua.main_state();
1184        unsafe {
1185            check_stack(state, 3)?;
1186            protect_lua!(state, 0, 0, |state| {
1187                ffi::lua_gc(state, ffi::LUA_GCSTEP, 0) != 0
1188            })
1189        }
1190    }
1191
1192    /// Switches the GC to the given mode with the provided parameters.
1193    ///
1194    /// Returns the previous [`GcMode`]. Only the collector *mode* is reported, the returned value's
1195    /// parameter fields are always `None`.
1196    ///
1197    /// If the collector is internally stopped, the mode cannot be changed and the requested mode is
1198    /// returned as-is.
1199    ///
1200    /// # Examples
1201    ///
1202    /// Switch to generational mode (Lua 5.4+):
1203    /// ```ignore
1204    /// let prev = lua.gc_set_mode(GcMode::Generational(GcGenParams::default()));
1205    /// ```
1206    ///
1207    /// Switch to incremental mode with custom parameters:
1208    /// ```ignore
1209    /// lua.gc_set_mode(GcMode::Incremental(
1210    ///     GcIncParams::default().step_multiplier(100)
1211    /// ));
1212    /// ```
1213    pub fn gc_set_mode(&self, mode: GcMode) -> GcMode {
1214        let lua = self.lock();
1215        let state = lua.main_state();
1216
1217        match mode {
1218            #[cfg(feature = "lua55")]
1219            GcMode::Incremental(params) => unsafe {
1220                if let Some(v) = params.pause {
1221                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPPAUSE, v);
1222                }
1223                if let Some(v) = params.step_multiplier {
1224                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPMUL, v);
1225                }
1226                if let Some(v) = params.step_size {
1227                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPSIZE, v);
1228                }
1229                match ffi::lua_gc(state, ffi::LUA_GCINC) {
1230                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1231                    _ => GcMode::Incremental(GcIncParams::default()),
1232                }
1233            },
1234            #[cfg(feature = "lua54")]
1235            GcMode::Incremental(params) => unsafe {
1236                let pause = params.pause.unwrap_or(0);
1237                let step_mul = params.step_multiplier.unwrap_or(0);
1238                let step_size = params.step_size.unwrap_or(0);
1239                match ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_mul, step_size) {
1240                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1241                    _ => GcMode::Incremental(GcIncParams::default()),
1242                }
1243            },
1244            #[cfg(any(feature = "lua53", feature = "lua52", feature = "lua51", feature = "luajit"))]
1245            GcMode::Incremental(params) => unsafe {
1246                if let Some(v) = params.pause {
1247                    ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, v);
1248                }
1249                if let Some(v) = params.step_multiplier {
1250                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1251                }
1252                GcMode::Incremental(GcIncParams::default())
1253            },
1254            #[cfg(feature = "luau")]
1255            GcMode::Incremental(params) => unsafe {
1256                if let Some(v) = params.goal {
1257                    ffi::lua_gc(state, ffi::LUA_GCSETGOAL, v);
1258                }
1259                if let Some(v) = params.step_multiplier {
1260                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1261                }
1262                if let Some(v) = params.step_size {
1263                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, v);
1264                }
1265                GcMode::Incremental(GcIncParams::default())
1266            },
1267
1268            #[cfg(feature = "lua55")]
1269            GcMode::Generational(params) => unsafe {
1270                if let Some(v) = params.minor_multiplier {
1271                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMUL, v);
1272                }
1273                if let Some(v) = params.minor_to_major {
1274                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMAJOR, v);
1275                }
1276                if let Some(v) = params.major_to_minor {
1277                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMAJORMINOR, v);
1278                }
1279                match ffi::lua_gc(state, ffi::LUA_GCGEN) {
1280                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1281                    _ => GcMode::Generational(GcGenParams::default()),
1282                }
1283            },
1284            #[cfg(feature = "lua54")]
1285            GcMode::Generational(params) => unsafe {
1286                let minor = params.minor_multiplier.unwrap_or(0);
1287                let minor_to_major = params.minor_to_major.unwrap_or(0);
1288                match ffi::lua_gc(state, ffi::LUA_GCGEN, minor, minor_to_major) {
1289                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1290                    _ => GcMode::Generational(GcGenParams::default()),
1291                }
1292            },
1293        }
1294    }
1295
1296    /// Sets a default Luau compiler (with custom options).
1297    ///
1298    /// This compiler will be used by default to load all Lua chunks
1299    /// including via `require` function.
1300    ///
1301    /// See [`Compiler`] for details and possible options.
1302    #[cfg(any(feature = "luau", doc))]
1303    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1304    pub fn set_compiler(&self, compiler: Compiler) {
1305        let lua = self.lock();
1306        unsafe { (*lua.extra.get()).compiler = Some(compiler) };
1307    }
1308
1309    /// Toggles JIT compilation mode for new chunks of code.
1310    ///
1311    /// By default JIT is enabled. Changing this option does not have any effect on
1312    /// already loaded functions.
1313    #[cfg(any(feature = "luau-jit", doc))]
1314    #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1315    pub fn enable_jit(&self, enable: bool) {
1316        let lua = self.lock();
1317        unsafe { (*lua.extra.get()).enable_jit = enable };
1318    }
1319
1320    /// Configures JIT options for this Lua VM.
1321    #[cfg(any(feature = "luau-jit", doc))]
1322    #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1323    pub fn set_jit_options(&self, options: JitOptions) {
1324        let lua = self.lock();
1325        unsafe {
1326            let state = lua.main_state();
1327            if options.inliner {
1328                ffi::luau_enable_jit_inliner(state);
1329            } else {
1330                ffi::luau_disable_jit_inliner(state);
1331            }
1332        }
1333    }
1334
1335    /// Sets Luau feature flag (global setting).
1336    ///
1337    /// Flags must be configured before creating any Lua VMs or compiling any Luau code.
1338    /// This function must not run concurrently with any other Luau operation, including itself.
1339    /// Changing flags later can cause data races or invalidate compiled bytecode.
1340    ///
1341    /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
1342    #[cfg(feature = "luau")]
1343    #[doc(hidden)]
1344    #[allow(clippy::result_unit_err)]
1345    pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1346        // TODO: Make this function unsafe in the next breaking release.
1347        if let Ok(name) = std::ffi::CString::new(name)
1348            && unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 }
1349        {
1350            return Ok(());
1351        }
1352        Err(())
1353    }
1354
1355    /// Returns Lua source code as a `Chunk` builder type.
1356    ///
1357    /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
1358    /// similar on the returned builder. Code is not even parsed until one of these methods is
1359    /// called.
1360    ///
1361    /// [`Chunk::exec`]: crate::chunk::Chunk::exec
1362    #[track_caller]
1363    pub fn load<'a>(&self, chunk: impl AsChunk + 'a) -> Chunk<'a> {
1364        self.load_with_location(chunk, Location::caller())
1365    }
1366
1367    pub(crate) fn load_with_location<'a>(
1368        &self,
1369        chunk: impl AsChunk + 'a,
1370        location: &'static Location<'static>,
1371    ) -> Chunk<'a> {
1372        Chunk {
1373            lua: self.weak(),
1374            name: chunk
1375                .name()
1376                .unwrap_or_else(|| format!("@{}:{}", location.file(), location.line())),
1377            env: chunk.environment(self),
1378            mode: chunk.mode(),
1379            source: chunk.source(),
1380            #[cfg(feature = "luau")]
1381            compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
1382        }
1383    }
1384
1385    /// Creates and returns an interned Lua string.
1386    ///
1387    /// Lua strings can be arbitrary `[u8]` data including embedded nulls, so in addition to `&str`
1388    /// and `&String`, you can also pass plain `&[u8]` here.
1389    #[inline]
1390    pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<LuaString> {
1391        unsafe { self.lock().create_string(s.as_ref()) }
1392    }
1393
1394    /// Creates and returns an external Lua string.
1395    ///
1396    /// External string is a string where the memory is managed by Rust code, and Lua only holds a
1397    /// reference to it. This can be used to avoid copying large strings into Lua memory.
1398    #[cfg(feature = "lua55")]
1399    #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
1400    #[inline]
1401    pub fn create_external_string(&self, s: impl Into<Vec<u8>>) -> Result<LuaString> {
1402        unsafe { self.lock().create_external_string(s.into()) }
1403    }
1404
1405    /// Creates and returns a Luau [buffer] object from a byte slice of data.
1406    ///
1407    /// [buffer]: https://luau.org/library#buffer-library
1408    #[cfg(any(feature = "luau", doc))]
1409    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1410    pub fn create_buffer(&self, data: impl AsRef<[u8]>) -> Result<Buffer> {
1411        let lua = self.lock();
1412        let data = data.as_ref();
1413        unsafe {
1414            let (ptr, buffer) = lua.create_buffer_with_capacity(data.len())?;
1415            ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
1416            Ok(buffer)
1417        }
1418    }
1419
1420    /// Creates and returns a Luau [buffer] object with the specified size.
1421    ///
1422    /// Size limit is 1GB. All bytes will be initialized to zero.
1423    ///
1424    /// [buffer]: https://luau.org/library#buffer-library
1425    #[cfg(any(feature = "luau", doc))]
1426    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1427    pub fn create_buffer_with_capacity(&self, size: usize) -> Result<Buffer> {
1428        unsafe { Ok(self.lock().create_buffer_with_capacity(size)?.1) }
1429    }
1430
1431    /// Creates and returns a new empty table.
1432    #[inline]
1433    pub fn create_table(&self) -> Result<Table> {
1434        self.create_table_with_capacity(0, 0)
1435    }
1436
1437    /// Creates and returns a new empty table, with the specified capacity.
1438    ///
1439    /// - `narr` is a hint for how many elements the table will have as a sequence.
1440    /// - `nrec` is a hint for how many other elements the table will have.
1441    ///
1442    /// Lua may use these hints to preallocate memory for the new table.
1443    pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1444        unsafe { self.lock().create_table_with_capacity(narr, nrec) }
1445    }
1446
1447    /// Creates a table and fills it with values from an iterator.
1448    pub fn create_table_from<K, V>(&self, iter: impl IntoIterator<Item = (K, V)>) -> Result<Table>
1449    where
1450        K: IntoLua,
1451        V: IntoLua,
1452    {
1453        unsafe { self.lock().create_table_from(iter) }
1454    }
1455
1456    /// Creates a table from an iterator of values, using `1..` as the keys.
1457    pub fn create_sequence_from<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<Table>
1458    where
1459        T: IntoLua,
1460    {
1461        unsafe { self.lock().create_sequence_from(iter) }
1462    }
1463
1464    /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1465    ///
1466    /// The function's return value is always a `Result`: If the function returns `Err`, the error
1467    /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1468    /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1469    /// intermediate Lua code.
1470    ///
1471    /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1472    /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and
1473    /// [`IntoLuaMulti`] traits.
1474    ///
1475    /// # Examples
1476    ///
1477    /// Create a function which prints its argument:
1478    ///
1479    /// ```
1480    /// # use mlua::{Lua, Result};
1481    /// # fn main() -> Result<()> {
1482    /// # let lua = Lua::new();
1483    /// let greet = lua.create_function(|_, name: String| {
1484    ///     println!("Hello, {}!", name);
1485    ///     Ok(())
1486    /// });
1487    /// # let _ = greet;    // used
1488    /// # Ok(())
1489    /// # }
1490    /// ```
1491    ///
1492    /// Use tuples to accept multiple arguments:
1493    ///
1494    /// ```
1495    /// # use mlua::{Lua, Result};
1496    /// # fn main() -> Result<()> {
1497    /// # let lua = Lua::new();
1498    /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1499    ///     println!("{} is {} years old!", name, age);
1500    ///     Ok(())
1501    /// });
1502    /// # let _ = print_person;    // used
1503    /// # Ok(())
1504    /// # }
1505    /// ```
1506    pub fn create_function<F, A, R>(&self, func: F) -> Result<Function>
1507    where
1508        F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
1509        A: FromLuaMulti,
1510        R: IntoLuaMulti,
1511    {
1512        (self.lock()).create_callback(Box::new(move |rawlua, nargs| unsafe {
1513            let args = A::from_stack_args(nargs, 1, None, rawlua)?;
1514            func(rawlua.lua(), args)?.push_into_stack_multi(rawlua)
1515        }))
1516    }
1517
1518    /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1519    ///
1520    /// This is a version of [`Lua::create_function`] that accepts a `FnMut` argument.
1521    pub fn create_function_mut<F, A, R>(&self, func: F) -> Result<Function>
1522    where
1523        F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
1524        A: FromLuaMulti,
1525        R: IntoLuaMulti,
1526    {
1527        let func = RefCell::new(func);
1528        self.create_function(move |lua, args| {
1529            (*func.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1530        })
1531    }
1532
1533    /// Wraps a C function, creating a callable Lua function handle to it.
1534    ///
1535    /// # Safety
1536    /// This function is unsafe because provides a way to execute unsafe C function.
1537    pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1538        let lua = self.lock();
1539        if cfg!(any(
1540            feature = "lua55",
1541            feature = "lua54",
1542            feature = "lua53",
1543            feature = "lua52"
1544        )) {
1545            ffi::lua_pushcfunction(lua.ref_thread(), func);
1546            return Ok(Function(lua.try_pop_ref_thread()?));
1547        }
1548
1549        // Lua <5.2 requires memory allocation to push a C function
1550        let state = lua.state();
1551        {
1552            let _sg = StackGuard::new(state);
1553            check_stack(state, 3)?;
1554
1555            protect_lua_mem!(lua, 0, 1, |state| ffi::lua_pushcfunction(state, func))?;
1556            Ok(Function(lua.try_pop_ref()?))
1557        }
1558    }
1559
1560    /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1561    ///
1562    /// While executing the function Rust will poll the Future and if the result is not ready,
1563    /// call `yield()` passing internal representation of a `Poll::Pending` value.
1564    ///
1565    /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its
1566    /// execution. An executor should be used to poll [`AsyncThread`] and mlua will take a provided
1567    /// Waker in that case. Otherwise noop waker will be used if try to call the function outside of
1568    /// Rust executors.
1569    ///
1570    /// The family of `call_async()` functions takes care about creating [`Thread`].
1571    ///
1572    /// # Examples
1573    ///
1574    /// Non blocking sleep:
1575    ///
1576    /// ```
1577    /// use std::time::Duration;
1578    /// use mlua::{Lua, Result};
1579    ///
1580    /// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
1581    ///     tokio::time::sleep(Duration::from_millis(n)).await;
1582    ///     Ok("done")
1583    /// }
1584    ///
1585    /// #[tokio::main]
1586    /// async fn main() -> Result<()> {
1587    ///     let lua = Lua::new();
1588    ///     lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1589    ///     let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1590    ///     assert_eq!(res, "done");
1591    ///     Ok(())
1592    /// }
1593    /// ```
1594    ///
1595    /// [`AsyncThread`]: crate::thread::AsyncThread
1596    #[cfg(feature = "async")]
1597    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1598    pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
1599    where
1600        F: Fn(Lua, A) -> FR + MaybeSend + 'static,
1601        A: FromLuaMulti,
1602        FR: Future<Output = Result<R>> + MaybeSend + 'static,
1603        R: IntoLuaMulti,
1604    {
1605        // In future we should switch to async closures when they are stable to capture `&Lua`
1606        // See https://rust-lang.github.io/rfcs/3668-async-closures.html
1607        (self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1608            let args = match A::from_stack_args(nargs, 1, None, rawlua) {
1609                Ok(args) => args,
1610                Err(e) => return Box::pin(future::ready(Err(e))),
1611            };
1612            let lua = rawlua.lua();
1613            let fut = func(lua.clone(), args);
1614            Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
1615        }))
1616    }
1617
1618    /// Wraps a Lua function into a new thread (or coroutine).
1619    ///
1620    /// Equivalent to `coroutine.create`.
1621    pub fn create_thread(&self, func: Function) -> Result<Thread> {
1622        unsafe { self.lock().create_thread(&func) }
1623    }
1624
1625    /// Creates a Lua userdata object from a custom userdata type.
1626    ///
1627    /// All userdata instances of the same type `T` shares the same metatable.
1628    #[inline]
1629    pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1630    where
1631        T: UserData + MaybeSend + MaybeSync + 'static,
1632    {
1633        unsafe { self.lock().make_userdata(UserDataStorage::new(data)) }
1634    }
1635
1636    /// Creates a Lua userdata object from a custom serializable userdata type.
1637    #[cfg(feature = "serde")]
1638    #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1639    #[inline]
1640    pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1641    where
1642        T: UserData + Serialize + MaybeSend + MaybeSync + 'static,
1643    {
1644        unsafe { self.lock().make_userdata(UserDataStorage::new_ser(data)) }
1645    }
1646
1647    /// Creates a Lua userdata object from a custom Rust type.
1648    ///
1649    /// You can register the type using [`Lua::register_userdata_type`] to add fields or methods
1650    /// _before_ calling this method.
1651    /// Otherwise, the userdata object will have an empty metatable.
1652    ///
1653    /// All userdata instances of the same type `T` shares the same metatable.
1654    #[inline]
1655    pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1656    where
1657        T: MaybeSend + MaybeSync + 'static,
1658    {
1659        unsafe { self.lock().make_any_userdata(UserDataStorage::new(data)) }
1660    }
1661
1662    /// Creates a Lua userdata object from a custom serializable Rust type.
1663    ///
1664    /// See [`Lua::create_any_userdata`] for more details.
1665    #[cfg(feature = "serde")]
1666    #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1667    #[inline]
1668    pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1669    where
1670        T: Serialize + MaybeSend + MaybeSync + 'static,
1671    {
1672        unsafe { (self.lock()).make_any_userdata(UserDataStorage::new_ser(data)) }
1673    }
1674
1675    /// Registers a custom Rust type in Lua to use in userdata objects.
1676    ///
1677    /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1678    pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1679        let type_id = TypeId::of::<T>();
1680        let mut registry = UserDataRegistry::new(self);
1681        f(&mut registry);
1682
1683        let lua = self.lock();
1684        unsafe {
1685            // Deregister the type if it already registered
1686            if let Some(table_id) = (*lua.extra.get()).registered_userdata_t.remove(&type_id) {
1687                ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
1688            }
1689
1690            // Add to "pending" registration map
1691            ((*lua.extra.get()).pending_userdata_reg).insert(type_id, registry.into_raw());
1692        }
1693        Ok(())
1694    }
1695
1696    /// Create a Lua userdata "proxy" object from a custom userdata type.
1697    ///
1698    /// Proxy object is an empty userdata object that has `T` metatable attached.
1699    /// The main purpose of this object is to provide access to static fields and functions
1700    /// without creating an instance of type `T`.
1701    ///
1702    /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1703    ///
1704    /// # Examples
1705    ///
1706    /// ```
1707    /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1708    /// # fn main() -> Result<()> {
1709    /// # let lua = Lua::new();
1710    /// struct MyUserData(i32);
1711    ///
1712    /// impl UserData for MyUserData {
1713    ///     fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
1714    ///         fields.add_field_method_get("val", |_, this| Ok(this.0));
1715    ///     }
1716    ///
1717    ///     fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1718    ///         methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1719    ///     }
1720    /// }
1721    ///
1722    /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1723    ///
1724    /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1725    /// # Ok(())
1726    /// # }
1727    /// ```
1728    #[inline]
1729    pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1730    where
1731        T: UserData + 'static,
1732    {
1733        let ud = UserDataProxy::<T>(PhantomData);
1734        unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
1735    }
1736
1737    /// Gets the metatable of a Lua built-in (primitive) type.
1738    ///
1739    /// The metatable is shared by all values of the given type.
1740    ///
1741    /// See [`Lua::set_type_metatable`] for examples.
1742    #[allow(private_bounds)]
1743    pub fn type_metatable<T: LuaType>(&self) -> Option<Table> {
1744        let lua = self.lock();
1745        let state = lua.state();
1746        unsafe {
1747            let _sg = StackGuard::new(state);
1748            assert_stack(state, 2);
1749
1750            if lua.push_primitive_type::<T>() && ffi::lua_getmetatable(state, -1) != 0 {
1751                return Some(Table(lua.pop_ref()));
1752            }
1753        }
1754        None
1755    }
1756
1757    /// Sets the metatable for a Lua built-in (primitive) type.
1758    ///
1759    /// The metatable will be shared by all values of the given type.
1760    ///
1761    /// # Examples
1762    ///
1763    /// Change metatable for Lua boolean type:
1764    ///
1765    /// ```
1766    /// # use mlua::{Lua, Result, Function};
1767    /// # fn main() -> Result<()> {
1768    /// # let lua = Lua::new();
1769    /// let mt = lua.create_table()?;
1770    /// mt.set("__tostring", lua.create_function(|_, b: bool| Ok(if b { "2" } else { "0" }))?)?;
1771    /// lua.set_type_metatable::<bool>(Some(mt));
1772    /// lua.load("assert(tostring(true) == '2')").exec()?;
1773    /// # Ok(())
1774    /// # }
1775    /// ```
1776    #[allow(private_bounds)]
1777    pub fn set_type_metatable<T: LuaType>(&self, metatable: Option<Table>) {
1778        let lua = self.lock();
1779        let state = lua.state();
1780        unsafe {
1781            let _sg = StackGuard::new(state);
1782            assert_stack(state, 2);
1783
1784            if lua.push_primitive_type::<T>() {
1785                match metatable {
1786                    Some(metatable) => lua.push_ref(&metatable.0),
1787                    None => ffi::lua_pushnil(state),
1788                }
1789                ffi::lua_setmetatable(state, -2);
1790            }
1791        }
1792    }
1793
1794    // Like `globals`, but returns an error if the stack cannot grow.
1795    pub(crate) fn try_globals(&self) -> Result<Table> {
1796        let lua = self.lock();
1797        unsafe {
1798            check_stack(lua.state(), 1)?;
1799            ffi::lua_pushglobaltable(lua.state());
1800            Ok(Table(lua.try_pop_ref()?))
1801        }
1802    }
1803
1804    /// Returns a handle to the global environment.
1805    pub fn globals(&self) -> Table {
1806        let lua = self.lock();
1807        let state = lua.state();
1808        unsafe {
1809            let _sg = StackGuard::new(state);
1810            assert_stack(state, 1);
1811            #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1812            ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1813            #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1814            ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1815            Table(lua.pop_ref())
1816        }
1817    }
1818
1819    /// Sets the global environment.
1820    ///
1821    /// This will replace the current global environment with the provided `globals` table.
1822    ///
1823    /// For Lua 5.2+ the globals table is stored in the registry and shared between all threads.
1824    /// For Lua 5.1 and Luau the globals table is stored in each thread.
1825    ///
1826    /// Please note that any existing Lua functions have cached global environment and will not
1827    /// see the changes made by this method.
1828    /// To update the environment for existing Lua functions, use [`Function::set_environment`].
1829    pub fn set_globals(&self, globals: Table) -> Result<()> {
1830        let lua = self.lock();
1831        let state = lua.state();
1832        unsafe {
1833            #[cfg(feature = "luau")]
1834            if (*lua.extra.get()).sandboxed {
1835                return Err(Error::runtime("cannot change globals in a sandboxed Lua state"));
1836            }
1837
1838            let _sg = StackGuard::new(state);
1839            check_stack(state, 1)?;
1840
1841            lua.push_ref(&globals.0);
1842
1843            #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1844            ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1845            #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1846            ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
1847        }
1848
1849        Ok(())
1850    }
1851
1852    /// Returns a handle to the active `Thread`.
1853    ///
1854    /// For calls to `Lua` this will be the main Lua thread, for parameters given to a callback,
1855    /// this will be whatever Lua thread called the callback.
1856    pub fn current_thread(&self) -> Thread {
1857        let lua = self.lock();
1858        let state = lua.state();
1859        unsafe {
1860            // If this thread is implicit (created by `call_async`), return the root user-owned
1861            // thread instead.
1862            #[cfg(feature = "async")]
1863            if let Some(&owner) = (*lua.extra.get()).thread_ownership_map.get(&state) {
1864                assert_stack(owner, 1);
1865                ffi::lua_pushthread(owner);
1866                ffi::lua_xmove(owner, lua.ref_thread(), 1);
1867                return Thread(lua.pop_ref_thread(), owner);
1868            }
1869
1870            let _sg = StackGuard::new(state);
1871            assert_stack(state, 1);
1872            ffi::lua_pushthread(state);
1873            Thread(lua.pop_ref(), state)
1874        }
1875    }
1876
1877    /// Calls the given function with a [`Scope`] parameter, giving the function the ability to
1878    /// create userdata and callbacks from Rust types that are `!Send` or non-`'static`.
1879    ///
1880    /// The lifetime of any function or userdata created through [`Scope`] lasts only until the
1881    /// completion of this method call, on completion all such created values are automatically
1882    /// dropped and Lua references to them are invalidated. If a script accesses a value created
1883    /// through [`Scope`] outside of this method, a Lua error will result. The Lua lock is held
1884    /// until all scoped values are invalidated, preventing other threads from accessing them.
1885    /// This allows `!Send` data types whose lifetimes only outlive the scope lifetime.
1886    pub fn scope<'env, R>(
1887        &self,
1888        f: impl for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> Result<R>,
1889    ) -> Result<R> {
1890        f(&Scope::new(self.lock_arc()))
1891    }
1892
1893    /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1894    /// behavior.
1895    ///
1896    /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1897    /// number.
1898    pub fn coerce_string(&self, v: Value) -> Result<Option<LuaString>> {
1899        Ok(match v {
1900            Value::String(s) => Some(s),
1901            v => unsafe {
1902                let lua = self.lock();
1903                let state = lua.state();
1904                let _sg = StackGuard::new(state);
1905                check_stack(state, 4)?;
1906
1907                lua.push_value(&v)?;
1908                let res = protect_lua_mem!(lua, 1, 1, |state| {
1909                    ffi::lua_tolstring(state, -1, ptr::null_mut())
1910                })?;
1911                if !res.is_null() {
1912                    Some(LuaString(lua.try_pop_ref()?))
1913                } else {
1914                    None
1915                }
1916            },
1917        })
1918    }
1919
1920    /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1921    /// behavior.
1922    ///
1923    /// To succeed, the value must be an integer, a floating point number that has an exact
1924    /// representation as an integer, or a string that can be converted to an integer. Refer to the
1925    /// Lua manual for details.
1926    pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1927        Ok(match v {
1928            Value::Integer(i) => Some(i),
1929            v => unsafe {
1930                let lua = self.lock();
1931                let state = lua.state();
1932                let _sg = StackGuard::new(state);
1933                check_stack(state, 2)?;
1934
1935                lua.push_value(&v)?;
1936                let mut isint = 0;
1937                let i = ffi::lua_tointegerx(state, -1, &mut isint);
1938                (isint != 0).then_some(i)
1939            },
1940        })
1941    }
1942
1943    /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1944    /// behavior.
1945    ///
1946    /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1947    /// to the Lua manual for details.
1948    pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1949        Ok(match v {
1950            Value::Number(n) => Some(n),
1951            v => unsafe {
1952                let lua = self.lock();
1953                let state = lua.state();
1954                let _sg = StackGuard::new(state);
1955                check_stack(state, 2)?;
1956
1957                lua.push_value(&v)?;
1958                let mut isnum = 0;
1959                let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1960                (isnum != 0).then_some(n)
1961            },
1962        })
1963    }
1964
1965    /// Converts a value that implements [`IntoLua`] into a [`Value`] instance.
1966    #[inline]
1967    pub fn pack(&self, t: impl IntoLua) -> Result<Value> {
1968        t.into_lua(self)
1969    }
1970
1971    /// Converts a [`Value`] instance into a value that implements [`FromLua`].
1972    #[inline]
1973    pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
1974        T::from_lua(value, self)
1975    }
1976
1977    /// Converts a value that implements [`IntoLua`] into a [`FromLua`] variant.
1978    #[inline]
1979    pub fn convert<U: FromLua>(&self, value: impl IntoLua) -> Result<U> {
1980        U::from_lua(value.into_lua(self)?, self)
1981    }
1982
1983    /// Converts a value that implements [`IntoLuaMulti`] into a [`MultiValue`] instance.
1984    #[inline]
1985    pub fn pack_multi(&self, t: impl IntoLuaMulti) -> Result<MultiValue> {
1986        t.into_lua_multi(self)
1987    }
1988
1989    /// Converts a [`MultiValue`] instance into a value that implements [`FromLuaMulti`].
1990    #[inline]
1991    pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
1992        T::from_lua_multi(value, self)
1993    }
1994
1995    /// Set a value in the Lua registry based on a string key.
1996    ///
1997    /// This value will be available to Rust from all Lua instances which share the same main
1998    /// state.
1999    pub fn set_named_registry_value(&self, key: &str, t: impl IntoLua) -> Result<()> {
2000        let lua = self.lock();
2001        let state = lua.state();
2002        unsafe {
2003            let _sg = StackGuard::new(state);
2004            check_stack(state, 5)?;
2005
2006            lua.push(t)?;
2007            rawset_field(state, ffi::LUA_REGISTRYINDEX, key)
2008        }
2009    }
2010
2011    /// Get a value from the Lua registry based on a string key.
2012    ///
2013    /// Any Lua instance which shares the underlying main state may call this method to
2014    /// get a value previously set by [`Lua::set_named_registry_value`].
2015    pub fn named_registry_value<T>(&self, key: &str) -> Result<T>
2016    where
2017        T: FromLua,
2018    {
2019        let lua = self.lock();
2020        let state = lua.state();
2021        unsafe {
2022            let _sg = StackGuard::new(state);
2023            check_stack(state, 3)?;
2024
2025            let protect = !lua.unlikely_memory_error();
2026            push_string(state, key.as_bytes(), protect)?;
2027            ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
2028
2029            T::from_stack(-1, &lua)
2030        }
2031    }
2032
2033    /// Removes a named value in the Lua registry.
2034    ///
2035    /// Equivalent to calling [`Lua::set_named_registry_value`] with a value of [`Nil`].
2036    #[inline]
2037    pub fn unset_named_registry_value(&self, key: &str) -> Result<()> {
2038        self.set_named_registry_value(key, Nil)
2039    }
2040
2041    /// Place a value in the Lua registry with an auto-generated key.
2042    ///
2043    /// This value will be available to Rust from all Lua instances which share the same main
2044    /// state.
2045    ///
2046    /// Be warned, garbage collection of values held inside the registry is not automatic, see
2047    /// [`RegistryKey`] for more details.
2048    /// However, dropped [`RegistryKey`]s automatically reused to store new values.
2049    pub fn create_registry_value(&self, t: impl IntoLua) -> Result<RegistryKey> {
2050        let lua = self.lock();
2051        let state = lua.state();
2052        unsafe {
2053            let _sg = StackGuard::new(state);
2054            check_stack(state, 4)?;
2055
2056            lua.push(t)?;
2057
2058            let unref_list = (*lua.extra.get()).registry_unref_list.clone();
2059
2060            // Check if the value is nil (no need to store it in the registry)
2061            if ffi::lua_isnil(state, -1) != 0 {
2062                return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
2063            }
2064
2065            // Try to reuse previously allocated slot
2066            let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
2067            if let Some(registry_id) = free_registry_id {
2068                // It must be safe to replace the value without triggering memory error
2069                ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2070                return Ok(RegistryKey::new(registry_id, unref_list));
2071            }
2072
2073            // Allocate a new RegistryKey slot
2074            let registry_id = protect_lua_mem!(lua, 1, 0, |state| {
2075                ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
2076            })?;
2077            Ok(RegistryKey::new(registry_id, unref_list))
2078        }
2079    }
2080
2081    /// Get a value from the Lua registry by its [`RegistryKey`]
2082    ///
2083    /// Any Lua instance which shares the underlying main state may call this method to get a value
2084    /// previously placed by [`Lua::create_registry_value`].
2085    pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
2086        let lua = self.lock();
2087        if !lua.owns_registry_value(key) {
2088            return Err(Error::MismatchedRegistryKey);
2089        }
2090
2091        let state = lua.state();
2092        match key.id() {
2093            ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
2094            registry_id => unsafe {
2095                let _sg = StackGuard::new(state);
2096                check_stack(state, 1)?;
2097
2098                ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2099                T::from_stack(-1, &lua)
2100            },
2101        }
2102    }
2103
2104    /// Removes a value from the Lua registry.
2105    ///
2106    /// You may call this function to manually remove a value placed in the registry with
2107    /// [`Lua::create_registry_value`]. In addition to manual [`RegistryKey`] removal, you can also
2108    /// call [`Lua::expire_registry_values`] to automatically remove values from the registry
2109    /// whose [`RegistryKey`]s have been dropped.
2110    pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
2111        let lua = self.lock();
2112        if !lua.owns_registry_value(&key) {
2113            return Err(Error::MismatchedRegistryKey);
2114        }
2115
2116        unsafe { ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take()) };
2117        Ok(())
2118    }
2119
2120    /// Replaces a value in the Lua registry by its [`RegistryKey`].
2121    ///
2122    /// An identifier used in [`RegistryKey`] may possibly be changed to a new value.
2123    ///
2124    /// See [`Lua::create_registry_value`] for more details.
2125    pub fn replace_registry_value(&self, key: &mut RegistryKey, t: impl IntoLua) -> Result<()> {
2126        let lua = self.lock();
2127        if !lua.owns_registry_value(key) {
2128            return Err(Error::MismatchedRegistryKey);
2129        }
2130
2131        let t = t.into_lua(self)?;
2132
2133        let state = lua.state();
2134        unsafe {
2135            let _sg = StackGuard::new(state);
2136            check_stack(state, 2)?;
2137
2138            match (t, key.id()) {
2139                (Value::Nil, ffi::LUA_REFNIL) => {
2140                    // Do nothing, no need to replace nil with nil
2141                }
2142                (Value::Nil, registry_id) => {
2143                    // Remove the value
2144                    ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
2145                    key.set_id(ffi::LUA_REFNIL);
2146                }
2147                (value, ffi::LUA_REFNIL) => {
2148                    // Allocate a new `RegistryKey`
2149                    let new_key = self.create_registry_value(value)?;
2150                    key.set_id(new_key.take());
2151                }
2152                (value, registry_id) => {
2153                    // It must be safe to replace the value without triggering memory error
2154                    lua.push_value(&value)?;
2155                    ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2156                }
2157            }
2158        }
2159        Ok(())
2160    }
2161
2162    /// Returns true if the given [`RegistryKey`] was created by a Lua which shares the
2163    /// underlying main state with this Lua instance.
2164    ///
2165    /// Other than this, methods that accept a [`RegistryKey`] will return
2166    /// [`Error::MismatchedRegistryKey`] if passed a [`RegistryKey`] that was not created with a
2167    /// matching [`Lua`] state.
2168    #[inline]
2169    pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
2170        self.lock().owns_registry_value(key)
2171    }
2172
2173    /// Remove any registry values whose [`RegistryKey`]s have all been dropped.
2174    ///
2175    /// Unlike normal handle values, [`RegistryKey`]s do not automatically remove themselves on
2176    /// Drop, but you can call this method to remove any unreachable registry values not
2177    /// manually removed by [`Lua::remove_registry_value`].
2178    pub fn expire_registry_values(&self) {
2179        let lua = self.lock();
2180        let state = lua.state();
2181        unsafe {
2182            let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
2183            let unref_list = unref_list.replace(Vec::new());
2184            for id in mlua_expect!(unref_list, "unref list is not set") {
2185                ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
2186            }
2187        }
2188    }
2189
2190    /// Sets or replaces an application data object of type `T`.
2191    ///
2192    /// Application data could be accessed at any time by using [`Lua::app_data_ref`] or
2193    /// [`Lua::app_data_mut`] methods where `T` is the data type.
2194    ///
2195    /// # Panics
2196    ///
2197    /// Panics if the app data container is currently borrowed.
2198    ///
2199    /// # Examples
2200    ///
2201    /// ```
2202    /// use mlua::{Lua, Result};
2203    ///
2204    /// fn hello(lua: &Lua, _: ()) -> Result<()> {
2205    ///     let mut s = lua.app_data_mut::<&str>().unwrap();
2206    ///     assert_eq!(*s, "hello");
2207    ///     *s = "world";
2208    ///     Ok(())
2209    /// }
2210    ///
2211    /// fn main() -> Result<()> {
2212    ///     let lua = Lua::new();
2213    ///     lua.set_app_data("hello");
2214    ///     lua.create_function(hello)?.call::<()>(())?;
2215    ///     let s = lua.app_data_ref::<&str>().unwrap();
2216    ///     assert_eq!(*s, "world");
2217    ///     Ok(())
2218    /// }
2219    /// ```
2220    #[track_caller]
2221    pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
2222        let lua = self.lock();
2223        let extra = unsafe { &*lua.extra.get() };
2224        extra.app_data.insert(data)
2225    }
2226
2227    /// Tries to set or replace an application data object of type `T`.
2228    ///
2229    /// Returns:
2230    /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
2231    /// - `Ok(None)` if the data object of type `T` was successfully inserted.
2232    /// - `Err(data)` if the data object of type `T` was not inserted because the container is
2233    ///   currently borrowed.
2234    ///
2235    /// See [`Lua::set_app_data`] for examples.
2236    pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
2237        let lua = self.lock();
2238        let extra = unsafe { &*lua.extra.get() };
2239        extra.app_data.try_insert(data)
2240    }
2241
2242    /// Gets a reference to an application data object stored by [`Lua::set_app_data`] of type
2243    /// `T`.
2244    ///
2245    /// # Panics
2246    ///
2247    /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable
2248    /// reads can be taken out at the same time.
2249    #[track_caller]
2250    pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<'_, T>> {
2251        let guard = self.lock_arc();
2252        let extra = unsafe { &*guard.extra.get() };
2253        extra.app_data.borrow(Some(guard))
2254    }
2255
2256    /// Tries to get a reference to an application data object stored by [`Lua::set_app_data`] of
2257    /// type `T`.
2258    pub fn try_app_data_ref<T: 'static>(&self) -> StdResult<Option<AppDataRef<'_, T>>, BorrowError> {
2259        let guard = self.lock_arc();
2260        let extra = unsafe { &*guard.extra.get() };
2261        extra.app_data.try_borrow(Some(guard))
2262    }
2263
2264    /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data`] of
2265    /// type `T`.
2266    ///
2267    /// # Panics
2268    ///
2269    /// Panics if the data object of type `T` is currently borrowed.
2270    #[track_caller]
2271    pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<'_, T>> {
2272        let guard = self.lock_arc();
2273        let extra = unsafe { &*guard.extra.get() };
2274        extra.app_data.borrow_mut(Some(guard))
2275    }
2276
2277    /// Tries to get a mutable reference to an application data object stored by
2278    /// [`Lua::set_app_data`] of type `T`.
2279    pub fn try_app_data_mut<T: 'static>(&self) -> StdResult<Option<AppDataRefMut<'_, T>>, BorrowMutError> {
2280        let guard = self.lock_arc();
2281        let extra = unsafe { &*guard.extra.get() };
2282        extra.app_data.try_borrow_mut(Some(guard))
2283    }
2284
2285    /// Removes an application data of type `T`.
2286    ///
2287    /// # Panics
2288    ///
2289    /// Panics if the app data container is currently borrowed.
2290    #[track_caller]
2291    pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
2292        let lua = self.lock();
2293        let extra = unsafe { &*lua.extra.get() };
2294        extra.app_data.remove()
2295    }
2296
2297    /// Returns an internal `Poll::Pending` constant used for executing async callbacks.
2298    ///
2299    /// Every time when [`Future`] is Pending, Lua corotine is suspended with this constant.
2300    #[cfg(feature = "async")]
2301    #[doc(hidden)]
2302    #[inline(always)]
2303    pub fn poll_pending() -> LightUserData {
2304        static ASYNC_POLL_PENDING: u8 = 0;
2305        LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut std::os::raw::c_void)
2306    }
2307
2308    #[cfg(feature = "async")]
2309    #[inline(always)]
2310    pub(crate) fn poll_terminate() -> LightUserData {
2311        static ASYNC_POLL_TERMINATE: u8 = 0;
2312        LightUserData(&ASYNC_POLL_TERMINATE as *const u8 as *mut std::os::raw::c_void)
2313    }
2314
2315    #[cfg(feature = "async")]
2316    #[inline(always)]
2317    pub(crate) fn poll_yield() -> LightUserData {
2318        static ASYNC_POLL_YIELD: u8 = 0;
2319        LightUserData(&ASYNC_POLL_YIELD as *const u8 as *mut std::os::raw::c_void)
2320    }
2321
2322    /// Suspends the current async function, returning the provided arguments to caller.
2323    ///
2324    /// This function is similar to [`coroutine.yield`] but allow yielding Rust functions
2325    /// and passing values to the caller.
2326    /// Please note that you cannot cross [`Thread`] boundaries (e.g. calling `yield_with` on one
2327    /// thread and resuming on another).
2328    ///
2329    /// # Examples
2330    ///
2331    /// Async iterator:
2332    ///
2333    /// ```
2334    /// # use mlua::{Lua, Result};
2335    /// #
2336    /// async fn generator(lua: Lua, _: ()) -> Result<()> {
2337    ///     for i in 0..10 {
2338    ///         lua.yield_with::<()>(i).await?;
2339    ///     }
2340    ///     Ok(())
2341    /// }
2342    ///
2343    /// fn main() -> Result<()> {
2344    ///     let lua = Lua::new();
2345    ///     lua.globals().set("generator", lua.create_async_function(generator)?)?;
2346    ///
2347    ///     lua.load(r#"
2348    ///        local n = 0
2349    ///        for i in coroutine.wrap(generator) do
2350    ///            n = n + i
2351    ///        end
2352    ///        assert(n == 45)
2353    ///     "#)
2354    ///     .exec()
2355    /// }
2356    /// ```
2357    ///
2358    /// Exchange values on yield:
2359    ///
2360    /// ```
2361    /// # use mlua::{Lua, Result, Value};
2362    /// #
2363    /// async fn pingpong(lua: Lua, mut val: i32) -> Result<()> {
2364    ///     loop {
2365    ///         val = lua.yield_with::<i32>(val).await? + 1;
2366    ///     }
2367    ///     Ok(())
2368    /// }
2369    ///
2370    /// # fn main() -> Result<()> {
2371    /// let lua = Lua::new();
2372    ///
2373    /// let co = lua.create_thread(lua.create_async_function(pingpong)?)?;
2374    /// assert_eq!(co.resume::<i32>(1)?, 1);
2375    /// assert_eq!(co.resume::<i32>(2)?, 3);
2376    /// assert_eq!(co.resume::<i32>(3)?, 4);
2377    ///
2378    /// # Ok(())
2379    /// # }
2380    /// ```
2381    ///
2382    /// [`coroutine.yield`]: https://www.lua.org/manual/5.4/manual.html#pdf-coroutine.yield
2383    #[cfg(feature = "async")]
2384    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2385    pub async fn yield_with<R: FromLuaMulti>(&self, args: impl IntoLuaMulti) -> Result<R> {
2386        let mut args = Some(args.into_lua_multi(self)?);
2387        future::poll_fn(move |_cx| match args.take() {
2388            Some(args) => unsafe {
2389                let lua = self.lock();
2390                lua.push(Self::poll_yield())?; // yield marker
2391                if args.len() <= 1 {
2392                    lua.push(args.front())?;
2393                } else {
2394                    lua.push(lua.create_sequence_from(&args)?)?;
2395                }
2396                lua.push(args.len())?;
2397                Poll::Pending
2398            },
2399            None => unsafe {
2400                let lua = self.lock();
2401                let state = lua.state();
2402                let top = ffi::lua_gettop(state);
2403                if top == 0 || ffi::lua_type(state, 1) != ffi::LUA_TUSERDATA {
2404                    // This must be impossible scenario if used correctly
2405                    return Poll::Ready(R::from_stack_multi(0, &lua));
2406                }
2407                let _sg = StackGuard::with_top(state, 1);
2408                Poll::Ready(R::from_stack_multi(top - 1, &lua))
2409            },
2410        })
2411        .await
2412    }
2413
2414    /// Returns a pointer to the underlying Lua state.
2415    #[doc(hidden)]
2416    pub fn state(&self) -> *mut ffi::lua_State {
2417        self.lock().state()
2418    }
2419
2420    /// Returns a weak reference to the Lua instance.
2421    ///
2422    /// This is useful for creating a reference to the Lua instance that does not prevent it from
2423    /// being deallocated.
2424    #[inline(always)]
2425    pub fn weak(&self) -> WeakLua {
2426        WeakLua(XRc::downgrade(&self.raw))
2427    }
2428
2429    #[cfg(not(feature = "luau"))]
2430    fn disable_c_modules(&self) -> Result<()> {
2431        let package: Table = self.try_globals()?.get("package")?;
2432
2433        package.set(
2434            "loadlib",
2435            self.create_function(|_, ()| -> Result<()> {
2436                Err(Error::SafetyError(
2437                    "package.loadlib is disabled in safe mode".to_string(),
2438                ))
2439            })?,
2440        )?;
2441
2442        #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
2443        let searchers: Table = package.get("searchers")?;
2444        #[cfg(any(feature = "lua51", feature = "luajit"))]
2445        let searchers: Table = package.get("loaders")?;
2446
2447        let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
2448
2449        // The third and fourth searchers looks for a loader as a C library
2450        searchers.raw_set(3, loader)?;
2451        if searchers.raw_len() >= 4 {
2452            searchers.raw_remove(4)?;
2453        }
2454
2455        Ok(())
2456    }
2457
2458    #[inline(always)]
2459    pub(crate) fn lock(&self) -> ReentrantMutexGuard<'_, RawLua> {
2460        let rawlua = self.raw.lock();
2461        #[cfg(feature = "luau")]
2462        if rawlua.is_running_gc() {
2463            panic!("Luau VM is suspended while GC is running");
2464        }
2465        rawlua
2466    }
2467
2468    #[inline(always)]
2469    pub(crate) fn lock_arc(&self) -> LuaGuard {
2470        let guard = LuaGuard(self.raw.lock_arc());
2471        #[cfg(feature = "luau")]
2472        if guard.is_running_gc() {
2473            panic!("Luau VM is suspended while GC is running");
2474        }
2475        guard
2476    }
2477
2478    /// Returns a handle to the unprotected Lua state without any synchronization.
2479    ///
2480    /// This is useful where we know that the lock is already held by the caller.
2481    #[cfg(feature = "async")]
2482    #[inline(always)]
2483    pub(crate) unsafe fn raw_lua(&self) -> &RawLua {
2484        &*self.raw.data_ptr()
2485    }
2486}
2487
2488impl WeakLua {
2489    #[track_caller]
2490    #[inline(always)]
2491    pub(crate) fn lock(&self) -> LuaGuard {
2492        let guard = LuaGuard::new(self.0.upgrade().expect("Lua instance is destroyed"));
2493        #[cfg(feature = "luau")]
2494        if guard.is_running_gc() {
2495            panic!("Luau VM is suspended while GC is running");
2496        }
2497        guard
2498    }
2499
2500    #[inline(always)]
2501    pub(crate) fn try_lock(&self) -> Option<LuaGuard> {
2502        // Reference cleanup must remain possible during Luau GC.
2503        Some(LuaGuard::new(self.0.upgrade()?))
2504    }
2505
2506    /// Upgrades the weak Lua reference to a strong reference.
2507    ///
2508    /// # Panics
2509    ///
2510    /// Panics if the Lua instance is destroyed.
2511    #[track_caller]
2512    #[inline(always)]
2513    pub fn upgrade(&self) -> Lua {
2514        Lua {
2515            raw: self.0.upgrade().expect("Lua instance is destroyed"),
2516            collect_garbage: false,
2517        }
2518    }
2519
2520    /// Tries to upgrade the weak Lua reference to a strong reference.
2521    ///
2522    /// Returns `None` if the Lua instance is destroyed.
2523    #[inline(always)]
2524    pub fn try_upgrade(&self) -> Option<Lua> {
2525        Some(Lua {
2526            raw: self.0.upgrade()?,
2527            collect_garbage: false,
2528        })
2529    }
2530}
2531
2532impl PartialEq for WeakLua {
2533    fn eq(&self, other: &Self) -> bool {
2534        XWeak::ptr_eq(&self.0, &other.0)
2535    }
2536}
2537
2538impl Eq for WeakLua {}
2539
2540impl LuaGuard {
2541    #[cfg(feature = "send")]
2542    pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2543        LuaGuard(handle.lock_arc())
2544    }
2545
2546    #[cfg(not(feature = "send"))]
2547    pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2548        LuaGuard(handle.into_lock_arc())
2549    }
2550}
2551
2552impl Deref for LuaGuard {
2553    type Target = RawLua;
2554
2555    fn deref(&self) -> &Self::Target {
2556        &self.0
2557    }
2558}
2559
2560pub(crate) mod extra;
2561mod raw;
2562pub(crate) mod util;
2563
2564#[cfg(test)]
2565mod assertions {
2566    use super::*;
2567
2568    // Lua has lots of interior mutability, should not be RefUnwindSafe
2569    static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
2570
2571    #[cfg(not(feature = "send"))]
2572    static_assertions::assert_not_impl_any!(Lua: Send);
2573    #[cfg(feature = "send")]
2574    static_assertions::assert_impl_all!(Lua: Send, Sync);
2575}