JetBrains/kotlin
Frontend (K2 / FIR)
Active contributors: Kirill Rakhman, Dmitriy Novozhilov, Mikhail Glukhikh
The K2 frontend lives in compiler/fir/ and is Kotlin's primary frontend since version 2.0 (May 2024). It replaced K1 (the legacy frontend at compiler/frontend/) as the default but K1 remains in the tree for the IDE plugin's compatibility window.
Purpose
K2 takes a parsed KtFile (or its lighter equivalent for performance-sensitive paths) and produces a fully resolved FIR (Frontend Intermediate Representation) tree, plus a stream of diagnostics. The output is then either translated to backend IR (via compiler/fir/fir2ir/) or consumed by the Analysis API for IDE features.
Directory layout
compiler/fir/
├── tree/ FIR tree types and renderers (Fir*)
├── cones/ Type-system primitives (ConeKotlinType, ...)
├── raw-fir/ PSI → raw FIR builder
├── resolve/ Resolution phases
├── checkers/ Diagnostic checkers + generated FirErrors
├── providers/ Symbol providers (declarations, library symbols)
├── semantics/ Semantic analyzers used inside resolution
├── entrypoint/ The K2 frontend entry points
├── fir2ir/ FIR → backend IR translator
├── fir-jvm/, fir-js/,
│ fir-native/ Platform-specific frontend extensions
├── fir-deserialization/ Reading library declarations as FIR
├── fir-serialization/ Writing FIR for klibs
├── analysis-tests/ Diagnostic tests (FIR-specific runners)
├── modularized-tests/ Multi-module compilation tests
├── plugin-utils/ Hooks for FIR-aware compiler plugins
├── diagnostic-renderers/ Pretty-printing of diagnostics
└── dump/ Text dumps of FIR for testingKey abstractions
| Type | File | Role |
|---|---|---|
FirElement |
compiler/fir/tree/.../FirElement.kt |
Root of the FIR class hierarchy. |
FirRegularClass, FirSimpleFunction, FirProperty, ... |
compiler/fir/tree/... |
Declaration nodes. |
FirSymbol |
compiler/fir/tree/.../symbols |
A reference to a declaration; primary identity in K2. |
FirResolvePhase |
compiler/fir/resolve/.../FirResolvePhase.kt |
Enumeration of resolve phases (RAW_FIR through BODY_RESOLVE). |
ConeKotlinType |
compiler/fir/cones/.../ConeKotlinType.kt |
The K2 type system's foundational type. |
FirSession |
compiler/fir/.../session |
Container for resolve services, providers, and configuration. |
FirDeclarationChecker, FirExpressionChecker |
compiler/fir/checkers/... |
Single-element checker base classes for diagnostics. |
FirErrors |
compiler/fir/checkers/gen/.../FirErrors.kt |
Generated table of diagnostic factories. |
How resolve works
K2 processes code in phases. The fundamental invariant (stated in compiler/AGENTS.md):
In phase B following phase A, all FIR elements visible in B are resolved to phase A.
The phases (see FirResolvePhase) progress from RAW_FIR (just-built tree, no resolution) up through IMPORTS, SUPER_TYPES, TYPES, STATUS, EXPECT_ACTUAL_MATCHING, CONTRACTS, IMPLICIT_TYPES_BODY_RESOLVE, and BODY_RESOLVE. Each phase enriches FIR nodes with information that later phases can rely on. The Analysis API's "low-level FIR" (analysis/low-level-api-fir/) drives this same machinery on demand for IDE features.
graph LR
RAW["RAW_FIR<br/>(from PSI)"] --> IMP[IMPORTS]
IMP --> SUP[SUPER_TYPES]
SUP --> TY[TYPES]
TY --> ST[STATUS]
ST --> EA[EXPECT_ACTUAL]
EA --> CT[CONTRACTS]
CT --> IB[IMPLICIT_TYPES_BODY_RESOLVE]
IB --> BR[BODY_RESOLVE]Diagnostics
Diagnostics in K2 are defined in two places:
- A central list in
compiler/fir/checkers/checkers-component-generator/src/.../FirDiagnosticsList.kt. - Generated tables in
compiler/fir/checkers/gen/.../FirErrors.ktandFirErrorsDefaultMessages.kt(one of the most-modified files in the repo).
Checkers themselves live in compiler/fir/checkers/ and inherit from FirDeclarationChecker, FirExpressionChecker, etc. The Analysis API mirrors the FIR diagnostic list in analysis/analysis-api-fir/gen/.../KaFirDiagnostics* so IDEs can consume them.
fir2ir
compiler/fir/fir2ir/ walks resolved FIR and produces backend IR. This is where the frontend hands off to the backends. It depends on compiler/ir/ir.tree/ for the output type.
Platform-specific extensions
Each Kotlin target adds its own frontend bits:
compiler/fir/fir-jvm/— JVM-specific resolution (e.g., Java interop, platform types).compiler/fir/fir-js/— JS-specific (externaldeclarations,dynamictype).compiler/fir/fir-native/— Native interop hooks.
compiler/fir/fir-deserialization/ reads previously compiled libraries (their klib metadata or class file metadata) back into FIR symbols so user code can resolve against them.
Testing
FIR tests have specialized infrastructure. The most relevant runner setups live in compiler/fir/analysis-tests/ and compiler/fir/fir2ir/test/. Test data uses the standard K2 directive vocabulary; see compiler/fir/analysis-tests/AGENTS.md for the full list.
Integration points
- Consumed by
compiler/fir/fir2ir/(and via that, every backend). - Consumed by
analysis/analysis-api-fir/andanalysis/low-level-api-fir/for IDE tooling. - Plugin extension points in
compiler/fir/plugin-utils/(and consumed inplugins/). - CLI driver in
compiler/cli/cli-jvm/etc. invokes the FIR pipeline based on-language-version(K2 is the default since 2.0).
Where to start
When extending K2 (adding a checker, a new phase, a new frontend feature), start in compiler/fir/checkers/ for diagnostics or compiler/fir/resolve/ for actual resolution logic. The compiler/fir/analysis-tests/AGENTS.md and docs/fir/fir-basics.md files are the canonical references. Cross-check the patterns and conventions page for K2/K1 dual-implementation expectations.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.