I have a huge problem with K2 and overload resolut...
# compiler
o
I have a huge problem with K2 and overload resolution of a function taking a lambda type. I have two possibilities and need two distinct implementations for one function (the name must be identical, it's a DSL function):
Copy code
fun <O : Any> test(doIt: () -> O) {
    TODO()
}

fun <O> test(doIt: () -> O?) {
    TODO()
}

fun demo() {
    test { "" }
    test { null }
}
test must exist in two flavors: • one where the lambda block can return anything that is nullable • another that must be chosen if the return value cannot be null. With my declaration as above, I think the compiler can find a matching method for the String and also for the null value: the first must resolve to the nun-nullable version, the second should (it's the only match!) resolve to the second implementation. But the reality is different, sadly - the one returning null is getting a compiler error:
Cannot infer type for type parameter 'O'. Specify it explicitly.
I tried every variation I could think of, nothing works. Also tried
@OverloadResolutionByLambdaReturnType
but that also did not change anything. Is there any trick I need to pull here to teach the compiler to take the second function for nullable lambda return types?
b
There is this combo of annotation and suppression you should not use:
Copy code
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
Also: don't blindly trust the IDE that it isn't working just because there are red squiggly lines 😉
but i am unsure it will help in your case
o
Never used these single or in combination... And no, it does not compile. It's not just the squiggly line...
b
Then join the dark side! We have the verboten annotations
o
Can anybody explain why exactly the compiler struggles? For me, looking at this - there is only one possible perfect match for the generics I specified....
The error explains only why the first function cannot work. But it ignores completely that there is another function where it works.
b
My wild guess would be that nullability alone is not enough to disambiguate, but no idea why
o
I tried you annotations, sadly they don't do the trick. 😞
If you explicitly put the type, the compiler has no problems identifying the method overload to chose:
Copy code
test<String?> { null }
works. But I do not want my users to understand generics and literally anything about the "magic" behind the scenes...
b
I tried your example in a Kotlin play and it compiles and runs: https://pl.kotl.in/SOoXlmcXq
Nvm, compilation is not the issue here, but wrong resolution
o
Yep. It compiles, but calls the wrong function. But I wonder why this works in Playground, but not in IntelliJ. I mean, the compilation...