Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misleading error message "field must be final" when actually requiring a property to be declared val #237

Closed
OliverO2 opened this issue Jul 13, 2022 · 3 comments
Assignees

Comments

@OliverO2
Copy link

Compile this for the JVM target:

import kotlinx.atomicfu.atomic

var atomicProperty = atomic(1)

The following error message will appear:

> Task :transformJvmMainAtomicfu FAILED
9 actionable tasks: 2 executed, 7 up-to-date
MainKt::atomicProperty field must be final

This is misleading. As the docs on properties state:

In Kotlin, a field is only used as a part of a property to hold its value in memory. Fields cannot be declared directly.

A better wording would be

The property MainKt::atomicProperty must be declared as val

Relevant source:
https://github.com/Kotlin/kotlinx.atomicfu/blob/450b056efa4c8e4f922f2a3f8d1958404513b1f7/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt#L318

Also affected:
https://github.com/Kotlin/kotlinx.atomicfu/blob/450b056efa4c8e4f922f2a3f8d1958404513b1f7/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt#L316-L317
https://github.com/Kotlin/kotlinx.atomicfu/blob/450b056efa4c8e4f922f2a3f8d1958404513b1f7/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt#L795
https://github.com/Kotlin/kotlinx.atomicfu/blob/450b056efa4c8e4f922f2a3f8d1958404513b1f7/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt#L1064
https://github.com/Kotlin/kotlinx.atomicfu/blob/450b056efa4c8e4f922f2a3f8d1958404513b1f7/atomicfu-transformer/src/main/kotlin/kotlinx/atomicfu/transformer/AtomicFUTransformer.kt#L1402

@mvicsokolova mvicsokolova self-assigned this Jul 14, 2022
@mvicsokolova
Copy link
Collaborator

Declaring atomic variable properties is not supported.

This way you can declare a variable delegated to the atomic property:

val atomicProperty = atomic(1)
var ap by atomicProperty

@mvicsokolova
Copy link
Collaborator

Moreover when the atomic variable is declared, the compiler JVM IR plugin fails with an error below. It should also provide a more meaningful message.

FUN DEFAULT_PROPERTY_ACCESSOR name:<set-atomicProperty> visibility:public modality:FINAL <> (<set-?>:kotlinx.atomicfu.AtomicInt) returnType:kotlin.Unit
  correspondingProperty: PROPERTY name:atomicProperty visibility:public modality:FINAL [var]
  VALUE_PARAMETER name:<set-?> index:0 type:kotlinx.atomicfu.AtomicInt
  BLOCK_BODY
    SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:atomicProperty type:kotlinx.atomicfu.AtomicInt visibility:private [static]' type=kotlin.Unit origin=null
      value: GET_VAR '<set-?>: kotlinx.atomicfu.AtomicInt declared in <root>.AtomicProperty$AA$VolatileWrapper.<set-atomicProperty>' type=kotlinx.atomicfu.AtomicInt origin=null

        at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
        at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate$default(FunctionCodegen.kt:41)
        at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethodNode(ClassCodegen.kt:392)
        at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generateMethod(ClassCodegen.kt:409)
        at org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen.generate(ClassCodegen.kt:152)
        at org.jetbrains.kotlin.backend.jvm.FileCodegen.lower(JvmPhases.kt:44)
        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.invoke(CompilerPhase.kt:96)
        at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65)
        ... 42 more
Caused by: java.lang.IllegalStateException: Parent of this declaration is not a class: FIELD PROPERTY_BACKING_FIELD name:atomicProperty type:kotlinx.atomicfu.AtomicInt visibility:private [static]
        at org.jetbrains.kotlin.ir.util.IrUtilsKt.getParentAsClass(IrUtils.kt:289)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitFieldAccess(ExpressionCodegen.kt:740)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitFieldAccess(ExpressionCodegen.kt:136)
        at org.jetbrains.kotlin.ir.visitors.IrElementVisitor$DefaultImpls.visitSetField(IrElementVisitor.kt:264)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitSetField(ExpressionCodegen.kt:776)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitSetField(ExpressionCodegen.kt:136)
        at org.jetbrains.kotlin.ir.expressions.IrSetField.accept(IrSetField.kt:22)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitStatementContainer(ExpressionCodegen.kt:464)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:468)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.visitBlockBody(ExpressionCodegen.kt:136)
        at org.jetbrains.kotlin.ir.expressions.IrBlockBody.accept(IrBlockBody.kt:24)
        at org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen.generate(ExpressionCodegen.kt:242)
        at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.doGenerate(FunctionCodegen.kt:118)
        at org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:45)

@mvicsokolova
Copy link
Collaborator

A lot of updates for JVM transformation performed by the compiler plugin are coming in 1.9.20 (see #322), including the fix for this diagnostic.
The error message will look like this:

e: java.lang.IllegalStateException: Please consider declaring [var atomicProperty: kotlinx.atomicfu.AtomicInt] from [FILE fqName:<root> fileName:/.../Main.kt] as a private val or internal val.

If you need to declare a variable with accessors delegated to the atomic property value, you can use a delegated property declared within the same scope, e.g:

private val _a = atomic<T>(initial) 
public var a: T by _a 

Unfortunately, no fix is provided for the legacy bytecode transformer so far. Please consider using the compiler plugin for the JVM transformation, check out this section of the documentation to learn how it can be enabled: https://github.com/Kotlin/kotlinx-atomicfu#atomicfu-compiler-plugin

mvicsokolova added a commit to JetBrains/kotlin that referenced this issue Aug 28, 2023
mvicsokolova added a commit to JetBrains/kotlin that referenced this issue Aug 28, 2023
KotlinBuild pushed a commit to JetBrains/kotlin that referenced this issue Aug 29, 2023
… values.

Fixes: Kotlin/kotlinx-atomicfu#237

YT: KT-61550


Merge-request: KT-MR-11886
Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
KotlinBuild pushed a commit to JetBrains/kotlin that referenced this issue Aug 30, 2023
… values.

Fixes: Kotlin/kotlinx-atomicfu#237

YT: KT-61550


Merge-request: KT-MR-11887
Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants