Why are Function parameters not `crossinline` by default?

@fatjoe79 My main point here is that the definer of the inline function is not aware that someone may pass lambdas with non-local returns.
Let’s call “Bob” the person who wrote the inline function, and “Alice” the person who calls the inline function. Bob makes a library that contains an inline fun foo(fn: () -> Unit), but due to not understanding inline functions, or due to carelessness or whatever reason, Bob didn’t realize that the function’s control flow may not fully complete (even assuming no exceptions), e.g. my indentLevel example in the OP. Bob may even have assumed that a loop containing fn will get executed exactly n times (so it can’t be solved with a simple try-finally block).
But these assumptions are not clearly documented, because Bob didn’t expect someone to return non-locally inside foo.
Now Alice calls foo() with a non-local return function. Note that Alice is aware of what non-local return means, and her logic is perfectly valid. She just doesn’t have the source code for the foo function, so she doesn’t know that foo executes something that needs restoration (e.g. setting a stack size to n and decrement every loop). And some bizarre bug occurs and Alice and Bob blame each other. (Mallory is happy)
Note that Alice did nothing wrong here. You may say that Bob has done a few wrong things:

  • If the logic reset is so important, he should have made it internal/private.
    • This boils down to the superman-in-underpants question.
    • Making something public doesn’t mean it can be messed up or must be foolproof and tolerate stupid code.
  • Bob doesn’t know about non-local returns.
    • But you can’t expect every Kotlin developer to recite all the features of the language.
    • A modern language should be designed to make the less common scenario special, not the common scenario special. This is also exactly why we have classes final by default.

The design that return jumps out of all functions looks misleading to people used to Java lambdas too, but that’s out of scope of this discussion. In this thread, I am assuming that people who write return in lambdas always know what they are doing; the point is that people who don’t write that return may forget that other people might do so.

1 Like