Otherwise:
* should the dispatch receiver of a call be another call to a `suspend
fun` wrapped in something that is optimized away later, the owner of
the method will be incorrect;
* references to functions returning non-Unit but casted to `() ->
Unit` (allowed by new inference) might in fact not return Unit after
tail call optimization.
* TailCallOptimizationLowering should go into local classes in order to
transform their suspend methods;
* the check for invokes of noinline lambda arguments in codegen was
incorrect, as it also returned true for calls of lambdas stored in
local variables;
* IrInlineCodegen should mark non-inlinable arguments used as inline
suspend parameters;
* detection of suspend/inline call sites was incorrect (or maybe it's
the `compilationContextDescriptor` that was incorrect?..)
`invoke` in suspend lambdas overrides FunctionN.invoke, so the
refactored BridgeLowering already generates correct bridges there.
All the hack does is break overrides of interface suspend methods.
2 tests muted due to duplicate variables found by the validator
If memory serves:
- there is a `suspend inline fun` and a callable reference to it
- the suspend function doesn't remove the original function in this
case anymore
- the duplicate `var`'s are inside the function body and the
callable reference state machine body
Otherwise, on creating suspend function views these functions will clash
with interface ones. Instead, compute name of their continuation classes
based on attributes of the interface class.
Now AddContinuationLowering is responsible for both adding continuation
classes to suspend functions and adding continuation parameters to
them.
Because we cannot create a view if inline suspend function is defined
in another file, we generate a stub without body when we encounter call
to it. And then, when we lower the file containing the function we add
the body. This way we have no unlowered views after the lowering.
Thus, after the lowering there should be no suspend function, which
are not views, therefore, remove VIEW origins.
Because transformations of suspend functions can copy them into another
object, use attribute as a key inside function to view map.
The issue was, that built IR function does not have a PSI element,
which is required to report error on suspend functions inside monitors.
In this case, use PSI element of the class, containing the function,
which is consistent with old BE.
It is easier to introduce a new lowering so the codegen will emit code for the old
tail-call optimizer to understand. Also, this is more flexible and would allow to
optimize cases, which are now feasible with the old optimizer.
Note, that because of bytecode inlining, we cannot replace the old one, but we cannot
emit code, that is simpler for it to optimize.
Since the markers replace ALOAD 0 as continuations, passed to suspend calls, in
JVM_IR we do not need this, since in JVM_IR all inline lambdas are static
functions.
The problem in the added test was that a suspend lambda was represented
by a function reference with a bound argument for the ObjectRef value,
and the corresponding parameter was not the first parameter of the
referenced local function. This happens because
LocalDeclarationsLowering lifts the local function up and adds a
new parameter for the captured ObjectRef (which is bound at the call
site), but the original receiver parameter remains the first unbound
parameter. So, it's no longer correct to rely on the fact that all bound
parameters of a function reference are located in the beginning of the
parameter list, which was kind of assumed in the `withIndex` call in
`AddContinuationLowering.addCreate`.
This is important for calls using reflection as the reflect
library assumes this ordering of arguments.
It would be nice if this could be handled in the lowerings.
Currently AddContinuationLowering is after
DefaultArgumentStubGenerator. If we could add the continuation
first and then do default stub generation maybe we could avoid
the reshuffling introduced in coroutine codegen in this change.
suspend lambda.
The Name for the special destructuring declaration parameter was
incorrectly turned into a regular/non-special Name when the parameter
was moved to a field.
The idea is the same as in case of anonymous objects: they are created only
from Kotlin code, so we are sure, that the parameters are valid.
Also, the inliner complains on their transformations.
The main idea is the following: since we need to generate
(fake)continuations before inlining, we move IrClasses of suspend
lambdas and continuation classes of named functions into the functions.
Thus, it allows the codegen to generate them prior to inlining and
the inliner will happily transform them for us.
Because of that, lowerings which transform call-site function are likely
to change reference to lowered suspend lambdas or functions.
Hence, do not rely on references to lowered suspend lambdas or
functions, instead, rely on attributes.
Do not generate continuation for inline suspend lambdas.
Previously, inline suspend lambdas were treated like suspend functions,
thus we generated continuations for them. Now we just do not treat them
as suspend functions or lambdas during AddContinuationLowering.
We should add continuation parameter to them, however.
Do not generate secondary constructor for suspend lambdas, otherwise,
the inliner is unable to transform them (it requires only one
constructor to be present).
Generate continuation classes for suspend functions as first statement
inside the function.
This enables suspend functions in local object inside inline functions.
Since we already have attributes inside suspend named functions, we
just reuse them to generate continuation class names. This allows us
to close the gap between code generated by old back-end and the new
one.
If a suspend named function captures crossinline lambda, we should
generate a template for inliner: a copy of the function without
state-machine and a continuation constructor call. The call is needed
so the inliner transforms the continuation as well.
Refactor CoroutineTransformerMethodVisitor, so it no longer depends on
PSI.
if it overrides functions with another return type.
Otherwise, we cannot determine on call site that the function returns Unit
and cannot { POP, PUSH Unit } in order to avoid the situation when callee's
continuation resumes with non-unit result. The observed behavior is that
suspend function, which should return Unit, suddenly returns other value.
#KT-35262: Fixed
In old BE we generate `create` for this kind of suspend lambdas, which,
like in simple suspend lambdas is responsible for putting arguments
(including extension receiver) to fields.
But, if number of parameters of suspend lambda (including receiver) >= 1,
there is no need to generate `create`, since `create` is called only by
`createCoroutine` and friends from stdlib, and there is no version of
`createCoroutine` for lambdas with multiple parameters.
Thus, in old BE we generate a redundant method, which affects method
count.
In JVM_BE we decided to 'inline' create into `invoke` for suspend lambdas
with multiple parameters.