Kotlin compiler mixing up reified type parameters

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.

3 Likes

Nice catch, have you created an issue over at https://youtrack.jetbrains.com?

Yes I have, KT-36237.

1 Like