Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sealed interface with a bounded type parameter generates code with errors #137

Open
eygraber opened this issue Jun 7, 2023 · 4 comments
Assignees
Labels
question Further information is requested

Comments

@eygraber
Copy link

eygraber commented Jun 7, 2023

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""")
    }
}
@alexvanyo
Copy link
Collaborator

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
}

@eygraber
Copy link
Author

eygraber commented Jun 7, 2023

No in my actual use case it needs to be invariant.

@alexvanyo
Copy link
Collaborator

Which type X would you expect SealedEnum<X> to be in your case?

@eygraber
Copy link
Author

eygraber commented Jun 7, 2023

That's a good question 😄

@alexvanyo alexvanyo added the question Further information is requested label Jun 11, 2023
@alexvanyo alexvanyo self-assigned this Jun 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants