drewhamilton/Poko

Not working with Jetpack Compose

drewhamilton opened this issue · 1 comments

When a @Poko class is in a module with Compose enabled, compilation fails when trying to generate the hashCode function. The issue only exists with hashCode – so with a manual hashCode override, the plugin skips generating it, but still generates equals and toString just fine. Thus, this TODO is suspicious.

It's also been suggested that this issue may be related but I'm not sure of that.

I'd start by finding the stacktrace in the Kotlin compiler source and going from there.

See https://github.com/drewhamilton/ComposePlayground/tree/poko to reproduce.

java.lang.IllegalStateException: Symbol for public kotlin/String.hashCode|3409210261493131192[0] is unbound
	at org.jetbrains.kotlin.ir.symbols.impl.IrBindablePublicSymbolBase.getOwner(IrPublicSymbolBase.kt:45)
	at org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionPublicSymbolImpl.getOwner(IrPublicSymbolBase.kt:67)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.visitCall(LiveLiteralTransformer.kt:609)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitCall(IrElementTransformerVoid.kt:199)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitCall(IrElementTransformerVoid.kt:24)
	at org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl.accept(IrCallImpl.kt:47)
	at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:33)
	at org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl.transformChildren(IrReturnImpl.kt:41)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitExpression(IrElementTransformerVoid.kt:131)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitReturn(IrElementTransformerVoid.kt:292)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitReturn(IrElementTransformerVoid.kt:293)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitReturn(IrElementTransformerVoid.kt:24)
	at org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl.accept(IrReturnImpl.kt:34)
	at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:33)
	at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:26)
	at org.jetbrains.kotlin.ir.expressions.IrBlockBody.transformChildren(IrBody.kt:62)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBody(IrElementTransformerVoid.kt:108)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBlockBody(IrElementTransformerVoid.kt:117)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.access$visitBlockBody$s1031542550(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitBlockBody$1.invoke(LiveLiteralTransformer.kt:795)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitBlockBody$1.invoke(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.siblings(DurableKeyVisitor.kt:117)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.siblings(LiveLiteralTransformer.kt:193)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.visitBlockBody(LiveLiteralTransformer.kt:794)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBlockBody(IrElementTransformerVoid.kt:118)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBlockBody(IrElementTransformerVoid.kt:24)
	at org.jetbrains.kotlin.ir.expressions.IrBlockBody.accept(IrBody.kt:54)
	at org.jetbrains.kotlin.ir.expressions.IrBody.transform(IrBody.kt:27)
	at org.jetbrains.kotlin.ir.declarations.IrFunction.transformChildren(IrFunction.kt:71)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitDeclaration(IrElementTransformerVoid.kt:57)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitFunction(IrElementTransformerVoid.kt:69)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:72)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.access$visitSimpleFunction$s1031542550(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitSimpleFunction$1.invoke(LiveLiteralTransformer.kt:654)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitSimpleFunction$1.invoke(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.enter(DurableKeyVisitor.kt:96)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.enter(LiveLiteralTransformer.kt:191)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.visitSimpleFunction(LiveLiteralTransformer.kt:654)
	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:28)
	at org.jetbrains.kotlin.ir.IrElement$DefaultImpls.transform(IrElement.kt:32)
	at org.jetbrains.kotlin.ir.IrElementBase.transform(IrElementBase.kt:19)
	at org.jetbrains.kotlin.ir.util.TransformKt.transformInPlace(transform.kt:35)
	at org.jetbrains.kotlin.ir.declarations.IrClass.transformChildren(IrClass.kt:66)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitDeclaration(IrElementTransformerVoid.kt:57)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitClass(IrElementTransformerVoid.kt:66)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.access$visitClass$s1031542550(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitClass$1.invoke(LiveLiteralTransformer.kt:450)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitClass$1.invoke(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.siblings(DurableKeyVisitor.kt:117)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor$siblings$1.invoke(DurableKeyVisitor.kt:131)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.enter(DurableKeyVisitor.kt:96)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.siblings(DurableKeyVisitor.kt:131)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.siblings(LiveLiteralTransformer.kt:192)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.visitClass(LiveLiteralTransformer.kt:449)
	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:55)
	at org.jetbrains.kotlin.ir.IrElement$DefaultImpls.transform(IrElement.kt:32)
	at org.jetbrains.kotlin.ir.IrElementBase.transform(IrElementBase.kt:19)
	at org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl.transformChildren(IrFileImpl.kt:71)
	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.LiveLiteralTransformer.access$visitFile$s1031542550(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitFile$1.invoke(LiveLiteralTransformer.kt:496)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer$visitFile$1.invoke(LiveLiteralTransformer.kt:158)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.siblings(DurableKeyVisitor.kt:117)
	at androidx.compose.compiler.plugins.kotlin.lower.DurableKeyVisitor.root(DurableKeyVisitor.kt:152)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.visitFile(LiveLiteralTransformer.kt:463)
	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.impl.IrFileImpl.accept(IrFileImpl.kt:63)
	at org.jetbrains.kotlin.ir.declarations.IrFile.transform(IrFile.kt:48)
	at org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl.transformChildren(IrModuleFragmentImpl.kt:45)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoidKt.transformChildrenVoid(IrElementTransformerVoid.kt:330)
	at androidx.compose.compiler.plugins.kotlin.lower.LiveLiteralTransformer.lower(LiveLiteralTransformer.kt:169)
	at androidx.compose.compiler.plugins.kotlin.ComposeIrGenerationExtension.generate(ComposeIrGenerationExtension.kt:68)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory$generateModule$1.invoke(JvmIrCodegenFactory.kt:93)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory$generateModule$1.invoke(JvmIrCodegenFactory.kt:89)
	at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:91)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:106)
	at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:35)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:595)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:211)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:154)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:169)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:88)
	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.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:386)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:110)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:286)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:111)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:74)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:607)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:96)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1659)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
	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(Native Method)
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

Indeed the linked TODO looks to be the culprit. equals and toString are unaffected because they take advantage of built-in IR extensions, but hashCode must fine each property's actual hashCode function reference and call that. The returned symbol comes back unbound. It seems that the data class generator marks these symbols as substituted so that they can be bound later on (though I can't find where that happens).