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