Skip to content

#[mlua::userdata_impl] fails to compile when the impl block is in a different module than the type #726

Description

@Dobee8

Version:

mlua 0.12.0 (mlua_derive 0.12.0), features: lua51, vendored, macros

Description

#[mlua::userdata_impl] only works when it is placed in the same module (or a descendant)
as #[derive(UserData)]. In any other module it fails to compile. This makes it impossible to
split a type's Rust-side code from its Lua bindings, which is a natural layout when embedding
Lua (e.g. a game core types module + a dedicated lua/ binding module).

Minimal reproduction

// src/types.rs  (module where the type is defined)
use mlua::UserData;

#[derive(UserData)]
pub struct A {}

// src/lua.rs  (separate module)
#[mlua::userdata_impl]
impl A {
    fn hello(&self) -> mlua::Result<()> {
        Ok(())
    }
}

Expected

Compiles; A:hello is registered for Lua.

Actual

error[E0422]: cannot find struct, variant or union type __MluaUserDataRegistration_A in this scope

Root cause

  • #[derive(UserData)] emits a private __MluaUserDataRegistration_A struct plus inventory::collect! and impl UserData in the type's module (mlua_derive/src/userdata/mod.rs).
  • #[mlua::userdata_impl] expands to inventory::submit! { __MluaUserDataRegistration_A { ... } } referencing the bare identifier (mlua_derive/src/userdata/userdata_impl.rs), which must resolve in the module where the macro is written. From a sibling module the private type is neither in scope nor importable, so resolution fails.

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