4
votes

I have an inline function with a reified type parameter taking a lambda, which returns a new instance of an anonymous class which has a single method taking that reified type parameter and passing it to the lambda.

inline fun <reified T : Any> eventHandler(crossinline handler: (T) -> Unit) = object {
    @Handler
    fun event(event: T) = handler(event)
}

It is used like eventHandler<ExampleEvent> { println(it.data); } and everything compiles.

However investigating the generated bytecode of the class created on the mentioned call, I get this for the event method:

public final void event(example.ExampleEvent);
    descriptor: (Ljava/lang/Object;)V
    [...]
    Signature: #53 // (Lexample.ExampleEvent;)V

So while it correctly remembers the type in the Signature, it discards it in the descriptor; therefore thatEventMethod.getParameterTypes() will have Object instead of ExampleEvent.

Is this a bug or intended behavior? Furthermore, if this is intended, could there be some other way of realizing my goal (which is to prevent having to create that clumsy object everywhere, add a dummy method with @Handler etc.)?

1
Why is T reified? That shouldn't be necessary in your code, unless this is just an simplified example and your actual code uses reification. - Ruckus T-Boom
Lambdas can have annotations. So you don't need object literals. (There will be a bridge method though, but it doesn't have that annotation so it's ok) - glee8e
I'm not sure if it's a bug or intented. You'd better file a ticket in the youtrack - glee8e
Looks like a bug to me. Indeed, please file a YouTrack issue. - yole

1 Answers

0
votes

So if I understand correctly your question is: is it ok that functions with reified generics in bytecode look like functions with erased types.

Answer is "yes". That's why functions with reified generics can bi inline-only. Their body is being full inlined into caller. And of course types are not erased there (at cost of bloating caller function bytecode size).