[K/N] Fix equality on fun-interface constructor references

^KT-50204
This commit is contained in:
Pavel Kunyavskiy
2022-01-11 15:36:50 +03:00
committed by Space
parent a378e1e128
commit afc548d5d9
3 changed files with 22 additions and 22 deletions
@@ -6,20 +6,18 @@
// IGNORE_BACKEND: WASM
// ^ 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_IR
// ^ TypeError: tmp is not a function
// FILE: funInterfaceConstructorEquality.kt
// FILE: funInterfaceConstructedObjectsEquality.kt
val ks1: (() -> String) -> KSupplier<String> =
::KSupplier
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 get(): String
@@ -71,5 +69,5 @@ fun bar() = "def"
val ks2: (() -> String) -> KSupplier<String> =
::KSupplier
val ks12Foo = ks1(::foo)
val ks12Foo get() = ks1(::foo)
val ks22Foo = ks2(::foo)
@@ -6,9 +6,6 @@
// IGNORE_BACKEND: WASM
// ^ 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_IR
// ^ Failed: ks1 != ks2 (same file, same SAM type)
@@ -318,7 +318,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
val name = ((functionReferenceTarget as? IrSimpleFunction)?.attributeOwnerId as? IrSimpleFunction)?.name
?: functionReferenceTarget.name
addOverride("computeName") { irString(name.asString()) }
addOverride("computeFqName") { irString(functionReferenceTarget.computeFullName()) }
addOverride("computeFqName") { irString(getFqName()) }
listOfNotNull(
@@ -390,22 +390,27 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
return BuiltFunctionReference(clazz, expression)
}
// this value is used only for hashCode and equals, to distinguish different wrappers on same functions
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 {
if (adaptedReferenceOriginalTarget == null) return 0
private fun getFqName() =
if (isFunInterfaceConstructorAdapter())
referencedFunction.returnType.getClass()!!.fqNameForIrSerialization.toString()
else
functionReferenceTarget.computeFullName()
val isVarargMappedToElementBit = if (hasVarargMappedToElement()) 1 else 0
val isSuspendConvertedBit =
if (!adaptedReferenceOriginalTarget.isSuspend && referencedFunction.isSuspend) 1 else 0
val isCoercedToUnitBit =
if (!adaptedReferenceOriginalTarget.returnType.isUnit() && referencedFunction.returnType.isUnit()) 1 else 0
private fun isFunInterfaceConstructorAdapter() =
referencedFunction.origin == IrDeclarationOrigin.ADAPTER_FOR_FUN_INTERFACE_CONSTRUCTOR
return isVarargMappedToElementBit +
(isSuspendConvertedBit shl 1) +
(isCoercedToUnitBit shl 2)
}
private fun isCoercedToUnit() =
adaptedReferenceOriginalTarget?.returnType?.isUnit() == true && referencedFunction.returnType.isUnit()
private fun hasVarargMappedToElement(): Boolean {
if (adaptedReferenceOriginalTarget == null) return false