Skip to main content

Scope

Struct Scope 

Source
pub struct Scope<'scope> { /* private fields */ }
Expand description

Handle passed to the closure body of Lua::scope.

Scope::create_userdata produces an AnyUserData whose backing storage is a borrow you provide; when the scope drops every cell it created is invalidated. Any later Lua call that reaches one of those userdatas fails with a clean error rather than touching freed memory.

Implementations§

Source§

impl<'scope> Scope<'scope>

Source

pub fn create_userdata_ref_mut<T>( &self, lua: &Lua, data: &'scope mut T, ) -> Result<AnyUserData>
where T: UserData,

Wrap a &mut T borrow as a Lua userdata that lives for the duration of this scope. Any call from Lua to the returned userdata after the scope ends fails with a clean Lua runtime error instead of touching the freed borrow.

Naming mirrors mlua’s Scope::create_userdata_ref_mut. The bare create_userdata name on Scope is intentionally reserved for the future by-value, non-'static constructor (mlua’s Scope::create_userdata<T: UserData + 'env>(T)), tracked as a follow-up to lua-rs#27.

Examples found in repository?
examples/scope_world.rs (line 70)
65fn main() -> Result<()> {
66    let lua = Lua::new();
67    let mut world = World::default();
68
69    let count: i64 = lua.scope(|s| {
70        let world_ud = s.create_userdata_ref_mut(&lua, &mut world)?;
71        lua.globals().set("world", &world_ud)?;
72
73        lua.load(
74            r#"
75            local a = world:spawn()
76            local b = world:spawn()
77
78            -- Direct mutation through a live sub-reference.
79            local pa = world:position(a)
80            pa.x, pa.y = 10, 20
81
82            local pb = world:position(b)
83            pb.x = pa.x + 5      -- reading pa here re-borrows; both are short-lived
84
85            -- Stash one to prove it dies with the scope.
86            escaped = world:position(a)
87
88            return world:count()
89        "#,
90        )
91        .eval()
92    })?;
93
94    println!("spawned {count} entities");
95    // The mutations are visible to Rust after the scope returns.
96    for (i, e) in world.entities.iter().enumerate() {
97        println!("entity {i} = ({}, {})", e.x, e.y);
98    }
99
100    // The handle the script stashed on `escaped` is now invalid. Reading a
101    // field raises a Lua error rather than touching the released `&mut World`.
102    // We surface the message through Lua's own `pcall` + `tostring`, since the
103    // error payload is a Lua value.
104    let (ok, msg): (bool, String) = lua
105        .load("local ok, e = pcall(function() return escaped.x end); return ok, tostring(e)")
106        .eval()?;
107    assert!(!ok, "stashed handle should be unusable after the scope");
108    println!("post-scope use of a stashed handle -> {msg}");
109
110    Ok(())
111}
Source

pub fn create_function<A, R, F>(&self, lua: &Lua, func: F) -> Result<Function>
where A: FromLuaMulti + 'static, R: IntoLuaMulti + 'static, F: Fn(&Lua, A) -> Result<R> + 'scope,

Build a Lua Function from a non-'static Rust closure. The closure is owned by a [ScopedFnCell] that the scope holds; once the scope drops, the cell drops the closure and any later Lua call that reaches the returned function fails cleanly with “no longer valid” instead of touching the released captures.

This is the function counterpart to [Self::create_userdata] — pair them when you want to hand Lua a &mut World plus a few closures that also borrow from the same stack frame.

Source

pub fn create_function_mut<A, R, F>( &self, lua: &Lua, func: F, ) -> Result<Function>
where A: FromLuaMulti + 'static, R: IntoLuaMulti + 'static, F: FnMut(&Lua, A) -> Result<R> + 'scope,

Like Self::create_function but accepts an FnMut. Mirrors Lua::create_function_mut: re-entrant calls into the same closure are rejected with an “already borrowed” runtime error rather than producing aliasing &mut captures.

Trait Implementations§

Source§

impl<'scope> Drop for Scope<'scope>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl<'scope> !Freeze for Scope<'scope>

§

impl<'scope> !RefUnwindSafe for Scope<'scope>

§

impl<'scope> !Send for Scope<'scope>

§

impl<'scope> !Sync for Scope<'scope>

§

impl<'scope> Unpin for Scope<'scope>

§

impl<'scope> UnsafeUnpin for Scope<'scope>

§

impl<'scope> !UnwindSafe for Scope<'scope>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.