Kotlin-native: Assertion failed on compilation to iOS framework with coroutines native

Created on 3 Oct 2018  路  7Comments  路  Source: JetBrains/kotlin-native

Hi,
Got exception when trying to compile FRAMEWORK for iOS.
Not sure why, but seems like it fails in coroutines when exporting class "kotlinx/coroutines/Deferred"

Don't know is it a bug or coroutines cannot be exported/used for iOS? Followed: #246

Attached konanc to debugger and find out that assertion fails when "descriptor" is

descriptor = {DeserializedClassDescriptor@9402} "deserialized class ChildHandle"
 classId = {ClassId@9438} "kotlinx/coroutines/ChildHandle"
 modality = {Modality@9439} "ABSTRACT"
 visibility = {Visibilities$4@9440} "internal"
 kind = {ClassKind@9441} "INTERFACE"
 c = {DeserializationContext@9442} 
  typeDeserializer = {TypeDeserializer@11130} "Deserializer for ChildHandle. Child of Deserializer for coroutines"
  memberDeserializer = {MemberDeserializer@11131} 

more deeper level, on getSuperProtocols:330: ObjCExportHeaderGeneratorImpl:

$receiver = {DeserializedClassDescriptor@10530} "deserialized class Deferred"
 classId = {ClassId@11338} "kotlinx/coroutines/Deferred"
 modality = {Modality@9439} "ABSTRACT"
 visibility = {Visibilities$5@10093} "public"
 kind = {ClassKind@9441} "INTERFACE"

and translateInterface:314, ObjCExportHeaderGeneratorImpl:

descriptor = {DeserializedClassDescriptor@10530} "deserialized class Deferred"
name = {ObjCExportNamer$ClassOrProtocolName@11332} "ClassOrProtocolName(swiftName=Kotlinx_coroutines_core_nativeDeferred, objCName=IosKotlinx_coroutines_core_nativeDeferred, binaryName=IosKotlinx_coroutines_core_nativeDeferred)"
 swiftName = "Kotlinx_coroutines_core_nativeDeferred"
 objCName = "IosKotlinx_coroutines_core_nativeDeferred"
 binaryName = "IosKotlinx_coroutines_core_nativeDeferred"

Versions:

    ext.kotlin_version = '1.3.0-rc-131'
    ext.serialization_version = '0.8.1-rc13'
    ext.coroutines_version = '0.30.1-eap13'
    ext.kotlin_native_version = '0.9.3'

Stacktrace:

exception: java.lang.AssertionError: Assertion failed
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateClassName(ObjCExportHeaderGenerator.kt:303)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.mapReferenceTypeIgnoringNullability$backend_native_compiler(ObjCExportHeaderGenerator.kt:855)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.mapReferenceType$backend_native_compiler(ObjCExportHeaderGenerator.kt:797)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.mapType(ObjCExportHeaderGenerator.kt:892)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.mapReturnType(ObjCExportHeaderGenerator.kt:754)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.buildMethod(ObjCExportHeaderGenerator.kt:687)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translatePlainMembers(ObjCExportHeaderGenerator.kt:547)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateBaseMembers(ObjCExportHeaderGenerator.kt:534)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateInterfaceMembers(ObjCExportHeaderGenerator.kt:465)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateInterface(ObjCExportHeaderGenerator.kt:313)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.access$translateInterface(ObjCExportHeaderGenerator.kt:26)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator$superProtocols$2.invoke(ObjCExportHeaderGenerator.kt:327)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator$superProtocols$2.invoke(ObjCExportHeaderGenerator.kt:26)
    at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:174)
    at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:685)
    at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:715)
    at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:706)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.getSuperProtocols(ObjCExportHeaderGenerator.kt:330)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateInterface(ObjCExportHeaderGenerator.kt:314)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportHeaderGenerator.translateModule(ObjCExportHeaderGenerator.kt:234)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport.produceFrameworkSpecific(ObjCExport.kt:68)
    at org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport.produce$backend_native_compiler(ObjCExport.kt:41)
    at org.jetbrains.kotlin.backend.konan.llvm.CodeGeneratorVisitor.visitModuleFragment(IrToBitcode.kt:382)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitModuleFragment(IrElementVisitorVoid.kt:28)
    at org.jetbrains.kotlin.backend.konan.llvm.CodeGeneratorVisitor.visitModuleFragment(IrToBitcode.kt:291)
    at org.jetbrains.kotlin.backend.konan.llvm.CodeGeneratorVisitor.visitModuleFragment(IrToBitcode.kt:291)

maybe related to #2120

Most helpful comment

Hi @brettwillis ,
by trial and error just found out how to do it.
Here is Instructions for intellj on mac (but should be similar):
1) add debug configuration. Run -> Debug... -> Edit configuration.. -> add Remote
Debugger mode: listen to remote JVM.
2) try to build your project with ./gradlew build --info and search for "konanc" compile options (should begin with -o src.kt src2.kt src_n.kt ...)
3) create a bash script "test_compiler.sh", don't forget chmod 755 test_compiler.sh

#!/bin/bash
export JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=y"
~/.konan/kotlin-native-macos-0.9.3/bin/konanc -o <put here your konanc arguments from step 2>

4) run your debug created in step 1 in intellij
5) in debug toolbar there are an icon where you can see all breakpoints, from there you can add breakpoints on exceptions just add exception you want to hit a breakpoint (my was java.lang.AssertionError)
5) run "./test_compiler.sh"
6) you should be breakpointed now

I've done this without actual source code of konan by just looking at github sources and stepped over stacktrace and watched variables.
I think this will be enough to find out what's going on, but for full debugging firstly there is a need to checkout full source code of compiler and creating intellj project for it.

All 7 comments

After more investigation it looks like it tries to generate "Deferred" class to iOS which is a subclass of "Job". And that Job contains a method "public fun attachChild(child: ChildJob): ChildHandle", but "ChildHandle" is "internal interface ChildHandle" and it's why shouldBeExposed() throws error.

Indeed it looks like a problematic code in kotlinx.coroutines, let's discuss how to fix it.

Strangely is that is unable to compile such code which public members contains internal arguments or return type. How coroutines when was compiled? Some extra compiler options? Maybe kotlin native could have some annotation to enable exporting internal api and coroutines internal could be marked as @ExportedInternal or something else.

I can't get my iOS framework to compile after migrating to the kotlin-multiplatform plugin, because of this very same error. I've tried coroutines versions 0.27.0~0.30.2. I'm also using kotlinx.serialization and kotlinx.atomicfu.

After checking, I don't have any internal/exposed unaccessible classes in my code.

@antanas-arvasevicius, how did you attach konanc to a debugger (or which debugger, I'm a bit of a noob at debugging a compiler)? I wish to give this a try because I can't figure out what's wrong not matter what I try.

Hi @brettwillis ,
by trial and error just found out how to do it.
Here is Instructions for intellj on mac (but should be similar):
1) add debug configuration. Run -> Debug... -> Edit configuration.. -> add Remote
Debugger mode: listen to remote JVM.
2) try to build your project with ./gradlew build --info and search for "konanc" compile options (should begin with -o src.kt src2.kt src_n.kt ...)
3) create a bash script "test_compiler.sh", don't forget chmod 755 test_compiler.sh

#!/bin/bash
export JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=y"
~/.konan/kotlin-native-macos-0.9.3/bin/konanc -o <put here your konanc arguments from step 2>

4) run your debug created in step 1 in intellij
5) in debug toolbar there are an icon where you can see all breakpoints, from there you can add breakpoints on exceptions just add exception you want to hit a breakpoint (my was java.lang.AssertionError)
5) run "./test_compiler.sh"
6) you should be breakpointed now

I've done this without actual source code of konan by just looking at github sources and stepped over stacktrace and watched variables.
I think this will be enough to find out what's going on, but for full debugging firstly there is a need to checkout full source code of compiler and creating intellj project for it.

Is this issue still reproducible?

No, everything is working fine with coroutines 1.0.0+

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brettwillis picture brettwillis  路  4Comments

benasher44 picture benasher44  路  4Comments

Cortlandd picture Cortlandd  路  4Comments

nvlizlo picture nvlizlo  路  4Comments

barsan-md picture barsan-md  路  4Comments