Kotlin 2.x, KSP & Collections Quiz

KOTLIN › Modern Kotlin

In which Kotlin version did the K2 compiler become Stable and the default?

Answer: Kotlin 2.0.0

K2 was Beta in 1.9.20 and reached Stable, becoming the default compiler, in Kotlin 2.0.0.

Which statement correctly contrasts kapt and KSP?

Answer: kapt generates Java stubs and runs javac, while KSP reads Kotlin symbols and is faster

kapt's stub generation plus a javac pass is the bottleneck; KSP processes Kotlin symbols directly, so it is faster, and kapt is in maintenance mode.

Which operation is a KSP SymbolProcessor actually allowed to perform?

Answer: Read declarations like classes and functions, then generate new files

KSP is read-only at the symbol level: it can see declarations and emit new files, but cannot modify source or inspect statements and expressions.

Given val numbers = mutableListOf("a"), which is true?

Answer: You can call numbers.add("b"), but you cannot reassign numbers

val fixes the reference so reassignment fails, but the MutableList's contents can still be changed with add/remove/update.

Why is MutableList<T> invariant while read-only List<T> is covariant?

Answer: Because MutableList takes T as input via add, while List only returns T

A type used as a function parameter (in position) breaks covariance; read-only List only produces T (out position), so it is safely covariant.

Which statement about Kotlin read-only collections is correct?

Answer: A read-only List has no mutators, but its backing data may change elsewhere

Read-only interfaces are restricted views, not immutability guarantees; the backing object can still be a MutableList. True immutability requires kotlinx.collections.immutable.

What is the status of context receivers in modern Kotlin (2.2+)?

Answer: They were experimental, now replaced by context parameters (still experimental)

Context receivers (-Xcontext-receivers) were experimental and superseded by context parameters (-Xcontext-parameters) in Kotlin 2.2; both remain experimental.

Architecturally, what part of the Kotlin compiler did the K2 rewrite actually replace?

Answer: The frontend (analysis, resolution, inference) via new FIR, reusing IR backends

K2 is a frontend rewrite built around FIR for resolution and type inference; it reuses the existing IR-based JVM/JS/Native backends rather than replacing them.

Which statement about Array versus List in Kotlin is correct?

Answer: Array has fixed size and isn't a Collection, unlike List

Array is a fixed-size type that is not part of the Collection hierarchy, whereas List is a Collection interface whose mutable form (ArrayList) can resize.

Which is a genuine example of the K2 compiler's improved smart casting?

Answer: It smart-casts a captured local variable when reassignment can be ruled out

K2 propagates smart casts to captured local variables when reassignment can be ruled out; properties from other modules or platform types still cannot be smart-cast because mutation can't be guaranteed safe.

What is KSP2?

Answer: A redesigned KSP implementation with a newer API built to work with K2

KSP2 is a redesigned KSP with an improved API built to work cleanly with the K2 compiler; it is not a stub-generating processor or a Gradle caching feature.

You need a list that genuinely cannot be mutated through any reference. Which approach actually achieves that?

Answer: Use a persistent collection from kotlinx.collections.immutable.

A val only fixes the reference and a read-only up-cast is just a restricted view of a still-mutable backing object; true immutability requires a persistent collection from kotlinx.collections.immutable.

Declaring an interface as interface Source<out T> means what?

Answer: T is only in out positions, so Source<Cat> <: Source<Animal>

out marks declaration-site covariance: T may be used only in producer/out positions, which makes Source<Cat> a subtype of Source<Animal>. The in keyword (contravariance) is the consumer case.

What is the relationship between MutableList<T> and List<T> in Kotlin's collection hierarchy?

Answer: MutableList extends List, adding add() and remove()

MutableList is a subinterface of List, inheriting read access and adding mutators; this is why a MutableList can be passed wherever a read-only List is expected.

Back to Kotlin 2.x, KSP & Collections