Bart van Heukelom
Bart van Heukelom

Reputation: 44094

Call inline lambda with another inline lambda argument

I'm trying to make this higher-order Kotlin function:

private inline fun <T> reentrant(entered: ThreadLocal<Boolean>, block: () -> T, enter: (() -> T) -> T) =
    if (entered.get()) block()
    else {
        try {
            entered.set(true)
            enter(block)
        } finally {
            entered.set(false)
        }
    }

To be used like this, for example:

reentrant(fooing, block) { b ->
  try {
    log("Entering a state of foo")
    b()
    // sidenote: while writing this question it dawned on me,
    //           that i could just calll the captured `block` here,
    //           as a workaround
  } finally {
    log("Foo nevermore")
  }
}

However, apparently the construct enter(block) is not allowed (Illegal usage of inline parameter block).

Since everything here is inline, I think it should be technically possible. Is this feature just not supported by the compiler? Or is there a way I can do this after all?

Upvotes: 1

Views: 587

Answers (1)

Yoni Gibbs
Yoni Gibbs

Reputation: 7018

You get the same error if you do something like val x = block. If you try to decompile that Kotlin into Bytecode the very last error you'll see is:

Trying to access skipped parameter

I think the point is that when you inline something it's no longer an object in the code, so you can't directly refer to it. Obviously just calling the function itself is OK as that's inlined into your calling code.

This is explained in more detail here. When the function parameter is inlined, there is no Function object created. I wonder if in your question what you're implying is: "Why doesn't the compiler inline enter and then inline block into that?" And I guess the reason is that this would assume that all enter does is invoke block. But what if it didn't? What if it wanted to store a reference to it, e.g. in a list of functions to call at some point in future? It couldn't do this, as there's no Function object for it to reference.

Upvotes: 1

Related Questions