Fix extensible class inheritance: derived Lua method overwrites base class slot#207
Conversation
…se class table When a Lua method was defined on a derived extensible class (e.g. `function Derived:init()`), try_call_newindex_extensible was storing it in the BASE class table — not the derived one — because the search loop could end on a parent's class table and the final rawsetfield used whatever ct was on the stack. Two fixes in try_call_newindex_extensible (CFunctions.h): 1. After the search loop, always store the new value in the ORIGINAL (derived) class table by re-fetching it from lua_getmetatable(L,1) — the static table passed as arg1 — instead of from wherever the search ended. 2. When a C++ cfunction is found in a parent class and allowOverridingMethods is set, COPY it as "super_<name>" into the derived class table rather than renaming it in the parent. This leaves the parent class table untouched so that base-class instances still call the original C++ function. Three regression tests added to ClassExtensibleTests.cpp: - ExtensibleDerivedDoesNotPollutBaseMethod (the reported bug) - ExtensibleDerivedMethodIsolatedFromBase - ExtensibleDerivedOverridePreservesCppBaseMethod Agent-Logs-Url: https://github.com/kunitoki/LuaBridge3/sessions/87bf2fae-8707-414e-940a-6a5b521d10e7 Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Agent-Logs-Url: https://github.com/kunitoki/LuaBridge3/sessions/87bf2fae-8707-414e-940a-6a5b521d10e7 Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
kunitoki
left a comment
There was a problem hiding this comment.
With this solution i get failures:
[ RUN ] ClassExtensibleTests.IndexAndNewMetaMethodCalledInBaseClass
Tests/Source/ClassExtensibleTests.cpp:779: Failure
Expected equality of these values:
102
result<int>()
Which is: 200
Tests/Source/ClassExtensibleTests.cpp:787: Failure
Expected equality of these values:
3
result<int>()
Which is: 100
[ FAILED ] ClassExtensibleTests.IndexAndNewMetaMethodCalledInBaseClass (0 ms)
Thank you for catching this. The fix has been revised (commit Root cause of the regression: the previous fix unconditionally redirected all static writes to Corrected approach — the new fix distinguishes two cases after the search loop:
Results on Lua 5.2–5.5: all 28 tests pass. There is one remaining failure on Lua 5.1 only ( |
|
Failure |
When same-named Lua methods were defined on both a base and derived extensible class, the derived method was silently stored in the base class table, causing
base:init()to dispatch toDerived:init().Root cause
try_call_newindex_extensiblesearched up the class hierarchy for an existing method, then stored the new value at whatever class table the search loop landed on — often the parent's. Additionally, whenallowOverridingMethodswas set and a C++ function was found in a parent, it was renamed in the parent table (super_<name>), breaking base-class instances that expected to call the original C++ function.Fix (
Source/LuaBridge/detail/CFunctions.h)After the search loop, the storage location is chosen based on the type of value being assigned:
function Derived:init()) — stored in the original (derived) class table, resolved vialua_getmetatable(L, 1)→push_class_or_const_table. This ensures each class has its own independent method slot and the derived method never pollutes the base class table.Derived.property = 100) — stored at the original location (wherever the search loop ended). This preserves compatibility with classes that register a custom index fallback on a parent to handle per-instance storage: the fallback fires beforerawgetat that level, so the parent-stored property is correctly shadowed by the per-instance value.super_<name>copy — when a C++ cfunction is found in a parent andallowOverridingMethodsis set, it is copied into the derived class table assuper_<name>without modifying the parent. Base-class instances continue to find and call the original C++ function via their own class table.Tests (
Tests/Source/ClassExtensibleTests.cpp)Three regression tests added:
ExtensibleDerivedDoesNotPollutBaseMethod— the reported bug exactlyExtensibleDerivedMethodIsolatedFromBase— both classes dispatch to their own Lua method independentlyExtensibleDerivedOverridePreservesCppBaseMethod—allowOverridingMethodsoverride in derived class leaves the C++ base method intact for base instances💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.