Equality comparison for bound callable references takes into account bound receiver.

Fixed KT-14939: use expected receiver type when generating receiver code in get/set methods for bound property references.
Otherwise we have VerifyError for bound receiver 'null' of type 'Nothing?', which is mapped to 'java.lang.Void'.

TODO: proper equality comparison for property accessors ('x::prop.getter', 'x::prop.setter').
This commit is contained in:
Dmitry Petrov
2016-11-23 14:03:23 +03:00
parent ce6cf6475c
commit 3dd0c9d1c7
28 changed files with 525 additions and 20 deletions
@@ -0,0 +1,7 @@
class A {
companion object {
fun ok() = "OK"
}
}
fun box() = (A.Companion::ok)()
@@ -9,8 +9,11 @@ enum class E {
fun box(): String {
val f = E.A::foo
val ef = E::foo
if (f() != "A") return "Fail 1: ${f()}"
if (f != E.B::foo) return "Fail 2"
if (f == E.B::foo) return "Fail 2"
if (ef != E::foo) return "Fail 3"
return "OK"
}
@@ -0,0 +1,37 @@
// TODO: investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// See https://youtrack.jetbrains.com/issue/KT-14938
// WITH_REFLECT
class A
val a = A()
val aa = A()
fun A?.foo() {}
var A?.bar: Int
get() = 42
set(value) {}
val aFoo = a::foo
val A_foo = A::foo
val nullFoo = null::foo
val aBar = a::bar
val A_bar = A::bar
val nullBar = null::bar
fun box(): String =
when {
nullFoo != null::foo -> "Bound extension refs with same receiver SHOULD be equal"
nullFoo == aFoo -> "Bound extension refs with different receivers SHOULD NOT be equal"
nullFoo == A_foo -> "Bound extension ref with receiver 'null' SHOULD NOT be equal to free ref"
nullBar != null::bar -> "Bound extension property refs with same receiver SHOULD be equal"
nullBar == aBar -> "Bound extension property refs with different receivers SHOULD NOT be equal"
nullBar == A_bar -> "Bound extension property ref with receiver 'null' SHOULD NOT be equal to free property ref"
else -> "OK"
}
@@ -0,0 +1,27 @@
// TODO: investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
package test
class A {
fun foo() {}
fun bar() {}
}
val a = A()
val aa = A()
val aFoo = a::foo
val aBar = a::bar
val aaFoo = aa::foo
val A_foo = A::foo
fun box(): String =
when {
aFoo != a::foo -> "Bound refs with same receiver SHOULD be equal"
aFoo == aBar -> "Bound refs to different members SHOULD NOT be equal"
aFoo == aaFoo -> "Bound refs with different receiver SHOULD NOT be equal"
aFoo == A_foo -> "Bound ref SHOULD NOT be equal to free ref"
else -> "OK"
}
@@ -0,0 +1,9 @@
// TODO: investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
// See https://youtrack.jetbrains.com/issue/KT-14939
val String?.ok: String
get() = "OK"
fun box() = (null::ok).get()
@@ -0,0 +1,5 @@
object Singleton {
fun ok() = "OK"
}
fun box() = (Singleton::ok)()
@@ -0,0 +1,29 @@
// TODO: investigate should it be ran for JS or not
// IGNORE_BACKEND: JS
fun Boolean.foo() = 1
fun Byte.foo() = 2
fun Short.foo() = 3
fun Int.foo() = 4
fun Long.foo() = 5
fun Char.foo() = 6
fun Float.foo() = 7
fun Double.foo() = 8
fun testRef(name: String, f: () -> Int, expected: Int) {
val actual = f()
if (actual != expected) throw AssertionError("$name: $actual != $expected")
}
fun box(): String {
testRef("Boolean", true::foo, 1)
testRef("Byte", 1.toByte()::foo, 2)
testRef("Short", 1.toShort()::foo, 3)
testRef("Int", 1::foo, 4)
testRef("Long", 1L::foo, 5)
testRef("Char", '1'::foo, 6)
testRef("Float", 1.0F::foo, 7)
testRef("Double", 1.0::foo, 8)
return "OK"
}
@@ -0,0 +1,9 @@
class A {
fun foo() {}
val bar = 42
}
val aFoo = A()::foo
val aBar = A()::bar
val A_foo = A::foo
val A_bar = A::bar
@@ -0,0 +1,66 @@
@kotlin.Metadata
public final class A {
private final field bar: int
public method <init>(): void
public final method foo(): void
public final method getBar(): int
}
@kotlin.Metadata
final class NoReceiverInCallableReferenceClassesKt$A_bar$1 {
public final static field INSTANCE: kotlin.reflect.KProperty1
static method <clinit>(): void
method <init>(): void
public @org.jetbrains.annotations.Nullable method get(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
public method getName(): java.lang.String
public method getOwner(): kotlin.reflect.KDeclarationContainer
public method getSignature(): java.lang.String
}
@kotlin.Metadata
final class NoReceiverInCallableReferenceClassesKt$A_foo$1 {
public final static field INSTANCE: NoReceiverInCallableReferenceClassesKt$A_foo$1
inner class NoReceiverInCallableReferenceClassesKt$A_foo$1
static method <clinit>(): void
method <init>(): void
public final method getName(): java.lang.String
public final method getOwner(): kotlin.reflect.KDeclarationContainer
public final method getSignature(): java.lang.String
public final method invoke(@org.jetbrains.annotations.NotNull p0: A): void
public synthetic method invoke(p0: java.lang.Object): java.lang.Object
}
@kotlin.Metadata
final class NoReceiverInCallableReferenceClassesKt$aBar$1 {
method <init>(p0: A): void
public @org.jetbrains.annotations.Nullable method get(): java.lang.Object
public method getName(): java.lang.String
public method getOwner(): kotlin.reflect.KDeclarationContainer
public method getSignature(): java.lang.String
}
@kotlin.Metadata
final class NoReceiverInCallableReferenceClassesKt$aFoo$1 {
inner class NoReceiverInCallableReferenceClassesKt$aFoo$1
method <init>(p0: A): void
public final method getName(): java.lang.String
public final method getOwner(): kotlin.reflect.KDeclarationContainer
public final method getSignature(): java.lang.String
public synthetic method invoke(): java.lang.Object
public final method invoke(): void
}
@kotlin.Metadata
public final class NoReceiverInCallableReferenceClassesKt {
private final static @org.jetbrains.annotations.NotNull field A_bar: kotlin.reflect.KProperty1
private final static @org.jetbrains.annotations.NotNull field A_foo: kotlin.reflect.KFunction
private final static @org.jetbrains.annotations.NotNull field aBar: kotlin.reflect.KProperty0
private final static @org.jetbrains.annotations.NotNull field aFoo: kotlin.reflect.KFunction
inner class NoReceiverInCallableReferenceClassesKt$A_foo$1
inner class NoReceiverInCallableReferenceClassesKt$aFoo$1
static method <clinit>(): void
public final static @org.jetbrains.annotations.NotNull method getABar(): kotlin.reflect.KProperty0
public final static @org.jetbrains.annotations.NotNull method getAFoo(): kotlin.reflect.KFunction
public final static @org.jetbrains.annotations.NotNull method getA_bar(): kotlin.reflect.KProperty1
public final static @org.jetbrains.annotations.NotNull method getA_foo(): kotlin.reflect.KFunction
}