summaryrefslogtreecommitdiff
path: root/tests/compile
diff options
context:
space:
mode:
Diffstat (limited to 'tests/compile')
-rw-r--r--tests/compile/async_nonstatic_userdata.rs17
-rw-r--r--tests/compile/async_nonstatic_userdata.stderr36
-rw-r--r--tests/compile/function_borrow.rs12
-rw-r--r--tests/compile/function_borrow.stderr20
-rw-r--r--tests/compile/lua_norefunwindsafe.rs8
-rw-r--r--tests/compile/lua_norefunwindsafe.stderr11
-rw-r--r--tests/compile/non_send.rs17
-rw-r--r--tests/compile/non_send.stderr14
-rw-r--r--tests/compile/ref_nounwindsafe.rs9
-rw-r--r--tests/compile/ref_nounwindsafe.stderr13
-rw-r--r--tests/compile/scope_callback_capture.rs18
-rw-r--r--tests/compile/scope_callback_capture.stderr45
-rw-r--r--tests/compile/scope_callback_inner.rs15
-rw-r--r--tests/compile/scope_callback_inner.stderr45
-rw-r--r--tests/compile/scope_callback_outer.rs15
-rw-r--r--tests/compile/scope_callback_outer.stderr11
-rw-r--r--tests/compile/scope_invariance.rs23
-rw-r--r--tests/compile/scope_invariance.stderr25
-rw-r--r--tests/compile/scope_mutable_aliasing.rs15
-rw-r--r--tests/compile/scope_mutable_aliasing.stderr9
-rw-r--r--tests/compile/scope_userdata_borrow.rs19
-rw-r--r--tests/compile/scope_userdata_borrow.stderr13
-rw-r--r--tests/compile/static_callback_args.rs32
-rw-r--r--tests/compile/static_callback_args.stderr35
-rw-r--r--tests/compile/userdata_borrow.rs19
-rw-r--r--tests/compile/userdata_borrow.stderr13
26 files changed, 509 insertions, 0 deletions
diff --git a/tests/compile/async_nonstatic_userdata.rs b/tests/compile/async_nonstatic_userdata.rs
new file mode 100644
index 0000000..8aede32
--- /dev/null
+++ b/tests/compile/async_nonstatic_userdata.rs
@@ -0,0 +1,17 @@
+use mlua::{Lua, UserData, UserDataMethods};
+
+fn main() {
+ let ref lua = Lua::new();
+
+ #[derive(Clone)]
+ struct MyUserData<'a>(&'a i64);
+
+ impl<'a> UserData for MyUserData<'a> {
+ fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_async_method("print", |_, data, ()| async move {
+ println!("{}", data.0);
+ Ok(())
+ });
+ }
+ }
+}
diff --git a/tests/compile/async_nonstatic_userdata.stderr b/tests/compile/async_nonstatic_userdata.stderr
new file mode 100644
index 0000000..a604cd4
--- /dev/null
+++ b/tests/compile/async_nonstatic_userdata.stderr
@@ -0,0 +1,36 @@
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+ --> $DIR/async_nonstatic_userdata.rs:11:72
+ |
+11 | methods.add_async_method("print", |_, data, ()| async move {
+ | ________________________________________________________________________^
+12 | | println!("{}", data.0);
+13 | | Ok(())
+14 | | });
+ | |_____________^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:10...
+ --> $DIR/async_nonstatic_userdata.rs:9:10
+ |
+9 | impl<'a> UserData for MyUserData<'a> {
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/async_nonstatic_userdata.rs:11:72
+ |
+11 | methods.add_async_method("print", |_, data, ()| async move {
+ | ________________________________________________________________________^
+12 | | println!("{}", data.0);
+13 | | Ok(())
+14 | | });
+ | |_____________^
+ = note: expected `main::MyUserData<'_>`
+ found `main::MyUserData<'a>`
+note: but, the lifetime must be valid for the lifetime `'lua` as defined on the method body at 10:24...
+ --> $DIR/async_nonstatic_userdata.rs:10:24
+ |
+10 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ | ^^^^
+note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
+ --> $DIR/async_nonstatic_userdata.rs:11:21
+ |
+11 | methods.add_async_method("print", |_, data, ()| async move {
+ | ^^^^^^^^^^^^^^^^
diff --git a/tests/compile/function_borrow.rs b/tests/compile/function_borrow.rs
new file mode 100644
index 0000000..f64f3b8
--- /dev/null
+++ b/tests/compile/function_borrow.rs
@@ -0,0 +1,12 @@
+use mlua::{Lua, Result};
+
+struct Test(i32);
+
+fn main() {
+ let test = Test(0);
+
+ let lua = Lua::new();
+ let _ = lua.create_function(|_, ()| -> Result<i32> {
+ Ok(test.0)
+ });
+}
diff --git a/tests/compile/function_borrow.stderr b/tests/compile/function_borrow.stderr
new file mode 100644
index 0000000..c1c4d1f
--- /dev/null
+++ b/tests/compile/function_borrow.stderr
@@ -0,0 +1,20 @@
+error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function
+ --> $DIR/function_borrow.rs:9:33
+ |
+9 | let _ = lua.create_function(|_, ()| -> Result<i32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `test`
+10 | Ok(test.0)
+ | ---- `test` is borrowed here
+ |
+note: function requires argument type to outlive `'static`
+ --> $DIR/function_borrow.rs:9:13
+ |
+9 | let _ = lua.create_function(|_, ()| -> Result<i32> {
+ | _____________^
+10 | | Ok(test.0)
+11 | | });
+ | |______^
+help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword
+ |
+9 | let _ = lua.create_function(move |_, ()| -> Result<i32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/compile/lua_norefunwindsafe.rs b/tests/compile/lua_norefunwindsafe.rs
new file mode 100644
index 0000000..805f61f
--- /dev/null
+++ b/tests/compile/lua_norefunwindsafe.rs
@@ -0,0 +1,8 @@
+use std::panic::catch_unwind;
+
+use mlua::Lua;
+
+fn main() {
+ let lua = Lua::new();
+ catch_unwind(|| lua.create_table().unwrap());
+}
diff --git a/tests/compile/lua_norefunwindsafe.stderr b/tests/compile/lua_norefunwindsafe.stderr
new file mode 100644
index 0000000..6dff810
--- /dev/null
+++ b/tests/compile/lua_norefunwindsafe.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the type `std::cell::UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+ --> $DIR/lua_norefunwindsafe.rs:7:5
+ |
+7 | catch_unwind(|| lua.create_table().unwrap());
+ | ^^^^^^^^^^^^ `std::cell::UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+ |
+ = help: within `mlua::lua::Lua`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<()>`
+ = note: required because it appears within the type `std::marker::PhantomData<std::cell::UnsafeCell<()>>`
+ = note: required because it appears within the type `mlua::lua::Lua`
+ = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&mlua::lua::Lua`
+ = note: required because it appears within the type `[closure@$DIR/tests/compile/lua_norefunwindsafe.rs:7:18: 7:48 lua:&mlua::lua::Lua]`
diff --git a/tests/compile/non_send.rs b/tests/compile/non_send.rs
new file mode 100644
index 0000000..fe030a5
--- /dev/null
+++ b/tests/compile/non_send.rs
@@ -0,0 +1,17 @@
+use std::cell::Cell;
+use std::rc::Rc;
+
+use mlua::{Lua, Result};
+
+fn main() -> Result<()> {
+ let lua = Lua::new();
+
+ let data = Rc::new(Cell::new(0));
+
+ lua.create_function(move |_, ()| {
+ Ok(data.get())
+ })?
+ .call::<_, i32>(())?;
+
+ Ok(())
+}
diff --git a/tests/compile/non_send.stderr b/tests/compile/non_send.stderr
new file mode 100644
index 0000000..e830d33
--- /dev/null
+++ b/tests/compile/non_send.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+ --> $DIR/non_send.rs:11:9
+ |
+11 | lua.create_function(move |_, ()| {
+ | _________^^^^^^^^^^^^^^^_-
+ | | |
+ | | `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+12 | | Ok(data.get())
+13 | | })?
+ | |_____- within this `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6 data:std::rc::Rc<std::cell::Cell<i32>>]`
+ |
+ = help: within `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6 data:std::rc::Rc<std::cell::Cell<i32>>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
+ = note: required because it appears within the type `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6 data:std::rc::Rc<std::cell::Cell<i32>>]`
+ = note: required because of the requirements on the impl of `mlua::types::MaybeSend` for `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6 data:std::rc::Rc<std::cell::Cell<i32>>]`
diff --git a/tests/compile/ref_nounwindsafe.rs b/tests/compile/ref_nounwindsafe.rs
new file mode 100644
index 0000000..8518c40
--- /dev/null
+++ b/tests/compile/ref_nounwindsafe.rs
@@ -0,0 +1,9 @@
+use std::panic::catch_unwind;
+
+use mlua::Lua;
+
+fn main() {
+ let lua = Lua::new();
+ let table = lua.create_table().unwrap();
+ catch_unwind(move || table.set("a", "b").unwrap());
+}
diff --git a/tests/compile/ref_nounwindsafe.stderr b/tests/compile/ref_nounwindsafe.stderr
new file mode 100644
index 0000000..0b1b649
--- /dev/null
+++ b/tests/compile/ref_nounwindsafe.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the type `std::cell::UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+ --> $DIR/ref_nounwindsafe.rs:8:5
+ |
+8 | catch_unwind(move || table.set("a", "b").unwrap());
+ | ^^^^^^^^^^^^ `std::cell::UnsafeCell<()>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+ |
+ = help: within `mlua::lua::Lua`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<()>`
+ = note: required because it appears within the type `std::marker::PhantomData<std::cell::UnsafeCell<()>>`
+ = note: required because it appears within the type `mlua::lua::Lua`
+ = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&mlua::lua::Lua`
+ = note: required because it appears within the type `mlua::types::LuaRef<'_>`
+ = note: required because it appears within the type `mlua::table::Table<'_>`
+ = note: required because it appears within the type `[closure@$DIR/tests/compile/ref_nounwindsafe.rs:8:18: 8:54 table:mlua::table::Table<'_>]`
diff --git a/tests/compile/scope_callback_capture.rs b/tests/compile/scope_callback_capture.rs
new file mode 100644
index 0000000..927c36d
--- /dev/null
+++ b/tests/compile/scope_callback_capture.rs
@@ -0,0 +1,18 @@
+use mlua::{Lua, Table};
+
+fn main() {
+ let lua = Lua::new();
+ lua.scope(|scope| {
+ let mut inner: Option<Table> = None;
+ let f = scope
+ .create_function_mut(move |_, t: Table| {
+ if let Some(old) = inner.take() {
+ // Access old callback `Lua`.
+ }
+ inner = Some(t);
+ Ok(())
+ })?;
+ f.call::<_, ()>(lua.create_table()?)?;
+ Ok(())
+ });
+}
diff --git a/tests/compile/scope_callback_capture.stderr b/tests/compile/scope_callback_capture.stderr
new file mode 100644
index 0000000..8e9dec5
--- /dev/null
+++ b/tests/compile/scope_callback_capture.stderr
@@ -0,0 +1,45 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+ --> $DIR/scope_callback_capture.rs:8:14
+ |
+8 | .create_function_mut(move |_, t: Table| {
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 5:15...
+ --> $DIR/scope_callback_capture.rs:5:15
+ |
+5 | lua.scope(|scope| {
+ | _______________^
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(move |_, t: Table| {
+... |
+16 | | Ok(())
+17 | | });
+ | |_____^
+note: ...so that reference does not outlive borrowed content
+ --> $DIR/scope_callback_capture.rs:7:17
+ |
+7 | let f = scope
+ | ^^^^^
+note: but, the lifetime must be valid for the method call at 5:5...
+ --> $DIR/scope_callback_capture.rs:5:5
+ |
+5 | / lua.scope(|scope| {
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(move |_, t: Table| {
+... |
+16 | | Ok(())
+17 | | });
+ | |______^
+note: ...so that a type/lifetime parameter is in scope here
+ --> $DIR/scope_callback_capture.rs:5:5
+ |
+5 | / lua.scope(|scope| {
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(move |_, t: Table| {
+... |
+16 | | Ok(())
+17 | | });
+ | |______^
diff --git a/tests/compile/scope_callback_inner.rs b/tests/compile/scope_callback_inner.rs
new file mode 100644
index 0000000..037c6ac
--- /dev/null
+++ b/tests/compile/scope_callback_inner.rs
@@ -0,0 +1,15 @@
+use mlua::{Lua, Table};
+
+fn main() {
+ let lua = Lua::new();
+ lua.scope(|scope| {
+ let mut inner: Option<Table> = None;
+ let f = scope
+ .create_function_mut(|_, t: Table| {
+ inner = Some(t);
+ Ok(())
+ })?;
+ f.call::<_, ()>(lua.create_table()?)?;
+ Ok(())
+ });
+}
diff --git a/tests/compile/scope_callback_inner.stderr b/tests/compile/scope_callback_inner.stderr
new file mode 100644
index 0000000..1c5f3b5
--- /dev/null
+++ b/tests/compile/scope_callback_inner.stderr
@@ -0,0 +1,45 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+ --> $DIR/scope_callback_inner.rs:8:14
+ |
+8 | .create_function_mut(|_, t: Table| {
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 5:15...
+ --> $DIR/scope_callback_inner.rs:5:15
+ |
+5 | lua.scope(|scope| {
+ | _______________^
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(|_, t: Table| {
+... |
+13 | | Ok(())
+14 | | });
+ | |_____^
+note: ...so that reference does not outlive borrowed content
+ --> $DIR/scope_callback_inner.rs:7:17
+ |
+7 | let f = scope
+ | ^^^^^
+note: but, the lifetime must be valid for the method call at 5:5...
+ --> $DIR/scope_callback_inner.rs:5:5
+ |
+5 | / lua.scope(|scope| {
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(|_, t: Table| {
+... |
+13 | | Ok(())
+14 | | });
+ | |______^
+note: ...so that a type/lifetime parameter is in scope here
+ --> $DIR/scope_callback_inner.rs:5:5
+ |
+5 | / lua.scope(|scope| {
+6 | | let mut inner: Option<Table> = None;
+7 | | let f = scope
+8 | | .create_function_mut(|_, t: Table| {
+... |
+13 | | Ok(())
+14 | | });
+ | |______^
diff --git a/tests/compile/scope_callback_outer.rs b/tests/compile/scope_callback_outer.rs
new file mode 100644
index 0000000..7c9974e
--- /dev/null
+++ b/tests/compile/scope_callback_outer.rs
@@ -0,0 +1,15 @@
+use mlua::{Lua, Table};
+
+fn main() {
+ let lua = Lua::new();
+ let mut outer: Option<Table> = None;
+ lua.scope(|scope| {
+ let f = scope
+ .create_function_mut(|_, t: Table| {
+ outer = Some(t);
+ Ok(())
+ })?;
+ f.call::<_, ()>(lua.create_table()?)?;
+ Ok(())
+ });
+}
diff --git a/tests/compile/scope_callback_outer.stderr b/tests/compile/scope_callback_outer.stderr
new file mode 100644
index 0000000..e1f98ce
--- /dev/null
+++ b/tests/compile/scope_callback_outer.stderr
@@ -0,0 +1,11 @@
+error: borrowed data cannot be stored outside of its closure
+ --> $DIR/scope_callback_outer.rs:7:17
+ |
+5 | let mut outer: Option<Table> = None;
+ | --------- ...so that variable is valid at time of its declaration
+6 | lua.scope(|scope| {
+ | ------- borrowed data cannot outlive this closure
+7 | let f = scope
+ | ^^^^^ cannot be stored outside of its closure
+8 | .create_function_mut(|_, t: Table| {
+ | ------------------- cannot infer an appropriate lifetime...
diff --git a/tests/compile/scope_invariance.rs b/tests/compile/scope_invariance.rs
new file mode 100644
index 0000000..e4f4ea7
--- /dev/null
+++ b/tests/compile/scope_invariance.rs
@@ -0,0 +1,23 @@
+use mlua::Lua;
+
+struct Test {
+ field: i32,
+}
+
+fn main() {
+ let lua = Lua::new();
+ lua.scope(|scope| {
+ let f = {
+ let mut test = Test { field: 0 };
+
+ scope
+ .create_function_mut(|_, ()| {
+ test.field = 42;
+ //~^ error: `test` does not live long enough
+ Ok(())
+ })?
+ };
+
+ f.call::<_, ()>(())
+ });
+}
diff --git a/tests/compile/scope_invariance.stderr b/tests/compile/scope_invariance.stderr
new file mode 100644
index 0000000..ee2a525
--- /dev/null
+++ b/tests/compile/scope_invariance.stderr
@@ -0,0 +1,25 @@
+error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function
+ --> $DIR/scope_invariance.rs:14:38
+ |
+9 | lua.scope(|scope| {
+ | ----- has type `&mlua::scope::Scope<'_, '1>`
+...
+14 | .create_function_mut(|_, ()| {
+ | ^^^^^^^ may outlive borrowed value `test`
+15 | test.field = 42;
+ | ---- `test` is borrowed here
+ |
+note: function requires argument type to outlive `'1`
+ --> $DIR/scope_invariance.rs:13:13
+ |
+13 | / scope
+14 | | .create_function_mut(|_, ()| {
+15 | | test.field = 42;
+16 | | //~^ error: `test` does not live long enough
+17 | | Ok(())
+18 | | })?
+ | |__________________^
+help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword
+ |
+14 | .create_function_mut(move |_, ()| {
+ | ^^^^^^^^^^^^
diff --git a/tests/compile/scope_mutable_aliasing.rs b/tests/compile/scope_mutable_aliasing.rs
new file mode 100644
index 0000000..6bdf498
--- /dev/null
+++ b/tests/compile/scope_mutable_aliasing.rs
@@ -0,0 +1,15 @@
+use mlua::{Lua, UserData};
+
+fn main() {
+ struct MyUserData<'a>(&'a mut i32);
+ impl<'a> UserData for MyUserData<'a> {};
+
+ let mut i = 1;
+
+ let lua = Lua::new();
+ lua.scope(|scope| {
+ let _a = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
+ let _b = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
+ Ok(())
+ });
+}
diff --git a/tests/compile/scope_mutable_aliasing.stderr b/tests/compile/scope_mutable_aliasing.stderr
new file mode 100644
index 0000000..c661826
--- /dev/null
+++ b/tests/compile/scope_mutable_aliasing.stderr
@@ -0,0 +1,9 @@
+error[E0499]: cannot borrow `i` as mutable more than once at a time
+ --> $DIR/scope_mutable_aliasing.rs:12:61
+ |
+11 | let _a = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
+ | ------ first mutable borrow occurs here
+12 | let _b = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
+ | ------------------------- ^^^^^^ second mutable borrow occurs here
+ | |
+ | first borrow later used by call
diff --git a/tests/compile/scope_userdata_borrow.rs b/tests/compile/scope_userdata_borrow.rs
new file mode 100644
index 0000000..6546633
--- /dev/null
+++ b/tests/compile/scope_userdata_borrow.rs
@@ -0,0 +1,19 @@
+use mlua::{Lua, UserData};
+
+fn main() {
+ // Should not allow userdata borrow to outlive lifetime of AnyUserData handle
+ struct MyUserData<'a>(&'a i32);
+ impl<'a> UserData for MyUserData<'a> {};
+
+ let igood = 1;
+
+ let lua = Lua::new();
+ lua.scope(|scope| {
+ let _ugood = scope.create_nonstatic_userdata(MyUserData(&igood)).unwrap();
+ let _ubad = {
+ let ibad = 42;
+ scope.create_nonstatic_userdata(MyUserData(&ibad)).unwrap();
+ };
+ Ok(())
+ });
+}
diff --git a/tests/compile/scope_userdata_borrow.stderr b/tests/compile/scope_userdata_borrow.stderr
new file mode 100644
index 0000000..1e422f4
--- /dev/null
+++ b/tests/compile/scope_userdata_borrow.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `ibad` does not live long enough
+ --> $DIR/scope_userdata_borrow.rs:15:56
+ |
+11 | lua.scope(|scope| {
+ | ----- has type `&mlua::scope::Scope<'_, '1>`
+...
+15 | scope.create_nonstatic_userdata(MyUserData(&ibad)).unwrap();
+ | -------------------------------------------^^^^^--
+ | | |
+ | | borrowed value does not live long enough
+ | argument requires that `ibad` is borrowed for `'1`
+16 | };
+ | - `ibad` dropped here while still borrowed
diff --git a/tests/compile/static_callback_args.rs b/tests/compile/static_callback_args.rs
new file mode 100644
index 0000000..66dbf8b
--- /dev/null
+++ b/tests/compile/static_callback_args.rs
@@ -0,0 +1,32 @@
+use std::cell::RefCell;
+
+use mlua::{Lua, Result, Table};
+
+fn main() -> Result<()> {
+ thread_local! {
+ static BAD_TIME: RefCell<Option<Table<'static>>> = RefCell::new(None);
+ }
+
+ let lua = Lua::new();
+
+ lua.create_function(|_, table: Table| {
+ BAD_TIME.with(|bt| {
+ *bt.borrow_mut() = Some(table);
+ });
+ Ok(())
+ })?
+ .call::<_, ()>(lua.create_table()?)?;
+
+ // In debug, this will panic with a reference leak before getting to the next part but
+ // it segfaults anyway.
+ drop(lua);
+
+ BAD_TIME.with(|bt| {
+ println!(
+ "you're gonna have a bad time: {}",
+ bt.borrow().as_ref().unwrap().len().unwrap()
+ );
+ });
+
+ Ok(())
+}
diff --git a/tests/compile/static_callback_args.stderr b/tests/compile/static_callback_args.stderr
new file mode 100644
index 0000000..561bcbe
--- /dev/null
+++ b/tests/compile/static_callback_args.stderr
@@ -0,0 +1,35 @@
+error[E0597]: `lua` does not live long enough
+ --> $DIR/static_callback_args.rs:12:5
+ |
+12 | lua.create_function(|_, table: Table| {
+ | -^^
+ | |
+ | _____borrowed value does not live long enough
+ | |
+13 | | BAD_TIME.with(|bt| {
+14 | | *bt.borrow_mut() = Some(table);
+15 | | });
+16 | | Ok(())
+17 | | })?
+ | |______- argument requires that `lua` is borrowed for `'static`
+...
+32 | }
+ | - `lua` dropped here while still borrowed
+
+error[E0505]: cannot move out of `lua` because it is borrowed
+ --> $DIR/static_callback_args.rs:22:10
+ |
+12 | lua.create_function(|_, table: Table| {
+ | ---
+ | |
+ | _____borrow of `lua` occurs here
+ | |
+13 | | BAD_TIME.with(|bt| {
+14 | | *bt.borrow_mut() = Some(table);
+15 | | });
+16 | | Ok(())
+17 | | })?
+ | |______- argument requires that `lua` is borrowed for `'static`
+...
+22 | drop(lua);
+ | ^^^ move out of `lua` occurs here
diff --git a/tests/compile/userdata_borrow.rs b/tests/compile/userdata_borrow.rs
new file mode 100644
index 0000000..26eb3c7
--- /dev/null
+++ b/tests/compile/userdata_borrow.rs
@@ -0,0 +1,19 @@
+use mlua::{AnyUserData, Lua, Table, UserData, Result};
+
+fn main() -> Result<()> {
+ let lua = Lua::new();
+ let globals = lua.globals();
+
+ // Should not allow userdata borrow to outlive lifetime of AnyUserData handle
+ struct MyUserData;
+ impl UserData for MyUserData {};
+ let _userdata_ref;
+ {
+ let touter = globals.get::<_, Table>("touter")?;
+ touter.set("userdata", lua.create_userdata(MyUserData)?)?;
+ let userdata = touter.get::<_, AnyUserData>("userdata")?;
+ _userdata_ref = userdata.borrow::<MyUserData>();
+ //~^ error: `userdata` does not live long enough
+ }
+ Ok(())
+}
diff --git a/tests/compile/userdata_borrow.stderr b/tests/compile/userdata_borrow.stderr
new file mode 100644
index 0000000..7ac9670
--- /dev/null
+++ b/tests/compile/userdata_borrow.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `userdata` does not live long enough
+ --> $DIR/userdata_borrow.rs:15:25
+ |
+15 | _userdata_ref = userdata.borrow::<MyUserData>();
+ | ^^^^^^^^ borrowed value does not live long enough
+16 | //~^ error: `userdata` does not live long enough
+17 | }
+ | - `userdata` dropped here while still borrowed
+18 | Ok(())
+19 | }
+ | - borrow might be used here, when `_userdata_ref` is dropped and runs the destructor for type `std::result::Result<std::cell::Ref<'_, main::MyUserData>, mlua::error::Error>`
+ |
+ = note: values in a scope are dropped in the opposite order they are defined