From dc361af48bc9a1353b10b39997bb806b48f51656 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Fri, 2 Apr 2021 12:25:07 +0900 Subject: [PATCH] Fix incorrect binding of classmethod when called on instance of subclass --- src/vm.c | 5 +++-- test/testClassMethodInherited.krk | 10 ++++++++++ test/testClassMethodInherited.krk.expect | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/testClassMethodInherited.krk create mode 100644 test/testClassMethodInherited.krk.expect diff --git a/src/vm.c b/src/vm.c index aacd817..4e07647 100644 --- a/src/vm.c +++ b/src/vm.c @@ -910,6 +910,7 @@ KrkValue krk_callSimple(KrkValue value, int argCount, int isMethod) { * Works for managed and native method calls. */ int krk_bindMethod(KrkClass * _class, KrkString * name) { + KrkClass * originalClass = _class; KrkValue method, out; while (_class) { if (krk_tableGet_fast(&_class->methods, name, &method)) break; @@ -920,7 +921,7 @@ int krk_bindMethod(KrkClass * _class, KrkString * name) { if (((KrkNative*)AS_OBJECT(method))->flags & KRK_NATIVE_FLAGS_IS_DYNAMIC_PROPERTY) { out = AS_NATIVE(method)->function(1, (KrkValue[]){krk_peek(0)}, 0); } else if (((KrkNative*)AS_OBJECT(method))->flags & KRK_NATIVE_FLAGS_IS_CLASS_METHOD) { - out = OBJECT_VAL(krk_newBoundMethod(OBJECT_VAL(_class), AS_OBJECT(method))); + out = OBJECT_VAL(krk_newBoundMethod(OBJECT_VAL(originalClass), AS_OBJECT(method))); } else if (((KrkNative*)AS_OBJECT(method))->flags & KRK_NATIVE_FLAGS_IS_STATIC_METHOD) { out = method; } else { @@ -928,7 +929,7 @@ int krk_bindMethod(KrkClass * _class, KrkString * name) { } } else if (IS_CLOSURE(method)) { if (AS_CLOSURE(method)->flags & KRK_FUNCTION_FLAGS_IS_CLASS_METHOD) { - out = OBJECT_VAL(krk_newBoundMethod(OBJECT_VAL(_class), AS_OBJECT(method))); + out = OBJECT_VAL(krk_newBoundMethod(OBJECT_VAL(originalClass), AS_OBJECT(method))); } else if (AS_CLOSURE(method)->flags & KRK_FUNCTION_FLAGS_IS_STATIC_METHOD) { out = method; } else { diff --git a/test/testClassMethodInherited.krk b/test/testClassMethodInherited.krk new file mode 100644 index 0000000..bc57f87 --- /dev/null +++ b/test/testClassMethodInherited.krk @@ -0,0 +1,10 @@ +class Foo: + @classmethod + def doThing(cls): + print("Called from a",cls) +class Bar(Foo): + pass +Foo.doThing() +Foo().doThing() +Bar.doThing() +Bar().doThing() diff --git a/test/testClassMethodInherited.krk.expect b/test/testClassMethodInherited.krk.expect new file mode 100644 index 0000000..1a90b5e --- /dev/null +++ b/test/testClassMethodInherited.krk.expect @@ -0,0 +1,4 @@ +Called from a +Called from a +Called from a +Called from a