用于重载的JvmName使代码得以编译,但是在调用函数时会引发错误

时间:2018-07-29 14:12:29

标签: kotlin

从另一个question开始,我正在尝试调用2个函数:

@JvmName("myFunction1")
fun <T> Foo<T>.myFunction(func: () -> Foo<Any>): Foo<T>

@JvmName("myFunction2")
fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T>

但我收到此错误:

Cannot choose among the following candidates without completing type inference:
@JvmName public fun <T> Foo<Any>.myFunction(func: () → Foo<Any>): Foo<Any> defined in common.result
@JvmName public fun <T> Foo<Any>.myFunction(func: () → Unit): Foo<Any> defined in common.result

有人知道如何解决此问题吗?

我试图按以下方式调用函数:

myFoo.myFunction{ methodReturningUnit() }
myFoo.myFunction{ methodReturningFooOfAny() }

1 个答案:

答案 0 :(得分:2)

我想我可以看到这里发生了什么。您正在执行以下操作:

class Foo<T> {}

@JvmName("myFunction1")
fun <T> Foo<T>.myFunction(func: () -> Foo<T>): Foo<T> {
   // ...
}

@JvmName("myFunction2")
fun <T> Foo<T>.myFunction(func: () -> Unit): Foo<T> {
   // ...
}

// call the function, but get a compiler error
fooInstance.myFunction { somethingThatReturnsFooAny() } // ERROR!

所以错误是因为编译器试图通过使用传递给它的方法签名来推断lambda函数的类型(因为这将指示传入的参数和退出的结果),但是函数本身具有不明确的声明,仅在返回类型上有所不同。因此,我认为循环类似于:首先可以从调用的函数推断出lambda输入参数,然后知道返回类型,并且可以对lambda强制执行该返回类型。由于匹配参数列表,因此无法完成该循环。我认为返回类型就足够了,但这似乎是类型推断系统中同时向两个方向发展的一个漏洞。

您可以执行的操作有点丑陋,但是请键入函数调用:

fooInstance.myFunction(fun ():Foo<Any> { return somethingThatReturnsFooAny() })

val funcy = fun (): Foo<Any>  { return somethingThatReturnsFooAny() }
fooInstance.myFunction(funcy)

这样编译器不必猜测两个方向,也不必缺少信息。

大多数类型推断已知错误均作为此问题的子级列出:KT-11289。您可以在此处查看相关问题,也可以添加自己的问题。