Improve support of custom equals in inline classes

- Ensure that typed equals parameter's type is a star projection of
  corresponding inline class

- Make possible to declare typed equals that returns 'Nothing'

- Forbid type parameters in typed equals operator declaration

^KT-54909 fixed
^KT-54910 fixed
This commit is contained in:
vladislav.grechko
2022-11-11 16:44:03 +01:00
parent 02484baf07
commit 36b8ba8df3
38 changed files with 369 additions and 136 deletions
@@ -81,8 +81,47 @@ public final class IC4 {
public synthetic final method unbox-impl(): int
}
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class IC5 {
// source: 'inlineClassEqualsOverride.kt'
private final field value: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): IC5
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static @org.jetbrains.annotations.NotNull method equals-impl0(p0: int, p1: int): java.lang.Void
public final method getValue(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class IC6 {
// source: 'inlineClassEqualsOverride.kt'
private final field value: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): IC6
public static method constructor-impl(p0: int): int
public final @org.jetbrains.annotations.NotNull method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Void
public final static @org.jetbrains.annotations.NotNull method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Void
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getValue(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class InlineClassEqualsOverrideKt {
// source: 'inlineClassEqualsOverride.kt'
public synthetic final static method assertThrows(p0: kotlin.jvm.functions.Function0): boolean
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -19,7 +19,7 @@ interface I {
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC2(val value: Int) : I {
override fun equals(param: IC2): Boolean {
override operator fun equals(param: IC2): Boolean {
return abs(value - param.value) < 2
}
}
@@ -34,6 +34,26 @@ value class IC4(val value: Int) {
override fun equals(other: Any?) = TODO()
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC5(val value: Int) {
operator fun equals(other: IC5): Nothing = TODO()
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC6(val value: Int) {
override fun equals(other: Any?): Nothing = TODO()
}
inline fun <reified T> assertThrows(block: () -> Unit): Boolean {
try {
block.invoke()
} catch (t: Throwable) {
return t is T
}
return false
}
fun box() = when {
IC1(1.0) != IC1(1.05) -> "Fail 1.1"
(IC1(1.0) as Any) != IC1(1.05) -> "Fail 1.2"
@@ -68,5 +88,9 @@ fun box() = when {
IC1(1.0) == Any() -> "Fail 7.1"
(IC1(1.0) as Any) == Any() -> "Fail 7.2"
!assertThrows<NotImplementedError> { IC5(0) == IC5(1) } -> "Fail 8.1"
!assertThrows<NotImplementedError> { IC6(0) == IC6(1) } -> "Fail 8.2"
else -> "OK"
}
@@ -81,8 +81,47 @@ public final class IC4 {
public synthetic final method unbox-impl(): int
}
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class IC5 {
// source: 'inlineClassEqualsOverride.kt'
private final field value: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): IC5
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static @org.jetbrains.annotations.NotNull method equals-impl0(p0: int, p1: int): java.lang.Void
public final method getValue(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class IC6 {
// source: 'inlineClassEqualsOverride.kt'
private final field value: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): IC6
public static method constructor-impl(p0: int): int
public @org.jetbrains.annotations.NotNull method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Void
public static @org.jetbrains.annotations.NotNull method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): java.lang.Void
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getValue(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@kotlin.Metadata
public final class InlineClassEqualsOverrideKt {
// source: 'inlineClassEqualsOverride.kt'
public synthetic final static method assertThrows(p0: kotlin.jvm.functions.Function0): boolean
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -7,7 +7,7 @@ import kotlin.math.abs
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC(val x: Double) {
fun equals(other: IC): Boolean {
operator fun equals(other: IC): Boolean {
return abs(x - other.x) < 0.1
}
@@ -6,7 +6,7 @@
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC1<T : Number>(val x: T) {
fun equals(other: Int) = false
fun equals(other: IC1<T>) = true
operator fun equals(other: IC1<*>) = true
}
class Generic<T, R>(val x: T, val y: R)
@@ -14,19 +14,19 @@ class Generic<T, R>(val x: T, val y: R)
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC2<T, R>(val value: Generic<T, R>) {
fun equals(other: IC1<Double>) = false
fun equals(other: IC2<T, R>) = true
operator fun equals(other: IC2<*, *>) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC3<T>(val value: T) {
fun equals(other: Int) = false
fun equals(other: IC3<*>) = true
operator fun equals(other: IC3<*>) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC4<T>(val value: T) {
fun equals(other: String) = false
fun equals(other: IC4<String>) = true
operator fun equals(other: IC4<*>) = true
}
@@ -6,7 +6,7 @@
OPTIONAL_JVM_INLINE_ANNOTATION
value class A(val x: Int) {
fun equals(other: A) = true
operator fun equals(other: A) = true
}
class C
@@ -20,13 +20,13 @@ value class B2(val x: A?)
OPTIONAL_JVM_INLINE_ANNOTATION
value class D1(val x: C) {
fun equals(other: D1) = true
operator fun equals(other: D1) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class D2(val x: C?) {
fun equals(other: D2) = true
operator fun equals(other: D2) = true
}
OPTIONAL_JVM_INLINE_ANNOTATION
+1 -1
View File
@@ -5,7 +5,7 @@
OPTIONAL_JVM_INLINE_ANNOTATION
value class A(val x: Int) {
fun equals(other: A) = x % 5 == other.x % 5
operator fun equals(other: A) = x % 5 == other.x % 5
}
OPTIONAL_JVM_INLINE_ANNOTATION