Skip to content

Kotlin 2.3.20 / 2.4.0 compatibility — version-adapter layer + unified IR API migration#52

Merged
arnaudgiuliani merged 5 commits into
1.0.1from
arnaud/ktz-4150-kotlin-compat
Jun 8, 2026
Merged

Kotlin 2.3.20 / 2.4.0 compatibility — version-adapter layer + unified IR API migration#52
arnaudgiuliani merged 5 commits into
1.0.1from
arnaud/ktz-4150-kotlin-compat

Conversation

@arnaudgiuliani

Copy link
Copy Markdown
Member

Fixes #19
Closes InsertKoinIO/koin#2431 (duplicate of #19)
Addresses the failure family of #42 (binary breaks across Kotlin versions)

Problem

The plugin compiles against exactly one kotlin-compiler version and ships a single artifact, but FIR/IR plugin APIs are unstable across Kotlin minors. Two releases in a row broke users:

Every new Kotlin minor was a potential hard crash, fixable only by re-releasing the whole plugin.

Solution — two prongs

1. Core migrated to the unified IR API (a2f8622)

All IR-phase code now uses parameters / IrParameterKind / arguments / typeArguments (available since 2.3.20, the API Kotlin itself migrated to) instead of the removed-in-2.4.0 valueParameters / putValueArgument / extensionReceiver accessors. ~480 version-split call sites eliminated; the regular-index ↔ indexInParameters mapping is centralized in ir/IrArgumentMapping.kt. Behavior-identical: full box-test suite unchanged and green.

2. Version-adapter layer for the irreconcilable rest (a0c759f, 0b25301)

New koin-compiler-version-adapter/ module: a 3-member KotlinVersionAdapter interface — each member documents the exact incompatibility forcing it via @KotlinApiChange:

Member Kotlin change
registerCompilerExtensions 2.4.0 FIR registration binary contract (#19)
setAnnotations 2.4.0: IrAnnotationContainer.annotations became List<IrAnnotation>
refreshDeprecations 2.4.0: getDeprecationsProvider receiver specialized (NoSuchMethodError on multi-module builds)

Per-version implementations (kotlin-2.3.20/, kotlin-2.4.0/), each compiled against its own kotlin-compiler, all embedded in the published jar — the artifact stays a single jar. At plugin load, KotlinAdapterLoader picks the adapter from a registry file (META-INF/koin/kotlin-version-adapters.properties); only the selected adapter is ever classloaded.

Fallback policy:

  • Kotlin newer than the newest adapter → STRONG_WARNING + best-effort newest adapter
  • Kotlin older than 2.3.20 (floor) → clear, actionable error naming the supported versions

Tooling (0b25301)

tools/abi-check/ — hierarchy-aware bytecode scanner verifying every compiler-API reference in the plugin's bytecode resolves against a target Kotlin version. Catches binary-only breaks (the #42/#19 class) before release instead of via user crash reports. Current state: 411/411 refs resolve on both 2.3.20 and 2.4.0.

Verification

Check Result
Box tests (Kotlin 2.3.20) 291/291 ✅
ABI scan vs 2.3.20 and 2.4.0 411/411 refs resolve ✅
playground-apps/app-floor-2320 (new minimal floor guard, 2.3.20 + -PkotlinVersion=2.4.0 probe) ✅ ✅
playground-apps/app-dsl — Android, Kotlin 2.4.0 BUILD SUCCESSFUL ✅
playground-apps/app-annotations — Android, Kotlin 2.4.0 (FIR/annotations path) BUILD SUCCESSFUL ✅
Version-parser unit tests (Beta/RC/dev/floor boundaries)

Before this branch, both Android playground apps reproduced the exact #19 ClassCastException on Kotlin 2.4.0.

Release notes (1.0.1)

  • ✅ One plugin artifact now supports Kotlin 2.3.20 → 2.4.x (see supported-kotlin-versions.txt)
  • ⚠️ Kotlin 2.3.0–2.3.1x are below the support floor (the plugin requires the 2.3.20+ KLIB/FIR baseline); these users get a clear diagnostic and should upgrade Kotlin or stay on an older plugin
  • Playground apps moved to Kotlin 2.4.0; new app-floor-2320 guards the floor

Supporting a future Kotlin version

  1. ./tools/abi-check/check-kotlin-abi.sh <version> — if 411/411 resolve and the FIR layer behaves, no adapter needed (newest adapter is reused)
  2. If something broke: add one kotlin-<version>/ adapter module + a registry line + supported-kotlin-versions.txt entry
  3. Playground matrix run on both lines

🤖 Generated with Claude Code

arnaudgiuliani and others added 5 commits June 5, 2026 16:00
….4.0 compatible)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… and 2.4.0

- koin-compiler-version-adapter: KotlinVersionAdapter interface, registry-based
  KotlinAdapterLoader (only the selected adapter is classloaded), maturity-aware
  KotlinReleaseVersion parser
- per-version adapters compiled against their own kotlin-compiler artifact:
  kotlin-2.3.20 and kotlin-2.4.0 (FIR registration binary contract + IrAnnotation
  conversion)
- adapters embedded into the published koin-compiler-plugin jar (single artifact)
- unknown newer Kotlin: WARN + newest adapter; older than floor: clear error
- playground-apps: app-dsl/app-annotations on Kotlin 2.4.0, new app-floor-2320
  guard on 2.3.20 with -PkotlinVersion override

Fixes #19
- getDeprecationsProvider's receiver was specialized in 2.4.0 (NoSuchMethodError
  in markAsDeprecatedHidden on multi-module builds): routed through new
  KotlinVersionAdapter.refreshDeprecations, implemented per version
- tools/abi-check: hierarchy-aware bytecode reference scanner — verifies every
  compiler-API ref in the plugin's bytecode resolves against a target Kotlin
  version (catches binary breaks that source recompiles can't see).
  Plugin bytecode: 411/411 refs resolve on both 2.3.20 and 2.4.0
- verified: box tests green, app-dsl + app-annotations build on Kotlin 2.4.0
…th version warnings, doc version

- setExtensionReceiverArgument: error instead of silent no-op when callee has
  no extension receiver (avoids silently dropping the argument)
- KotlinAdapterLoader.current: emit selection warnings on stderr on the
  self-init path (registrar path already routes them to messageCollector)
- playground README: Compiler Plugin 1.0.0 -> 1.0.1
@arnaudgiuliani arnaudgiuliani added this to the 1.0.1 milestone Jun 8, 2026
@arnaudgiuliani arnaudgiuliani merged commit 02fae3e into 1.0.1 Jun 8, 2026
2 checks passed
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

Successfully merging this pull request may close these issues.

1 participant