Fix specialization of equality comparison calls for inline classes
Receiver of equals() call should be checked instead of argument ^KT-57261: Fixed
This commit is contained in:
committed by
teamcity
parent
8039e30bbd
commit
35dfcb61bb
+6
@@ -22619,6 +22619,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt57261.kt")
|
||||||
|
public void testKt57261() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57261.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lateinitInlineClasses.kt")
|
@TestMetadata("lateinitInlineClasses.kt")
|
||||||
public void testLateinitInlineClasses() throws Exception {
|
public void testLateinitInlineClasses() throws Exception {
|
||||||
|
|||||||
+6
@@ -22619,6 +22619,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt57261.kt")
|
||||||
|
public void testKt57261() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57261.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lateinitInlineClasses.kt")
|
@TestMetadata("lateinitInlineClasses.kt")
|
||||||
public void testLateinitInlineClasses() throws Exception {
|
public void testLateinitInlineClasses() throws Exception {
|
||||||
|
|||||||
+17
-18
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||||
import org.jetbrains.kotlin.ir.transformStatement
|
import org.jetbrains.kotlin.ir.transformStatement
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
@@ -335,11 +334,11 @@ internal class JvmInlineClassLowering(
|
|||||||
coerceInlineClasses(arg, expression.symbol.owner.dispatchReceiverParameter!!.type, expression.type)
|
coerceInlineClasses(arg, expression.symbol.owner.dispatchReceiverParameter!!.type, expression.type)
|
||||||
}
|
}
|
||||||
// Specialize calls to equals when the left argument is a value of inline class type.
|
// Specialize calls to equals when the left argument is a value of inline class type.
|
||||||
expression.isSpecializedInlineClassEqEq || expression.isSpecializedInlineClassEquals -> {
|
expression.isEqEqCallOnInlineClass || expression.isEqualsMethodCallOnInlineClass -> {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
val leftOp: IrExpression
|
val leftOp: IrExpression
|
||||||
val rightOp: IrExpression
|
val rightOp: IrExpression
|
||||||
if (expression.isSpecializedInlineClassEqEq) {
|
if (expression.isEqEqCallOnInlineClass) {
|
||||||
leftOp = expression.getValueArgument(0)!!
|
leftOp = expression.getValueArgument(0)!!
|
||||||
rightOp = expression.getValueArgument(1)!!
|
rightOp = expression.getValueArgument(1)!!
|
||||||
} else {
|
} else {
|
||||||
@@ -354,29 +353,29 @@ internal class JvmInlineClassLowering(
|
|||||||
super.visitCall(expression)
|
super.visitCall(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrCall.isSpecializedInlineClassEquals: Boolean
|
private val IrCall.isEqualsMethodCallOnInlineClass: Boolean
|
||||||
get() {
|
get() {
|
||||||
return isSpecializedInlineClassEqualityCheck { symbol.owner.isEquals() }
|
if (!symbol.owner.isEquals()) return false
|
||||||
|
val receiverClass = dispatchReceiver?.type?.classOrNull?.owner
|
||||||
|
return receiverClass?.canUseSpecializedEqMethod ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrCall.isSpecializedInlineClassEqEq: Boolean
|
private val IrCall.isEqEqCallOnInlineClass: Boolean
|
||||||
get() {
|
get() {
|
||||||
// Note that reference equality (x === y) is not allowed on values of inline class type,
|
// Note that reference equality (x === y) is not allowed on values of inline class type,
|
||||||
// so it is enough to check for eqeq.
|
// so it is enough to check for eqeq.
|
||||||
return isSpecializedInlineClassEqualityCheck { symbol == context.irBuiltIns.eqeqSymbol }
|
if (symbol != context.irBuiltIns.eqeqSymbol) return false
|
||||||
|
val leftOperandClass = getValueArgument(0)?.type?.classOrNull?.owner
|
||||||
|
return leftOperandClass?.canUseSpecializedEqMethod ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun IrCall.isSpecializedInlineClassEqualityCheck(calleePredicate: (IrSimpleFunctionSymbol) -> Boolean): Boolean {
|
private val IrClass.canUseSpecializedEqMethod: Boolean
|
||||||
|
get() {
|
||||||
if (!calleePredicate(symbol)) return false
|
if (!isSingleFieldValueClass) return false
|
||||||
|
// Before version 1.4, we cannot rely on the Result.equals-impl0 method
|
||||||
val leftClass = getValueArgument(0)?.type?.classOrNull?.owner?.takeIf { it.isSingleFieldValueClass }
|
return fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME ||
|
||||||
?: return false
|
context.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4
|
||||||
|
}
|
||||||
// Before version 1.4, we cannot rely on the Result.equals-impl0 method
|
|
||||||
return (leftClass.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME) ||
|
|
||||||
context.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitGetField(expression: IrGetField): IrExpression {
|
override fun visitGetField(expression: IrGetField): IrExpression {
|
||||||
val field = expression.symbol.owner
|
val field = expression.symbol.owner
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// WITH_STDLIB
|
||||||
|
// WORKS_WHEN_VALUE_CLASS
|
||||||
|
// LANGUAGE: +ValueClasses
|
||||||
|
|
||||||
|
OPTIONAL_JVM_INLINE_ANNOTATION
|
||||||
|
value class Ic(val x: Int)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
val strAsAny : Any = "a"
|
||||||
|
|
||||||
|
if ("a".equals(Ic(1))) return "Fail 1"
|
||||||
|
if (strAsAny.equals(Ic(1))) return "Fail 2"
|
||||||
|
if (Ic(1).equals("a")) return "Fail 3"
|
||||||
|
if (Ic(1).equals(strAsAny)) return "Fail 4"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -22619,6 +22619,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57242.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt57261.kt")
|
||||||
|
public void testKt57261() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/kt57261.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lateinitInlineClasses.kt")
|
@TestMetadata("lateinitInlineClasses.kt")
|
||||||
public void testLateinitInlineClasses() throws Exception {
|
public void testLateinitInlineClasses() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user