Skip to main content

mlua/
state.rs

1//! Lua state management.
2//!
3//! This module provides the main [`Lua`] state handle together with state-specific
4//! configuration and garbage collector controls.
5
6use std::any::TypeId;
7use std::cell::{BorrowError, BorrowMutError, RefCell};
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::os::raw::{c_char, c_int};
11use std::panic::Location;
12use std::result::Result as StdResult;
13use std::{fmt, mem, ptr};
14
15use crate::chunk::{AsChunk, Chunk};
16use crate::debug::Debug;
17use crate::error::{Error, Result};
18use crate::function::Function;
19use crate::memory::MemoryState;
20use crate::multi::MultiValue;
21use crate::scope::Scope;
22use crate::stdlib::StdLib;
23use crate::string::LuaString;
24use crate::table::Table;
25use crate::thread::{Thread, ThreadEvent, ThreadTriggers};
26use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
27use crate::types::{
28    AppDataRef, AppDataRefMut, ArcReentrantMutexGuard, Integer, LuaType, MaybeSend, MaybeSync, Number,
29    ReentrantMutex, ReentrantMutexGuard, RegistryKey, VmState, XRc, XWeak,
30};
31use crate::userdata::{AnyUserData, UserData, UserDataProxy, UserDataRegistry, UserDataStorage};
32use crate::util::{StackGuard, assert_stack, check_stack, protect_lua_closure, push_string, rawset_field};
33use crate::value::{Nil, Value};
34
35#[cfg(not(feature = "luau"))]
36use crate::{debug::HookTriggers, types::HookKind};
37
38#[cfg(any(feature = "luau", doc))]
39use crate::{buffer::Buffer, chunk::Compiler};
40
41#[cfg(feature = "async")]
42use {
43    crate::types::LightUserData,
44    std::future::{self, Future},
45    std::task::Poll,
46};
47
48#[cfg(feature = "serde")]
49use serde::Serialize;
50
51pub(crate) use extra::ExtraData;
52#[doc(hidden)]
53pub use raw::RawLua;
54pub(crate) use util::callback_error_ext;
55
56/// Top level Lua struct which represents an instance of Lua VM.
57pub struct Lua {
58    pub(self) raw: XRc<ReentrantMutex<RawLua>>,
59    // Controls whether garbage collection should be run on drop
60    pub(self) collect_garbage: bool,
61}
62
63/// Weak reference to Lua instance.
64///
65/// This can used to prevent circular references between Lua and Rust objects.
66#[derive(Clone)]
67pub struct WeakLua(XWeak<ReentrantMutex<RawLua>>);
68
69pub(crate) struct LuaGuard(ArcReentrantMutexGuard<RawLua>);
70
71/// Tuning parameters for the incremental GC collector.
72///
73/// 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 callback invoked when thread lifecycle events occur.
846    ///
847    /// `triggers` controls which events trigger the callback, see [`ThreadTriggers`] for more
848    /// details.
849    ///
850    /// Only one callback can be registered at a time. Calling this again replaces the previous
851    /// callback and its triggers.
852    ///
853    /// # Example
854    ///
855    /// Subscribe only to yield events:
856    ///
857    /// ```
858    /// # use mlua::{Lua, Result, ThreadTriggers, ThreadEvent};
859    /// # fn main() -> Result<()> {
860    /// let lua = Lua::new();
861    /// lua.set_thread_event_callback(
862    ///     ThreadTriggers::ON_YIELD,
863    ///     |_lua, event| {
864    ///         if let ThreadEvent::Yield(thread) = event {
865    ///             println!("thread yielded");
866    ///         }
867    ///         Ok(())
868    ///     },
869    /// );
870    /// # Ok(())
871    /// # }
872    /// ```
873    pub fn set_thread_event_callback<F>(&self, triggers: ThreadTriggers, callback: F)
874    where
875        F: Fn(&Lua, ThreadEvent) -> Result<()> + MaybeSend + 'static,
876    {
877        let lua = self.lock();
878        unsafe {
879            (*lua.extra.get()).thread_triggers = triggers;
880            (*lua.extra.get()).thread_event_callback = Some(XRc::new(callback));
881            #[cfg(feature = "luau")]
882            {
883                let proc = Self::userthread_proc as _;
884                (*ffi::lua_callbacks(lua.main_state())).userthread = triggers.on_create.then(|| proc);
885            }
886        }
887    }
888
889    /// Removes the thread event callback previously set by [`Lua::set_thread_event_callback`].
890    ///
891    /// This function has no effect if a callback was not previously set.
892    pub fn remove_thread_event_callback(&self) {
893        let lua = self.lock();
894        let extra = lua.extra.get();
895        unsafe {
896            (*extra).thread_triggers = ThreadTriggers::new();
897            (*extra).thread_event_callback = None;
898            #[cfg(feature = "luau")]
899            {
900                (*ffi::lua_callbacks(lua.main_state())).userthread = None;
901            }
902        }
903    }
904
905    #[cfg(feature = "luau")]
906    unsafe extern "C-unwind" fn userthread_proc(parent: *mut ffi::lua_State, child: *mut ffi::lua_State) {
907        // Only handle thread creation
908        if parent.is_null() {
909            return;
910        }
911
912        let extra = ExtraData::get(child);
913        if !(*extra).thread_triggers.on_create {
914            return;
915        }
916        let callback = match &(*extra).thread_event_callback {
917            Some(cb) if XRc::strong_count(cb) == 1 => cb.clone(),
918            _ => return,
919        };
920        ffi::lua_pushthread(child);
921        ffi::lua_xmove(child, (*extra).ref_thread, 1);
922        let thread = Thread((*extra).raw_lua().pop_ref_thread(), child);
923        callback_error_ext(parent, extra, false, move |extra, _| {
924            callback((*extra).lua(), ThreadEvent::Create(thread))
925        })
926    }
927
928    /// Sets the warning function to be used by Lua to emit warnings.
929    #[cfg(any(feature = "lua55", feature = "lua54"))]
930    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
931    pub fn set_warning_function<F>(&self, callback: F)
932    where
933        F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
934    {
935        use std::ffi::CStr;
936        use std::os::raw::{c_char, c_void};
937
938        unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
939            let extra = ud as *mut ExtraData;
940            callback_error_ext((*extra).raw_lua().state(), extra, false, |extra, _| {
941                let warn_callback = (*extra).warn_callback.clone();
942                let warn_callback = mlua_expect!(warn_callback, "no warning callback set in warn_proc");
943                if XRc::strong_count(&warn_callback) > 2 {
944                    return Ok(());
945                }
946                let msg = String::from_utf8_lossy(CStr::from_ptr(msg).to_bytes());
947                warn_callback((*extra).lua(), &msg, tocont != 0)
948            });
949        }
950
951        let lua = self.lock();
952        unsafe {
953            (*lua.extra.get()).warn_callback = Some(XRc::new(callback));
954            ffi::lua_setwarnf(lua.state(), Some(warn_proc), lua.extra.get() as *mut c_void);
955        }
956    }
957
958    /// Removes warning function previously set by `set_warning_function`.
959    ///
960    /// This function has no effect if a warning function was not previously set.
961    #[cfg(any(feature = "lua55", feature = "lua54"))]
962    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
963    pub fn remove_warning_function(&self) {
964        let lua = self.lock();
965        unsafe {
966            (*lua.extra.get()).warn_callback = None;
967            ffi::lua_setwarnf(lua.state(), None, ptr::null_mut());
968        }
969    }
970
971    /// Emits a warning with the given message.
972    ///
973    /// A message in a call with `incomplete` set to `true` should be continued in
974    /// another call to this function.
975    #[cfg(any(feature = "lua55", feature = "lua54"))]
976    #[cfg_attr(docsrs, doc(cfg(any(feature = "lua55", feature = "lua54"))))]
977    pub fn warning(&self, msg: impl AsRef<str>, incomplete: bool) {
978        let msg = msg.as_ref();
979        let mut bytes = vec![0; msg.len() + 1];
980        bytes[..msg.len()].copy_from_slice(msg.as_bytes());
981        let real_len = bytes.iter().position(|&c| c == 0).unwrap();
982        bytes.truncate(real_len);
983        let lua = self.lock();
984        unsafe {
985            ffi::lua_warning(lua.state(), bytes.as_ptr() as *const _, incomplete as c_int);
986        }
987    }
988
989    /// Gets information about the interpreter runtime stack at the given level.
990    ///
991    /// This function calls callback `f`, passing the [`struct@Debug`] structure that can be used to
992    /// get information about the function executing at a given level.
993    /// Level `0` is the current running function, whereas level `n+1` is the function that has
994    /// called level `n` (except for tail calls, which do not count in the stack).
995    pub fn inspect_stack<R>(&self, level: usize, f: impl FnOnce(&Debug) -> R) -> Option<R> {
996        let lua = self.lock();
997        unsafe {
998            let mut ar = mem::zeroed::<ffi::lua_Debug>();
999            let level = level as c_int;
1000            #[cfg(not(feature = "luau"))]
1001            if ffi::lua_getstack(lua.state(), level, &mut ar) == 0 {
1002                return None;
1003            }
1004            #[cfg(feature = "luau")]
1005            if ffi::lua_getinfo(lua.state(), level, cstr!(""), &mut ar) == 0 {
1006                return None;
1007            }
1008
1009            Some(f(&Debug::new(&lua, level, &mut ar)))
1010        }
1011    }
1012
1013    /// Creates a traceback of the call stack at the given level.
1014    ///
1015    /// The `msg` parameter, if provided, is added at the beginning of the traceback.
1016    /// The `level` parameter works the same way as in [`Lua::inspect_stack`].
1017    pub fn traceback(&self, msg: Option<&str>, level: usize) -> Result<LuaString> {
1018        let lua = self.lock();
1019        unsafe {
1020            check_stack(lua.state(), 3)?;
1021            protect_lua!(lua.state(), 0, 1, |state| {
1022                let msg = match msg {
1023                    Some(s) => ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len()),
1024                    None => ptr::null(),
1025                };
1026                // `protect_lua` adds it's own call frame, so we need to increase level by 1
1027                ffi::luaL_traceback(state, state, msg, (level + 1) as c_int);
1028            })?;
1029            Ok(LuaString(lua.pop_ref()))
1030        }
1031    }
1032
1033    /// Returns the amount of memory (in bytes) currently used inside this Lua state.
1034    pub fn used_memory(&self) -> usize {
1035        let lua = self.lock();
1036        let state = lua.main_state();
1037        unsafe {
1038            match MemoryState::get(state) {
1039                mem_state if !mem_state.is_null() => (*mem_state).used_memory(),
1040                _ => {
1041                    // Get data from the Lua GC
1042                    let used_kbytes = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0);
1043                    let used_kbytes_rem = ffi::lua_gc(state, ffi::LUA_GCCOUNTB, 0);
1044                    (used_kbytes as usize) * 1024 + (used_kbytes_rem as usize)
1045                }
1046            }
1047        }
1048    }
1049
1050    /// Sets a memory limit (in bytes) on this Lua state.
1051    ///
1052    /// Once an allocation occurs that would pass this memory limit, a `Error::MemoryError` is
1053    /// generated instead.
1054    /// Returns previous limit (zero means no limit).
1055    ///
1056    /// Does not work in module mode where Lua state is managed externally.
1057    pub fn set_memory_limit(&self, limit: usize) -> Result<usize> {
1058        let lua = self.lock();
1059        unsafe {
1060            match MemoryState::get(lua.state()) {
1061                mem_state if !mem_state.is_null() => Ok((*mem_state).set_memory_limit(limit)),
1062                _ => Err(Error::MemoryControlNotAvailable),
1063            }
1064        }
1065    }
1066
1067    /// Returns `true` if the garbage collector is currently running automatically.
1068    #[cfg(any(
1069        feature = "lua55",
1070        feature = "lua54",
1071        feature = "lua53",
1072        feature = "lua52",
1073        feature = "luau"
1074    ))]
1075    pub fn gc_is_running(&self) -> bool {
1076        let lua = self.lock();
1077        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCISRUNNING, 0) != 0 }
1078    }
1079
1080    /// Stops the Lua GC from running.
1081    pub fn gc_stop(&self) {
1082        let lua = self.lock();
1083        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCSTOP, 0) };
1084    }
1085
1086    /// Restarts the Lua GC if it is not running.
1087    pub fn gc_restart(&self) {
1088        let lua = self.lock();
1089        unsafe { ffi::lua_gc(lua.main_state(), ffi::LUA_GCRESTART, 0) };
1090    }
1091
1092    /// Performs a full garbage-collection cycle.
1093    ///
1094    /// It may be necessary to call this function twice to collect all currently unreachable
1095    /// objects. Once to finish the current gc cycle, and once to start and finish the next cycle.
1096    pub fn gc_collect(&self) -> Result<()> {
1097        let lua = self.lock();
1098        let state = lua.main_state();
1099        unsafe {
1100            check_stack(state, 2)?;
1101            protect_lua!(state, 0, 0, fn(state) ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0))
1102        }
1103    }
1104
1105    /// Performs a basic step of garbage collection.
1106    ///
1107    /// In incremental mode, a basic step corresponds to the current step size. In generational
1108    /// mode, a basic step performs a full minor collection or an incremental step, if the collector
1109    /// has scheduled one.
1110    ///
1111    /// In incremental mode, returns `true` if this step has finished a collection cycle.
1112    /// In generational mode, returns `true` if the step finished a major collection.
1113    pub fn gc_step(&self) -> Result<bool> {
1114        let lua = self.lock();
1115        let state = lua.main_state();
1116        unsafe {
1117            check_stack(state, 3)?;
1118            protect_lua!(state, 0, 0, |state| {
1119                ffi::lua_gc(state, ffi::LUA_GCSTEP, 0) != 0
1120            })
1121        }
1122    }
1123
1124    /// Switches the GC to the given mode with the provided parameters.
1125    ///
1126    /// Returns the previous [`GcMode`]. The returned value's parameter fields are always
1127    /// `None` because Lua's C API does not provide a way to read back current parameter values
1128    /// without changing them.
1129    ///
1130    /// # Examples
1131    ///
1132    /// Switch to generational mode (Lua 5.4+):
1133    /// ```ignore
1134    /// let prev = lua.gc_set_mode(GcMode::Generational(GcGenParams::default()));
1135    /// ```
1136    ///
1137    /// Switch to incremental mode with custom parameters:
1138    /// ```ignore
1139    /// lua.gc_set_mode(GcMode::Incremental(
1140    ///     GcIncParams::default().pause(200).step_multiplier(100)
1141    /// ));
1142    /// ```
1143    pub fn gc_set_mode(&self, mode: GcMode) -> GcMode {
1144        let lua = self.lock();
1145        let state = lua.main_state();
1146
1147        match mode {
1148            #[cfg(feature = "lua55")]
1149            GcMode::Incremental(params) => unsafe {
1150                if let Some(v) = params.pause {
1151                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPPAUSE, v);
1152                }
1153                if let Some(v) = params.step_multiplier {
1154                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPMUL, v);
1155                }
1156                if let Some(v) = params.step_size {
1157                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPSTEPSIZE, v);
1158                }
1159                match ffi::lua_gc(state, ffi::LUA_GCINC) {
1160                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1161                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1162                    _ => unreachable!(),
1163                }
1164            },
1165            #[cfg(feature = "lua54")]
1166            GcMode::Incremental(params) => unsafe {
1167                let pause = params.pause.unwrap_or(0);
1168                let step_mul = params.step_multiplier.unwrap_or(0);
1169                let step_size = params.step_size.unwrap_or(0);
1170                match ffi::lua_gc(state, ffi::LUA_GCINC, pause, step_mul, step_size) {
1171                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1172                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1173                    _ => unreachable!(),
1174                }
1175            },
1176            #[cfg(any(feature = "lua53", feature = "lua52", feature = "lua51", feature = "luajit"))]
1177            GcMode::Incremental(params) => unsafe {
1178                if let Some(v) = params.pause {
1179                    ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, v);
1180                }
1181                if let Some(v) = params.step_multiplier {
1182                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1183                }
1184                GcMode::Incremental(GcIncParams::default())
1185            },
1186            #[cfg(feature = "luau")]
1187            GcMode::Incremental(params) => unsafe {
1188                if let Some(v) = params.goal {
1189                    ffi::lua_gc(state, ffi::LUA_GCSETGOAL, v);
1190                }
1191                if let Some(v) = params.step_multiplier {
1192                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPMUL, v);
1193                }
1194                if let Some(v) = params.step_size {
1195                    ffi::lua_gc(state, ffi::LUA_GCSETSTEPSIZE, v);
1196                }
1197                GcMode::Incremental(GcIncParams::default())
1198            },
1199
1200            #[cfg(feature = "lua55")]
1201            GcMode::Generational(params) => unsafe {
1202                if let Some(v) = params.minor_multiplier {
1203                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMUL, v);
1204                }
1205                if let Some(v) = params.minor_to_major {
1206                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMINORMAJOR, v);
1207                }
1208                if let Some(v) = params.major_to_minor {
1209                    ffi::lua_gc(state, ffi::LUA_GCPARAM, ffi::LUA_GCPMAJORMINOR, v);
1210                }
1211                match ffi::lua_gc(state, ffi::LUA_GCGEN) {
1212                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1213                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1214                    _ => unreachable!(),
1215                }
1216            },
1217            #[cfg(feature = "lua54")]
1218            GcMode::Generational(params) => unsafe {
1219                let minor = params.minor_multiplier.unwrap_or(0);
1220                let minor_to_major = params.minor_to_major.unwrap_or(0);
1221                match ffi::lua_gc(state, ffi::LUA_GCGEN, minor, minor_to_major) {
1222                    ffi::LUA_GCGEN => GcMode::Generational(GcGenParams::default()),
1223                    ffi::LUA_GCINC => GcMode::Incremental(GcIncParams::default()),
1224                    _ => unreachable!(),
1225                }
1226            },
1227        }
1228    }
1229
1230    /// Sets a default Luau compiler (with custom options).
1231    ///
1232    /// This compiler will be used by default to load all Lua chunks
1233    /// including via `require` function.
1234    ///
1235    /// See [`Compiler`] for details and possible options.
1236    #[cfg(any(feature = "luau", doc))]
1237    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1238    pub fn set_compiler(&self, compiler: Compiler) {
1239        let lua = self.lock();
1240        unsafe { (*lua.extra.get()).compiler = Some(compiler) };
1241    }
1242
1243    /// Toggles JIT compilation mode for new chunks of code.
1244    ///
1245    /// By default JIT is enabled. Changing this option does not have any effect on
1246    /// already loaded functions.
1247    #[cfg(any(feature = "luau-jit", doc))]
1248    #[cfg_attr(docsrs, doc(cfg(feature = "luau-jit")))]
1249    pub fn enable_jit(&self, enable: bool) {
1250        let lua = self.lock();
1251        unsafe { (*lua.extra.get()).enable_jit = enable };
1252    }
1253
1254    /// Sets Luau feature flag (global setting).
1255    ///
1256    /// See https://github.com/luau-lang/luau/blob/master/CONTRIBUTING.md#feature-flags for details.
1257    #[cfg(feature = "luau")]
1258    #[doc(hidden)]
1259    #[allow(clippy::result_unit_err)]
1260    pub fn set_fflag(name: &str, enabled: bool) -> StdResult<(), ()> {
1261        if let Ok(name) = std::ffi::CString::new(name)
1262            && unsafe { ffi::luau_setfflag(name.as_ptr(), enabled as c_int) != 0 }
1263        {
1264            return Ok(());
1265        }
1266        Err(())
1267    }
1268
1269    /// Returns Lua source code as a `Chunk` builder type.
1270    ///
1271    /// In order to actually compile or run the resulting code, you must call [`Chunk::exec`] or
1272    /// similar on the returned builder. Code is not even parsed until one of these methods is
1273    /// called.
1274    ///
1275    /// [`Chunk::exec`]: crate::Chunk::exec
1276    #[track_caller]
1277    pub fn load<'a>(&self, chunk: impl AsChunk + 'a) -> Chunk<'a> {
1278        self.load_with_location(chunk, Location::caller())
1279    }
1280
1281    pub(crate) fn load_with_location<'a>(
1282        &self,
1283        chunk: impl AsChunk + 'a,
1284        location: &'static Location<'static>,
1285    ) -> Chunk<'a> {
1286        Chunk {
1287            lua: self.weak(),
1288            name: chunk
1289                .name()
1290                .unwrap_or_else(|| format!("@{}:{}", location.file(), location.line())),
1291            env: chunk.environment(self),
1292            mode: chunk.mode(),
1293            source: chunk.source(),
1294            #[cfg(feature = "luau")]
1295            compiler: unsafe { (*self.lock().extra.get()).compiler.clone() },
1296        }
1297    }
1298
1299    /// Creates and returns an interned Lua string.
1300    ///
1301    /// Lua strings can be arbitrary `[u8]` data including embedded nulls, so in addition to `&str`
1302    /// and `&String`, you can also pass plain `&[u8]` here.
1303    #[inline]
1304    pub fn create_string(&self, s: impl AsRef<[u8]>) -> Result<LuaString> {
1305        unsafe { self.lock().create_string(s.as_ref()) }
1306    }
1307
1308    /// Creates and returns an external Lua string.
1309    ///
1310    /// External string is a string where the memory is managed by Rust code, and Lua only holds a
1311    /// reference to it. This can be used to avoid copying large strings into Lua memory.
1312    #[cfg(feature = "lua55")]
1313    #[cfg_attr(docsrs, doc(cfg(feature = "lua55")))]
1314    #[inline]
1315    pub fn create_external_string(&self, s: impl Into<Vec<u8>>) -> Result<LuaString> {
1316        unsafe { self.lock().create_external_string(s.into()) }
1317    }
1318
1319    /// Creates and returns a Luau [buffer] object from a byte slice of data.
1320    ///
1321    /// [buffer]: https://luau.org/library#buffer-library
1322    #[cfg(any(feature = "luau", doc))]
1323    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1324    pub fn create_buffer(&self, data: impl AsRef<[u8]>) -> Result<Buffer> {
1325        let lua = self.lock();
1326        let data = data.as_ref();
1327        unsafe {
1328            let (ptr, buffer) = lua.create_buffer_with_capacity(data.len())?;
1329            ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
1330            Ok(buffer)
1331        }
1332    }
1333
1334    /// Creates and returns a Luau [buffer] object with the specified size.
1335    ///
1336    /// Size limit is 1GB. All bytes will be initialized to zero.
1337    ///
1338    /// [buffer]: https://luau.org/library#buffer-library
1339    #[cfg(any(feature = "luau", doc))]
1340    #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
1341    pub fn create_buffer_with_capacity(&self, size: usize) -> Result<Buffer> {
1342        unsafe { Ok(self.lock().create_buffer_with_capacity(size)?.1) }
1343    }
1344
1345    /// Creates and returns a new empty table.
1346    #[inline]
1347    pub fn create_table(&self) -> Result<Table> {
1348        self.create_table_with_capacity(0, 0)
1349    }
1350
1351    /// Creates and returns a new empty table, with the specified capacity.
1352    ///
1353    /// - `narr` is a hint for how many elements the table will have as a sequence.
1354    /// - `nrec` is a hint for how many other elements the table will have.
1355    ///
1356    /// Lua may use these hints to preallocate memory for the new table.
1357    pub fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
1358        unsafe { self.lock().create_table_with_capacity(narr, nrec) }
1359    }
1360
1361    /// Creates a table and fills it with values from an iterator.
1362    pub fn create_table_from<K, V>(&self, iter: impl IntoIterator<Item = (K, V)>) -> Result<Table>
1363    where
1364        K: IntoLua,
1365        V: IntoLua,
1366    {
1367        unsafe { self.lock().create_table_from(iter) }
1368    }
1369
1370    /// Creates a table from an iterator of values, using `1..` as the keys.
1371    pub fn create_sequence_from<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<Table>
1372    where
1373        T: IntoLua,
1374    {
1375        unsafe { self.lock().create_sequence_from(iter) }
1376    }
1377
1378    /// Wraps a Rust function or closure, creating a callable Lua function handle to it.
1379    ///
1380    /// The function's return value is always a `Result`: If the function returns `Err`, the error
1381    /// is raised as a Lua error, which can be caught using `(x)pcall` or bubble up to the Rust code
1382    /// that invoked the Lua code. This allows using the `?` operator to propagate errors through
1383    /// intermediate Lua code.
1384    ///
1385    /// If the function returns `Ok`, the contained value will be converted to one or more Lua
1386    /// values. For details on Rust-to-Lua conversions, refer to the [`IntoLua`] and
1387    /// [`IntoLuaMulti`] traits.
1388    ///
1389    /// # Examples
1390    ///
1391    /// Create a function which prints its argument:
1392    ///
1393    /// ```
1394    /// # use mlua::{Lua, Result};
1395    /// # fn main() -> Result<()> {
1396    /// # let lua = Lua::new();
1397    /// let greet = lua.create_function(|_, name: String| {
1398    ///     println!("Hello, {}!", name);
1399    ///     Ok(())
1400    /// });
1401    /// # let _ = greet;    // used
1402    /// # Ok(())
1403    /// # }
1404    /// ```
1405    ///
1406    /// Use tuples to accept multiple arguments:
1407    ///
1408    /// ```
1409    /// # use mlua::{Lua, Result};
1410    /// # fn main() -> Result<()> {
1411    /// # let lua = Lua::new();
1412    /// let print_person = lua.create_function(|_, (name, age): (String, u8)| {
1413    ///     println!("{} is {} years old!", name, age);
1414    ///     Ok(())
1415    /// });
1416    /// # let _ = print_person;    // used
1417    /// # Ok(())
1418    /// # }
1419    /// ```
1420    pub fn create_function<F, A, R>(&self, func: F) -> Result<Function>
1421    where
1422        F: Fn(&Lua, A) -> Result<R> + MaybeSend + 'static,
1423        A: FromLuaMulti,
1424        R: IntoLuaMulti,
1425    {
1426        (self.lock()).create_callback(Box::new(move |rawlua, nargs| unsafe {
1427            let args = A::from_stack_args(nargs, 1, None, rawlua)?;
1428            func(rawlua.lua(), args)?.push_into_stack_multi(rawlua)
1429        }))
1430    }
1431
1432    /// Wraps a Rust mutable closure, creating a callable Lua function handle to it.
1433    ///
1434    /// This is a version of [`Lua::create_function`] that accepts a `FnMut` argument.
1435    pub fn create_function_mut<F, A, R>(&self, func: F) -> Result<Function>
1436    where
1437        F: FnMut(&Lua, A) -> Result<R> + MaybeSend + 'static,
1438        A: FromLuaMulti,
1439        R: IntoLuaMulti,
1440    {
1441        let func = RefCell::new(func);
1442        self.create_function(move |lua, args| {
1443            (*func.try_borrow_mut().map_err(|_| Error::RecursiveMutCallback)?)(lua, args)
1444        })
1445    }
1446
1447    /// Wraps a C function, creating a callable Lua function handle to it.
1448    ///
1449    /// # Safety
1450    /// This function is unsafe because provides a way to execute unsafe C function.
1451    pub unsafe fn create_c_function(&self, func: ffi::lua_CFunction) -> Result<Function> {
1452        let lua = self.lock();
1453        if cfg!(any(
1454            feature = "lua55",
1455            feature = "lua54",
1456            feature = "lua53",
1457            feature = "lua52"
1458        )) {
1459            ffi::lua_pushcfunction(lua.ref_thread(), func);
1460            return Ok(Function(lua.pop_ref_thread()));
1461        }
1462
1463        // Lua <5.2 requires memory allocation to push a C function
1464        let state = lua.state();
1465        {
1466            let _sg = StackGuard::new(state);
1467            check_stack(state, 3)?;
1468
1469            if lua.unlikely_memory_error() {
1470                ffi::lua_pushcfunction(state, func);
1471            } else {
1472                protect_lua!(state, 0, 1, |state| ffi::lua_pushcfunction(state, func))?;
1473            }
1474            Ok(Function(lua.pop_ref()))
1475        }
1476    }
1477
1478    /// Wraps a Rust async function or closure, creating a callable Lua function handle to it.
1479    ///
1480    /// While executing the function Rust will poll the Future and if the result is not ready,
1481    /// call `yield()` passing internal representation of a `Poll::Pending` value.
1482    ///
1483    /// The function must be called inside Lua coroutine ([`Thread`]) to be able to suspend its
1484    /// execution. An executor should be used to poll [`AsyncThread`] and mlua will take a provided
1485    /// Waker in that case. Otherwise noop waker will be used if try to call the function outside of
1486    /// Rust executors.
1487    ///
1488    /// The family of `call_async()` functions takes care about creating [`Thread`].
1489    ///
1490    /// # Examples
1491    ///
1492    /// Non blocking sleep:
1493    ///
1494    /// ```
1495    /// use std::time::Duration;
1496    /// use mlua::{Lua, Result};
1497    ///
1498    /// async fn sleep(_lua: Lua, n: u64) -> Result<&'static str> {
1499    ///     tokio::time::sleep(Duration::from_millis(n)).await;
1500    ///     Ok("done")
1501    /// }
1502    ///
1503    /// #[tokio::main]
1504    /// async fn main() -> Result<()> {
1505    ///     let lua = Lua::new();
1506    ///     lua.globals().set("sleep", lua.create_async_function(sleep)?)?;
1507    ///     let res: String = lua.load("return sleep(...)").call_async(100).await?; // Sleep 100ms
1508    ///     assert_eq!(res, "done");
1509    ///     Ok(())
1510    /// }
1511    /// ```
1512    ///
1513    /// [`AsyncThread`]: crate::thread::AsyncThread
1514    #[cfg(feature = "async")]
1515    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1516    pub fn create_async_function<F, A, FR, R>(&self, func: F) -> Result<Function>
1517    where
1518        F: Fn(Lua, A) -> FR + MaybeSend + 'static,
1519        A: FromLuaMulti,
1520        FR: Future<Output = Result<R>> + MaybeSend + 'static,
1521        R: IntoLuaMulti,
1522    {
1523        // In future we should switch to async closures when they are stable to capture `&Lua`
1524        // See https://rust-lang.github.io/rfcs/3668-async-closures.html
1525        (self.lock()).create_async_callback(Box::new(move |rawlua, nargs| unsafe {
1526            let args = match A::from_stack_args(nargs, 1, None, rawlua) {
1527                Ok(args) => args,
1528                Err(e) => return Box::pin(future::ready(Err(e))),
1529            };
1530            let lua = rawlua.lua();
1531            let fut = func(lua.clone(), args);
1532            Box::pin(async move { fut.await?.push_into_stack_multi(lua.raw_lua()) })
1533        }))
1534    }
1535
1536    /// Wraps a Lua function into a new thread (or coroutine).
1537    ///
1538    /// Equivalent to `coroutine.create`.
1539    pub fn create_thread(&self, func: Function) -> Result<Thread> {
1540        unsafe { self.lock().create_thread(&func) }
1541    }
1542
1543    /// Creates a Lua userdata object from a custom userdata type.
1544    ///
1545    /// All userdata instances of the same type `T` shares the same metatable.
1546    #[inline]
1547    pub fn create_userdata<T>(&self, data: T) -> Result<AnyUserData>
1548    where
1549        T: UserData + MaybeSend + MaybeSync + 'static,
1550    {
1551        unsafe { self.lock().make_userdata(UserDataStorage::new(data)) }
1552    }
1553
1554    /// Creates a Lua userdata object from a custom serializable userdata type.
1555    #[cfg(feature = "serde")]
1556    #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1557    #[inline]
1558    pub fn create_ser_userdata<T>(&self, data: T) -> Result<AnyUserData>
1559    where
1560        T: UserData + Serialize + MaybeSend + MaybeSync + 'static,
1561    {
1562        unsafe { self.lock().make_userdata(UserDataStorage::new_ser(data)) }
1563    }
1564
1565    /// Creates a Lua userdata object from a custom Rust type.
1566    ///
1567    /// You can register the type using [`Lua::register_userdata_type`] to add fields or methods
1568    /// _before_ calling this method.
1569    /// Otherwise, the userdata object will have an empty metatable.
1570    ///
1571    /// All userdata instances of the same type `T` shares the same metatable.
1572    #[inline]
1573    pub fn create_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1574    where
1575        T: MaybeSend + MaybeSync + 'static,
1576    {
1577        unsafe { self.lock().make_any_userdata(UserDataStorage::new(data)) }
1578    }
1579
1580    /// Creates a Lua userdata object from a custom serializable Rust type.
1581    ///
1582    /// See [`Lua::create_any_userdata`] for more details.
1583    #[cfg(feature = "serde")]
1584    #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1585    #[inline]
1586    pub fn create_ser_any_userdata<T>(&self, data: T) -> Result<AnyUserData>
1587    where
1588        T: Serialize + MaybeSend + MaybeSync + 'static,
1589    {
1590        unsafe { (self.lock()).make_any_userdata(UserDataStorage::new_ser(data)) }
1591    }
1592
1593    /// Registers a custom Rust type in Lua to use in userdata objects.
1594    ///
1595    /// This methods provides a way to add fields or methods to userdata objects of a type `T`.
1596    pub fn register_userdata_type<T: 'static>(&self, f: impl FnOnce(&mut UserDataRegistry<T>)) -> Result<()> {
1597        let type_id = TypeId::of::<T>();
1598        let mut registry = UserDataRegistry::new(self);
1599        f(&mut registry);
1600
1601        let lua = self.lock();
1602        unsafe {
1603            // Deregister the type if it already registered
1604            if let Some(table_id) = (*lua.extra.get()).registered_userdata_t.remove(&type_id) {
1605                ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, table_id);
1606            }
1607
1608            // Add to "pending" registration map
1609            ((*lua.extra.get()).pending_userdata_reg).insert(type_id, registry.into_raw());
1610        }
1611        Ok(())
1612    }
1613
1614    /// Create a Lua userdata "proxy" object from a custom userdata type.
1615    ///
1616    /// Proxy object is an empty userdata object that has `T` metatable attached.
1617    /// The main purpose of this object is to provide access to static fields and functions
1618    /// without creating an instance of type `T`.
1619    ///
1620    /// You can get or set uservalues on this object but you cannot borrow any Rust type.
1621    ///
1622    /// # Examples
1623    ///
1624    /// ```
1625    /// # use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
1626    /// # fn main() -> Result<()> {
1627    /// # let lua = Lua::new();
1628    /// struct MyUserData(i32);
1629    ///
1630    /// impl UserData for MyUserData {
1631    ///     fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
1632    ///         fields.add_field_method_get("val", |_, this| Ok(this.0));
1633    ///     }
1634    ///
1635    ///     fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1636    ///         methods.add_function("new", |_, value: i32| Ok(MyUserData(value)));
1637    ///     }
1638    /// }
1639    ///
1640    /// lua.globals().set("MyUserData", lua.create_proxy::<MyUserData>()?)?;
1641    ///
1642    /// lua.load("assert(MyUserData.new(321).val == 321)").exec()?;
1643    /// # Ok(())
1644    /// # }
1645    /// ```
1646    #[inline]
1647    pub fn create_proxy<T>(&self) -> Result<AnyUserData>
1648    where
1649        T: UserData + 'static,
1650    {
1651        let ud = UserDataProxy::<T>(PhantomData);
1652        unsafe { self.lock().make_userdata(UserDataStorage::new(ud)) }
1653    }
1654
1655    /// Gets the metatable of a Lua built-in (primitive) type.
1656    ///
1657    /// The metatable is shared by all values of the given type.
1658    ///
1659    /// See [`Lua::set_type_metatable`] for examples.
1660    #[allow(private_bounds)]
1661    pub fn type_metatable<T: LuaType>(&self) -> Option<Table> {
1662        let lua = self.lock();
1663        let state = lua.state();
1664        unsafe {
1665            let _sg = StackGuard::new(state);
1666            assert_stack(state, 2);
1667
1668            if lua.push_primitive_type::<T>() && ffi::lua_getmetatable(state, -1) != 0 {
1669                return Some(Table(lua.pop_ref()));
1670            }
1671        }
1672        None
1673    }
1674
1675    /// Sets the metatable for a Lua built-in (primitive) type.
1676    ///
1677    /// The metatable will be shared by all values of the given type.
1678    ///
1679    /// # Examples
1680    ///
1681    /// Change metatable for Lua boolean type:
1682    ///
1683    /// ```
1684    /// # use mlua::{Lua, Result, Function};
1685    /// # fn main() -> Result<()> {
1686    /// # let lua = Lua::new();
1687    /// let mt = lua.create_table()?;
1688    /// mt.set("__tostring", lua.create_function(|_, b: bool| Ok(if b { "2" } else { "0" }))?)?;
1689    /// lua.set_type_metatable::<bool>(Some(mt));
1690    /// lua.load("assert(tostring(true) == '2')").exec()?;
1691    /// # Ok(())
1692    /// # }
1693    /// ```
1694    #[allow(private_bounds)]
1695    pub fn set_type_metatable<T: LuaType>(&self, metatable: Option<Table>) {
1696        let lua = self.lock();
1697        let state = lua.state();
1698        unsafe {
1699            let _sg = StackGuard::new(state);
1700            assert_stack(state, 2);
1701
1702            if lua.push_primitive_type::<T>() {
1703                match metatable {
1704                    Some(metatable) => lua.push_ref(&metatable.0),
1705                    None => ffi::lua_pushnil(state),
1706                }
1707                ffi::lua_setmetatable(state, -2);
1708            }
1709        }
1710    }
1711
1712    /// Returns a handle to the global environment.
1713    pub fn globals(&self) -> Table {
1714        let lua = self.lock();
1715        let state = lua.state();
1716        unsafe {
1717            let _sg = StackGuard::new(state);
1718            assert_stack(state, 1);
1719            #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1720            ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1721            #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1722            ffi::lua_pushvalue(state, ffi::LUA_GLOBALSINDEX);
1723            Table(lua.pop_ref())
1724        }
1725    }
1726
1727    /// Sets the global environment.
1728    ///
1729    /// This will replace the current global environment with the provided `globals` table.
1730    ///
1731    /// For Lua 5.2+ the globals table is stored in the registry and shared between all threads.
1732    /// For Lua 5.1 and Luau the globals table is stored in each thread.
1733    ///
1734    /// Please note that any existing Lua functions have cached global environment and will not
1735    /// see the changes made by this method.
1736    /// To update the environment for existing Lua functions, use [`Function::set_environment`].
1737    pub fn set_globals(&self, globals: Table) -> Result<()> {
1738        let lua = self.lock();
1739        let state = lua.state();
1740        unsafe {
1741            #[cfg(feature = "luau")]
1742            if (*lua.extra.get()).sandboxed {
1743                return Err(Error::runtime("cannot change globals in a sandboxed Lua state"));
1744            }
1745
1746            let _sg = StackGuard::new(state);
1747            check_stack(state, 1)?;
1748
1749            lua.push_ref(&globals.0);
1750
1751            #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
1752            ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
1753            #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
1754            ffi::lua_replace(state, ffi::LUA_GLOBALSINDEX);
1755        }
1756
1757        Ok(())
1758    }
1759
1760    /// Returns a handle to the active `Thread`.
1761    ///
1762    /// For calls to `Lua` this will be the main Lua thread, for parameters given to a callback,
1763    /// this will be whatever Lua thread called the callback.
1764    pub fn current_thread(&self) -> Thread {
1765        let lua = self.lock();
1766        let state = lua.state();
1767        unsafe {
1768            let _sg = StackGuard::new(state);
1769            assert_stack(state, 1);
1770            ffi::lua_pushthread(state);
1771            Thread(lua.pop_ref(), state)
1772        }
1773    }
1774
1775    /// Calls the given function with a [`Scope`] parameter, giving the function the ability to
1776    /// create userdata and callbacks from Rust types that are `!Send` or non-`'static`.
1777    ///
1778    /// The lifetime of any function or userdata created through [`Scope`] lasts only until the
1779    /// completion of this method call, on completion all such created values are automatically
1780    /// dropped and Lua references to them are invalidated. If a script accesses a value created
1781    /// through [`Scope`] outside of this method, a Lua error will result. Since we can ensure the
1782    /// lifetime of values created through [`Scope`], and we know that [`Lua`] cannot be sent to
1783    /// another thread while [`Scope`] is live, it is safe to allow `!Send` data types and whose
1784    /// lifetimes only outlive the scope lifetime.
1785    pub fn scope<'env, R>(
1786        &self,
1787        f: impl for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> Result<R>,
1788    ) -> Result<R> {
1789        f(&Scope::new(self.lock_arc()))
1790    }
1791
1792    /// Attempts to coerce a Lua value into a String in a manner consistent with Lua's internal
1793    /// behavior.
1794    ///
1795    /// To succeed, the value must be a string (in which case this is a no-op), an integer, or a
1796    /// number.
1797    pub fn coerce_string(&self, v: Value) -> Result<Option<LuaString>> {
1798        Ok(match v {
1799            Value::String(s) => Some(s),
1800            v => unsafe {
1801                let lua = self.lock();
1802                let state = lua.state();
1803                let _sg = StackGuard::new(state);
1804                check_stack(state, 4)?;
1805
1806                lua.push_value(&v)?;
1807                let res = if lua.unlikely_memory_error() {
1808                    ffi::lua_tolstring(state, -1, ptr::null_mut())
1809                } else {
1810                    protect_lua!(state, 1, 1, |state| {
1811                        ffi::lua_tolstring(state, -1, ptr::null_mut())
1812                    })?
1813                };
1814                if !res.is_null() {
1815                    Some(LuaString(lua.pop_ref()))
1816                } else {
1817                    None
1818                }
1819            },
1820        })
1821    }
1822
1823    /// Attempts to coerce a Lua value into an integer in a manner consistent with Lua's internal
1824    /// behavior.
1825    ///
1826    /// To succeed, the value must be an integer, a floating point number that has an exact
1827    /// representation as an integer, or a string that can be converted to an integer. Refer to the
1828    /// Lua manual for details.
1829    pub fn coerce_integer(&self, v: Value) -> Result<Option<Integer>> {
1830        Ok(match v {
1831            Value::Integer(i) => Some(i),
1832            v => unsafe {
1833                let lua = self.lock();
1834                let state = lua.state();
1835                let _sg = StackGuard::new(state);
1836                check_stack(state, 2)?;
1837
1838                lua.push_value(&v)?;
1839                let mut isint = 0;
1840                let i = ffi::lua_tointegerx(state, -1, &mut isint);
1841                if isint == 0 { None } else { Some(i) }
1842            },
1843        })
1844    }
1845
1846    /// Attempts to coerce a Lua value into a Number in a manner consistent with Lua's internal
1847    /// behavior.
1848    ///
1849    /// To succeed, the value must be a number or a string that can be converted to a number. Refer
1850    /// to the Lua manual for details.
1851    pub fn coerce_number(&self, v: Value) -> Result<Option<Number>> {
1852        Ok(match v {
1853            Value::Number(n) => Some(n),
1854            v => unsafe {
1855                let lua = self.lock();
1856                let state = lua.state();
1857                let _sg = StackGuard::new(state);
1858                check_stack(state, 2)?;
1859
1860                lua.push_value(&v)?;
1861                let mut isnum = 0;
1862                let n = ffi::lua_tonumberx(state, -1, &mut isnum);
1863                if isnum == 0 { None } else { Some(n) }
1864            },
1865        })
1866    }
1867
1868    /// Converts a value that implements [`IntoLua`] into a [`Value`] instance.
1869    #[inline]
1870    pub fn pack(&self, t: impl IntoLua) -> Result<Value> {
1871        t.into_lua(self)
1872    }
1873
1874    /// Converts a [`Value`] instance into a value that implements [`FromLua`].
1875    #[inline]
1876    pub fn unpack<T: FromLua>(&self, value: Value) -> Result<T> {
1877        T::from_lua(value, self)
1878    }
1879
1880    /// Converts a value that implements [`IntoLua`] into a [`FromLua`] variant.
1881    #[inline]
1882    pub fn convert<U: FromLua>(&self, value: impl IntoLua) -> Result<U> {
1883        U::from_lua(value.into_lua(self)?, self)
1884    }
1885
1886    /// Converts a value that implements [`IntoLuaMulti`] into a [`MultiValue`] instance.
1887    #[inline]
1888    pub fn pack_multi(&self, t: impl IntoLuaMulti) -> Result<MultiValue> {
1889        t.into_lua_multi(self)
1890    }
1891
1892    /// Converts a [`MultiValue`] instance into a value that implements [`FromLuaMulti`].
1893    #[inline]
1894    pub fn unpack_multi<T: FromLuaMulti>(&self, value: MultiValue) -> Result<T> {
1895        T::from_lua_multi(value, self)
1896    }
1897
1898    /// Set a value in the Lua registry based on a string key.
1899    ///
1900    /// This value will be available to Rust from all Lua instances which share the same main
1901    /// state.
1902    pub fn set_named_registry_value(&self, key: &str, t: impl IntoLua) -> Result<()> {
1903        let lua = self.lock();
1904        let state = lua.state();
1905        unsafe {
1906            let _sg = StackGuard::new(state);
1907            check_stack(state, 5)?;
1908
1909            lua.push(t)?;
1910            rawset_field(state, ffi::LUA_REGISTRYINDEX, key)
1911        }
1912    }
1913
1914    /// Get a value from the Lua registry based on a string key.
1915    ///
1916    /// Any Lua instance which shares the underlying main state may call this method to
1917    /// get a value previously set by [`Lua::set_named_registry_value`].
1918    pub fn named_registry_value<T>(&self, key: &str) -> Result<T>
1919    where
1920        T: FromLua,
1921    {
1922        let lua = self.lock();
1923        let state = lua.state();
1924        unsafe {
1925            let _sg = StackGuard::new(state);
1926            check_stack(state, 3)?;
1927
1928            let protect = !lua.unlikely_memory_error();
1929            push_string(state, key.as_bytes(), protect)?;
1930            ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
1931
1932            T::from_stack(-1, &lua)
1933        }
1934    }
1935
1936    /// Removes a named value in the Lua registry.
1937    ///
1938    /// Equivalent to calling [`Lua::set_named_registry_value`] with a value of [`Nil`].
1939    #[inline]
1940    pub fn unset_named_registry_value(&self, key: &str) -> Result<()> {
1941        self.set_named_registry_value(key, Nil)
1942    }
1943
1944    /// Place a value in the Lua registry with an auto-generated key.
1945    ///
1946    /// This value will be available to Rust from all Lua instances which share the same main
1947    /// state.
1948    ///
1949    /// Be warned, garbage collection of values held inside the registry is not automatic, see
1950    /// [`RegistryKey`] for more details.
1951    /// However, dropped [`RegistryKey`]s automatically reused to store new values.
1952    pub fn create_registry_value(&self, t: impl IntoLua) -> Result<RegistryKey> {
1953        let lua = self.lock();
1954        let state = lua.state();
1955        unsafe {
1956            let _sg = StackGuard::new(state);
1957            check_stack(state, 4)?;
1958
1959            lua.push(t)?;
1960
1961            let unref_list = (*lua.extra.get()).registry_unref_list.clone();
1962
1963            // Check if the value is nil (no need to store it in the registry)
1964            if ffi::lua_isnil(state, -1) != 0 {
1965                return Ok(RegistryKey::new(ffi::LUA_REFNIL, unref_list));
1966            }
1967
1968            // Try to reuse previously allocated slot
1969            let free_registry_id = unref_list.lock().as_mut().and_then(|x| x.pop());
1970            if let Some(registry_id) = free_registry_id {
1971                // It must be safe to replace the value without triggering memory error
1972                ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
1973                return Ok(RegistryKey::new(registry_id, unref_list));
1974            }
1975
1976            // Allocate a new RegistryKey slot
1977            let registry_id = if lua.unlikely_memory_error() {
1978                ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
1979            } else {
1980                protect_lua!(state, 1, 0, |state| {
1981                    ffi::luaL_ref(state, ffi::LUA_REGISTRYINDEX)
1982                })?
1983            };
1984            Ok(RegistryKey::new(registry_id, unref_list))
1985        }
1986    }
1987
1988    /// Get a value from the Lua registry by its [`RegistryKey`]
1989    ///
1990    /// Any Lua instance which shares the underlying main state may call this method to get a value
1991    /// previously placed by [`Lua::create_registry_value`].
1992    pub fn registry_value<T: FromLua>(&self, key: &RegistryKey) -> Result<T> {
1993        let lua = self.lock();
1994        if !lua.owns_registry_value(key) {
1995            return Err(Error::MismatchedRegistryKey);
1996        }
1997
1998        let state = lua.state();
1999        match key.id() {
2000            ffi::LUA_REFNIL => T::from_lua(Value::Nil, self),
2001            registry_id => unsafe {
2002                let _sg = StackGuard::new(state);
2003                check_stack(state, 1)?;
2004
2005                ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2006                T::from_stack(-1, &lua)
2007            },
2008        }
2009    }
2010
2011    /// Removes a value from the Lua registry.
2012    ///
2013    /// You may call this function to manually remove a value placed in the registry with
2014    /// [`Lua::create_registry_value`]. In addition to manual [`RegistryKey`] removal, you can also
2015    /// call [`Lua::expire_registry_values`] to automatically remove values from the registry
2016    /// whose [`RegistryKey`]s have been dropped.
2017    pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
2018        let lua = self.lock();
2019        if !lua.owns_registry_value(&key) {
2020            return Err(Error::MismatchedRegistryKey);
2021        }
2022
2023        unsafe { ffi::luaL_unref(lua.state(), ffi::LUA_REGISTRYINDEX, key.take()) };
2024        Ok(())
2025    }
2026
2027    /// Replaces a value in the Lua registry by its [`RegistryKey`].
2028    ///
2029    /// An identifier used in [`RegistryKey`] may possibly be changed to a new value.
2030    ///
2031    /// See [`Lua::create_registry_value`] for more details.
2032    pub fn replace_registry_value(&self, key: &mut RegistryKey, t: impl IntoLua) -> Result<()> {
2033        let lua = self.lock();
2034        if !lua.owns_registry_value(key) {
2035            return Err(Error::MismatchedRegistryKey);
2036        }
2037
2038        let t = t.into_lua(self)?;
2039
2040        let state = lua.state();
2041        unsafe {
2042            let _sg = StackGuard::new(state);
2043            check_stack(state, 2)?;
2044
2045            match (t, key.id()) {
2046                (Value::Nil, ffi::LUA_REFNIL) => {
2047                    // Do nothing, no need to replace nil with nil
2048                }
2049                (Value::Nil, registry_id) => {
2050                    // Remove the value
2051                    ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, registry_id);
2052                    key.set_id(ffi::LUA_REFNIL);
2053                }
2054                (value, ffi::LUA_REFNIL) => {
2055                    // Allocate a new `RegistryKey`
2056                    let new_key = self.create_registry_value(value)?;
2057                    key.set_id(new_key.take());
2058                }
2059                (value, registry_id) => {
2060                    // It must be safe to replace the value without triggering memory error
2061                    lua.push_value(&value)?;
2062                    ffi::lua_rawseti(state, ffi::LUA_REGISTRYINDEX, registry_id as Integer);
2063                }
2064            }
2065        }
2066        Ok(())
2067    }
2068
2069    /// Returns true if the given [`RegistryKey`] was created by a Lua which shares the
2070    /// underlying main state with this Lua instance.
2071    ///
2072    /// Other than this, methods that accept a [`RegistryKey`] will return
2073    /// [`Error::MismatchedRegistryKey`] if passed a [`RegistryKey`] that was not created with a
2074    /// matching [`Lua`] state.
2075    #[inline]
2076    pub fn owns_registry_value(&self, key: &RegistryKey) -> bool {
2077        self.lock().owns_registry_value(key)
2078    }
2079
2080    /// Remove any registry values whose [`RegistryKey`]s have all been dropped.
2081    ///
2082    /// Unlike normal handle values, [`RegistryKey`]s do not automatically remove themselves on
2083    /// Drop, but you can call this method to remove any unreachable registry values not
2084    /// manually removed by [`Lua::remove_registry_value`].
2085    pub fn expire_registry_values(&self) {
2086        let lua = self.lock();
2087        let state = lua.state();
2088        unsafe {
2089            let mut unref_list = (*lua.extra.get()).registry_unref_list.lock();
2090            let unref_list = unref_list.replace(Vec::new());
2091            for id in mlua_expect!(unref_list, "unref list is not set") {
2092                ffi::luaL_unref(state, ffi::LUA_REGISTRYINDEX, id);
2093            }
2094        }
2095    }
2096
2097    /// Sets or replaces an application data object of type `T`.
2098    ///
2099    /// Application data could be accessed at any time by using [`Lua::app_data_ref`] or
2100    /// [`Lua::app_data_mut`] methods where `T` is the data type.
2101    ///
2102    /// # Panics
2103    ///
2104    /// Panics if the app data container is currently borrowed.
2105    ///
2106    /// # Examples
2107    ///
2108    /// ```
2109    /// use mlua::{Lua, Result};
2110    ///
2111    /// fn hello(lua: &Lua, _: ()) -> Result<()> {
2112    ///     let mut s = lua.app_data_mut::<&str>().unwrap();
2113    ///     assert_eq!(*s, "hello");
2114    ///     *s = "world";
2115    ///     Ok(())
2116    /// }
2117    ///
2118    /// fn main() -> Result<()> {
2119    ///     let lua = Lua::new();
2120    ///     lua.set_app_data("hello");
2121    ///     lua.create_function(hello)?.call::<()>(())?;
2122    ///     let s = lua.app_data_ref::<&str>().unwrap();
2123    ///     assert_eq!(*s, "world");
2124    ///     Ok(())
2125    /// }
2126    /// ```
2127    #[track_caller]
2128    pub fn set_app_data<T: MaybeSend + 'static>(&self, data: T) -> Option<T> {
2129        let lua = self.lock();
2130        let extra = unsafe { &*lua.extra.get() };
2131        extra.app_data.insert(data)
2132    }
2133
2134    /// Tries to set or replace an application data object of type `T`.
2135    ///
2136    /// Returns:
2137    /// - `Ok(Some(old_data))` if the data object of type `T` was successfully replaced.
2138    /// - `Ok(None)` if the data object of type `T` was successfully inserted.
2139    /// - `Err(data)` if the data object of type `T` was not inserted because the container is
2140    ///   currently borrowed.
2141    ///
2142    /// See [`Lua::set_app_data`] for examples.
2143    pub fn try_set_app_data<T: MaybeSend + 'static>(&self, data: T) -> StdResult<Option<T>, T> {
2144        let lua = self.lock();
2145        let extra = unsafe { &*lua.extra.get() };
2146        extra.app_data.try_insert(data)
2147    }
2148
2149    /// Gets a reference to an application data object stored by [`Lua::set_app_data`] of type
2150    /// `T`.
2151    ///
2152    /// # Panics
2153    ///
2154    /// Panics if the data object of type `T` is currently mutably borrowed. Multiple immutable
2155    /// reads can be taken out at the same time.
2156    #[track_caller]
2157    pub fn app_data_ref<T: 'static>(&self) -> Option<AppDataRef<'_, T>> {
2158        let guard = self.lock_arc();
2159        let extra = unsafe { &*guard.extra.get() };
2160        extra.app_data.borrow(Some(guard))
2161    }
2162
2163    /// Tries to get a reference to an application data object stored by [`Lua::set_app_data`] of
2164    /// type `T`.
2165    pub fn try_app_data_ref<T: 'static>(&self) -> StdResult<Option<AppDataRef<'_, T>>, BorrowError> {
2166        let guard = self.lock_arc();
2167        let extra = unsafe { &*guard.extra.get() };
2168        extra.app_data.try_borrow(Some(guard))
2169    }
2170
2171    /// Gets a mutable reference to an application data object stored by [`Lua::set_app_data`] of
2172    /// type `T`.
2173    ///
2174    /// # Panics
2175    ///
2176    /// Panics if the data object of type `T` is currently borrowed.
2177    #[track_caller]
2178    pub fn app_data_mut<T: 'static>(&self) -> Option<AppDataRefMut<'_, T>> {
2179        let guard = self.lock_arc();
2180        let extra = unsafe { &*guard.extra.get() };
2181        extra.app_data.borrow_mut(Some(guard))
2182    }
2183
2184    /// Tries to get a mutable reference to an application data object stored by
2185    /// [`Lua::set_app_data`] of type `T`.
2186    pub fn try_app_data_mut<T: 'static>(&self) -> StdResult<Option<AppDataRefMut<'_, T>>, BorrowMutError> {
2187        let guard = self.lock_arc();
2188        let extra = unsafe { &*guard.extra.get() };
2189        extra.app_data.try_borrow_mut(Some(guard))
2190    }
2191
2192    /// Removes an application data of type `T`.
2193    ///
2194    /// # Panics
2195    ///
2196    /// Panics if the app data container is currently borrowed.
2197    #[track_caller]
2198    pub fn remove_app_data<T: 'static>(&self) -> Option<T> {
2199        let lua = self.lock();
2200        let extra = unsafe { &*lua.extra.get() };
2201        extra.app_data.remove()
2202    }
2203
2204    /// Returns an internal `Poll::Pending` constant used for executing async callbacks.
2205    ///
2206    /// Every time when [`Future`] is Pending, Lua corotine is suspended with this constant.
2207    #[cfg(feature = "async")]
2208    #[doc(hidden)]
2209    #[inline(always)]
2210    pub fn poll_pending() -> LightUserData {
2211        static ASYNC_POLL_PENDING: u8 = 0;
2212        LightUserData(&ASYNC_POLL_PENDING as *const u8 as *mut std::os::raw::c_void)
2213    }
2214
2215    #[cfg(feature = "async")]
2216    #[inline(always)]
2217    pub(crate) fn poll_terminate() -> LightUserData {
2218        static ASYNC_POLL_TERMINATE: u8 = 0;
2219        LightUserData(&ASYNC_POLL_TERMINATE as *const u8 as *mut std::os::raw::c_void)
2220    }
2221
2222    #[cfg(feature = "async")]
2223    #[inline(always)]
2224    pub(crate) fn poll_yield() -> LightUserData {
2225        static ASYNC_POLL_YIELD: u8 = 0;
2226        LightUserData(&ASYNC_POLL_YIELD as *const u8 as *mut std::os::raw::c_void)
2227    }
2228
2229    /// Suspends the current async function, returning the provided arguments to caller.
2230    ///
2231    /// This function is similar to [`coroutine.yield`] but allow yielding Rust functions
2232    /// and passing values to the caller.
2233    /// Please note that you cannot cross [`Thread`] boundaries (e.g. calling `yield_with` on one
2234    /// thread and resuming on another).
2235    ///
2236    /// # Examples
2237    ///
2238    /// Async iterator:
2239    ///
2240    /// ```
2241    /// # use mlua::{Lua, Result};
2242    /// #
2243    /// async fn generator(lua: Lua, _: ()) -> Result<()> {
2244    ///     for i in 0..10 {
2245    ///         lua.yield_with::<()>(i).await?;
2246    ///     }
2247    ///     Ok(())
2248    /// }
2249    ///
2250    /// fn main() -> Result<()> {
2251    ///     let lua = Lua::new();
2252    ///     lua.globals().set("generator", lua.create_async_function(generator)?)?;
2253    ///
2254    ///     lua.load(r#"
2255    ///        local n = 0
2256    ///        for i in coroutine.wrap(generator) do
2257    ///            n = n + i
2258    ///        end
2259    ///        assert(n == 45)
2260    ///     "#)
2261    ///     .exec()
2262    /// }
2263    /// ```
2264    ///
2265    /// Exchange values on yield:
2266    ///
2267    /// ```
2268    /// # use mlua::{Lua, Result, Value};
2269    /// #
2270    /// async fn pingpong(lua: Lua, mut val: i32) -> Result<()> {
2271    ///     loop {
2272    ///         val = lua.yield_with::<i32>(val).await? + 1;
2273    ///     }
2274    ///     Ok(())
2275    /// }
2276    ///
2277    /// # fn main() -> Result<()> {
2278    /// let lua = Lua::new();
2279    ///
2280    /// let co = lua.create_thread(lua.create_async_function(pingpong)?)?;
2281    /// assert_eq!(co.resume::<i32>(1)?, 1);
2282    /// assert_eq!(co.resume::<i32>(2)?, 3);
2283    /// assert_eq!(co.resume::<i32>(3)?, 4);
2284    ///
2285    /// # Ok(())
2286    /// # }
2287    /// ```
2288    ///
2289    /// [`coroutine.yield`]: https://www.lua.org/manual/5.4/manual.html#pdf-coroutine.yield
2290    #[cfg(feature = "async")]
2291    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
2292    pub async fn yield_with<R: FromLuaMulti>(&self, args: impl IntoLuaMulti) -> Result<R> {
2293        let mut args = Some(args.into_lua_multi(self)?);
2294        future::poll_fn(move |_cx| match args.take() {
2295            Some(args) => unsafe {
2296                let lua = self.lock();
2297                lua.push(Self::poll_yield())?; // yield marker
2298                if args.len() <= 1 {
2299                    lua.push(args.front())?;
2300                } else {
2301                    lua.push(lua.create_sequence_from(&args)?)?;
2302                }
2303                lua.push(args.len())?;
2304                Poll::Pending
2305            },
2306            None => unsafe {
2307                let lua = self.lock();
2308                let state = lua.state();
2309                let top = ffi::lua_gettop(state);
2310                if top == 0 || ffi::lua_type(state, 1) != ffi::LUA_TUSERDATA {
2311                    // This must be impossible scenario if used correctly
2312                    return Poll::Ready(R::from_stack_multi(0, &lua));
2313                }
2314                let _sg = StackGuard::with_top(state, 1);
2315                Poll::Ready(R::from_stack_multi(top - 1, &lua))
2316            },
2317        })
2318        .await
2319    }
2320
2321    /// Returns a weak reference to the Lua instance.
2322    ///
2323    /// This is useful for creating a reference to the Lua instance that does not prevent it from
2324    /// being deallocated.
2325    #[inline(always)]
2326    pub fn weak(&self) -> WeakLua {
2327        WeakLua(XRc::downgrade(&self.raw))
2328    }
2329
2330    #[cfg(not(feature = "luau"))]
2331    fn disable_c_modules(&self) -> Result<()> {
2332        let package: Table = self.globals().get("package")?;
2333
2334        package.set(
2335            "loadlib",
2336            self.create_function(|_, ()| -> Result<()> {
2337                Err(Error::SafetyError(
2338                    "package.loadlib is disabled in safe mode".to_string(),
2339                ))
2340            })?,
2341        )?;
2342
2343        #[cfg(any(feature = "lua55", feature = "lua54", feature = "lua53", feature = "lua52"))]
2344        let searchers: Table = package.get("searchers")?;
2345        #[cfg(any(feature = "lua51", feature = "luajit"))]
2346        let searchers: Table = package.get("loaders")?;
2347
2348        let loader = self.create_function(|_, ()| Ok("\n\tcan't load C modules in safe mode"))?;
2349
2350        // The third and fourth searchers looks for a loader as a C library
2351        searchers.raw_set(3, loader)?;
2352        if searchers.raw_len() >= 4 {
2353            searchers.raw_remove(4)?;
2354        }
2355
2356        Ok(())
2357    }
2358
2359    #[inline(always)]
2360    pub(crate) fn lock(&self) -> ReentrantMutexGuard<'_, RawLua> {
2361        let rawlua = self.raw.lock();
2362        #[cfg(feature = "luau")]
2363        if unsafe { (*rawlua.extra.get()).running_gc } {
2364            panic!("Luau VM is suspended while GC is running");
2365        }
2366        rawlua
2367    }
2368
2369    #[inline(always)]
2370    pub(crate) fn lock_arc(&self) -> LuaGuard {
2371        LuaGuard(self.raw.lock_arc())
2372    }
2373
2374    /// Returns a handle to the unprotected Lua state without any synchronization.
2375    ///
2376    /// This is useful where we know that the lock is already held by the caller.
2377    #[cfg(feature = "async")]
2378    #[inline(always)]
2379    pub(crate) unsafe fn raw_lua(&self) -> &RawLua {
2380        &*self.raw.data_ptr()
2381    }
2382}
2383
2384impl WeakLua {
2385    #[track_caller]
2386    #[inline(always)]
2387    pub(crate) fn lock(&self) -> LuaGuard {
2388        let guard = LuaGuard::new(self.0.upgrade().expect("Lua instance is destroyed"));
2389        #[cfg(feature = "luau")]
2390        if unsafe { (*guard.extra.get()).running_gc } {
2391            panic!("Luau VM is suspended while GC is running");
2392        }
2393        guard
2394    }
2395
2396    #[inline(always)]
2397    pub(crate) fn try_lock(&self) -> Option<LuaGuard> {
2398        Some(LuaGuard::new(self.0.upgrade()?))
2399    }
2400
2401    /// Upgrades the weak Lua reference to a strong reference.
2402    ///
2403    /// # Panics
2404    ///
2405    /// Panics if the Lua instance is destroyed.
2406    #[track_caller]
2407    #[inline(always)]
2408    pub fn upgrade(&self) -> Lua {
2409        Lua {
2410            raw: self.0.upgrade().expect("Lua instance is destroyed"),
2411            collect_garbage: false,
2412        }
2413    }
2414
2415    /// Tries to upgrade the weak Lua reference to a strong reference.
2416    ///
2417    /// Returns `None` if the Lua instance is destroyed.
2418    #[inline(always)]
2419    pub fn try_upgrade(&self) -> Option<Lua> {
2420        Some(Lua {
2421            raw: self.0.upgrade()?,
2422            collect_garbage: false,
2423        })
2424    }
2425}
2426
2427impl PartialEq for WeakLua {
2428    fn eq(&self, other: &Self) -> bool {
2429        XWeak::ptr_eq(&self.0, &other.0)
2430    }
2431}
2432
2433impl Eq for WeakLua {}
2434
2435impl LuaGuard {
2436    #[cfg(feature = "send")]
2437    pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2438        LuaGuard(handle.lock_arc())
2439    }
2440
2441    #[cfg(not(feature = "send"))]
2442    pub(crate) fn new(handle: XRc<ReentrantMutex<RawLua>>) -> Self {
2443        LuaGuard(handle.into_lock_arc())
2444    }
2445}
2446
2447impl Deref for LuaGuard {
2448    type Target = RawLua;
2449
2450    fn deref(&self) -> &Self::Target {
2451        &self.0
2452    }
2453}
2454
2455pub(crate) mod extra;
2456mod raw;
2457pub(crate) mod util;
2458
2459#[cfg(test)]
2460mod assertions {
2461    use super::*;
2462
2463    // Lua has lots of interior mutability, should not be RefUnwindSafe
2464    static_assertions::assert_not_impl_any!(Lua: std::panic::RefUnwindSafe);
2465
2466    #[cfg(not(feature = "send"))]
2467    static_assertions::assert_not_impl_any!(Lua: Send);
2468    #[cfg(feature = "send")]
2469    static_assertions::assert_impl_all!(Lua: Send, Sync);
2470}