Otherwise, the cached instances cannot be reused for different wrapped
types. Also, if the wrapped type is regenerated during inlining, the
inliner would produce a call to a nonexistent constructor that takes the
regenerated type as an argument.
To avoid bytecode sequences like
new _1Kt$sam$i$java_lang_Runnable$0
dup
new _1Kt$f$1
dup
invokespecial _1Kt$f$1.<init>()V
invokespecial _1Kt$sam$i$java_lang_Runnable$0.<init>(...)V
as the different order of `new` and `<init>` confuses the inliner.
Consider the following constraint system (from the test example):
Nothing? <: V1
F!! <: V2
Inv<V1> <: S
Inv<V2> <: S
Where V1, V2, S are type variables, and F has nullable upper bound.
Type variable fixation order should be: V2 -> V1 -> S, and the problem
was that previously after fixation of type variable V2 we were trying
to fix S (before V1), so we had the following constraints on S:
Inv<F!!> <: S
Inv<V1> <: S
=> S were fixed to Inv<F!!>
And after this V1 was fixed to F!! which is contradictory as Nothing?
is not a subtype of F!!.
#KT-33033 Fixed
#KT-30297 Fixed
#KT-32168 Fixed
#KT-27722 Fixed (actually, it was fixed with addition of DefNotNullTypes, and now test was added to save this behavior)
#KT-32345 Fixed
Namely, anonymous objects defined in lambdas that have all captured
variables as loose fields instead of a single reference to the parent.
The question is, when a lambda inside an inline function defines an
anonymous object, and that object is not regenerated during codegen for
the inline function itself, but then has to be regenerated at call site
anyway, do we use an outer `this` or loose capture fields? For example,
before KT-28064:
inline fun f1(g: () -> Unit) = object { g() }
// -> f1$1 { $g: () -> Unit }
inline fun f2(g: () -> Unit) = f1 { object { g() } }
// -> f2$$inlined$f1$1 { $g: () -> Unit }
// f2$$inlined$f1$1$lambda$1 { this$0: f2$$inlined$f1$1 }
inline fun f3(g: () -> Unit) = f2 { object { g() } }
// -> f3$$inlined$f2$1 { $g: () -> Unit }
// f3$$inlined$f2$1$1 { this$0: f3$$inlined$f2$1 }
// f3$$inlined$f2$1$1$lambda$1 { this$0: f3$$inlined$f2$1$1 }
After KT-28064:
inline fun f2(g: () -> Unit) = f1 { object { g() } }
// -> f2$$inlined$f1$1 { $g: () -> Unit }
// f2$1$1 { $g: () -> Unit }
inline fun f3(g: () -> Unit) = f2 { object { g() } }
// -> f3$$inlined$f2$1 { $g: () -> Unit }
// f3$$inlined$f2$2 { ??? }
// f3$1$1 { $g: () -> Unit }
Should `???` be `this$0: f3$$inlined$f2$1` or `$g: () -> Unit`? This
commit chooses the latter for KT-28064 bytecode and keeps `this$0` when
inlining the old bytecode.
Revert "[JS IR] Build hybrid versions of stdlib and kotlin.test"
This reverts commit b9f88350dd.
Revert "[JS IR] Add gradle plugin integration tests"
This reverts commit d872b27663.
Revert "Update bootstrap"
This reverts commit bc47594c7a.
Revert "[JS IR] Support generating both IR and pre-IR libraries"
This reverts commit 1b8df45bfe.
These changes allow us to accurately distinguish between statements and
expressions in the IR.
This also fixes the types of non-exhaustive conditional statements.
We should only insert a return statement at the end of a lambda or
function if the final statement is used as an expression (slice
USED_AS_RESULT_OF_LAMBDA and USED_AS_EXPRESSION).
- Added tests to demonstrate broken behaviour: the interaction of inline
functions and callable references with varargs and defaults in various
combinations.
- Refactored InlineCallableReferencesToLambdaPhase to look like and use
some of the infrastructure from CallableReferenceLowering.
- Lifted some of this infrastructure out to be broadly reusable.
Take branching and method calls into account when finding the line
number of the continuation. If there is no line number before
branching instructions or method calls, the following code is
still on the line of the suspend call itself.
This fixes a couple of issues with incorrect line numbers for
multiple throws on the same line or multipe suspend calls on
the same line.
In addition, it avoids the need to spam the method node with
repeated line number instructions in the IR backend.