Reputation: 736
Let's say we have a 3rd-party Java library with such class:
//----------------------------------------------------------------------------------------
package foo;
public final class Functions {
public interface VoidFunc0 {
void call();
}
public interface VoidFunc1<T> {
void call(T t);
}
@SuppressWarnings("unchecked")
public static <T> NoOpFunc<T> noOp() {
return new NoOpFunc();
}
/*public*/ static final class NoOpFunc<T> implements VoidFunc0, VoidFunc1<T> {
@Override public void call() { /* deliberately no op */}
@Override public void call(T t) { /* deliberately no op */ }
}
}
//----------------------------------------------------------------------------------------
We successfully used its Functions.noOp()
method in our Java application, but when we began to rewrite it in Kotlin, we faced the issue that the code below doesn't compile and gives us two errors:
//----------------------------------------------------------------------------------------
package bar
import foo.Functions
object KotlinApp {
@JvmStatic
fun main(args: Array<String>) {
/*
* Error:(XX, XX) Kotlin: Type inference failed: Not enough information
* to infer parameter T in fun <T : Any!> noOp(): Functions.NoOpFunc<T!>!
* Please specify it explicitly.
*/
callVoidFunc0(Functions.noOp()) // ERROR 1
/*
* Error:(XX, XX) Kotlin: Type Functions.NoOpFunc<Any!>! is inaccessible
* in this context due to: Functions.NoOpFunc<Any!>!
*/
callVoidFunc1(Functions.noOp()) // ERROR 2
}
fun callVoidFunc0(func0: Functions.VoidFunc0) {
func0.call()
}
fun callVoidFunc1(func1: Functions.VoidFunc1<Any>) {
func1.call("A")
}
}
//----------------------------------------------------------------------------------------
but the same code previously written in Java compiles and works well:
//----------------------------------------------------------------------------------------
package bar;
import foo.Functions;
public class JavaApp {
public static void main(String[] args) {
callVoidFunc0(Functions.noOp()); // OK
callVoidFunc1(Functions.noOp()); // OK
}
public static void callVoidFunc0(Functions.VoidFunc0 func0) {
func0.call();
}
public static void callVoidFunc1(Functions.VoidFunc1<Object> func1) {
func1.call("A");
}
}
//----------------------------------------------------------------------------------------
Type inference fails even if we specify T
explicitly. Error 2 goes away when NoOpFunc
declared as public
, but Error 1 still remains.
Upvotes: 4
Views: 8701
Reputation: 736
The problem is a bug in Kotlin. Here's the link to the issue: https://youtrack.jetbrains.com/issue/KT-14499. Please vote.
UPD To fix the issue there's a workaround:
@JvmStatic
fun main(args: Array<String>) {
@Suppress("INACCESSIBLE_TYPE")
callVoidFunc0(Functions.noOp()) // (1)
@Suppress("INACCESSIBLE_TYPE")
callVoidFunc1(Functions.noOp<Any>()) // (2)
}
To fix (1) one must suppress the compilation warning, to fix (2) - additionally specify the type explicitly.
Upvotes: 4