For-in-string loop can be generated using specialized 'length' and
'charAt' method calls, and with cached string length.
Note that update of the string variable in loop body doesn't affect
loop execution semantics.
#KT-21322 Fixed Target versions 1.2.20
If the range expression is not a local variable (which can be updated in
the loop body affecting loop behavior, see KT-21354), we can cache the
array length, thus turning a for-in-array loop into a simple optimizable
counter loop.
#KT-21321 In Progress
Existing code for receiver generation accidentally worked in most cases
for object members imported by name. However, it generated strange
bytecode (such as
GETFIELD AnObject.INSTANCE
GETFIELD AnObject.INSTANCE
POP
), and worked incorrectly for augmented assignments.
#KT-21343 Fixed Target versions 1.2.20
Consider a context with uninitialized this, e.g.:
fun foo() {
val x = "..."
class Local(y: String) : Base(L@{ x + y })
}
Lambda 'L' is an argument of a super class constructor call.
Here 'this@Local' is not initialized yet. Thus local variables captured
in 'Local' can't be used. Instead, they should be captured by lambda 'L'
itself.
Note that lambda 'L' sees both 'x' and 'y' as local variables that
should be captured.
When in context with uninitialized this (generating arguments for super
type constructor or delegating constructor call), and a variable in
question is not found in the current context, use enclosing local lookup
to determine whether a local variable should be captured by a closure.
Enclosing class for closure is a class whose instance is captured by
closure as an outer 'this', and stored in a field 'this$0'.
Usually enclosing class for closure is an immediate outer class,
including classes for nested closures. For example:
class C {
fun foo() {}
val example1 = L1@ { foo() }
// Enclosing class for lambda 'L1' is 'C'
val example2 = L2a@ { L2b@ { foo() } }
// Enclosing class for nested lambda 'L2b'
// is a closure class for outer lambda 'L2a'
}
However, if the closure is created in a super type constructor call for
the outer class, corresponding instance is considered "uninitialized",
and can't be used as a proper class instance, and can't be referenced:
corresponding code is rejected by front-end.
class Outer {
fun foo() {}
inner class Inner : Base(L3@ { foo() })
// Enclosing class for lambda 'L3' is 'Outer',
// because 'Inner' is uninitialized in super type constructor call.
}
In CodegenAnnotatingVisitor, we maintain a stack of currently
uninitialized classes, and chose enclosing class for closure
as an inner-most surrounding class with initialized instance.
When generating code for this or outer class instance, we skip
contexts corresponding to classes with uninitialized instances.
This fixes a number of bytecode verification errors caused by incorrect
enclosing class for closure.
#KT-4174 Fixed Target versions 1.2.20
#KT-13454 Fixed Target versions 1.2.20
#KT-14148 Fixed Target versions 1.2.20
When a local function or class A creates an instance of a local class B
capturing an outer variable 'x', it should use ref for 'x', but not the
value of 'x'.
When a local function is captured, corresponding field accesses are
later transformed by the inliner. It doesn't have enough information to
restore the original semantics completely, so it has to rely on field
names. Local functions can be overloaded or can have names matching
local variable names, in both cases we generated fields with the same
name for captured values.
Now, we use the same '$<local-class-number>' suffix for field names for
local functions as it is present in the corresponding local class name.
This allows to distinguish captured local functions from captured local
variables and between different overloads of a function with the same
name.
#KT-19827 Fixed
#KT-18639 Fixed
Given a singleton class 'S' with possibly uninitialized static instance
(enum entry, interface companion object).
Such singleton can be referenced by name, or as an explicit or implicit
'this'.
For a given singleton class 'S' we
either use 'this@S' from context (local or captured),
or 'S' as a static instance.
Local or captured 'this@S' should be used if:
- we are in the constructor for 'S',
and corresponding instance is initialized
by super or delegating constructor call;
- we are in any other member of 'S' or any of its inner classes.
Otherwise, a static instance should be used.
It might differ from the JVM package FQ name if the JvmPackageName
annotation is used. This will be useful for faster indexing in the IDE
and for reflection
Constant expressions are inlined if they do not depend on non-inlineable
vals.
Java constants are always inlined.
Kotlin constants are inlined in LV 1.1+.
This commit support the following case.
Suppose we have such declaration:
fun <T> foo(): T { ... }
Then in code we want to use it like this: `foo() as String`.
But in LV <= 1.1 we have type inference error: "Not enough
information for type parameter `T`". This error happened because we
do not use type from cast as expected type for call.
In this commit we fix this problem and use this type as expected type
in following cases:
- our function has only one type parameter (this can be relaxed later)
- function parameter types and extension receiver type not contains `T`
Also this fix problem with `findViewById`.
Already signature was: `fun findViewById(...): View`
and was used like: `findViewById() as MyView`.
New signature is `fun <T : View> findViewById(...): T`
and old usage was broken because of problem described above