Skip to content

UserDataBorrowError when using send feature with Rust 1.93 #700

@wez

Description

@wez

I noticed this when updating the toolchain; reproducing code below. The actual code uses a different struct and isn't simply an i64; this is just a minimal reproducing example.

With rustc 1.92, this prints "ok".

With rustc 1.93, this prints:

   BadArgument { to: Some("Delta.__add"), pos: 1, name: Some("self"),
                 cause: UserDataBorrowError }

Toggling off the send feature in Cargo.toml makes the error go away on
rustc 1.93 as well, suggesting the issue is in the Send-aware borrow
tracking path inside mlua.

The __add metamethod is registered with add_meta_method (which only
needs a shared borrow of this) and the operand is taken as
UserDataRef<Delta> (also a shared borrow). When both Lua operands refer
to the same underlying userdata (e.g. local x = d; return x + x), the
argument extraction reports a borrow conflict against the still-live
this borrow.

Adding two different userdata values of the same type works fine; only
same + same fails.

use mlua::{Lua, MetaMethod, UserData, UserDataMethods, UserDataRef};

#[derive(Clone, Copy)]
struct Delta(i64);

impl UserData for Delta {
    fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
        methods.add_meta_method(MetaMethod::Add, |_, this, other: UserDataRef<Delta>| {
            Ok(Delta(this.0 + other.0))
        });
    }
}

fn main() -> mlua::Result<()> {
    let lua = Lua::new();
    let globals = lua.globals();
    globals.set("d1", Delta(1))?;
    globals.set("d2", Delta(2))?;

    // Two distinct userdata values: works on both 1.92 and 1.93.
    lua.load("local r = d1 + d2 assert(r) print('distinct ok')")
        .exec()?;

    // Same underlying userdata on both sides: works on 1.92, fails on 1.93
    // when the `send` feature is enabled.
    lua.load("local r = d1 + d1 print('same ok')").exec()?;

    Ok(())
}
[dependencies]
mlua = { version = "0.11", features = ["vendored", "lua54", "async", "send", "serialize"] }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions