Files
kotlin/compiler/testData/codegen/box/reflection/methodsFromAny/fakeOverrideEqualsHashCode.kt
Alexander Udalov 9d27771f86 Fix instance parameter type of inherited declaration in reflection
Both for callables obtained via reflection API (KClass.members etc) and
for callables obtained via ::-references, the instance parameter is now
the class which was used to construct the type at the left-hand side of
the reference, NOT the class where the callable is originally declared
as is known at compile-time. The reason is to reduce the difference in
behavior of KCallable.call vs FunctionN.invoke: the latter always
required the subclass instance for a fake override, and it's reasonable
that the former would require it as well.

Note that in Java reflection, behavior could differ in a similar case.
For a simple fake override, Class.getMethod would return the method
declared in the base class and that method will accept instances of the
base class in invoke. However, it's difficult to rely on this behavior
because if there's a bridge for a fake override in the derived class
(e.g. when overridden members have different signatures), the returned
Method object is accepting the derived class as the receiver. This just
confirms the fact that Java reflection operates on a different level of
abstraction, namely JVM methods in .class files, which is not applicable
to our use cases directly. Another reason not to replicate Java
reflection's behavior is the uncertainty as to which member is returned
in case there are several in the hierarchy for a given fake override:
see the "otherwise one of the methods is chosen arbitrarily" note in
javadoc on Class.getMethod.

 #KT-24170 Fixed
2018-09-21 17:32:43 +03:00

26 lines
573 B
Kotlin
Vendored

// IGNORE_BACKEND: JS_IR, JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertNotEquals
open class A<T> {
fun foo(t: T) {}
}
open class B<U> : A<U>()
class C : B<String>()
fun box(): String {
val afoo = A::class.members.single { it.name == "foo" }
val bfoo = B::class.members.single { it.name == "foo" }
val cfoo = C::class.members.single { it.name == "foo" }
assertNotEquals(afoo, bfoo)
assertNotEquals(afoo.hashCode(), bfoo.hashCode())
assertNotEquals(bfoo, cfoo)
assertNotEquals(bfoo.hashCode(), cfoo.hashCode())
return "OK"
}