diff --git a/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructedObjectsEquality.kt b/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructedObjectsEquality.kt index 0482ad21247..565a4bd542a 100644 --- a/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructedObjectsEquality.kt +++ b/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructedObjectsEquality.kt @@ -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 = ::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 = ::KSupplier -val ks12Foo = ks1(::foo) +val ks12Foo get() = ks1(::foo) val ks22Foo = ks2(::foo) \ No newline at end of file diff --git a/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt b/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt index ade4facc758..2135d1db2e6 100644 --- a/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt +++ b/compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt @@ -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) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt index f9539c157f7..c9159b37e59 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionReferenceLowering.kt @@ -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