mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f14d93c2b | |||
| 29c6c9cb58 | |||
| e01af22bac | |||
| cfa959e599 | |||
| e523fb2c86 | |||
| 81a9998559 | |||
| 050ac4f5ad | |||
| 967cbb53b0 | |||
| 44a8d86d8a | |||
| 33278d4a64 | |||
| 20a16839aa | |||
| 83ed442bf9 | |||
| bf6708ba58 | |||
| 0cd724f63b | |||
| 5330b900fd | |||
| ee32dc33f3 | |||
| ab029b087d | |||
| 185fee956d | |||
| 4fc69be5f6 | |||
| 3ec076693a | |||
| 95adf8df8e | |||
| 4a25eab257 | |||
| 40fe937878 | |||
| a6b178328d | |||
| f3f173fcb6 | |||
| d3b48cf2f3 | |||
| f9ff6116db | |||
| f75af6d75f | |||
| 059e41bafb | |||
| f7ee6dc635 | |||
| 0919ff21c9 | |||
| 553251761f |
@@ -10,14 +10,14 @@ jobs:
|
||||
options: --security-opt seccomp=unconfined
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Generate code coverage
|
||||
- name: Generate coverage report
|
||||
run: |
|
||||
cargo tarpaulin --verbose --features lua54,vendored,async,send,serialize,macros --out xml --exclude-files benches --exclude-files build --exclude-files mlua_derive --exclude-files src/ffi --exclude-files tests
|
||||
|
||||
- name: Upload to codecov.io
|
||||
uses: codecov/codecov-action@v1
|
||||
- name: Upload report to codecov.io
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{secrets.CODECOV_TOKEN}}
|
||||
fail_ci_if_error: false
|
||||
|
||||
+134
-143
@@ -7,35 +7,34 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
os: [ubuntu-22.04, macos-latest, windows-latest]
|
||||
rust: [stable]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
- os: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Build ${{ matrix.lua }} vendored
|
||||
run: |
|
||||
cargo build --features "${{ matrix.lua }},vendored"
|
||||
cargo build --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- name: Build ${{ matrix.lua }} pkg-config
|
||||
if: ${{ matrix.os == 'ubuntu-20.04' && matrix.lua != 'lua54' }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends liblua5.3-dev liblua5.2-dev liblua5.1-0-dev libluajit-5.1-dev
|
||||
cargo build --features "${{ matrix.lua }}"
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Build ${{ matrix.lua }} vendored
|
||||
run: |
|
||||
cargo build --features "${{ matrix.lua }},vendored"
|
||||
cargo build --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- name: Build ${{ matrix.lua }} pkg-config
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends liblua5.4-dev liblua5.3-dev liblua5.2-dev liblua5.1-0-dev libluajit-5.1-dev
|
||||
cargo build --features "${{ matrix.lua }}"
|
||||
|
||||
build_aarch64_cross_macos:
|
||||
name: Cross-compile to aarch64-apple-darwin
|
||||
@@ -45,60 +44,57 @@ jobs:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-apple-darwin
|
||||
override: true
|
||||
- name: Cross-compile
|
||||
run: cargo build --target aarch64-apple-darwin --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-apple-darwin
|
||||
- name: Cross-compile
|
||||
run: cargo build --target aarch64-apple-darwin --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
|
||||
build_aarch64_cross_ubuntu:
|
||||
name: Cross-compile to aarch64-unknown-linux-gnu
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
override: true
|
||||
- name: Install ARM compiler toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends gcc-aarch64-linux-gnu libc6-dev-arm64-cross
|
||||
shell: bash
|
||||
- name: Cross-compile
|
||||
run: cargo build --target aarch64-unknown-linux-gnu --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
target: aarch64-unknown-linux-gnu
|
||||
- name: Install ARM compiler toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends gcc-aarch64-linux-gnu libc6-dev-arm64-cross
|
||||
shell: bash
|
||||
- name: Cross-compile
|
||||
run: cargo build --target aarch64-unknown-linux-gnu --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
|
||||
build_armv7_cross_ubuntu:
|
||||
name: Cross-compile to armv7-unknown-linux-gnueabihf
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
override: true
|
||||
- name: Install ARM compiler toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends gcc-arm-linux-gnueabihf libc-dev-armhf-cross
|
||||
shell: bash
|
||||
- name: Cross-compile
|
||||
run: cargo build --target armv7-unknown-linux-gnueabihf --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
- name: Install ARM compiler toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends gcc-arm-linux-gnueabihf libc-dev-armhf-cross
|
||||
shell: bash
|
||||
- name: Cross-compile
|
||||
run: cargo build --target armv7-unknown-linux-gnueabihf --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
|
||||
test:
|
||||
name: Test
|
||||
@@ -106,35 +102,34 @@ jobs:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
os: [ubuntu-22.04, macos-latest, windows-latest]
|
||||
rust: [stable, nightly]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luajit52, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
- os: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} tests
|
||||
run: |
|
||||
cargo test --features "${{ matrix.lua }},vendored"
|
||||
cargo test --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- name: Run compile tests (macos lua54)
|
||||
if: ${{ matrix.os == 'macos-latest' && matrix.lua == 'lua54' }}
|
||||
run: |
|
||||
TRYBUILD=overwrite cargo test --features "${{ matrix.lua }},vendored" -- --ignored
|
||||
TRYBUILD=overwrite cargo test --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot" -- --ignored
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} tests
|
||||
run: |
|
||||
cargo test --features "${{ matrix.lua }},vendored"
|
||||
cargo test --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot"
|
||||
shell: bash
|
||||
- name: Run compile tests (macos lua54)
|
||||
if: ${{ matrix.os == 'macos-latest' && matrix.lua == 'lua54' }}
|
||||
run: |
|
||||
TRYBUILD=overwrite cargo test --features "${{ matrix.lua }},vendored" -- --ignored
|
||||
TRYBUILD=overwrite cargo test --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot" -- --ignored
|
||||
shell: bash
|
||||
|
||||
test_with_sanitizer:
|
||||
name: Test with address sanitizer
|
||||
@@ -142,25 +137,24 @@ jobs:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
os: [ubuntu-22.04]
|
||||
rust: [nightly]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} tests with address sanitizer
|
||||
run: |
|
||||
RUSTFLAGS="-Z sanitizer=address" \
|
||||
cargo test --tests --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot" --target x86_64-unknown-linux-gnu -- --skip test_too_many_recursions
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} tests with address sanitizer
|
||||
run: |
|
||||
RUSTFLAGS="-Z sanitizer=address" \
|
||||
cargo test --tests --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot" --target x86_64-unknown-linux-gnu -- --skip test_too_many_recursions
|
||||
shell: bash
|
||||
|
||||
test_modules:
|
||||
name: Test modules
|
||||
@@ -168,27 +162,26 @@ jobs:
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-22.04, macos-latest]
|
||||
rust: [stable]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} module tests
|
||||
run: |
|
||||
(cd tests/module && cargo build --release --features "${{ matrix.lua }}")
|
||||
(cd tests/module/loader && cargo test --release --features "${{ matrix.lua }},vendored")
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Run ${{ matrix.lua }} module tests
|
||||
run: |
|
||||
(cd tests/module && cargo build --release --features "${{ matrix.lua }}")
|
||||
(cd tests/module/loader && cargo test --release --features "${{ matrix.lua }},vendored")
|
||||
shell: bash
|
||||
|
||||
test_modules_windows:
|
||||
name: Test modules on Windows
|
||||
@@ -201,41 +194,39 @@ jobs:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Rust & Lua
|
||||
run: |
|
||||
pacman -S --noconfirm mingw-w64-x86_64-rust mingw-w64-x86_64-lua mingw-w64-x86_64-luajit mingw-w64-x86_64-pkg-config
|
||||
- name: Run ${{ matrix.lua }} module tests
|
||||
run: |
|
||||
(cd tests/module && cargo build --release --features "${{ matrix.lua }}")
|
||||
(cd tests/module/loader && cargo test --release --features "${{ matrix.lua }}")
|
||||
- uses: msys2/setup-msys2@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Rust & Lua
|
||||
run: |
|
||||
pacman -S --noconfirm mingw-w64-x86_64-rust mingw-w64-x86_64-lua mingw-w64-x86_64-luajit mingw-w64-x86_64-pkg-config
|
||||
- name: Run ${{ matrix.lua }} module tests
|
||||
run: |
|
||||
(cd tests/module && cargo build --release --features "${{ matrix.lua }}")
|
||||
(cd tests/module/loader && cargo test --release --features "${{ matrix.lua }}")
|
||||
|
||||
rustfmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
override: true
|
||||
- run: cargo fmt -- --check
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
- run: cargo fmt -- --check
|
||||
|
||||
clippy:
|
||||
name: Clippy check
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
override: true
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## v0.8.4
|
||||
|
||||
- Minimal Luau updated to 0.548
|
||||
|
||||
## v0.8.3
|
||||
|
||||
- Close to-be-closed variables for Lua 5.4 when using call_async functions (#192)
|
||||
- Fixed Lua assertion when inspecting another thread stack. (#195)
|
||||
- Use more reliable way to create LuaJIT VM (which can fail if use Rust allocator on non-x86 platforms)
|
||||
|
||||
## v0.8.2
|
||||
|
||||
- Performance optimizations in handling UserData
|
||||
- Minimal Luau updated to 0.536
|
||||
- Fixed bug in `Function::bind` when passing empty binds and no arguments (#189)
|
||||
|
||||
## v0.8.1
|
||||
|
||||
- Added `Lua::create_proxy` for accessing to UserData static fields and functions without instance
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.8.1" # remember to update html_root_url and mlua_derive
|
||||
version = "0.8.4" # remember to update html_root_url and mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@chucklefish.org>"]
|
||||
edition = "2021"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
@@ -58,10 +58,10 @@ cc = { version = "1.0" }
|
||||
pkg-config = { version = "0.3.17" }
|
||||
lua-src = { version = ">= 544.0.0, < 550.0.0", optional = true }
|
||||
luajit-src = { version = ">= 210.4.0, < 220.0.0", optional = true }
|
||||
luau0-src = { version = "0.3.2", optional = true }
|
||||
luau0-src = { version = "0.4.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rustyline = "9.0"
|
||||
rustyline = "10.0"
|
||||
criterion = { version = "0.3.4", features = ["html_reports", "async_tokio"] }
|
||||
trybuild = "1.0"
|
||||
futures = "0.3.5"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# mlua FAQ
|
||||
|
||||
This file is for general questions that don't fit into the README or crate docs.
|
||||
|
||||
## Loading a C module fails with error `undefined symbol: lua_xxx`. How to fix?
|
||||
|
||||
Add the following rustflags to your [.cargo/config](http://doc.crates.io/config.html) in order to properly export Lua symbols:
|
||||
|
||||
```toml
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
rustflags = ["-C", "link-args=-rdynamic"]
|
||||
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = ["-C", "link-args=-rdynamic"]
|
||||
```
|
||||
|
||||
## I want to add support for a Lua VM fork to mlua. Do you accept pull requests?
|
||||
|
||||
Adding new feature flag to support a Lua VM fork is a major step that requires huge effort to maintain it.
|
||||
Regular updates, testing, checking compatibility, etc.
|
||||
That's why I don't plan to support new Lua VM forks or other languages in mlua.
|
||||
@@ -11,7 +11,11 @@
|
||||
[codecov.io]: https://codecov.io/gh/khvzak/mlua
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.56+-brightgreen.svg?&logo=rust
|
||||
|
||||
[Guided Tour](examples/guided_tour.rs)
|
||||
[Guided Tour] | [Benchmarks] | [FAQ]
|
||||
|
||||
[Guided Tour]: examples/guided_tour.rs
|
||||
[Benchmarks]: https://github.com/khvzak/script-bench-rs
|
||||
[FAQ]: FAQ.md
|
||||
|
||||
`mlua` is bindings to [Lua](https://www.lua.org) programming language for Rust with a goal to provide
|
||||
_safe_ (as far as it's possible), high level, easy to use, practical and flexible API.
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ use rustyline::Editor;
|
||||
|
||||
fn main() {
|
||||
let lua = Lua::new();
|
||||
let mut editor = Editor::<()>::new();
|
||||
let mut editor = Editor::<()>::new().expect("Failed to make rustyline editor");
|
||||
|
||||
loop {
|
||||
let mut prompt = "> ";
|
||||
|
||||
@@ -324,6 +324,12 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||
lua_pushvalue(from, idx);
|
||||
lua_xmove(from, to, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Debug API
|
||||
//
|
||||
|
||||
@@ -410,6 +410,12 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua_tolstring(L, i, ptr::null_mut())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||
lua_pushvalue(from, idx);
|
||||
lua_xmove(from, to, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Debug API
|
||||
//
|
||||
|
||||
@@ -434,6 +434,12 @@ pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
|
||||
lua_pop(L, 1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||
lua_pushvalue(from, idx);
|
||||
lua_xmove(from, to, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Debug API
|
||||
//
|
||||
|
||||
@@ -455,6 +455,12 @@ pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
|
||||
lua_pop(L, 1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||
lua_pushvalue(from, idx);
|
||||
lua_xmove(from, to, 1);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void {
|
||||
lua_newuserdatauv(L, sz, 1)
|
||||
|
||||
@@ -341,7 +341,7 @@ pub unsafe fn luaL_loadbufferx(
|
||||
fn free(p: *mut c_void);
|
||||
}
|
||||
|
||||
let chunk_is_text = (*data as u8) >= b'\n';
|
||||
let chunk_is_text = size == 0 || (*data as u8) >= b'\n';
|
||||
if !mode.is_null() {
|
||||
let modeb = CStr::from_ptr(mode).to_bytes();
|
||||
if !chunk_is_text && !modeb.contains(&b'b') {
|
||||
@@ -423,7 +423,7 @@ pub unsafe fn luaL_traceback(
|
||||
level = numlevels - COMPAT53_LEVELS2; // and skip to last ones
|
||||
} else {
|
||||
lua_getinfo(L1, level, cstr!("sln"), &mut ar);
|
||||
lua_pushfstring(L, cstr!("\n\t%s:"), ar.short_src.as_ptr());
|
||||
lua_pushfstring(L, cstr!("\n\t%s:"), ar.short_src);
|
||||
if ar.currentline > 0 {
|
||||
lua_pushfstring(L, cstr!("%d:"), ar.currentline);
|
||||
}
|
||||
|
||||
+11
-2
@@ -257,15 +257,18 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_rawiter(L: *mut lua_State, idx: c_int, iter: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
// TODO: lua_encodepointer
|
||||
pub fn lua_clock() -> c_double;
|
||||
pub fn lua_setuserdatatag(L: *mut lua_State, idx: c_int, tag: c_int);
|
||||
pub fn lua_setuserdatadtor(
|
||||
L: *mut lua_State,
|
||||
tag: c_int,
|
||||
dtor: Option<unsafe extern "C" fn(*mut lua_State, *mut c_void)>,
|
||||
);
|
||||
pub fn lua_clonefunction(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_cleartable(L: *mut lua_State, idx: c_int);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -437,7 +440,12 @@ extern "C" {
|
||||
pub fn lua_setupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
|
||||
|
||||
pub fn lua_singlestep(L: *mut lua_State, enabled: c_int);
|
||||
pub fn lua_breakpoint(L: *mut lua_State, funcindex: c_int, line: c_int, enabled: c_int);
|
||||
pub fn lua_breakpoint(
|
||||
L: *mut lua_State,
|
||||
funcindex: c_int,
|
||||
line: c_int,
|
||||
enabled: c_int,
|
||||
) -> c_int;
|
||||
|
||||
pub fn lua_getcoverage(
|
||||
L: *mut lua_State,
|
||||
@@ -454,13 +462,14 @@ pub struct lua_Debug {
|
||||
pub name: *const c_char,
|
||||
pub what: *const c_char,
|
||||
pub source: *const c_char,
|
||||
pub short_src: *const c_char,
|
||||
pub linedefined: c_int,
|
||||
pub currentline: c_int,
|
||||
pub nupvals: u8,
|
||||
pub nparams: u8,
|
||||
pub isvararg: c_char,
|
||||
pub short_src: [c_char; LUA_IDSIZE],
|
||||
pub userdata: *mut c_void,
|
||||
pub ssbuf: [c_char; LUA_IDSIZE],
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+3
-1
@@ -79,9 +79,11 @@ pub(crate) fn keep_lua_symbols() {
|
||||
symbols.push(lua_tocfunction as _);
|
||||
symbols.push(luaL_loadstring as _);
|
||||
symbols.push(luaL_openlibs as _);
|
||||
if cfg!(any(feature = "lua54", feature = "lua53", feature = "lua52")) {
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
{
|
||||
symbols.push(lua_getglobal as _);
|
||||
symbols.push(lua_setglobal as _);
|
||||
symbols.push(luaL_setfuncs as _);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -114,7 +114,7 @@ impl<'lua> Function<'lua> {
|
||||
R::from_lua_multi(results, lua)
|
||||
}
|
||||
|
||||
/// Returns a Feature that, when polled, calls `self`, passing `args` as function arguments,
|
||||
/// Returns a future that, when polled, calls `self`, passing `args` as function arguments,
|
||||
/// and drives the execution.
|
||||
///
|
||||
/// Internally it wraps the function to an [`AsyncThread`].
|
||||
@@ -198,7 +198,9 @@ impl<'lua> Function<'lua> {
|
||||
for i in 0..nbinds {
|
||||
ffi::lua_pushvalue(state, ffi::lua_upvalueindex(i + 2));
|
||||
}
|
||||
ffi::lua_rotate(state, 1, nbinds);
|
||||
if nargs > 0 {
|
||||
ffi::lua_rotate(state, 1, nbinds);
|
||||
}
|
||||
|
||||
nargs + nbinds
|
||||
}
|
||||
@@ -208,6 +210,10 @@ impl<'lua> Function<'lua> {
|
||||
let args = args.to_lua_multi(lua)?;
|
||||
let nargs = args.len() as c_int;
|
||||
|
||||
if nargs == 0 {
|
||||
return Ok(self.clone());
|
||||
}
|
||||
|
||||
if nargs + 1 > ffi::LUA_MAX_UPVALUES {
|
||||
return Err(Error::BindError);
|
||||
}
|
||||
@@ -267,10 +273,13 @@ impl<'lua> Function<'lua> {
|
||||
name_what: None,
|
||||
what: ptr_to_cstr_bytes(ar.what).map(|s| s.to_vec()),
|
||||
source: ptr_to_cstr_bytes(ar.source).map(|s| s.to_vec()),
|
||||
short_src: ptr_to_cstr_bytes(&ar.short_src as *const _).map(|s| s.to_vec()),
|
||||
line_defined: ar.linedefined as i32,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
last_line_defined: ar.lastlinedefined as i32,
|
||||
short_src: ptr_to_cstr_bytes(ar.short_src.as_ptr()).map(|s| s.to_vec()),
|
||||
#[cfg(feature = "luau")]
|
||||
short_src: ptr_to_cstr_bytes(ar.short_src).map(|s| s.to_vec()),
|
||||
line_defined: ar.linedefined,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
last_line_defined: ar.lastlinedefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,8 +315,7 @@ impl<'lua> Function<'lua> {
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
let data_ptr = &mut data as *mut Vec<u8> as *mut c_void;
|
||||
let strip = if strip { 1 } else { 0 };
|
||||
ffi::lua_dump(lua.state, writer, data_ptr, strip);
|
||||
ffi::lua_dump(lua.state, writer, data_ptr, strip as i32);
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -102,10 +102,13 @@ impl<'lua> Debug<'lua> {
|
||||
|
||||
DebugSource {
|
||||
source: ptr_to_cstr_bytes((*self.ar.get()).source),
|
||||
short_src: ptr_to_cstr_bytes((*self.ar.get()).short_src.as_ptr()),
|
||||
line_defined: (*self.ar.get()).linedefined as i32,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
last_line_defined: (*self.ar.get()).lastlinedefined as i32,
|
||||
short_src: ptr_to_cstr_bytes((*self.ar.get()).short_src.as_ptr()),
|
||||
#[cfg(feature = "luau")]
|
||||
short_src: ptr_to_cstr_bytes((*self.ar.get()).short_src),
|
||||
line_defined: (*self.ar.get()).linedefined,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
last_line_defined: (*self.ar.get()).lastlinedefined,
|
||||
what: ptr_to_cstr_bytes((*self.ar.get()).what),
|
||||
}
|
||||
}
|
||||
@@ -125,7 +128,7 @@ impl<'lua> Debug<'lua> {
|
||||
"lua_getinfo failed with `l`"
|
||||
);
|
||||
|
||||
(*self.ar.get()).currentline as i32
|
||||
(*self.ar.get()).currentline
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@
|
||||
//! [`serde::Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
|
||||
|
||||
// mlua types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.8.1")]
|
||||
#![doc(html_root_url = "https://docs.rs/mlua/0.8.4")]
|
||||
// Deny warnings inside doc tests / examples. When this isn't present, rustdoc doesn't show *any*
|
||||
// warnings at all.
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
|
||||
+42
-21
@@ -25,7 +25,7 @@ use crate::string::String;
|
||||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{
|
||||
Callback, CallbackUpvalue, DestructedUserdataMT, Integer, LightUserData, LuaRef, MaybeSend,
|
||||
Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData, LuaRef, MaybeSend,
|
||||
Number, RegistryKey,
|
||||
};
|
||||
use crate::userdata::{AnyUserData, UserData, UserDataCell};
|
||||
@@ -111,6 +111,9 @@ pub(crate) struct ExtraData {
|
||||
#[cfg(feature = "async")]
|
||||
recycled_thread_cache: Vec<c_int>,
|
||||
|
||||
// Address of `WrappedFailure` metatable
|
||||
wrapped_failure_mt_ptr: *const c_void,
|
||||
|
||||
// Index of `Option<Waker>` userdata on the ref thread
|
||||
#[cfg(feature = "async")]
|
||||
ref_waker_idx: c_int,
|
||||
@@ -434,12 +437,19 @@ impl Lua {
|
||||
let use_rust_allocator = !(cfg!(feature = "luajit") && cfg!(not(feature = "vendored")));
|
||||
|
||||
let (state, mem_info) = if use_rust_allocator {
|
||||
let mem_info = Box::into_raw(Box::new(MemoryInfo::default()));
|
||||
let state = ffi::lua_newstate(allocator, mem_info as *mut c_void);
|
||||
let mut mem_info = Box::into_raw(Box::new(MemoryInfo::default()));
|
||||
let mut state = ffi::lua_newstate(allocator, mem_info as *mut c_void);
|
||||
// If state is null (it's possible for LuaJIT on non-x86 arch) then switch to Lua internal allocator
|
||||
if state.is_null() {
|
||||
drop(Box::from_raw(mem_info));
|
||||
mem_info = ptr::null_mut();
|
||||
state = ffi::luaL_newstate();
|
||||
}
|
||||
(state, mem_info)
|
||||
} else {
|
||||
(ffi::luaL_newstate(), ptr::null_mut())
|
||||
};
|
||||
assert!(!state.is_null(), "Failed to instantiate Lua VM");
|
||||
|
||||
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
@@ -493,6 +503,7 @@ impl Lua {
|
||||
/// by calling this function again.
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
|
||||
assert!(!state.is_null(), "Lua state is NULL");
|
||||
let main_state = get_main_state(state).unwrap_or(state);
|
||||
let main_state_top = ffi::lua_gettop(main_state);
|
||||
|
||||
@@ -538,6 +549,13 @@ impl Lua {
|
||||
"Error while creating ref thread",
|
||||
);
|
||||
|
||||
let wrapped_failure_mt_ptr = {
|
||||
get_gc_metatable::<WrappedFailure>(state);
|
||||
let ptr = ffi::lua_topointer(state, -1);
|
||||
ffi::lua_pop(state, 1);
|
||||
ptr
|
||||
};
|
||||
|
||||
// Create empty Waker slot on the ref thread
|
||||
#[cfg(feature = "async")]
|
||||
let ref_waker_idx = {
|
||||
@@ -568,6 +586,7 @@ impl Lua {
|
||||
multivalue_cache: Vec::with_capacity(MULTIVALUE_CACHE_SIZE),
|
||||
#[cfg(feature = "async")]
|
||||
recycled_thread_cache: Vec::new(),
|
||||
wrapped_failure_mt_ptr,
|
||||
#[cfg(feature = "async")]
|
||||
ref_waker_idx,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
@@ -591,13 +610,13 @@ impl Lua {
|
||||
"Error while storing extra data",
|
||||
);
|
||||
|
||||
// Register `DestructedUserdataMT` type
|
||||
// Register `DestructedUserdata` type
|
||||
get_destructed_userdata_metatable(main_state);
|
||||
let destructed_mt_ptr = ffi::lua_topointer(main_state, -1);
|
||||
let destructed_mt_typeid = Some(TypeId::of::<DestructedUserdataMT>());
|
||||
let destructed_ud_typeid = TypeId::of::<DestructedUserdata>();
|
||||
(*extra.get())
|
||||
.registered_userdata_mt
|
||||
.insert(destructed_mt_ptr, destructed_mt_typeid);
|
||||
.insert(destructed_mt_ptr, Some(destructed_ud_typeid));
|
||||
ffi::lua_pop(main_state, 1);
|
||||
|
||||
mlua_debug_assert!(
|
||||
@@ -1105,7 +1124,7 @@ impl Lua {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
|
||||
pub fn warning<S: Into<Vec<u8>>>(&self, msg: S, tocont: bool) -> Result<()> {
|
||||
let msg = CString::new(msg).map_err(|err| Error::RuntimeError(err.to_string()))?;
|
||||
unsafe { ffi::lua_warning(self.state, msg.as_ptr(), if tocont { 1 } else { 0 }) };
|
||||
unsafe { ffi::lua_warning(self.state, msg.as_ptr(), tocont as c_int) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1701,15 +1720,16 @@ impl Lua {
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) {
|
||||
pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) -> bool {
|
||||
let extra = &mut *self.extra.get();
|
||||
let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index);
|
||||
if extra.recycled_thread_cache.len() < extra.recycled_thread_cache.capacity() {
|
||||
let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index);
|
||||
#[cfg(feature = "lua54")]
|
||||
let status = ffi::lua_resetthread(thread_state);
|
||||
#[cfg(feature = "lua54")]
|
||||
if status != ffi::LUA_OK {
|
||||
return;
|
||||
// Error object is on top, drop it
|
||||
ffi::lua_settop(thread_state, 0);
|
||||
}
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
ffi::lua_resetthread(self.state, thread_state);
|
||||
@@ -1717,7 +1737,9 @@ impl Lua {
|
||||
ffi::lua_resetthread(thread_state);
|
||||
extra.recycled_thread_cache.push(thread.0.index);
|
||||
thread.0.index = 0;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Create a Lua userdata object from a custom userdata type.
|
||||
@@ -2241,7 +2263,7 @@ impl Lua {
|
||||
}
|
||||
|
||||
Value::Boolean(b) => {
|
||||
ffi::lua_pushboolean(self.state, if b { 1 } else { 0 });
|
||||
ffi::lua_pushboolean(self.state, b as c_int);
|
||||
}
|
||||
|
||||
Value::LightUserData(ud) => {
|
||||
@@ -2293,6 +2315,8 @@ impl Lua {
|
||||
// Uses 2 stack spaces, does not call checkstack
|
||||
pub(crate) unsafe fn pop_value(&self) -> Value {
|
||||
let state = self.state;
|
||||
let extra = &mut *self.extra.get();
|
||||
|
||||
match ffi::lua_type(state, -1) {
|
||||
ffi::LUA_TNIL => {
|
||||
ffi::lua_pop(state, 1);
|
||||
@@ -2353,9 +2377,11 @@ impl Lua {
|
||||
ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
|
||||
|
||||
ffi::LUA_TUSERDATA => {
|
||||
let wrapped_failure_mt_ptr = extra.wrapped_failure_mt_ptr;
|
||||
// We must prevent interaction with userdata types other than UserData OR a WrappedError.
|
||||
// WrappedPanics are automatically resumed.
|
||||
match get_gc_userdata::<WrappedFailure>(state, -1).as_mut() {
|
||||
match get_gc_userdata::<WrappedFailure>(state, -1, wrapped_failure_mt_ptr).as_mut()
|
||||
{
|
||||
Some(WrappedFailure::Error(err)) => {
|
||||
let err = err.clone();
|
||||
ffi::lua_pop(state, 1);
|
||||
@@ -2394,12 +2420,6 @@ impl Lua {
|
||||
"Lua instance passed Value created from a different main Lua state"
|
||||
);
|
||||
let extra = &*self.extra.get();
|
||||
#[cfg(not(feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushvalue(extra.ref_thread, lref.index);
|
||||
ffi::lua_xmove(extra.ref_thread, self.state, 1);
|
||||
}
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::lua_xpush(extra.ref_thread, self.state, lref.index);
|
||||
}
|
||||
|
||||
@@ -2571,6 +2591,7 @@ impl Lua {
|
||||
pub(crate) unsafe fn push_userdata_ref(&self, lref: &LuaRef) -> Result<Option<TypeId>> {
|
||||
self.push_ref(lref);
|
||||
if ffi::lua_getmetatable(self.state, -1) == 0 {
|
||||
ffi::lua_pop(self.state, 1);
|
||||
return Err(Error::UserDataTypeMismatch);
|
||||
}
|
||||
let mt_ptr = ffi::lua_topointer(self.state, -1);
|
||||
@@ -2578,7 +2599,7 @@ impl Lua {
|
||||
|
||||
let extra = &*self.extra.get();
|
||||
match extra.registered_userdata_mt.get(&mt_ptr) {
|
||||
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdataMT>()) => {
|
||||
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdata>()) => {
|
||||
Err(Error::UserDataDestructed)
|
||||
}
|
||||
Some(&type_id) => Ok(type_id),
|
||||
@@ -2952,14 +2973,14 @@ struct StateGuard<'a>(&'a mut LuaInner, *mut ffi::lua_State);
|
||||
|
||||
impl<'a> StateGuard<'a> {
|
||||
fn new(inner: &'a mut LuaInner, mut state: *mut ffi::lua_State) -> Self {
|
||||
mem::swap(&mut (*inner).state, &mut state);
|
||||
mem::swap(&mut inner.state, &mut state);
|
||||
Self(inner, state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for StateGuard<'a> {
|
||||
fn drop(&mut self) {
|
||||
mem::swap(&mut (*self.0).state, &mut self.1);
|
||||
mem::swap(&mut self.0.state, &mut self.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-4
@@ -4,7 +4,7 @@ use std::os::raw::c_int;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::types::LuaRef;
|
||||
use crate::util::{check_stack, error_traceback, pop_error, StackGuard};
|
||||
use crate::util::{check_stack, error_traceback_thread, pop_error, StackGuard};
|
||||
use crate::value::{FromLuaMulti, ToLuaMulti};
|
||||
|
||||
#[cfg(any(
|
||||
@@ -136,8 +136,12 @@ impl<'lua> Thread<'lua> {
|
||||
|
||||
let ret = ffi::lua_resume(thread_state, lua.state, nargs, &mut nresults as *mut c_int);
|
||||
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
||||
protect_lua!(lua.state, 0, 0, |_| error_traceback(thread_state))?;
|
||||
return Err(pop_error(thread_state, ret));
|
||||
check_stack(lua.state, 3)?;
|
||||
protect_lua!(lua.state, 0, 1, |state| error_traceback_thread(
|
||||
state,
|
||||
thread_state
|
||||
))?;
|
||||
return Err(pop_error(lua.state, ret));
|
||||
}
|
||||
|
||||
let mut results = args; // Reuse MultiValue container
|
||||
@@ -357,7 +361,16 @@ impl<'lua, R> Drop for AsyncThread<'lua, R> {
|
||||
fn drop(&mut self) {
|
||||
if self.recycle {
|
||||
unsafe {
|
||||
self.thread.0.lua.recycle_thread(&mut self.thread);
|
||||
let lua = self.thread.0.lua;
|
||||
// For Lua 5.4 this also closes all pending to-be-closed variables
|
||||
if !lua.recycle_thread(&mut self.thread) {
|
||||
#[cfg(feature = "lua54")]
|
||||
if self.thread.status() == ThreadStatus::Error {
|
||||
let thread_state =
|
||||
lua.ref_thread_exec(|t| ffi::lua_tothread(t, self.thread.0.index));
|
||||
ffi::lua_resetthread(thread_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ pub trait MaybeSend {}
|
||||
#[cfg(not(feature = "send"))]
|
||||
impl<T> MaybeSend for T {}
|
||||
|
||||
pub(crate) struct DestructedUserdataMT;
|
||||
pub(crate) struct DestructedUserdata;
|
||||
|
||||
/// An auto generated key into the Lua registry.
|
||||
///
|
||||
|
||||
+53
-31
@@ -1,6 +1,7 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::Write;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
|
||||
use std::sync::Arc;
|
||||
@@ -136,26 +137,21 @@ where
|
||||
F: Fn(*mut ffi::lua_State) -> R,
|
||||
R: Copy,
|
||||
{
|
||||
union URes<R: Copy> {
|
||||
uninit: (),
|
||||
init: R,
|
||||
}
|
||||
|
||||
struct Params<F, R: Copy> {
|
||||
function: F,
|
||||
result: URes<R>,
|
||||
result: MaybeUninit<R>,
|
||||
nresults: c_int,
|
||||
}
|
||||
|
||||
unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
|
||||
where
|
||||
R: Copy,
|
||||
F: Fn(*mut ffi::lua_State) -> R,
|
||||
R: Copy,
|
||||
{
|
||||
let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
|
||||
ffi::lua_pop(state, 1);
|
||||
|
||||
(*params).result.init = ((*params).function)(state);
|
||||
(*params).result.write(((*params).function)(state));
|
||||
|
||||
if (*params).nresults == ffi::LUA_MULTRET {
|
||||
ffi::lua_gettop(state)
|
||||
@@ -174,7 +170,7 @@ where
|
||||
|
||||
let mut params = Params {
|
||||
function: f,
|
||||
result: URes { uninit: () },
|
||||
result: MaybeUninit::uninit(),
|
||||
nresults,
|
||||
};
|
||||
|
||||
@@ -185,7 +181,7 @@ where
|
||||
if ret == ffi::LUA_OK {
|
||||
// `LUA_OK` is only returned when the `do_call` function has completed successfully, so
|
||||
// `params.result` is definitely initialized.
|
||||
Ok(params.result.init)
|
||||
Ok(params.result.assume_init())
|
||||
} else {
|
||||
Err(pop_error(state, ret))
|
||||
}
|
||||
@@ -203,7 +199,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
|
||||
"pop_error called with non-error return code"
|
||||
);
|
||||
|
||||
match get_gc_userdata::<WrappedFailure>(state, -1).as_mut() {
|
||||
match get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_mut() {
|
||||
Some(WrappedFailure::Error(err)) => {
|
||||
ffi::lua_pop(state, 1);
|
||||
err.clone()
|
||||
@@ -314,13 +310,10 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool)
|
||||
#[inline]
|
||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool) -> Result<()> {
|
||||
unsafe extern "C" fn destructor<T>(ud: *mut c_void) {
|
||||
let ud = ud as *mut T;
|
||||
if *(ud.offset(1) as *mut u8) == 0 {
|
||||
ptr::drop_in_place(ud);
|
||||
}
|
||||
ptr::drop_in_place(ud as *mut T);
|
||||
}
|
||||
|
||||
let size = mem::size_of::<T>() + 1;
|
||||
let size = mem::size_of::<T>();
|
||||
let ud = if protect {
|
||||
protect_lua!(state, 0, 1, |state| {
|
||||
ffi::lua_newuserdatadtor(state, size, destructor::<T>) as *mut T
|
||||
@@ -329,7 +322,6 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool)
|
||||
ffi::lua_newuserdatadtor(state, size, destructor::<T>) as *mut T
|
||||
};
|
||||
ptr::write(ud, t);
|
||||
*(ud.offset(1) as *mut u8) = 0; // Mark as not destructed
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -373,10 +365,12 @@ pub unsafe fn take_userdata<T>(state: *mut ffi::lua_State) -> T {
|
||||
get_destructed_userdata_metatable(state);
|
||||
ffi::lua_setmetatable(state, -2);
|
||||
let ud = get_userdata::<T>(state, -1);
|
||||
|
||||
// Update userdata tag to disable destructor and mark as destructed
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::lua_setuserdatatag(state, -1, 1);
|
||||
|
||||
ffi::lua_pop(state, 1);
|
||||
if cfg!(feature = "luau") {
|
||||
*(ud.offset(1) as *mut u8) = 1; // Mark as destructed
|
||||
}
|
||||
ptr::read(ud)
|
||||
}
|
||||
|
||||
@@ -394,16 +388,28 @@ pub unsafe fn push_gc_userdata<T: Any>(
|
||||
}
|
||||
|
||||
// Uses 2 stack spaces, does not call checkstack
|
||||
pub unsafe fn get_gc_userdata<T: Any>(state: *mut ffi::lua_State, index: c_int) -> *mut T {
|
||||
pub unsafe fn get_gc_userdata<T: Any>(
|
||||
state: *mut ffi::lua_State,
|
||||
index: c_int,
|
||||
mt_ptr: *const c_void,
|
||||
) -> *mut T {
|
||||
let ud = ffi::lua_touserdata(state, index) as *mut T;
|
||||
if ud.is_null() || ffi::lua_getmetatable(state, index) == 0 {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
get_gc_metatable::<T>(state);
|
||||
let res = ffi::lua_rawequal(state, -1, -2);
|
||||
ffi::lua_pop(state, 2);
|
||||
if res == 0 {
|
||||
return ptr::null_mut();
|
||||
if !mt_ptr.is_null() {
|
||||
let ud_mt_ptr = ffi::lua_topointer(state, -1);
|
||||
ffi::lua_pop(state, 1);
|
||||
if !ptr::eq(ud_mt_ptr, mt_ptr) {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
} else {
|
||||
get_gc_metatable::<T>(state);
|
||||
let res = ffi::lua_rawequal(state, -1, -2);
|
||||
ffi::lua_pop(state, 2);
|
||||
if res == 0 {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
}
|
||||
ud
|
||||
}
|
||||
@@ -679,7 +685,7 @@ pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if get_gc_userdata::<WrappedFailure>(state, -1).is_null() {
|
||||
if get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).is_null() {
|
||||
let s = ffi::luaL_tolstring(state, -1, ptr::null_mut());
|
||||
if ffi::lua_checkstack(state, ffi::LUA_TRACEBACK_STACK) != 0 {
|
||||
ffi::luaL_traceback(state, state, s, 0);
|
||||
@@ -690,6 +696,20 @@ pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
|
||||
1
|
||||
}
|
||||
|
||||
// A variant of `error_traceback` that can safely inspect another (yielded) thread stack
|
||||
pub unsafe fn error_traceback_thread(state: *mut ffi::lua_State, thread: *mut ffi::lua_State) {
|
||||
// Move error object to the main thread to safely call `__tostring` metamethod if present
|
||||
ffi::lua_xmove(thread, state, 1);
|
||||
|
||||
if get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).is_null() {
|
||||
let s = ffi::luaL_tolstring(state, -1, ptr::null_mut());
|
||||
if ffi::lua_checkstack(state, ffi::LUA_TRACEBACK_STACK) != 0 {
|
||||
ffi::luaL_traceback(state, thread, s, 0);
|
||||
ffi::lua_remove(state, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A variant of `pcall` that does not allow Lua to catch Rust panics from `callback_error`.
|
||||
pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::luaL_checkstack(state, 2, ptr::null());
|
||||
@@ -706,7 +726,7 @@ pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_gettop(state)
|
||||
} else {
|
||||
if let Some(WrappedFailure::Panic(_)) =
|
||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
||||
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||
{
|
||||
ffi::lua_error(state);
|
||||
}
|
||||
@@ -722,7 +742,7 @@ pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::luaL_checkstack(state, 2, ptr::null());
|
||||
|
||||
if let Some(WrappedFailure::Panic(_)) =
|
||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
||||
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||
{
|
||||
1
|
||||
} else {
|
||||
@@ -752,7 +772,7 @@ pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_gettop(state) - 1
|
||||
} else {
|
||||
if let Some(WrappedFailure::Panic(_)) =
|
||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
||||
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||
{
|
||||
ffi::lua_error(state);
|
||||
}
|
||||
@@ -836,7 +856,7 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
||||
callback_error(state, |_| {
|
||||
check_stack(state, 3)?;
|
||||
|
||||
let err_buf = match get_gc_userdata::<WrappedFailure>(state, -1).as_ref() {
|
||||
let err_buf = match get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref() {
|
||||
Some(WrappedFailure::Error(error)) => {
|
||||
let err_buf_key = &ERROR_PRINT_BUFFER_KEY as *const u8 as *const c_void;
|
||||
ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, err_buf_key);
|
||||
@@ -936,6 +956,8 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
||||
"__pairs",
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luajit52"))]
|
||||
"__ipairs",
|
||||
#[cfg(feature = "luau")]
|
||||
"__iter",
|
||||
#[cfg(feature = "lua54")]
|
||||
"__close",
|
||||
] {
|
||||
|
||||
+15
-2
@@ -239,7 +239,7 @@ impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self.0).iter().rev()
|
||||
self.0.iter().rev()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,15 @@ impl<'lua> Index<usize> for MultiValue<'lua> {
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.0[self.0.len() - index - 1]
|
||||
if let Some(result) = self.get(index) {
|
||||
result
|
||||
} else {
|
||||
panic!(
|
||||
"index out of bounds: the len is {} but the index is {}",
|
||||
self.len(),
|
||||
index
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +274,11 @@ impl<'lua> MultiValue<'lua> {
|
||||
v
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: usize) -> Option<&Value<'lua>> {
|
||||
self.0.get(self.0.len() - index - 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn reserve(&mut self, size: usize) {
|
||||
self.0.reserve(size);
|
||||
|
||||
@@ -174,6 +174,38 @@ async fn test_async_return_async_closure() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
#[tokio::test]
|
||||
async fn test_async_lua54_to_be_closed() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let globals = lua.globals();
|
||||
globals.set("close_count", 0)?;
|
||||
|
||||
let code = r#"
|
||||
local t <close> = setmetatable({}, {
|
||||
__close = function()
|
||||
close_count = close_count + 1
|
||||
end
|
||||
})
|
||||
error "test"
|
||||
"#;
|
||||
let f = lua.load(code).into_function()?;
|
||||
|
||||
// Test close using call_async
|
||||
let _ = f.call_async::<_, ()>(()).await;
|
||||
assert_eq!(globals.get::<_, usize>("close_count")?, 1);
|
||||
|
||||
// Don't close by default when awaiting async threads
|
||||
let co = lua.create_thread(f.clone())?;
|
||||
let _ = co.clone().into_async::<_, ()>(()).await;
|
||||
assert_eq!(globals.get::<_, usize>("close_count")?, 1);
|
||||
let _ = co.reset(f);
|
||||
assert_eq!(globals.get::<_, usize>("close_count")?, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_thread_stream() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
@@ -278,6 +310,28 @@ async fn test_async_table() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_thread_cache() -> Result<()> {
|
||||
let options = LuaOptions::new().thread_cache_size(4);
|
||||
let lua = Lua::new_with(StdLib::ALL_SAFE, options)?;
|
||||
|
||||
let error_f = lua.create_async_function(|_, ()| async move {
|
||||
Delay::new(Duration::from_millis(10)).await;
|
||||
Err::<(), _>(Error::RuntimeError("test".to_string()))
|
||||
})?;
|
||||
|
||||
let sleep = lua.create_async_function(|_, n| async move {
|
||||
Delay::new(Duration::from_millis(n)).await;
|
||||
Ok(format!("elapsed:{}ms", n))
|
||||
})?;
|
||||
|
||||
assert!(error_f.call_async::<_, ()>(()).await.is_err());
|
||||
// Next call should use cached thread
|
||||
assert_eq!(sleep.call_async::<_, String>(3).await?, "elapsed:3ms");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_userdata() -> Result<()> {
|
||||
#[derive(Clone)]
|
||||
@@ -372,6 +426,30 @@ async fn test_async_userdata() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_thread_error() -> Result<()> {
|
||||
struct MyUserData;
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method("__tostring", |_, _this, ()| Ok("myuserdata error"))
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let result = lua
|
||||
.load("function x(...) error(...) end x(...)")
|
||||
.set_name("chunk")?
|
||||
.call_async::<_, ()>(MyUserData)
|
||||
.await;
|
||||
assert!(
|
||||
matches!(result, Err(Error::RuntimeError(cause)) if cause.contains("myuserdata error")),
|
||||
"improper error traceback from dead thread"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_async_scope() -> Result<()> {
|
||||
let ref lua = Lua::new();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use mlua::{Lua, UserData, UserDataMethods};
|
||||
use mlua::{UserData, UserDataMethods};
|
||||
|
||||
fn main() {
|
||||
let ref lua = Lua::new();
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MyUserData<'a>(&'a i64);
|
||||
|
||||
|
||||
@@ -1,41 +1,14 @@
|
||||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
||||
--> tests/compile/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 here...
|
||||
--> tests/compile/async_nonstatic_userdata.rs:9:10
|
||||
|
|
||||
9 | impl<'a> UserData for MyUserData<'a> {
|
||||
| ^^
|
||||
note: ...so that the types are compatible
|
||||
--> tests/compile/async_nonstatic_userdata.rs:11:72
|
||||
|
|
||||
11 | methods.add_async_method("print", |_, data, ()| async move {
|
||||
| ________________________________________________________________________^
|
||||
12 | | println!("{}", data.0);
|
||||
13 | | Ok(())
|
||||
14 | | });
|
||||
| |_____________^
|
||||
= note: expected `(MyUserData<'_>,)`
|
||||
found `(MyUserData<'a>,)`
|
||||
note: but, the lifetime must be valid for the lifetime `'lua` as defined here...
|
||||
--> tests/compile/async_nonstatic_userdata.rs:10:24
|
||||
|
|
||||
10 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
| ^^^^
|
||||
note: ...so that the type `impl Future<Output = [async output]>` will meet its required lifetime bounds...
|
||||
--> tests/compile/async_nonstatic_userdata.rs:11:21
|
||||
|
|
||||
11 | methods.add_async_method("print", |_, data, ()| async move {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: ...that is required by this bound
|
||||
--> src/userdata.rs
|
||||
|
|
||||
| MR: 'lua + Future<Output = Result<R>>;
|
||||
| ^^^^
|
||||
error: lifetime may not live long enough
|
||||
--> tests/compile/async_nonstatic_userdata.rs:9:13
|
||||
|
|
||||
7 | impl<'a> UserData for MyUserData<'a> {
|
||||
| -- lifetime `'a` defined here
|
||||
8 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
| ---- lifetime `'lua` defined here
|
||||
9 | / methods.add_async_method("print", |_, data, ()| async move {
|
||||
10 | | println!("{}", data.0);
|
||||
11 | | Ok(())
|
||||
12 | | });
|
||||
| |______________^ argument requires that `'a` must outlive `'lua`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'lua`
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function
|
||||
error[E0373]: closure may outlive the current function, but it borrows `test.0`, which is owned by the current function
|
||||
--> tests/compile/function_borrow.rs:9:33
|
||||
|
|
||||
9 | let _ = lua.create_function(|_, ()| -> Result<i32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `test`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `test.0`
|
||||
10 | Ok(test.0)
|
||||
| ------ `test` is borrowed here
|
||||
| ------ `test.0` is borrowed here
|
||||
|
|
||||
note: function requires argument type to outlive `'static`
|
||||
--> tests/compile/function_borrow.rs:9:13
|
||||
@@ -14,7 +14,7 @@ note: function requires argument type to outlive `'static`
|
||||
10 | | Ok(test.0)
|
||||
11 | | });
|
||||
| |______^
|
||||
help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword
|
||||
help: to force the closure to take ownership of `test.0` (and any other referenced variables), use the `move` keyword
|
||||
|
|
||||
9 | let _ = lua.create_function(move |_, ()| -> Result<i32> {
|
||||
| ++++
|
||||
|
||||
@@ -10,7 +10,11 @@ error[E0277]: the type `UnsafeCell<mlua::lua::LuaInner>` may contain interior mu
|
||||
= note: required because it appears within the type `Arc<UnsafeCell<mlua::lua::LuaInner>>`
|
||||
= note: required because it appears within the type `Lua`
|
||||
= note: required because of the requirements on the impl of `UnwindSafe` for `&Lua`
|
||||
= note: required because it appears within the type `[closure@$DIR/tests/compile/lua_norefunwindsafe.rs:7:18: 7:48]`
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/lua_norefunwindsafe.rs:7:18
|
||||
|
|
||||
7 | catch_unwind(|| lua.create_table().unwrap());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `catch_unwind`
|
||||
--> $RUST/std/src/panic.rs
|
||||
|
|
||||
|
||||
@@ -10,7 +10,14 @@ error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
|
||||
| |_____- within this `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]`
|
||||
|
|
||||
= help: within `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
|
||||
= note: required because it appears within the type `[closure@$DIR/tests/compile/non_send.rs:11:25: 13:6]`
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/non_send.rs:11:25
|
||||
|
|
||||
11 | lua.create_function(move |_, ()| {
|
||||
| _________________________^
|
||||
12 | | Ok(data.get())
|
||||
13 | | })?
|
||||
| |_____^
|
||||
= 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]`
|
||||
note: required by a bound in `Lua::create_function`
|
||||
--> src/lua.rs
|
||||
|
||||
@@ -12,7 +12,11 @@ error[E0277]: the type `UnsafeCell<mlua::lua::LuaInner>` may contain interior mu
|
||||
= note: required because of the requirements on the impl of `UnwindSafe` for `&Lua`
|
||||
= note: required because it appears within the type `mlua::types::LuaRef<'_>`
|
||||
= note: required because it appears within the type `LuaTable<'_>`
|
||||
= note: required because it appears within the type `[closure@$DIR/tests/compile/ref_nounwindsafe.rs:8:18: 8:54]`
|
||||
note: required because it's used within this closure
|
||||
--> tests/compile/ref_nounwindsafe.rs:8:18
|
||||
|
|
||||
8 | catch_unwind(move || table.set("a", "b").unwrap());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `catch_unwind`
|
||||
--> $RUST/std/src/panic.rs
|
||||
|
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
error[E0373]: closure may outlive the current function, but it borrows `test`, which is owned by the current function
|
||||
error[E0373]: closure may outlive the current function, but it borrows `test.field`, which is owned by the current function
|
||||
--> tests/compile/scope_invariance.rs:14:38
|
||||
|
|
||||
9 | lua.scope(|scope| {
|
||||
| ----- has type `&mlua::Scope<'_, '1>`
|
||||
...
|
||||
14 | .create_function_mut(|_, ()| {
|
||||
| ^^^^^^^ may outlive borrowed value `test`
|
||||
| ^^^^^^^ may outlive borrowed value `test.field`
|
||||
15 | test.field = 42;
|
||||
| ---------- `test` is borrowed here
|
||||
| ---------- `test.field` is borrowed here
|
||||
|
|
||||
note: function requires argument type to outlive `'1`
|
||||
--> tests/compile/scope_invariance.rs:13:13
|
||||
@@ -19,7 +19,7 @@ note: function requires argument type to outlive `'1`
|
||||
17 | | Ok(())
|
||||
18 | | })?
|
||||
| |__________________^
|
||||
help: to force the closure to take ownership of `test` (and any other referenced variables), use the `move` keyword
|
||||
help: to force the closure to take ownership of `test.field` (and any other referenced variables), use the `move` keyword
|
||||
|
|
||||
14 | .create_function_mut(move |_, ()| {
|
||||
| ++++
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
error[E0597]: `lua` does not live long enough
|
||||
--> tests/compile/static_callback_args.rs:12:5
|
||||
|
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | | BAD_TIME.with(|bt| {
|
||||
14 | | *bt.borrow_mut() = Some(table);
|
||||
15 | | });
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| | ^
|
||||
| | |
|
||||
| |______borrowed value does not live long enough
|
||||
| argument requires that `lua` is borrowed for `'static`
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | | BAD_TIME.with(|bt| {
|
||||
| |_________-
|
||||
14 | || *bt.borrow_mut() = Some(table);
|
||||
15 | || });
|
||||
| ||__________- argument requires that `lua` is borrowed for `'static`
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| |______^ borrowed value does not live long enough
|
||||
...
|
||||
32 | }
|
||||
| - `lua` dropped here while still borrowed
|
||||
32 | }
|
||||
| - `lua` dropped here while still borrowed
|
||||
|
||||
error[E0505]: cannot move out of `lua` because it is borrowed
|
||||
--> tests/compile/static_callback_args.rs:22:10
|
||||
|
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | | BAD_TIME.with(|bt| {
|
||||
14 | | *bt.borrow_mut() = Some(table);
|
||||
15 | | });
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| | -
|
||||
| | |
|
||||
| |______borrow of `lua` occurs here
|
||||
| argument requires that `lua` is borrowed for `'static`
|
||||
12 | / lua.create_function(|_, table: Table| {
|
||||
13 | | BAD_TIME.with(|bt| {
|
||||
| |_________-
|
||||
14 | || *bt.borrow_mut() = Some(table);
|
||||
15 | || });
|
||||
| ||__________- argument requires that `lua` is borrowed for `'static`
|
||||
16 | | Ok(())
|
||||
17 | | })?
|
||||
| |______- borrow of `lua` occurs here
|
||||
...
|
||||
22 | drop(lua);
|
||||
| ^^^ move out of `lua` occurs here
|
||||
22 | drop(lua);
|
||||
| ^^^ move out of `lua` occurs here
|
||||
|
||||
@@ -42,11 +42,17 @@ fn test_bind() -> Result<()> {
|
||||
concat = concat.bind("foo")?;
|
||||
concat = concat.bind("bar")?;
|
||||
concat = concat.bind(("baz", "baf"))?;
|
||||
assert_eq!(concat.call::<_, String>(())?, "foobarbazbaf");
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(("hi", "wut"))?,
|
||||
"foobarbazbafhiwut"
|
||||
);
|
||||
|
||||
let mut concat2 = globals.get::<_, Function>("concat")?;
|
||||
concat2 = concat2.bind(())?;
|
||||
assert_eq!(concat2.call::<_, String>(())?, "");
|
||||
assert_eq!(concat2.call::<_, String>(("ab", "cd"))?, "abcd");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ fn test_readonly_table() -> Result<()> {
|
||||
assert!(t.is_readonly());
|
||||
|
||||
match t.set("key", "value") {
|
||||
Err(Error::RuntimeError(err)) if err.contains("Attempt to modify a readonly table") => {}
|
||||
Err(Error::RuntimeError(err)) if err.contains("attempt to modify a readonly table") => {}
|
||||
r => panic!(
|
||||
"expected RuntimeError(...) with a specific message, got {:?}",
|
||||
r
|
||||
|
||||
@@ -73,6 +73,7 @@ fn test_load() -> Result<()> {
|
||||
let result: i32 = func.call(())?;
|
||||
assert_eq!(result, 3);
|
||||
|
||||
assert!(lua.load("").exec().is_ok());
|
||||
assert!(lua.load("§$%§&$%&").exec().is_err());
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user