Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing SAM-constructor with lambda with covariant type

Tags:

kotlin

I have got the following Java interfaces:

interface Action1<T> {

    void call(T t);
}

interface Test<T> {

    void test(Action1<? super T> action)
}

And the following Kotlin class:

interface A {
    fun go()
}

abstract class Main {

    abstract fun a(): Test<out A>

    fun main() {
        a().test(Action1 { it.go() })
        a().test { it.go() }
    }
}

Now in the function main, the first statement compiles, but IntelliJ gives a warning that the SAM-constructor can be replaced with a lambda. This would result in the second statement.

However, this second statement does not compile, because it has type Any?, not A. Removing the out modifier makes it compile again.

Why does this happen?


The use case of this is when the implementing class of Main needs to return Test<B> for the function a(), where B implements A:

class B : A {

    override fun go() {
        TODO()
    }
}

class MainImp : Main() {
    override fun a(): Test<out A> {
        val value: Test<B> = object : Test<B> {
            override fun test(action: Action1<in B>?) {
                TODO()
            }
        };

        return value
    }
}
like image 472
nhaarman Avatar asked Apr 08 '16 09:04

nhaarman


1 Answers

It is a compiler bug. You can track it here: https://youtrack.jetbrains.com/issue/KT-12238.

like image 68
erokhins Avatar answered Oct 25 '22 10:10

erokhins