-1

Don't think the title is best wording for this question, I have an interface with two type arguments, and I seem to be able to cast this as both of the types at the same time, see reproducable example:

interface BaseResult<S : BaseResult<S, E>, E : BaseResult<S, E>> {

    @Suppress("UNCHECKED_CAST")
    fun isSuccess(): Boolean {
        return try {
            val a = this as S //ClassCastException expected
            val b = this as E
            println(a) //com.BaseResultTest$ExampleResult$Error@17d10166
            println(b) //com.BaseResultTest$ExampleResult$Error@17d10166
            true
        } catch (e: Exception) {
            false
        }
    }
}

Test:

class BaseResultTest {

    sealed class ExampleResult: BaseResult<ExampleResult.Success, ExampleResult.Error> {
        object Success: ExampleResult()
        object Error: ExampleResult()
    }

    @Test
    fun test() {
        val error = ExampleResult.Error
        assertEquals(error.isSuccess(), false)
    }
}

Am I missing something, or is this a bug in the language? Using v1.3.61

John Sardinha
  • 3,079
  • 4
  • 21
  • 50

2 Answers2

1

It is type erasure, which works the same way for all generics, not just for interfaces. In this case both casts become equivalent to as BaseResult<*, *>.

Kotlin has a way to avoid it, but only for type parameters of inline methods, not classes or interfaces.

Alexey Romanov
  • 154,018
  • 31
  • 276
  • 433
0

This isn't so much of a bug in the Language, but more of a logic error of the writer. While you can inflect the type of S and E, they're still similar to an Option and it's sub types of Some and None (Some is always typed to the Option<_> whereas None always is empty.

Part of your problem here is that you cannot guarantee the subclass is a type of S or E without explicitly declaring the subtypes for those cases. You can see examples of this in trying to implement Either, and some other examples including this one about Either.

I hope this helps answer the question.

gabizou
  • 103
  • 6