Inline Receivers

For consistency, I think it is desirable to be able to inline receivers whenever those are function types. Currently

inline fun (() -> Unit).runThenPrint(str: String) {
     this()
     println(str)
}

generates the expected warning that expected performance gain is negligible, since the receiver is not inlined. And one can verify the byte code emitted at calls site to see that indeed, no inlining is performed.

Why is it desirable?

For one it would make some kind of DSL much easier to write while preserving their performance, especially where function composition is involved.

For instance, if receivers were inlined, you would be able to compose multiple Sequence-style operation without creating an intermediate sequence each time.

Here is a gist that showcases that idea: Showcasing the usefulness of inline receivers in Kotlin · GitHub

Note how the desugaring produces tight nested loops instead of creating two intermediate sequences which have to call to the previous sequence.

I have the same use case when I use a DSL to compose parsers written in kotlin. Here is a parser definition for an identifier:

fun iden()
    = word { seq { alpha() && repeat0 { alphanum() } } }

I have to write it this way to benefit from inlining, but I would really like to write:

fun iden()
    = seq { alpha() && alphanum.repeat0() }.word

I’m sure there are many other use cases. The point is that the ability would be tremendously useful to define efficient DSLs.

I’m prepared to write a KEEP if the idea is not rejected out of hand.

1 Like

This request is being tracked in the issue https://youtrack.jetbrains.com/issue/KT-5837

2 Likes