[K/N] Fix equality on fun-interface constructor references
^KT-50204
This commit is contained in:
+4
-6
@@ -6,20 +6,18 @@
|
|||||||
// IGNORE_BACKEND: WASM
|
// IGNORE_BACKEND: WASM
|
||||||
// ^ wasm-function[1893]:0x1cf8a: RuntimeError: dereferencing a null pointer
|
// ^ wasm-function[1893]:0x1cf8a: RuntimeError: dereferencing a null pointer
|
||||||
|
|
||||||
// IGNORE_BACKEND: NATIVE
|
|
||||||
// ^ Fail due to the initialization order. Doesn't fail with new MM
|
|
||||||
|
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_BACKEND: JS_IR
|
// IGNORE_BACKEND: JS_IR
|
||||||
// ^ TypeError: tmp is not a function
|
// ^ TypeError: tmp is not a function
|
||||||
|
|
||||||
// FILE: funInterfaceConstructorEquality.kt
|
// FILE: funInterfaceConstructedObjectsEquality.kt
|
||||||
|
|
||||||
val ks1: (() -> String) -> KSupplier<String> =
|
val ks1: (() -> String) -> KSupplier<String> =
|
||||||
::KSupplier
|
::KSupplier
|
||||||
|
|
||||||
val ks11Foo = ks1(::foo)
|
val ks11Foo = ks1(::foo)
|
||||||
val ks21Foo = ks2(::foo)
|
// getter is used to avoid dependency on lazy initialization support
|
||||||
|
val ks21Foo get() = ks2(::foo)
|
||||||
|
|
||||||
fun interface KStringSupplier {
|
fun interface KStringSupplier {
|
||||||
fun get(): String
|
fun get(): String
|
||||||
@@ -71,5 +69,5 @@ fun bar() = "def"
|
|||||||
val ks2: (() -> String) -> KSupplier<String> =
|
val ks2: (() -> String) -> KSupplier<String> =
|
||||||
::KSupplier
|
::KSupplier
|
||||||
|
|
||||||
val ks12Foo = ks1(::foo)
|
val ks12Foo get() = ks1(::foo)
|
||||||
val ks22Foo = ks2(::foo)
|
val ks22Foo = ks2(::foo)
|
||||||
-3
@@ -6,9 +6,6 @@
|
|||||||
// IGNORE_BACKEND: WASM
|
// IGNORE_BACKEND: WASM
|
||||||
// ^ Failed: ks1 != ks2 (same file, same SAM type)
|
// ^ Failed: ks1 != ks2 (same file, same SAM type)
|
||||||
|
|
||||||
// IGNORE_BACKEND: NATIVE
|
|
||||||
// ^ Fail due to the initialization order. Doesn't fail with new MM
|
|
||||||
|
|
||||||
// IGNORE_BACKEND: JS
|
// IGNORE_BACKEND: JS
|
||||||
// IGNORE_BACKEND: JS_IR
|
// IGNORE_BACKEND: JS_IR
|
||||||
// ^ Failed: ks1 != ks2 (same file, same SAM type)
|
// ^ Failed: ks1 != ks2 (same file, same SAM type)
|
||||||
|
|||||||
+18
-13
@@ -318,7 +318,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val name = ((functionReferenceTarget as? IrSimpleFunction)?.attributeOwnerId as? IrSimpleFunction)?.name
|
val name = ((functionReferenceTarget as? IrSimpleFunction)?.attributeOwnerId as? IrSimpleFunction)?.name
|
||||||
?: functionReferenceTarget.name
|
?: functionReferenceTarget.name
|
||||||
addOverride("computeName") { irString(name.asString()) }
|
addOverride("computeName") { irString(name.asString()) }
|
||||||
addOverride("computeFqName") { irString(functionReferenceTarget.computeFullName()) }
|
addOverride("computeFqName") { irString(getFqName()) }
|
||||||
|
|
||||||
|
|
||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
@@ -390,22 +390,27 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
return BuiltFunctionReference(clazz, expression)
|
return BuiltFunctionReference(clazz, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this value is used only for hashCode and equals, to distinguish different wrappers on same functions
|
||||||
private fun getFlags() =
|
private fun getFlags() =
|
||||||
(if (referencedFunction.isSuspend) 1 else 0) + getAdaptedCallableReferenceFlags() shl 1
|
listOfNotNull(
|
||||||
|
(1 shl 0).takeIf { referencedFunction.isSuspend },
|
||||||
|
(1 shl 1).takeIf { hasVarargMappedToElement() },
|
||||||
|
(1 shl 2).takeIf { adaptedReferenceOriginalTarget?.isSuspend == false && referencedFunction.isSuspend },
|
||||||
|
(1 shl 3).takeIf { isCoercedToUnit() },
|
||||||
|
(1 shl 4).takeIf { isFunInterfaceConstructorAdapter() }
|
||||||
|
).sum()
|
||||||
|
|
||||||
private fun getAdaptedCallableReferenceFlags(): Int {
|
private fun getFqName() =
|
||||||
if (adaptedReferenceOriginalTarget == null) return 0
|
if (isFunInterfaceConstructorAdapter())
|
||||||
|
referencedFunction.returnType.getClass()!!.fqNameForIrSerialization.toString()
|
||||||
|
else
|
||||||
|
functionReferenceTarget.computeFullName()
|
||||||
|
|
||||||
val isVarargMappedToElementBit = if (hasVarargMappedToElement()) 1 else 0
|
private fun isFunInterfaceConstructorAdapter() =
|
||||||
val isSuspendConvertedBit =
|
referencedFunction.origin == IrDeclarationOrigin.ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR
|
||||||
if (!adaptedReferenceOriginalTarget.isSuspend && referencedFunction.isSuspend) 1 else 0
|
|
||||||
val isCoercedToUnitBit =
|
|
||||||
if (!adaptedReferenceOriginalTarget.returnType.isUnit() && referencedFunction.returnType.isUnit()) 1 else 0
|
|
||||||
|
|
||||||
return isVarargMappedToElementBit +
|
private fun isCoercedToUnit() =
|
||||||
(isSuspendConvertedBit shl 1) +
|
adaptedReferenceOriginalTarget?.returnType?.isUnit() == true && referencedFunction.returnType.isUnit()
|
||||||
(isCoercedToUnitBit shl 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasVarargMappedToElement(): Boolean {
|
private fun hasVarargMappedToElement(): Boolean {
|
||||||
if (adaptedReferenceOriginalTarget == null) return false
|
if (adaptedReferenceOriginalTarget == null) return false
|
||||||
|
|||||||
Reference in New Issue
Block a user