I observe an interesting type inference behavior r...
# compiler
k
I observe an interesting type inference behavior regarding
it
parameter in lambdas contained in pairs, lists or other data structures. This code sample
Copy code
var pair: Pair<Int, (String) -> String> = 2 to { "param $it" }
var pair2: Pair<Int, (String) -> String> = 2 to { p -> "param $p" }

var list: List<(String) -> String> = listOf { "param $it" }
var list2: List<(String) -> String> = listOf { p -> "param $p" }
looks fine to IDE, but fails to compile with the following errors for the lines using
it
lambda parameter:
Copy code
Type inference failed. Expected type mismatch: inferred type is Pair<Int, () -> String> but Pair<Int, (String) -> String> was expected
Unresolved reference: it
Type inference failed. Expected type mismatch: inferred type is List<() -> String> but List<(String) -> String> was expected
Unresolved reference: it
But the compiler is happy with the root-level lambda declarations like this
Copy code
var func: (String) -> String = { "param $it" }
var func2: (String) -> String = { p -> "param $p" }
Is this a bug or an intended behavior? Are there any workarounds that would make the compiler happy and at the same time keep the code neat (that is, using
it
but without full lambda type annotations at usage site)? I'm using Kotlin 1.3.71 in multiplatform project and can see this both in JVM and JS targets.
w
Regarding IDE vs compiler difference, perhaps you have new type inference enabled in IDE?
k
That was the case, thank you. After disabling it IDE reports the same type inference error too.
So I guess now that this behavior is going to change in one of the upcoming compiler versions?
w
Seems like it. As far as I understand though, new inference shouldn’t be more restrictive than the existing one, and any mismatch like this one is a (potential) bug
k
It looks the other way round, the old type inference is more restrictive than a new one. The old one doesn't expect
it
parameter despite of the expected function type, while the new one takes the expected function type into account and allows using
it
.
w
Ah, sorry, then I guess you’ll have what you want once new inference is enabled by default, right? (I suppose you can enable it early, too)
k
Yes, but I don't think I can enable it for the compiler too, can I?
Oh, I can see now that I can. I'll give it a try, thank you for the idea!
I actually found my case described in https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-4-m1-released/, under the "Inferring type automatically in more use-cases" header 🙂