JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.01k stars 1.17k forks source link

JS/IR - Assertion Failure compiling JS with BlendMode in Composable #3094

Closed ahmedre closed 1 year ago

ahmedre commented 1 year ago

Describe the bug On Kotlin 1.8.20, if I add this to my code:

  @Composable
  fun Test(blendMode: BlendMode = BlendMode.SrcIn) {
      blendMode
  }

It fails to compile on JS/IR with the following exception:

kotlin version: 1.8.20
error message: java.lang.AssertionError: Assertion failed
    at org.jetbrains.kotlin.ir.util.AdditionalIrUtilsKt.getPropertyGetter(AdditionalIrUtils.kt:267)
    at androidx.compose.compiler.plugins.kotlin.lower.AbstractComposeLowering.unboxValueIfInline(AbstractComposeLowering.kt:268)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.irChanged(ComposableFunctionBodyTransformer.kt:2141)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.buildPreambleStatementsAndReturnIfSkippingPossible(ComposableFunctionBodyTransformer.kt:1494)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.visitRestartableComposableFunction(ComposableFunctionBodyTransformer.kt:1189)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.visitFunctionInScope(ComposableFunctionBodyTransformer.kt:770)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.visitFunction(ComposableFunctionBodyTransformer.kt:736)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:72)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:73)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:24)
    at org.jetbrains.kotlin.ir.declarations.IrSimpleFunction.accept(IrSimpleFunction.kt:36)
    at org.jetbrains.kotlin.ir.IrElementBase.transform(IrElementBase.kt:24)
    at org.jetbrains.kotlin.ir.util.TransformKt.transformInPlace(transform.kt:35)
    at org.jetbrains.kotlin.ir.declarations.IrClass.transformChildren(IrClass.kt:74)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitDeclaration(IrElementTransformerVoid.kt:57)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.visitClass(ComposableFunctionBodyTransformer.kt:729)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitClass(IrElementTransformerVoid.kt:67)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitClass(IrElementTransformerVoid.kt:24)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.IrElementBase.transform(IrElementBase.kt:24)
    at org.jetbrains.kotlin.ir.util.TransformKt.transformInPlace(transform.kt:35)
    at org.jetbrains.kotlin.ir.declarations.IrFile.transformChildren(IrFile.kt:40)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitPackageFragment(IrElementTransformerVoid.kt:41)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitFile(IrElementTransformerVoid.kt:47)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.visitFile(ComposableFunctionBodyTransformer.kt:1878)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitFile(IrElementTransformerVoid.kt:48)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitFile(IrElementTransformerVoid.kt:24)
    at org.jetbrains.kotlin.ir.declarations.IrFile.accept(IrFile.kt:30)
    at org.jetbrains.kotlin.ir.declarations.IrFile.transform(IrFile.kt:33)
    at org.jetbrains.kotlin.ir.declarations.IrFile.transform(IrFile.kt:21)
    at org.jetbrains.kotlin.ir.util.TransformKt.transformInPlace(transform.kt:35)
    at org.jetbrains.kotlin.ir.declarations.IrModuleFragment.transformChildren(IrModuleFragment.kt:51)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoidKt.transformChildrenVoid(IrElementTransformerVoid.kt:346)
    at androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer.lower(ComposableFunctionBodyTransformer.kt:480)
    at androidx.compose.compiler.plugins.kotlin.ComposeIrGenerationExtension.generate(ComposeIrGenerationExtension.kt:171)
    at org.jetbrains.kotlin.ir.backend.js.KlibKt.generateModuleFragmentWithPlugins$lambda$16(klib.kt:425)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:107)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment$default(Psi2IrTranslator.kt:84)
    at org.jetbrains.kotlin.ir.backend.js.KlibKt.generateModuleFragmentWithPlugins(klib.kt:434)
    at org.jetbrains.kotlin.cli.js.klib.IrForKlibKt.generateIrForKlibSerialization(irForKlib.kt:94)
    at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.processSourceModule(K2JsIrCompiler.kt:454)
    at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.doExecute(K2JsIrCompiler.kt:295)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:180)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:72)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:100)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:46)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:213)
    at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:84)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:486)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:409)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:290)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:112)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile$default(IncrementalCompilerRunner.kt:94)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execJsIncrementalCompiler(CompileServiceImpl.kt:567)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execJsIncrementalCompiler(CompileServiceImpl.kt:101)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1678)
    at jdk.internal.reflect.GeneratedMethodAccessor107.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)

Note that if you remove the usage of blendMode in this case, it compiles fine. The code works fine on desktop and Android. This might be related to the fact that BlendMode is a value class that is provided by Compose libraries? Also note that "wrapping" blend mode fixes it (even switching the parameter to a nullable, for example).

Previously filed on YouTrack but was asked to file here instead.

Affected platforms Select one of the platforms below:

Versions

eymar commented 1 year ago

Hi @ahmedre ! I didn't manage to reproduce the error.

I use the following snippet:

fun main() {
    onWasmReady {
        Window("Test") {
            Test()
        }
    }
}

 @Composable
 fun Test(blendMode: BlendMode = BlendMode.SrcIn) {
     println(blendMode)
 }

When I run it, it prints SrcIn in the brower console.

I guess, there could be something in the project setup. Do you apply id("org.jetbrains.compose") plugin? Do you override the compose compiler plugin version or artefact by chance? JFYI: the Jetpack Compose compiler plugin doesn't support k/js and k/native, so Compose Multiplatform compiler plugin has to be used.

If you can share the project where the issue is reproducible, we can try to find out the cause.

ahmedre commented 1 year ago

Thanks, really appreciate it - while preparing a minimal repro for this, I found the issue - we had some code like:

  kotlinCompilerPlugin.set(libs.androidx.compose.compiler.map { it.toString() })

in our Gradle configs that forced the usage of the non-multiplatform Compose compiler instead of the Compose Multiplatform compiler itself. Removing that version override fixes the problem.

okushnikov commented 1 month ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.