kotlingradleintellij-ideakotlin-delegate

Why Kotlin delegation is different between an Intellij Project and a Gradle project


My Intellij Version is 2024.2.4 (Build #IU-242.23726.103, built on October 23, 2024)

I created the following code in :

interface Base {
    fun printMessage()
}

class BaseImpl(val x: Int) : Base {
    override fun printMessage() { println(x) }
}


class BaseImpl2(val x: Int) : Base {
    override fun printMessage() { println("2 $x") }
}

class Derived(var b: Base) : Base by b {

}

fun main() {
    val base1 = BaseImpl(10)
    val base2 = BaseImpl(12)
    val derived = Derived(base1)
    derived.printMessage()
    derived.b = base2
    derived.printMessage()
}

Intellij project execution outputs :

10
12

Gradle project execution outputs :

10
10

Finally, I'm experiencing in the gradle version what exeplain here.

The difference in the bytecode generated is there :

public final class Editeur implements Base {
   @NotNull
   private Base b;
   // $FF: synthetic field
   private final Base $$delegate_0;

But we don't have the final delegate in Intellij :

public final class Editeur implements Base {
   @NotNull
   private Base b;

Why the bytecode generated is different between the both projects ?

Complements

Complement 1

Version of kotlin is both 2.0.20 for the lib, not for the compiler :

Gradle

plugins {
    kotlin("jvm") version "2.0.20"
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

...

Gradle is using 2.0.20 plugin, with the 2.0.20 koltinc version.

Intellij Version

I have the version during the build logs

Executing pre-compile tasks…
Running 'before' tasks
Checking sources
Kotlin: connecting to daemon
Kotlin: compiling [untitled]
Kotlin: kotlinc-jvm 1.9.24-release-822 (JRE 23.0.1+11-39)
Kotlin: Language version 2.0 is experimental, there are no backwards compatibility guarantees for new language and library features
Kotlin: performing incremental compilation analysis
Checking dependencies… [untitled]
Dependency analysis found 0 affected files
Updating dependency information… [untitled]

Intellij is using the 2.0.20 kotlin libs but the 1.9.24 kotlinc version

Complement 2

This is reproduced on Ubuntu version of Intellij and Windows on different desktop (This appeared during a training session)

Complement 3

I put the project in github there. You can play with the src/test1/Base2.kt


Solution

  • In a newly-created IntelliJ project, the compiler version is set to 1.9.24, but the language and API versions are set to 2.0.

    enter image description here

    It is this combination of settings that produces the bug. If you use an API and language version of 1.9, or if you change the compiler version to 2.0+, the "10 12" behaviour is no longer reproducible.

    On the other hand, a new gradle project uses the 2.0.20 compiler

    plugins {
        kotlin("jvm") version "2.0.20"
    }
    

    If you wrote this instead, you can reproduce the same behaviour as the IntelliJ project.

    plugins {
        kotlin("jvm") version "1.9.24"
    }
    
    kotlin {
        jvmToolchain(23)
        compilerOptions {
            apiVersion.set(KotlinVersion.KOTLIN_2_0)
            languageVersion.set(KotlinVersion.KOTLIN_2_0)
        }
    }