JVM_IR JavaSamConversionEqualsHashCode
This commit is contained in:
+28
@@ -44774,6 +44774,34 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/sam/equality/simpleLambdas.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classImplementingFunctionInterface.kt")
|
||||
public void testClassImplementingFunctionInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/classImplementingFunctionInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionReference.kt")
|
||||
public void testFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/functionReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionalExpression.kt")
|
||||
public void testFunctionalExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/functionalExpression.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+7
-2
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmSymbols
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.*
|
||||
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -75,6 +76,9 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
private val shouldGenerateIndyLambdas =
|
||||
context.state.lambdasScheme == JvmClosureGenerationScheme.INDY
|
||||
|
||||
private val isJavaSamConversionWithEqualsHashCode =
|
||||
context.state.languageVersionSettings.supportsFeature(LanguageFeature.JavaSamConversionEqualsHashCode)
|
||||
|
||||
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||
if (!expression.origin.isLambda)
|
||||
return super.visitBlock(expression)
|
||||
@@ -444,7 +448,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean {
|
||||
val samClass = samSuperType.classOrNull
|
||||
?: throw AssertionError("Class type expected: ${samSuperType.render()}")
|
||||
if (!samClass.owner.isFromJava())
|
||||
if (!samClass.owner.isFromJava() || isJavaSamConversionWithEqualsHashCode)
|
||||
return false
|
||||
if (expression is IrBlock && expression.origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE)
|
||||
return false
|
||||
@@ -595,7 +599,8 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
private val isKotlinFunInterface = samInterface != null && !samInterface.isFromJava()
|
||||
|
||||
private val needToGenerateSamEqualsHashCodeMethods =
|
||||
isKotlinFunInterface && (isAdaptedReference || !isLambda)
|
||||
(isKotlinFunInterface || isJavaSamConversionWithEqualsHashCode) &&
|
||||
(isAdaptedReference || !isLambda)
|
||||
|
||||
private val superType =
|
||||
samSuperType
|
||||
|
||||
+7
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.rawType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -34,6 +35,10 @@ internal val singleAbstractMethodPhase = makeIrFilePhase(
|
||||
)
|
||||
|
||||
private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : SingleAbstractMethodLowering(context) {
|
||||
|
||||
private val isJavaSamConversionWithEqualsHashCode =
|
||||
context.state.languageVersionSettings.supportsFeature(LanguageFeature.JavaSamConversionEqualsHashCode)
|
||||
|
||||
override val inInlineFunctionScope: Boolean
|
||||
get() = allScopes.any { it.irElement.safeAs<IrDeclaration>()?.isInPublicInlineScope == true }
|
||||
|
||||
@@ -56,5 +61,6 @@ private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : Sing
|
||||
private val IrType.isKotlinFunInterface: Boolean
|
||||
get() = getClass()?.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
|
||||
override val IrType.needEqualsHashCodeMethods get() = isKotlinFunInterface
|
||||
override val IrType.needEqualsHashCodeMethods
|
||||
get() = isKotlinFunInterface || isJavaSamConversionWithEqualsHashCode
|
||||
}
|
||||
|
||||
+7
-4
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.findInterfaceImplementation
|
||||
import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
@@ -80,6 +81,10 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
private val context: JvmBackendContext,
|
||||
private val crossinlineLambdas: Set<IrSimpleFunction>
|
||||
) {
|
||||
|
||||
private val isJavaSamConversionWithEqualsHashCode =
|
||||
context.state.languageVersionSettings.supportsFeature(LanguageFeature.JavaSamConversionEqualsHashCode)
|
||||
|
||||
/**
|
||||
* @see java.lang.invoke.LambdaMetafactory
|
||||
*/
|
||||
@@ -99,12 +104,10 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
|
||||
// Can't use JDK LambdaMetafactory for function references by default (because of 'equals').
|
||||
// TODO special mode that would generate indy everywhere?
|
||||
if (!reference.origin.isLambda && !samClass.isFromJava()) {
|
||||
if (!reference.origin.isLambda && (!samClass.isFromJava() || isJavaSamConversionWithEqualsHashCode)) {
|
||||
semanticsHazard = true
|
||||
}
|
||||
|
||||
// Don't use JDK LambdaMetafactory for serializable lambdas
|
||||
// TODO implement support for serializable lambdas with LambdaMetafactory (requires additional code for deserialization)
|
||||
if (samClass.isInheritedFromSerializable()) {
|
||||
shouldBeSerializable = true
|
||||
}
|
||||
@@ -133,7 +136,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
functionHazard = true
|
||||
}
|
||||
|
||||
// Can't use invokedynamic if the referenced function has to be inlined for correct semantics
|
||||
// Can't use invokedynamic if the referenced function has to be inlined for correct semantics.
|
||||
// Also in some cases like `private inline fun` we'd need accessors, which `SyntheticAccessorLowering`
|
||||
// won't generate under the assumption that the inline function will be inlined. Plus if the function
|
||||
// is in a different module we should probably copy it anyway (and regenerate all objects in it).
|
||||
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
// !LANGUAGE: +JavaSamConversionEqualsHashCode
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
|
||||
class F(val v: String) : () -> Unit {
|
||||
override fun invoke() {}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is F && other.v == v
|
||||
|
||||
override fun hashCode(): Int =
|
||||
v.hashCode()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val r1 = Runnable(F("abc"))
|
||||
val r2 = Runnable(F("abc"))
|
||||
|
||||
if (r1 != r2)
|
||||
return "r1 != r2"
|
||||
if (r1.hashCode() != r2.hashCode())
|
||||
return "r1.hashCode() != r2.hashCode()"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !LANGUAGE: +JavaSamConversionEqualsHashCode
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
|
||||
fun foo() {}
|
||||
|
||||
fun box(): String {
|
||||
val r1 = Runnable(::foo)
|
||||
val r2 = Runnable(::foo)
|
||||
|
||||
if (r1 != r2)
|
||||
return "r1 != r2"
|
||||
if (r1.hashCode() != r2.hashCode())
|
||||
return "r1.hashCode() != r2.hashCode()"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !LANGUAGE: +JavaSamConversionEqualsHashCode
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
|
||||
fun box(): String {
|
||||
val lambda: () -> Unit = { }
|
||||
val r1 = Runnable(lambda)
|
||||
val r2 = Runnable(lambda)
|
||||
|
||||
if (r1 != r2)
|
||||
return "r1 != r2"
|
||||
if (r1.hashCode() != r2.hashCode())
|
||||
return "r1.hashCode() != r2.hashCode()"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+10
@@ -44252,6 +44252,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/sam/equality/simpleLambdas.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+28
@@ -44774,6 +44774,34 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/sam/equality/simpleLambdas.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classImplementingFunctionInterface.kt")
|
||||
public void testClassImplementingFunctionInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/classImplementingFunctionInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionReference.kt")
|
||||
public void testFunctionReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/functionReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionalExpression.kt")
|
||||
public void testFunctionalExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode/functionalExpression.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -35755,6 +35755,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/sam/equality/simpleLambdas.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaSamWithEqualsHashCode extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/sameFileInSourceAndDependencies")
|
||||
|
||||
@@ -290,6 +290,7 @@ enum class LanguageFeature(
|
||||
ContextReceivers(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
|
||||
GenericInlineClassParameter(sinceVersion = null, defaultState = State.ENABLED_WITH_WARNING, kind = UNSTABLE_FEATURE),
|
||||
ValueClasses(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
|
||||
JavaSamConversionEqualsHashCode(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
|
||||
;
|
||||
|
||||
val presentableName: String
|
||||
|
||||
+10
@@ -32290,6 +32290,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/equality"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+10
@@ -32392,6 +32392,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/equality"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+13
@@ -26982,6 +26982,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/equality"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaSamWithEqualsHashCode extends AbstractIrCodegenBoxWasmTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/sameFileInSourceAndDependencies")
|
||||
|
||||
+12
@@ -35331,6 +35331,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/equality"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("codegen")
|
||||
@UseExtTestCaseGroupProvider()
|
||||
public class JavaSamWithEqualsHashCode {
|
||||
@Test
|
||||
public void testAllFilesPresentInJavaSamWithEqualsHashCode() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/javaSamWithEqualsHashCode"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
Reference in New Issue
Block a user