Expressions and control flow
This page describes the current checkout, including unreleased work. Status and evidence policy applies to every entry.
Scalar when with individual branches
Status: Supported.
Int, Char, Boolean, and String subjects, plus subjectless boolean conditions, lower to bounded
deterministic branches; matched and fallback paths execute in the VM.
Evidence:
MinimalScriptLoweringTest,
tests bounded when lowers deterministically for vm execution and bounded when forms compile for admitted
scalar types, and
kotlin_writer.rs,
test k2_bounded_when_selects_matched_and_fallback_branches.
Pattern-rich when
Status: Partial.
The tested constant scalar range-membership and comma-joined branches accept Unit statements. Broader pattern combinations are outside this support claim. Type branches over the admitted sealed class subset are handled separately under the object model.
Evidence:
MinimalScriptLoweringTest,
test when range and alternative branches accept Unit statements.
Related work: not scheduled
if, blocks, mutable locals, and while
Status: Partial.
These forms compile and are used by the checked-in shell, including nested loops and reassignment. break and
continue target either the innermost loop or an active enclosing labeled loop. There is no source-level
conformance suite covering every expression/result shape.
Evidence:
MinimalScriptLoweringTest,
tests shell language subset lowers control flow scalars strings and raw terminal calls, checked in shell
compiles deterministically, and while loop jumps lower locally.
Related work: not scheduled
Allocation-free Int for loops
Status: Supported.
start..endInclusive, start until endExclusive, start..<endExclusive, start downTo endInclusive, and
one positive step on those progressions evaluate and snapshot their bounds and step once, then execute as
scalar frame slots with no range, progression, or iterator allocation. Invalid dynamic steps throw a Guest
argument error. Empty, reversed, singleton, negative, Int.MIN_VALUE, and Int.MAX_VALUE boundaries preserve
Kotlin behavior. Local and labeled break and continue are supported, including nested loops. Every
repeated path crosses an existing loop-header quota safepoint.
Evidence:
MinimalScriptLoweringTest,
tests inclusive Int for loops lower without range or iterator allocation, exclusive Int for loops lower
without range or iterator allocation, Int for loop supplies its generated increment constant, and
allocation free Int loops lower deterministically for vm execution (including descending, stepped, edge, and
invalid-step execution), plus
kotlin_writer.rs,
test k2_int_loops_execute_across_quota_slices_without_host_io.
Primitive ranges and progressions
Status: Supported.
Stored ranges, progression iterators and membership execute through the range library. Direct Int loops retain the
allocation-free lowering described above.
Post-test do-while loops
Status: Supported.
Ordinary do-while executes its body before testing the condition. Each local continue runs intervening
finally cleanup and reaches the condition; local break and function return run cleanup and skip the
condition. Body-local declarations retain Kotlin’s condition scope. Nested loops select their own local
targets. Exceptions from the body or condition use ordinary managed handlers, and loop execution resumes
across instruction-budget slices. Labeled jumps preserve these condition and cleanup rules.
Evidence: MinimalScriptLoweringTest, test do while loops preserve post test order jumps cleanup and
exceptions for vm execution, executed by testKotlinIntLoopsVmConformance with instruction budgets of 64
and 512. DiagnosticQueryTest, test do while analysis admits body scoped conditions and local cleanup jumps,
checks source-attached and metadata-only IDE sessions.
Related work: #737
Labeled loop jumps
Status: Supported.
break@label and continue@label resolve to an active enclosing loop by K2 IR identity, including nested
while, do-while, optimized Int progression loops, primitive and reference-array loops, and admitted Iterable loops.
A break exits that loop; a continue reaches its condition, progression increment, array index advancement,
or iterator check. Reused label names resolve to the nearest matching loop according to Kotlin scope.
Only crossed finally scopes run, from the innermost outward; cleanup surrounding the target loop stays
active. A return, another loop jump, or exception from cleanup overrides the pending jump. This adds no
instructions or ABI changes and does not widen jumps across function or inline-lambda boundaries. Invalid
or out-of-scope labels produce diagnostics without publishing an artifact.
Evidence: MinimalScriptLoweringTest, tests labeled loop jumps preserve target advancement and cleanup
for vm execution (deterministic artifact) and invalid loop labels publish no artifact.
testKotlinIntLoopsVmConformance requires the labeled-loop artifact and executes its assertions at instruction
budgets of 64 and 512. DiagnosticQueryTest, test labeled loop analysis resolves mixed targets with source
and metadata inputs, checks both IDE input forms.
Related work: #738
Direct reference-array loops
Status: Supported for admitted element representations.
for (element in array) traverses Array<T> in ascending index order without allocating an iterator.
Concrete non-null primitive element specializations load dense scalars directly; nullable/reference and
value-class elements retain their existing representation.
The source expression and array reference evaluate once; reassigning a source variable does not switch the
traversed array. Writes to that array’s later slots remain visible. An empty array does not execute the body.
Elements use the same representations as indexed reads: strings, source/imported references, Any, value
classes (including multi-field values), nullable elements and nullable primitive boxes, with concrete generic
specialization. Non-null value classes unbox into local values; nullable ones retain their managed boxes.
Local and labeled jumps, finally cleanup, managed exceptions and quota safepoints follow the other array
loops. Stored array iterators remain unavailable;
see the array library for storage boundaries.
Evidence:
MinimalScriptLoweringTest,
tests reference array loops preserve specialized elements source
identity and cleanup for vm execution (deterministic artifact) and
guest arrays reject stored iterators spread and nested storage. testKotlinReferenceArrayVmConformance
requires this loop artifact and executes
its assertions at budgets 64 and 512 with a 256 KiB heap, including allocation pressure and retained references.
DiagnosticQueryTest, test reference array loops resolve nullable generic and value class elements with
source and metadata inputs, checks both IDE input forms.
Related work: #741
Destructuring
Status: Partial.
Destructuring through source component1/component2 methods on concrete generic value classes executes in
testKotlinMfvcVmConformance. This does not imply support for every generated data-class component method.
Delegated expressions
Status: Unsupported.
Delegated storage remains outside the supported subset.
Related work: not scheduled