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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions