Fix equality comparison for inline class over inline class
^KT-54536: Fixed
This commit is contained in:
committed by
teamcity
parent
db133bedf9
commit
6f4a60ac91
+12
@@ -21647,6 +21647,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineInCompanionGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOverInlineWithCustomEquals.kt")
|
||||
public void testInlineOverInlineWithCustomEquals() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineOverInlineWithCustomEquals.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineToString.kt")
|
||||
public void testInlineToString() throws Exception {
|
||||
@@ -22265,6 +22271,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt54455.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54536.kt")
|
||||
public void testKt54536() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt54536.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54603.kt")
|
||||
public void testKt54603() throws Exception {
|
||||
|
||||
+15
-3
@@ -491,19 +491,31 @@ private class JvmInlineClassLowering(context: JvmBackendContext) : JvmValueClass
|
||||
val untypedEquals = valueClass.functions.single { it.isEquals(context) }
|
||||
|
||||
function.body = context.createIrBuilder(valueClass.symbol).run {
|
||||
val context = this@JvmInlineClassLowering.context
|
||||
val underlyingType = getInlineClassUnderlyingType(valueClass)
|
||||
irExprBody(
|
||||
if (untypedEquals.origin == IrDeclarationOrigin.DEFINED) {
|
||||
val boxFunction = this@JvmInlineClassLowering.context.inlineClassReplacements.getBoxFunction(valueClass)
|
||||
val boxFunction = context.inlineClassReplacements.getBoxFunction(valueClass)
|
||||
|
||||
fun irBox(expr: IrExpression) = irCall(boxFunction).apply { putValueArgument(0, expr) }
|
||||
|
||||
val underlyingType = getInlineClassUnderlyingType(valueClass)
|
||||
irCall(untypedEquals).apply {
|
||||
dispatchReceiver = irBox(coerceInlineClasses(irGet(left), left.type, underlyingType))
|
||||
putValueArgument(0, irBox(coerceInlineClasses(irGet(right), right.type, underlyingType)))
|
||||
}
|
||||
} else {
|
||||
irEquals(coerceInlineClasses(irGet(left), left.type, type), coerceInlineClasses(irGet(right), right.type, type))
|
||||
val underlyingClass = underlyingType.getClass()
|
||||
// We can't directly compare unboxed values of underlying inline class as this class can have custom equals
|
||||
if (underlyingClass?.isSingleFieldValueClass == true && !underlyingType.isNullable()) {
|
||||
val underlyingClassEq =
|
||||
context.inlineClassReplacements.getSpecializedEqualsMethod(underlyingClass, context.irBuiltIns)
|
||||
irCall(underlyingClassEq).apply {
|
||||
putValueArgument(0, coerceInlineClasses(irGet(left), left.type, underlyingType))
|
||||
putValueArgument(1, coerceInlineClasses(irGet(right), right.type, underlyingType))
|
||||
}
|
||||
} else {
|
||||
irEquals(coerceInlineClasses(irGet(left), left.type, type), coerceInlineClasses(irGet(right), right.type, type))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class A(val x: Int) {
|
||||
fun equals(other: A) = true
|
||||
}
|
||||
|
||||
class C
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class B1(val x: A)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class B2(val x: A?)
|
||||
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class D1(val x: C) {
|
||||
fun equals(other: D1) = true
|
||||
}
|
||||
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class D2(val x: C?) {
|
||||
fun equals(other: D2) = true
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class E1(val x: D1)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class E2(val x: D2)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class F<T>(val x: T)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class G<T : D1>(val x: T)
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class H<T>(val x: F<T>)
|
||||
|
||||
fun box(): String {
|
||||
if (E1(D1(C())) != E1(D1(C()))) return "Fail 1"
|
||||
|
||||
if (E2(D2(C())) != E2(D2(C()))) return "Fail 2.1"
|
||||
if (E2(D2(null)) != E2(D2(C()))) return "Fail 2.2"
|
||||
if (E2(D2(C())) != E2(D2(null))) return "Fail 2.3"
|
||||
if (E2(D2(null)) != E2(D2(null))) return "Fail 2.4"
|
||||
|
||||
if (B1(A(0)) != B1(A(5))) return "Fail 3"
|
||||
|
||||
if (B2(A(0)) != B2(A(5))) return "Fail 4.1"
|
||||
if (B2(null) == B2(A(5))) return "Fail 4.2"
|
||||
if (B2(A(0)) == B2(null)) return "Fail 4.3"
|
||||
if (B2(null) != B2(null)) return "Fail 4.4"
|
||||
|
||||
if (F(D1(C())) != F(D1(C()))) return "Fail 5"
|
||||
|
||||
if (G(D1(C())) != G(D1(C()))) return "Fail 6"
|
||||
|
||||
if (H(F(1)) == H(F(2))) return "Fail 7"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// WITH_STDLIB
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses, +CustomEqualsInInlineClasses
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class A(val x: Int) {
|
||||
fun equals(other: A) = x % 5 == other.x % 5
|
||||
}
|
||||
|
||||
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||
value class B(val x: A)
|
||||
|
||||
fun box() = if (B(A(0)) == B(A(5))) "OK" else "Fail"
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// 0 INVOKESTATIC B.box-impl
|
||||
// 0 INVOKESTATIC A.box-impl
|
||||
+12
@@ -21647,6 +21647,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineInCompanionGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOverInlineWithCustomEquals.kt")
|
||||
public void testInlineOverInlineWithCustomEquals() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/inlineOverInlineWithCustomEquals.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineToString.kt")
|
||||
public void testInlineToString() throws Exception {
|
||||
@@ -22265,6 +22271,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt54455.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54536.kt")
|
||||
public void testKt54536() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/kt54536.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt54603.kt")
|
||||
public void testKt54603() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user