I'm getting this after upgrading our project to Ko...
# k2-adopters
a
I'm getting this after upgrading our project to Kotlin 2.1.21 and building:
Copy code
java.lang.IllegalArgumentException: Only componentN functions should be cached this way, but got: hashCode
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.cacheIrFunctionSymbol(Fir2IrDeclarationStorage.kt:426)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol(Fir2IrDeclarationStorage.kt:1133)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol$default(Fir2IrDeclarationStorage.kt:1101)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator$MyDataClassMethodsGenerator$irDataClassMembersGenerator$1.getHashCodeFunctionInfo(Fir2IrDataClassMembersGenerator.kt:362)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator.getHashCodeOf(DataClassMembersGenerator.kt:282)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.getHashCodeOfProperty(DataClassMembersGenerator.kt:229)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.generateHashCodeMethodBody(DataClassMembersGenerator.kt:211)
	at org.jetbrains.kotlin.ir.util.IrBasedDataClassMembersGenerator.generateHashCodeMethod(DataClassMembersGenerator.kt:367)
I only found this issue where someone had a similar issue, but they get it by using the IJ debugger and evaluating an expression: KT-70376 K2 IDE / Kotlin Debugger: IAE “Only componentN functions should be cached this way, but got: toString” on evaluating toString() method for value class I tried a variety of versions from 2.0.x to 2.2.0-RC giving me the same error. Is there any way to figure out which code this exception refers to? Maybe that will make it possible to create a minimal reproducer
a
Could you please provide the whole trace? Thanks
d
Do you have some compiler plugins enabled, like Kopy?
a
Here is the full trace:
Copy code
java.lang.IllegalArgumentException: Only componentN functions should be cached this way, but got: hashCode
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.cacheIrFunctionSymbol(Fir2IrDeclarationStorage.kt:426)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol(Fir2IrDeclarationStorage.kt:1133)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol$default(Fir2IrDeclarationStorage.kt:1101)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator$MyDataClassMethodsGenerator$irDataClassMembersGenerator$1.getHashCodeFunctionInfo(Fir2IrDataClassMembersGenerator.kt:362)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator.getHashCodeOf(DataClassMembersGenerator.kt:282)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.getHashCodeOfProperty(DataClassMembersGenerator.kt:229)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.generateHashCodeMethodBody(DataClassMembersGenerator.kt:211)
	at org.jetbrains.kotlin.ir.util.IrBasedDataClassMembersGenerator.generateHashCodeMethod(DataClassMembersGenerator.kt:367)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator$MyDataClassMethodsGenerator.generateBodies(Fir2IrDataClassMembersGenerator.kt:248)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator.generateBodiesForClassesWithSyntheticDataClassMembers(Fir2IrDataClassMembersGenerator.kt:228)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.generateSyntheticBodiesOfDataValueMembers(convertToIr.kt:267)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.runActualizationPipeline(convertToIr.kt:205)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.convertToIrAndActualize(convertToIr.kt:130)
	at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize(convertToIr.kt:100)
	at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize$default(convertToIr.kt:75)
	at org.jetbrains.kotlin.cli.jvm.compiler.legacy.pipeline.JvmCompilerPipelineKt.convertToIrAndActualizeForJvm(jvmCompilerPipeline.kt:108)
	at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:26)
	at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:17)
	at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:68)
	at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:58)
	at org.jetbrains.kotlin.config.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:215)
	at org.jetbrains.kotlin.config.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:111)
	at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:28)
	at org.jetbrains.kotlin.config.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62)
	at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.runPhasedPipeline(AbstractCliPipeline.kt:106)
	at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.execute(AbstractCliPipeline.kt:65)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:61)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:36)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:80)
	at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.kt:337)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:466)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:75)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:514)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:431)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:310)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:137)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:678)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1805)
	at jdk.internal.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	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(AccessController.java:691)
	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:391)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)
Only compiler plugin used is the kotlinx-serialization one. I can try to bump it and see if I get a different result (current version used is 1.6.10)
Actually that's quite weird, I guess the serialization compiler plugin should follow the Kotlin version. Let me check
d
1.6.10
is a version of
kotlinx-serialization
library. The plugin version is alligned. Could you please report an issue with this stacktrace and maybe some reproducer? This is definitely a compiler bug
a
Yeah, for some reason we were running with the serialization plugin at 1.6.10 even when we ran Kotlin 1.9.20 (whereas the library version was 1.3.2) Anyway, bumping it didn't work, but at least it's aligned with the Kotlin version now. I'm at a bit of a loss with creating a reproducer. Is there any way to dig more information out about the exact lines it fails on?
d
Well, it fails on some data class. Unfortunately there is not much of other information in this particular error, so there I see only two possible ways: 1. Comment out some data classes in the code (or maybe comment just the
data
modifier), but it's kinda tedious 2. Debug the compiler itself on your project, but it's something too complicated to ask you to do. I can assist with it, but I'll understand if you'll discard this option
Does it happen on clean build? Or only on incremental builds?
a
Both. I'm digging around a bit more. Already tried removing data modifiers in a bunch of classes where we called hashCode on, but no luck so far. Will get back to you and create an issue
d
One hint I found, that it's a data class which contains some other (or the same) data class as parameter.
👀 1
It also could be a
value
class (they are processed similarly to
data
classes for
equals/hashCode/toString
methods)
WDYT if I publish a custom build of the compiler with more detailed error description and you try to run it on your project?
a
Yeah, sure I can give that a shot
d
Great. I'll come back in a few hours
🙌 1
I'm back. Add the following repo to your configuration and set the kotlin version to
2.1.21-319
Copy code
maven("<https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev>")
I've expanded the error message, so it should show the name of the class causing the failure
a
Nice, I'll test it right away
🔥 1
OK, took a while to get our repo setup across the project to play nicely with this. I now get this:
java.lang.IllegalArgumentException: Only componentN functions should be cached this way, but got: public open fun hashCode(): R|kotlin/Int|
seems to just print out the signature of the hashCode function instead of a class?
Full stack: `
Copy code
java.lang.IllegalArgumentException: Only componentN functions should be cached this way, but got: public open fun hashCode(): R|kotlin/Int|

	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.cacheIrFunctionSymbol(Fir2IrDeclarationStorage.kt:426)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol(Fir2IrDeclarationStorage.kt:1133)
	at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.getIrFunctionSymbol$default(Fir2IrDeclarationStorage.kt:1101)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator$MyDataClassMethodsGenerator$irDataClassMembersGenerator$1.getHashCodeFunctionInfo(Fir2IrDataClassMembersGenerator.kt:362)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator.getHashCodeOf(DataClassMembersGenerator.kt:282)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.getHashCodeOfProperty(DataClassMembersGenerator.kt:229)
	at org.jetbrains.kotlin.ir.util.DataClassMembersGenerator$MemberFunctionBuilder.generateHashCodeMethodBody(DataClassMembersGenerator.kt:211)
	at org.jetbrains.kotlin.ir.util.IrBasedDataClassMembersGenerator.generateHashCodeMethod(DataClassMembersGenerator.kt:367)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator$MyDataClassMethodsGenerator.generateBodies(Fir2IrDataClassMembersGenerator.kt:248)
	at org.jetbrains.kotlin.fir.backend.generators.Fir2IrDataClassGeneratedMemberBodyGenerator.generateBodiesForClassesWithSyntheticDataClassMembers(Fir2IrDataClassMembersGenerator.kt:228)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.generateSyntheticBodiesOfDataValueMembers(convertToIr.kt:267)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.runActualizationPipeline(convertToIr.kt:205)
	at org.jetbrains.kotlin.fir.pipeline.Fir2IrPipeline.convertToIrAndActualize(convertToIr.kt:130)
	at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize(convertToIr.kt:100)
	at org.jetbrains.kotlin.fir.pipeline.ConvertToIrKt.convertToIrAndActualize$default(convertToIr.kt:75)
	at org.jetbrains.kotlin.cli.jvm.compiler.legacy.pipeline.JvmCompilerPipelineKt.convertToIrAndActualizeForJvm(jvmCompilerPipeline.kt:108)
	at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:26)
	at org.jetbrains.kotlin.cli.pipeline.jvm.JvmFir2IrPipelinePhase.executePhase(JvmFir2IrPipelinePhase.kt:17)
	at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:68)
	at org.jetbrains.kotlin.cli.pipeline.PipelinePhase.phaseBody(PipelinePhase.kt:58)
	at org.jetbrains.kotlin.config.phaser.SimpleNamedCompilerPhase.phaseBody(CompilerPhase.kt:215)
	at org.jetbrains.kotlin.config.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:111)
	at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:28)
	at org.jetbrains.kotlin.config.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:62)
	at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.runPhasedPipeline(AbstractCliPipeline.kt:106)
	at org.jetbrains.kotlin.cli.pipeline.AbstractCliPipeline.execute(AbstractCliPipeline.kt:65)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:61)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecutePhased(K2JVMCompiler.kt:36)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:80)
	at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.kt:337)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:466)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:75)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:514)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:431)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:310)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:137)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:678)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1805)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	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(AccessController.java:691)
	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:391)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)
d
Damn, I expected that it will render more info. Let me publish another build
a
Sounds good, should be much faster for me to set up this time
d
Published
2.1.21-321
🔥 1
a
OK, I'm actually getting a data class from one of our own libraries that's compiled with Kotlin 1.5.31. I know it's not best practice to use data classes in public API's but I assume this should still work?
d
Do I understand correctly, that somewhere in your code you have something like this?
Copy code
data class Some(val x: ClassFromThatLibrary)
a
data class Weapon(val name:String)
The trace:
Copy code
java.lang.IllegalArgumentException: Only componentN functions should be cached this way, but got: public open fun hashCode(): R|kotlin/Int|

fakeOverrideOwnerLookupTag: Weapon
Dispatch receiver: org/hltv/csrules/Weapon
Oh sorry misunderstood
Let me check the usages
Yes correct, actually in several places we have data classes in our project that has that external data class from the library as parameter. E.g., in our project:
data class WeaponStat(val ordinal: Int, val weapon: Weapon, val kills: Int)
Where the data class from the Kotlin 1.5.31 library looks like this:
data class Weapon(val name:String)
Just realized this code looks quite morbid, sorry about that. It's about Counter Strike (the game), not real weapons
d
Great. Could you please share that maven coordinates of this library? I'll try to reproduce it locally
Just realized this code looks quite morbid, sorry about that. It's about Counter Strike (the game), not real weapons
It was my first thought, actually.
a
It's not publicly available unfortunately. But I will try to set up a reproducer library that accomplishes the same thing
👍 1
d
Could you share a
Weapon.class
file from
.jar
of this library?
I've tried to recreate the same setup (library compiled with 1.5.31, project compiled with 2.1.20) and it works fine. I suspect that
Weapon.class
was somehow modified, so
hashCode
function was removed from it, so the compiler tries to generate it as it would generate for source classes, which is something unexpected.
a
I think you're right
Copy code
public final data class Weapon public constructor(name: kotlin.String) {
    public final val name: kotlin.String /* compiled code */

    public final operator fun component1(): kotlin.String { /* compiled code */ }

    public final fun copy(name: kotlin.String = COMPILED_CODE): org.hltv.csrules.Weapon { /* compiled code */ }
}
I tried building the library again, and the resulting .class file looked just fine (with hashCode function). So I did a little digging, and it turns out the Git log didn't quite tell the truth about the published version of the library. It was actually compiled with Kotlin 1.0.5 (!!). As it did work in K1, I assume you might still consider this a bug? Either way, it's an easy fix for our specific project now, so thanks a lot for your help! Would never have isolated the issue to that library otherwise.
d
It was actually compiled with Kotlin 1.0.5 (!!).
Such an ancient time/
As it did work in K1, I assume you might still consider this a bug?
Well, it depends on if 1.0.5 really didn't put the
hashCode
into bytecode or if your binary was postprocessed by something else. In the latter case I wound consider it as undefined behavior. But anyway the fact that compiler crashes instead of giving reasonable message is not ok. I'll try to reproduce it for myself and I'll create ticket if I'll succeed.
so thanks a lot for your help!
Thank you for your responsiveness. As an additional outcome of this story I've added this expanded error message (and a lot of similar ones) to
master
of compiler, so in future, if something like this will strike again, it would be much easier to understand what's going on. I wanted to do it for a long time, but you actually gave me an incentive.
Can confirm that it's the general problem with old binaries. Created KT-77705
a
Thanks for the update!