Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin bad type inference gives overload resolution ambiguity

Consider the overloaded function foo:

fun foo(i: Int) { /* */ }
fun foo(i_s: Collection<Int>) { /* */ }

I get an overload resolution ambiguity error with the following code:

val bar = foo(Stream.empty<Int>().collect(Collectors.toList()))

Overload resolution ambiguity:
public fun foo(i: Int): Unit defined in ...
public fun foo(i_s: Collection): Unit defined in ...

As far as I can tell the resolution should be clear: I am collecting the stream to a list, so the foo(Collection<Int>) should be taken. Some more experiments suggest a failure to resolve the generics correctly, so:

  1. Why does the generics resolution fail in this case?
  2. Is this "flaw" documented somewhere? Is this a bug I should report?

I tested a few other things: foo(listOf()) does not error, neither does

val bar = Stream.empty<Int>().collect(Collectors.toList())
val baz = foo(bar)

Replacing toList() with toSet() does not alter the behavior, but toCollection { ArrayList<Int>() } compiles in all cases.

If I change foo to fun <T> foo(i_s: Collection<T>), the error changes to

Type inference failed. Expected type mismatch: inferred type is (Mutable)List! but Int was expected

This opens more questions for me:

  1. Why does the resolution work if I store the intermediate result in a variable? After all, its type is resolved automatically as well?
  2. What does the type inference error mean? Why does it occur?
like image 553
Qw3ry Avatar asked Jul 06 '19 09:07

Qw3ry


Video Answer


1 Answers

Looks like this is a bug in the old inference algorithm, because it works correctly with the new inference. I filed an issue in the Kotlin bug tracker, at least for adding a regression test. You can follow it for updates.

More information on new inference:

https://youtrack.jetbrains.com/issue/KT-31507

https://blog.jetbrains.com/kotlin/2019/06/kotlin-1-3-40-released/

like image 160
Alexey Belkov Avatar answered Sep 30 '22 03:09

Alexey Belkov