Allow #[mlua::userdata_impl] in a different module than the type - #727
Open
teddytennant wants to merge 1 commit into
Open
Allow #[mlua::userdata_impl] in a different module than the type#727teddytennant wants to merge 1 commit into
#[mlua::userdata_impl] in a different module than the type#727teddytennant wants to merge 1 commit into
Conversation
`#[derive(UserData)]` used to emit a private `__MluaUserDataRegistration_<Type>`
struct next to the type and `#[mlua::userdata_impl]` referred to it by bare
identifier, so the impl block had to sit in the same module as the derive.
Splitting a type from its Lua bindings failed with:
error[E0422]: cannot find struct, variant or union type
`__MluaUserDataRegistration_A` in this scope
Collect the registrations through the type instead: the derive implements the
hidden `UserDataRegistrar` trait, which owns the type's inventory registry, and
both macros submit `UserDataRegistration::<Type>` entries. The type is always in
scope where the impl block is written, so registrations now resolve from any
module, including through `use` aliases and fully qualified paths.
Closes mlua-rs#726
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
#[mlua::userdata_impl]only compiles when theimplblock is in the same module as#[derive(UserData)]. Splitting a type from its Lua bindings — a natural layout when embeddingLua — fails:
The derive emitted a private
__MluaUserDataRegistration_<Type>struct plus aninventory::collect!in the type's module, and#[mlua::userdata_impl]submitted to it by bareidentifier. That identifier only resolves in the module where the derive was expanded.
The fix
Route the collection through the type itself, since the type is by definition in scope wherever the
impl block is written.
mluagains two#[doc(hidden)]items behind themacrosfeature:#[derive(UserData)]implementsUserDataRegistrar(holding the per-typeinventory::Registrythat
inventory::collect!used to create), and both macros now submit::mlua::userdata::UserDataRegistration::<Type> { register: ... }. That is a fully qualified,const-constructible struct literal, which is what
inventory::submit!requires, and it names nomodule-local item.
This is the right layer for the fix: the resolution failure is purely an artifact of how the two
macros agreed on a name, so keeping the per-type inventory registry but keying it off the type
rather than off a generated identifier removes the module coupling without changing when or how
registrations run.
A type used with
#[mlua::userdata_impl]but no#[derive(UserData)]previously failed with thesame
E0422. It now reports the missing bound, with a#[diagnostic::on_unimplemented]message:Verification
New test
test_impl_in_other_moduleintests/userdata_macro.rsputs the derive and theuserdata_implin sibling modules and asserts that both the derive's field registration and theimpl block's methods land on the same type.
Before the fix (test applied, sources reverted):
After:
Full suite,
--features lua54,vendored,async,send,serde,macros: 286 tests passed, 0 failed(1 ignored: the
trybuildrunner), plus 48 doctests passed. The 6 pre-existingtrybuildstderrmismatches under
-- --ignoredare unchanged from a clean checkout ofmain(they are rustcspan-rendering differences; CI blesses them with
TRYBUILD=overwrite).Also checked by hand, all passing:
lua51,lua54,luautest runs and aluajitbuild — the derive is Lua-version independent;macrosdisabled, to confirm the new items are correctly feature-gated;pub usealias from the impl block's module;impl crate::types::deep::Deep;implblocks for one type in two different modules;#[cfg]-gated fields and methods;tests/userdata_macro.rscover;cargo +nightly fmt -- --checkis clean andcargo +nightly clippyreports no new warnings.Not changed
implblocks are still rejected by the macros, as before.CHANGELOG.mdentry, since that file looks maintainer-maintained at release time — happy toadd one if you'd like.