Sebastian Raaphorst
02/03/2024, 10:50 AMAbstractField
class with an inner AbstractFieldElement
class. When I do this, compiling using 1.9.22, I’m getting a compiler error. Can anyone see something I am doing wrong?
I’ve reduced the code down to the minimal example that causes the crash in the comment to this post to avoid taking up too much room along with the compiler error / stack trace.Sebastian Raaphorst
02/03/2024, 10:51 AMpackage org.example
abstract class AbstractField<F: AbstractField<F, E>, E: AbstractField<F, E>.AbstractFieldElement<E>> {
abstract val zero: E
abstract inner class AbstractFieldElement<E: AbstractFieldElement<E>> {
abstract operator fun plus(other: E): E
}
}
class Fp(val prime: Int): AbstractField<Fp, Fp.EFp>() {
override val zero = EFp(0)
inner class EFp(val value: Int): AbstractFieldElement<EFp>() {
override operator fun plus(other: EFp): EFp =
EFp((value + other.value) % prime)
override fun toString(): String =
"$value (mod $prime)"
}
}
fun main() {
val field = Fp(13)
val elem1 = field.EFp(8)
val elem2 = field.EFp(10)
println("$elem1 + $elem2 = ${elem1 + elem2}")
}
Sebastian Raaphorst
02/03/2024, 10:53 AMzero
member results in the same BackendException
message: I included the zero
here in the sample code to demonstrate why I am trying to do this.
org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
File being compiled: /Users/vorpal/dev/kotlin/field_bug/src/main/kotlin/Main.kt
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:51)
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253)
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:237)
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65)
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:52)
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:38)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:147)
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:94)
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29)
at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:16)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:147)
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:94)
at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43)
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:361)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runCodegen(KotlinToJVMBytecodeCompiler.kt:347)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:122)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:43)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:165)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:50)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:463)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:62)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:477)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:400)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:281)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:125)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:657)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:105)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1624)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
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:714)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.RuntimeException: Exception while generating code for:
FUN BRIDGE name:getZero visibility:public modality:OPEN <> ($this:org.example.Fp) returnType:org.example.AbstractField.AbstractFieldElement<*>
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:org.example.Fp
EXPRESSION_BODY
TYPE_OP type=org.example.AbstractField.AbstractFieldElement<*, *, *> origin=IMPLICIT_CAST typeOperand=org.example.AbstractField.AbstractFieldElement<*, *, *>
RETURN type=kotlin.Nothing from='public open fun getZero (): org.example.AbstractField.AbstractFieldElement<*> declared in org.example.Fp'
CALL 'public open fun <get-zero> (): org.example.Fp.EFp declared in org.example.Fp' type=org.example.Fp.EFp origin=BRIDGE_DELEGATION
$this: GET_VAR '<this>: org.example.Fp declared in org.example.Fp.getZero' type=org.example.Fp origin=null
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:51)
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate$default(FunctionCodegen.kt:43)
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethodNode(ClassCodegen.kt:390)
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethod(ClassCodegen.kt:407)
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:169)
at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:41)
at org.jetbrains.kotlin.backend.common.phaser.FileLoweringPhaseAdapter.invoke(PhaseBuilders.kt:120)
at org.jetbrains.kotlin.backend.common.phaser.FileLoweringPhaseAdapter.invoke(PhaseBuilders.kt:116)
at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.phaseBody(CompilerPhase.kt:147)
at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedCompilerPhase.invoke(CompilerPhase.kt:94)
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:62)
... 42 more
Caused by: java.lang.AssertionError: -2 trailing arguments were found in this type: org.example.AbstractField.AbstractFieldElement<*>
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMappingKt.buildPossiblyInnerType(IrTypeMapping.kt:71)
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMappingKt.buildPossiblyInnerType(IrTypeMapping.kt:81)
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMappingKt.buildPossiblyInnerType(IrTypeMapping.kt:64)
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper.writeGenericType(IrTypeMapper.kt:148)
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper.writeGenericType(IrTypeMapper.kt:41)
at org.jetbrains.kotlin.types.AbstractTypeMapper.mapClassType(AbstractTypeMapper.kt:192)
at org.jetbrains.kotlin.types.AbstractTypeMapper.mapType(AbstractTypeMapper.kt:89)
at org.jetbrains.kotlin.types.AbstractTypeMapper.mapType(AbstractTypeMapper.kt:53)
at org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper.mapType(IrTypeMapper.kt:134)
at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen$typeMapper$1.mapType(ClassCodegen.kt:101)
at org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper.mapReturnType(MethodSignatureMapper.kt:189)
at org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper.mapReturnType(MethodSignatureMapper.kt:169)
at org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper.mapSignature(MethodSignatureMapper.kt:277)
at org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper.mapSignature$default(MethodSignatureMapper.kt:227)
at org.jetbrains.kotlin.backend.jvm.mapping.MethodSignatureMapper.mapSignatureWithGeneric(MethodSignatureMapper.kt:225)
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.doGenerate(FunctionCodegen.kt:55)
at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
... 52 more
Youssef Shoaib [MOD]
02/03/2024, 11:07 AMSebastian Raaphorst
02/03/2024, 1:13 PMkotlinc
, everything is fine, but if I try to go through gradle, it borks like above. I’ve spent hours troubleshooting this and I have no idea what’s going on.Youssef Shoaib [MOD]
02/03/2024, 1:22 PMYoussef Shoaib [MOD]
02/03/2024, 1:28 PME
from AbstractFieldElement
. Because you're an inner class, it's not needed:
package org.example
abstract class AbstractField<F: AbstractField<F, E>, E: AbstractField<F, E>.AbstractFieldElement> {
abstract val zero: E
abstract inner class AbstractFieldElement {
abstract operator fun plus(other: E): E
}
}
class Fp(val prime: Int): AbstractField<Fp, Fp.EFp>() {
override val zero = EFp(0)
inner class EFp(val value: Int): AbstractFieldElement() {
override operator fun plus(other: EFp): EFp =
EFp((value + other.value) % prime)
override fun toString(): String =
"$value (mod $prime)"
}
}
fun main() {
val field = Fp(13)
val elem1 = field.EFp(8)
val elem2 = field.EFp(10)
println("$elem1 + $elem2 = ${elem1 + elem2}")
}
Youssef Shoaib [MOD]
02/03/2024, 1:37 PMpackage org.example
interface Field<F: Field<F, E>, E> {
val zero: E
operator fun E.plus(other: E): E
val E.repr: String
}
@JvmInline value class EFp(val value: Int) {
override fun toString(): String = "$value"
}
@JvmInline value class Fp(val prime: Int): Field<Fp, EFp> {
override val zero get() = EFp(0)
override operator fun EFp.plus(other: EFp): EFp =
efp(value + other.value)
override val EFp.repr get() = "$value (mod $prime)"
fun efp(value: Int) = EFp(value % prime)
}
fun main() {
with(Fp(13)) {
val elem1 = efp(8)
val elem2 = efp(10)
println("${elem1.repr} + ${elem2.repr} = ${(elem1 + elem2).repr}")
}
}
Youssef Shoaib [MOD]
02/03/2024, 1:41 PMSebastian Raaphorst
02/03/2024, 1:44 PMYoussef Shoaib [MOD]
02/03/2024, 1:47 PMFp
fields with different primes. The result would depend on which argument was passed first, thus making +
not commutative, and very weird. The code I provided makes the field you operate in an external choice based on what context you're in. I think that's more natural. It's also somewhat more performant because you can use `value class`es in a lot of places as a result of that decomposition. I find that `inner class`es rarily make sense in Kotlin nowadaysSebastian Raaphorst
02/03/2024, 1:59 PMF_p
(although there’s no reason it couldn’t just check that the primes are the same). I’d love to get some feedback on it and run it by someone, and I’ll look at your code and give it a think… I will probably have some questions for you.
I also have an implementation using JGMP - the Java bindings for GMP - so I can work with large primes effectively. It’s a little disorganized right now with a bunch of ideas, but the snippet I posted was just the minimal example I could find that represented the idea I was going for and that was crashing when I built it with Gradle.
I’m very grateful that you reminded me of the Kotlin playground and I could see that there’s something wrong with my setup and not so much with the code itself.
I hope you have a great day wherever you are and I’ll put together my stuff on GitHub and send you the link. Looking forward to chatting more!Sebastian Raaphorst
02/27/2024, 5:09 PMYoussef Shoaib [MOD]
02/27/2024, 6:26 PM