Kotlin / kotlinx-atomicfu

The idiomatic way to use atomic operations in Kotlin
Other
856 stars 56 forks source link

Use of update in init block leads to compile-time exception #360

Open vdshb opened 8 months ago

vdshb commented 8 months ago

kotlin 1.9.10, atomicfu-gradle-plugin 0.22.0 with default config

Code example:

import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.update

class Test {

    private val foo = atomic(1)

    init {
        foo.update { 2 }
    }

}

Compile time exception:

java.lang.IllegalArgumentException: Function containing loop invocation CALL 'public final fun update (function: kotlin.Function1<kotlin.Int, kotlin.Int>): kotlin.Unit [inline] declared in kotlinx.atomicfu.AtomicFU_commonKt' type=kotlin.Unit origin=null is null
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitCall(AtomicfuJvmIrTransformer.kt:522)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitCall(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.expressions.IrCall.accept(IrCall.kt:26)
    at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:31)
    at org.jetbrains.kotlin.ir.expressions.IrExpression.transform(IrExpression.kt:22)
    at org.jetbrains.kotlin.ir.util.TransformKt.transformInPlace(transform.kt:35)
    at org.jetbrains.kotlin.ir.expressions.IrBlockBody.transformChildren(IrBlockBody.kt:32)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitBody(IrElementTransformer.kt:178)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitBody(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitBody(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitBlockBody(IrElementTransformer.kt:185)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitBlockBody(AtomicfuJvmIrTransformer.kt:646)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitBlockBody(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.expressions.IrBlockBody.accept(IrBlockBody.kt:25)
    at org.jetbrains.kotlin.ir.expressions.IrBody.transform(IrBody.kt:22)
    at org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer.transformChildren(IrAnonymousInitializer.kt:41)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitDeclaration(IrElementTransformer.kt:103)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitDeclaration(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitDeclaration(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitAnonymousInitializer(IrElementTransformer.kt:114)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitAnonymousInitializer(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitAnonymousInitializer(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer.accept(IrAnonymousInitializer.kt:34)
    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:83)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitDeclaration(IrElementTransformer.kt:103)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitDeclaration(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitDeclaration(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitClass(IrElementTransformer.kt:110)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitClass(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitClass(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:73)
    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:41)
    at org.jetbrains.kotlin.ir.visitors.IrElementTransformer$DefaultImpls.visitFile(IrElementTransformer.kt:168)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitFile(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer$AtomicfuTransformer.visitFile(AtomicfuJvmIrTransformer.kt:483)
    at org.jetbrains.kotlin.ir.declarations.IrFile.accept(IrFile.kt:31)
    at org.jetbrains.kotlin.ir.declarations.IrFile.transform(IrFile.kt:34)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer.transformAtomicfuDeclarations(AtomicfuJvmIrTransformer.kt:84)
    at org.jetbrains.kotlinx.atomicfu.compiler.backend.jvm.AtomicfuJvmIrTransformer.transform(AtomicfuJvmIrTransformer.kt:64)
    at org.jetbrains.kotlinx.atomicfu.compiler.extensions.AtomicfuLoweringExtension.generate(AtomicfuLoweringExtension.kt:31)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$lambda$1(JvmIrCodegenFactory.kt:222)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:107)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:255)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:59)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.convertToIr(KotlinToJVMBytecodeCompiler.kt:224)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:101)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:168)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53)
    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.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:460)
    at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:62)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:476)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:399)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:280)
    at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:124)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:636)
    at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:101)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1598)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    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)
mvicsokolova commented 8 months ago

Hi! Thank you for the report. Unfortunatelly, atomicfu compiler plugin does not support initialization of atomics via calls to inline functions like update in the init {} block yet. update function should only be called from another function.

And in init {} block you can set the value of an atomic:

private val foo = atomic(1)

init {
  foo.value = 2
}

Or

private val foo: AtomicInt

init {
  foo = atomic(1)
}