Union types would make a big difference in Kotlin. At the moment, a sealed class is the closest thing to a union type, but it has several limitations, the biggest being that you can only have subtypes defined by you as part of a sealed class.
The proposal would be for the type system to understand union types as a concept. A few examples.
Dynamic casting:
val something: Int|String|Boolean = TODO("implement")
if (something is String|Boolean) {
// here it's a string or a boolean
} else {
// here it's an int
}
Intersection of available functions:
class First(val value: Int) {
fun speak() { println("shouting") }
}
class Second(val value: Int, val name: String) {
fun speak() { println("talking") }
}
fun main() {
val something: First|Second = TODO("implement")
val value = something.value
something.speak()
// something.name doesn't compile
}
Syntax sugar for Null type:
val messageOrNull: String? = TODO("implement")
val messageOrNull2: String|Null = TODO("implement")
Covariance and contravariance:
fun main() {
val consumerWider: (String|Int) -> Unit = TODO("implement")
val consumerNarrower: (Int) -> Unit = consumerWider
val producerNarrower: () -> Int = TODO("implement")
val producerWider: () -> String|Int = producerNarrower
}
Covariant and contravariant overriding:
interface MessageProcessor {
val format: String|Format
fun process(input: String|Message): String|Message
}
class InMemoryMessageProcessor(override val format: Format) : MessageProcessor {
override fun process(input: String|Message?): Message
}