JVM IR: fix generation of equals/hashCode for fun interfaces over references
... in case `-Xno-optimized-callable-references` is enabled. Before this change, the generated abstract equals/hashCode methods were considered as accidental overrides because they did not have equals/hashCode from the supertype in the overriddenSymbols list. #KT-43666 Fixed
This commit is contained in:
Generated
+5
@@ -12194,6 +12194,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
+12
-2
@@ -245,7 +245,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
|
||||
if (!useOptimizedSuperClass) {
|
||||
// This is the case of a fun interface wrapper over a (maybe adapted) function reference,
|
||||
// with `-Xno-optimized-callable-referenced` enabled. We can't use constructors of FunctionReferenceImpl,
|
||||
// with `-Xno-optimized-callable-references` enabled. We can't use constructors of FunctionReferenceImpl,
|
||||
// so we'd need to basically generate a full class for a reference inheriting from FunctionReference,
|
||||
// effectively disabling the optimization of fun interface wrappers over references.
|
||||
// This scenario is probably not very popular because it involves using equals/hashCode on function references
|
||||
@@ -254,8 +254,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
// TODO: generate getFunctionDelegate, equals and hashCode properly in this case
|
||||
functionReferenceClass.addFunction("equals", backendContext.irBuiltIns.booleanType, Modality.ABSTRACT).apply {
|
||||
addValueParameter("other", backendContext.irBuiltIns.anyNType)
|
||||
overriddenSymbols = listOf(functionSuperClass.functions.single { isEqualsFromAny(it.owner) })
|
||||
}
|
||||
functionReferenceClass.addFunction("hashCode", backendContext.irBuiltIns.intType, Modality.ABSTRACT).apply {
|
||||
overriddenSymbols = listOf(functionSuperClass.functions.single { isHashCodeFromAny(it.owner) })
|
||||
}
|
||||
functionReferenceClass.addFunction("hashCode", backendContext.irBuiltIns.intType, Modality.ABSTRACT)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -274,6 +277,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}.generate()
|
||||
}
|
||||
|
||||
private fun isEqualsFromAny(f: IrSimpleFunction): Boolean =
|
||||
f.name.asString() == "equals" && f.extensionReceiverParameter == null &&
|
||||
f.valueParameters.singleOrNull()?.type?.isNullableAny() == true
|
||||
|
||||
private fun isHashCodeFromAny(f: IrSimpleFunction): Boolean =
|
||||
f.name.asString() == "hashCode" && f.extensionReceiverParameter == null && f.valueParameters.isEmpty()
|
||||
|
||||
private fun createConstructor(): IrConstructor =
|
||||
functionReferenceClass.addConstructor {
|
||||
origin = JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_OPTIMIZED_CALLABLE_REFERENCES
|
||||
|
||||
fun interface P {
|
||||
fun get(): String
|
||||
}
|
||||
|
||||
class G(val p: P)
|
||||
|
||||
fun f(): String = "OK"
|
||||
|
||||
fun box(): String = G(::f).p.get()
|
||||
+5
@@ -13594,6 +13594,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
+5
@@ -13594,6 +13594,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
+5
@@ -12194,6 +12194,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
Generated
+5
@@ -10434,6 +10434,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
Generated
+5
@@ -10434,6 +10434,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
Generated
+5
@@ -10434,6 +10434,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonAbstractMethod.kt")
|
||||
public void testNonAbstractMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/nonAbstractMethod.kt");
|
||||
|
||||
Generated
+5
@@ -5214,6 +5214,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/funInterface/funConversionInVararg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOptimizedCallableReferences.kt")
|
||||
public void testNoOptimizedCallableReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/noOptimizedCallableReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("partialSam.kt")
|
||||
public void testPartialSam() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||
|
||||
Reference in New Issue
Block a user