bnorm / kotlin-power-assert

Kotlin compiler plugin to enable diagrammed function calls in the Kotlin programming language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fails to compile with K/N 1.4.10, when a message is provided to assert: java.lang.IllegalStateException: Expected IrDeclaration: BLOCK type=kotlin.Any origin=null

opened this issue · comments

 * Compiler version info: Konan: 1.4.10 / Kotlin: 1.4.10
 * Output kind: LIBRARY
e: java.lang.IllegalStateException: Expected IrDeclaration: BLOCK type=kotlin.Any origin=null
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrSymbol(IrFileSerializer.kt:287)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeReturn(IrFileSerializer.kt:664)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:935)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:968)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeBlock(IrFileSerializer.kt:445)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:914)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStringConcat(IrFileSerializer.kt:470)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:938)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeReturn(IrFileSerializer.kt:665)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:935)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:968)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeBlockBody(IrFileSerializer.kt:425)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:971)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrStatementBody(IrFileSerializer.kt:162)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrFunctionBase(IrFileSerializer.kt:1043)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrFunction(IrFileSerializer.kt:1055)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeFunctionExpression(IrFileSerializer.kt:530)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:925)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeMemberAccessCommon(IrFileSerializer.kt:501)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeCall(IrFileSerializer.kt:516)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:917)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeBranch(IrFileSerializer.kt:434)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:974)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeWhen(IrFileSerializer.kt:784)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:943)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:968)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeBlock(IrFileSerializer.kt:445)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeExpression(IrFileSerializer.kt:914)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:968)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeBlockBody(IrFileSerializer.kt:425)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeStatement(IrFileSerializer.kt:971)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrStatementBody(IrFileSerializer.kt:162)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrFunctionBase(IrFileSerializer.kt:1043)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrFunction(IrFileSerializer.kt:1055)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeDeclaration(IrFileSerializer.kt:1181)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrClass(IrFileSerializer.kt:1125)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeDeclaration(IrFileSerializer.kt:1189)
	at org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer.serializeIrFile(IrFileSerializer.kt:1240)
	at org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer.serializeIrFile(IrModuleSerializer.kt:28)
	at org.jetbrains.kotlin.backend.common.serialization.IrModuleSerializer.serializedIrModule(IrModuleSerializer.kt:35)
	at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$serializerPhase$1.invoke(ToplevelPhases.kt:314)
	at org.jetbrains.kotlin.backend.konan.ToplevelPhasesKt$serializerPhase$1.invoke(ToplevelPhases.kt)
	at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:149)
	at org.jetbrains.kotlin.backend.common.phaser.PhaseBuildersKt$namedOpUnitPhase$1.invoke(PhaseBuilders.kt:147)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper$runBody$1.invoke(CompilerPhase.kt:128)
	at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.downlevel(CompilerPhase.kt:24)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.runBody(CompilerPhase.kt:127)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.invoke(CompilerPhase.kt:105)
	at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:30)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper$runBody$1.invoke(CompilerPhase.kt:128)
	at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.downlevel(CompilerPhase.kt:24)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.runBody(CompilerPhase.kt:127)
	at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.invoke(CompilerPhase.kt:105)
	at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:42)
	at org.jetbrains.kotlin.backend.konan.KonanDriverKt.runTopLevelPhases(KonanDriver.kt:28)
	at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:78)
	at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:35)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:86)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:76)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:45)
	at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:227)
	at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:276)
	at org.jetbrains.kotlin.cli.bc.K2Native$Companion$mainNoExitWithGradleRenderer$1.invoke(K2Native.kt:260)
	at org.jetbrains.kotlin.util.UtilKt.profileIf(Util.kt:27)
	at org.jetbrains.kotlin.util.UtilKt.profile(Util.kt:21)
	at org.jetbrains.kotlin.cli.bc.K2Native$Companion.mainNoExitWithGradleRenderer(K2Native.kt:275)
	at org.jetbrains.kotlin.cli.bc.K2NativeKt.mainNoExitWithGradleRenderer(K2Native.kt:427)
	at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1.invoke(main.kt:39)
	at org.jetbrains.kotlin.cli.utilities.MainKt$daemonMain$1.invoke(main.kt)
	at org.jetbrains.kotlin.cli.utilities.MainKt.mainImpl(main.kt:17)
	at org.jetbrains.kotlin.cli.utilities.MainKt.daemonMain(main.kt:39)

Local testing with Kotlin/Native 1.4.10 does not reveal anything like this error. This stacktrace also doesn't show any problems specific to this plugin, and while that's not unusual, it doesn't help me track down what the problem could be. Do you have sample code which you know is causing this error?

import kotlin.random.Random

public fun test() {
    val r = Random.Default.nextInt()
    assert(r != 343423) { "abc" }
}

Ignore the random code, was just trying weird things with with due to the original stacktrace. However, if I remove the { "abc" }, it compiles fine.

This reliably reproduces the bug with org.jetbrains.kotlin.multiplatform 1.4.10 and com.bnorm.power.kotlin-power-assert 0.5.1 with a linuxX64 source set.

Thank you so much for the sample code! With it I was able to reproduce the problem. No idea what's wrong yet but it also occurs with 1.4.0 and on Windows.

Wow, this was a tough one. Thankfully it fails on Kotlin/JS as well so I was able to debug and step through the IR phases to figure out what the JS compiler does when inlining a function.

TL;DR: a fix has been added and will be released soon.

For those that want to dig into the details:

On Kotlin/JS, this fails only during the creation of the KLib. When creating the KLib, none of the IR lowering phases are executed since I suspect it is only concerned about compiler plugins generating code. However, my compiler transforms code, and does so into a form which the KLib serializer did not like.

Specifically, the part of the code which the serializer does not like is the result of inlining the assert function lambda. I'm was using a built-in function for performing this inline which I found via the AssertionLowering class in the Kotlin compiler. This is a JVM specific lowering but the IrFunction.inline(IrDeclarationParent, List<IrValueDeclaration>): IrReturnableBlock function it uses is available in the common IR backend package. For JVM, this function works, but for JS and Native, the returned IrReturnableBlock is insufficient.

Kotlin/JS and Kotlin/Native use the class FunctionInlining to performing the function inline phase but there is a later phase which uses the class ReturnableBlockTransformer to reduce the IrReturnableBlock generated by the inlining. When I copied this transformer and called it after inlining the assertion function, Kotlin/JS and Kotlin/Native were both happy with the result.

I planning to open a bug against the compiler to see if this inline function provided can be improved or a sibling function can be created for performing inlining like this along with the lowering of the returnable block.

Fixed in version 0.5.2 which is now available.

Please ref that issue here if you open it.