I think I may have encountered a compiler bug regarding reified type parameters. It’s probably easiest to explain with a code example:
fun main() {
println("Same:");
proxySame<Int>();
directSame<String, Int>();
println("\nDifferent:");
proxyDiff<Int>();
directDiff<String, Int>();
}
inline fun <reified P> proxySame() = directSame<String, P>();
inline fun <reified P, reified Z> directSame(
func: () -> Unit = {
println(Z::class.java.simpleName)
}
) = func();
inline fun <reified P> proxyDiff() = directDiff<String, P>();
inline fun <reified Q, reified Z> directDiff(
func: () -> Unit = {
println(Z::class.java.simpleName)
}
) = func();
This example is obviously not a real-world scenario, but it’s the simplest program I could find that still manifests the unexpected behavior.
In this code there are 2 types of functions: directX
and proxyX
, where X
is either Same
of Diff
. The only difference between the Same
and Diff
functions is the name of the first type parameter of the directX
function. For Same
it’s the same as the proxyX
function, for Diff
it’s different.
One would expect the output to be the same, regardless of whether directX
was called through the proxy function or not.Unfortunately, this is apparently not always the case:
Same:
String (proxy, wrong)
Integer (direct, correct)
Different:
Integer (proxy, correct)
Integer (direct, correct)
As you can see the output is different when calling through the proxy function, but only if the reified type parameters have the same name.
The value of P
of the proxy
function has somehow ended up in the Z
of the direct
function. However, this only happens inside the lambda function, printing the class name in the regular function body leads to the expected result.
I’m at a complete loss here. I can’t find any other explanation for this, other than it being a compiler bug. Have I truly run into some obscure bug, or have I somehow missed something here?
Edit: I just discovered that it works correctly if I add the noinline
modifier to the lambda parameters, so I’ll use that as a workaround for now.