JvmName for overloads makes code to compile, but w

2019-07-29 14:27发布

问题:

Following from my another question, I'm trying to call 2 functions:

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

and

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

but I get this error:

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

Does anybody know how to fix this?

I'm trying to call the functions as follows:

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

回答1:

I think I can see what is happening here. You are doing something like:

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!

So the error is because the compiler is trying to infer the type of the lambda function by using the method signature to which it is passed (because that will indicate the parameters coming in and the result going out), but the function itself has ambiguous declarations that only differ by return type. So I think the loop is something like: first the lambda input parameters can be inferred from the function being called, then the return type is known and can be enforced upon the lambda. And here that loop cannot be completed because of matching parameter lists. I would think the return type would be enough but it seems to be a hole in the type inference system to go both directions at the same time.

What you can do is slightly ugly, but type the function call:

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

or

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

So that the compiler is not having to guess both directions and being short on information.

Most of the type inference known bugs are listed as children of this issue: KT-11289. You can check there for related issues, or add your own.



标签: kotlin