Reified parameter evaluated in a surprising manner

Hello everyone,

when trying to solve an…interesting bug, I stumbled upon behavior that I consider opposed to the principle of least astonishment. I isolated it to the following code:

inline fun<reified T> bar(block: () -> (() -> Unit)) = block()

inline fun<reified T> foo() {

    val baz = bar<String> {
        { println(T::class.simpleName); }
    }

    baz()
}

foo<Int>() // Prints "String"

Running this code produces “String” as the output, contrary to what one would intuitively expect, which is “Int”. Changing one of the names of the type parameters solves the issue:

inline fun<reified R> bar(block: () -> (() -> Unit)) = block()

inline fun<reified T> foo() {

    val baz = bar<String> {
        { println(T::class.simpleName); }
    }

    baz()
}

foo<Int>() // Prints Int

I think I understand what happens and I’m not sure it’s even a bug, it’s just surprising. Maybe the compiler could issue a warning when this happens?

Kind regards,

Gabriel

EDIT: Removed the run() call from bar(), as it is not necessary to reproduce the behaviour.

Inside the scope of foo, T is indeed an Integer. If you print the name of T, not surprisingly, you will get Integer as output.

Furthermore, R inside bar is not even used.

I would agree entirely, except that you don’t get Integer as output. As I explicitly say in the OP, if the parameters are named the same, you get String (or whatever you pass to bar) as output.

Also, it’s an illustrative piece of code, it’s not supposed to do anything, just provide a minimal example of the issue :slight_smile:

1 Like

@gabriel-shanahan When I look at this, I think you have found either a compiler bug or a design edge case. I’m not sure which one. Somehow T inside the block is resolved against the variable in bar (while invoking block). I would say put it as a bug in to youtrack as it should be documented if a feature (as a feature it makes the name of the type parameter part of the API so it seems weird, also it should then work without the extra indirection).

Thanks for the tip. I did some searching and found out that this had already been reported a couple of days before I created this topic, but in a more complex environment. See here: https://youtrack.jetbrains.com/issue/KT-34856