sealed-enum
sealed-enum copied to clipboard
Sealed interface with a bounded type parameter generates code with errors
If I have the following code:
sealed interface Foo {
object Bar : Foo
object Baz : Foo
}
sealed interface FooProvider<T : Foo> {
object BarProvider : FooProvider<Foo.Bar>
object BazProvider : FooProvider<Foo.Baz>
@GenSealedEnum
companion object
}
then the resulting code is generated, but with errors (I added the errors as inline comments):
/**
* An implementation of [SealedEnum] for the sealed class [FooProvider]
*/
public object FooProviderSealedEnum : SealedEnum<FooProvider<Foo>> {
public override val values: List<FooProvider<Foo>> by lazy(mode =
LazyThreadSafetyMode.PUBLICATION) {
listOf(
FooProvider.BarProvider,
FooProvider.BazProvider
)
}
/*
*Property delegate must have a 'getValue(FooProviderSealedEnum, KProperty*>)' method. None of the following functions are suitable.
*Lazy<List<FooProvider<out Foo>>>.getValue(Any?, KProperty<*>) where T = List<FooProvider<out Foo>> for inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T defined in kotlin
*/
public override fun ordinalOf(obj: FooProvider<Foo>): Int = when (obj) {
is FooProvider.BarProvider -> 0 // Incompatible types: FooProvider.BarProvider and FooProvider<Foo>
is FooProvider.BazProvider -> 1 // Incompatible types: FooProvider.BazProvider and FooProvider<Foo>
}
public override fun nameOf(obj: FooProvider<Foo>): String = when (obj) {
is FooProvider.BarProvider -> "FooProvider_BarProvider" // Incompatible types: FooProvider.BarProvider and FooProvider<Foo>
is FooProvider.BazProvider -> "FooProvider_BazProvider" // Incompatible types: FooProvider.BazProvider and FooProvider<Foo>
}
public override fun valueOf(name: String): FooProvider<Foo> = when (name) {
"FooProvider_BarProvider" -> FooProvider.BarProvider // Type mismatch. Required: FooProvider<Foo> Found: FooProvider.BarProvider
"FooProvider_BazProvider" -> FooProvider.BazProvider // Type mismatch. Required: FooProvider<Foo> Found: FooProvider.BazProvider
else -> throw IllegalArgumentException("""No sealed enum constant $name""")
}
}
The processor is trying to match the type specified as close as possible, and the following won't compile either:
val values: List<FooProvider<Foo>> = listOf(
FooProvider.BarProvider,
FooProvider.BazProvider
)
Does it work for your case to have your generic type be defined as out T : Foo?
sealed interface FooProvider<out T : Foo> {
object BarProvider : FooProvider<Foo.Bar>
object BazProvider : FooProvider<Foo.Baz>
@GenSealedEnum
companion object
}
No in my actual use case it needs to be invariant.
Which type X would you expect SealedEnum<X> to be in your case?
That's a good question :smile: