Kotlin / KEEP

Kotlin Evolution and Enhancement Process
Apache License 2.0
3.3k stars 356 forks source link

Sealed inline classes #318

Open udalov opened 1 year ago

udalov commented 1 year ago

This issue is for discussion of the proposal to introduce sealed inline classes in Kotlin.

Proposal PR #312

udalov commented 1 year ago

The rules that govern which types are allowed as representations for sealed inline classes allow to have a final class and interface in two distinct subclasses of a sealed inline class.

For example, this is allowed:

@JvmInline
sealed value class Z

@JvmInline
value class A(val value: M): Z()

@JvmInline
value class B(val value: N): Z()

class M
interface N

However, if M is changed to inherit from N, an error is reported according to the proposal.

This makes adding a superinterface to a class a source-breaking change, in case some client code uses them as representations of sealed inline classes in different child subclasses.

Also, if M is changed without recompiling the client code, behavior of existing code will change. Something like this:

    val a: Z = A(M())
    println("is B: " + (a is B))

will start to incorrectly be true.

thumannw commented 1 year ago

From the restrictions, sealed value class cannot have primary constructor or backing fields, hence it essentially is a sealed value interface. This saves some () when declaring the children. Furthermore, the compiler needs to know all inheritors for generating the necessary code, so value implies sealed in this context (similar: sealed implies abstract implies open). We arrive at the very succinct value interface. Nice?