Skip to content

Proposal: Remove fixed Kotlin runtime version limitation in Gradle #16345

@ZacSweers

Description

@ZacSweers

Today Gradle bundles an embedded version of Kotlin. My understanding is that this is due to usage of private compiler APIs in order to support kotlin-dsl. This prevents all plugins on the classpath from using different (let alone newer) Kotlin versions though, even if both they and the consuming build are not using kotlin-dsl.

This is something that I feel is fundamentally holding back the ecosystem, because it negatively affects plugin developers in the following ways:

  • They must set arbitrary language settings on their build, like lowering the languageLevel setting to 1.3 today, otherwise risk accidentally writing incompatible code.
  • For much of Kotlin 1.4.x's release cycle, they could not use Kotlin 1.4 period. Kotlin 1.4 was not added until Gradle 6.8, and even then it didn't allow kotlin 1.4 language targeting.
  • Language level alone only covers their own sources, but then they must also meticulously test any Kotlin-using external libraries that may have updated to 1.4 and use 1.4 APIs.
    • A good example of where this comes up is Okio, OkHttp, or Coroutines. Even something as simple as a member reference becomes a breaking change when compiled in 1.4 and run in a 1.3 environment.

This would be less of an issue if Gradle updated its embedded Kotlin version regularly, but the judgement today is that it cannot target a new minor version of Kotlin (now on a ~6mo cadence) until a new major version of Gradle (~once per year). While this may have lined up somewhat with Kotlin's previous ~annual release strategy, this is unwinding now with Kotlin 1.5's upcoming release. As of now, Gradle is on track to miss the entirety of Kotlin 1.4 due to its reluctance to update or allow users to use a new version. This will only continue now that Kotlin's release cycle is accelerated.

I understand that part of this reluctance to allow newer versions is because they may break. However, I think this is easily remedied by simply making it clear what the currently supported version is. Gradle adopts this approach with Java today, where it often supports running on a newer version but may not officially support it until a later release (major or otherwise). Gradle added Java 15 support in the 6.7 minor release, for instance.

The private API usage does offer a good reason for using a fixed version, but again there is precedent for this too as Gradle uses private javac APIs too (namely from the private-ish tools jar) to support cases like incremental compilation.

I would like to propose adopting one of the following strategies (in order of preference, though they're not all mutually exclusive either):

  1. Unbundle Kotlin, remove private API usage or move it behind a flag. "If you want to use these APIs in kotlin-dsl, this must be enabled and comes with these restrictions"
  2. Unbundle Kotlin, use a simple minimum/supported version and denote new un-tested versions as unsupported "your mileage may vary"
  3. Allow/commit to more frequent updates. I.e. allow minor Kotlin version updates in minor Gradle version updates
  4. Unbundle Kotlin, shade the embedded kotlin compiler or its privately used APIs to avoid conflict

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions