This option has no effect on the production code. But in a custom
scenario of a local bootstrap, where the compiler is replaced with the
one where JVM IR backend is enabled by default, this option allows to
switch back to the old backend.
All of these arguments (except the one for compiling experimental
coroutines) are supposed to go away as soon as we fix related problems
in the JVM IR backend.
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`.
Also,
1. remove some redundant copies;
2. fix remapping of non-local returns in lambdas if the body is moved
after LocalDeclarationsLowering (the lambda is no longer inside the
body, but must still be visited)
The JVM IR backend was producing class names with "<no name provided>"
for unnamed functions (i.e., `fun(...) {}`). This produces class files
with names invalid in Windows. This change adds validation of names
using the same set of invalid characters used in the frontend, which
should ensure class file names are valid.
Rename and refactor interface delegation phase. It didn't actually do
what was said on the box. It should be more in line with the
intentions of the phase now.
Wrapped descriptors are still used in reporting of the "conflicting JVM
signatures" diagnostic in the JVM IR backend, and TODOs in
implementations prevent that diagnostic from being shown, obscuring even
the place where the error happens.
After an inaccurate merge of 31936890 and d6ed93b2, this test was now
failing with the newly added assertion. It seems that currently the best
way to handle it would be to special-case these two methods in
SyntheticAccessorLowering.kt.
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.
The first change here is swapping the isCompatibility and hasJvmDefault
checks. Otherwise behavior could be different depending on -Xjvm-default
mode even for non-JvmDefault declarations, which makes little sense.
Another change is avoiding generating $default stubs for fake overrides
in interfaces, which replicates the behavior of the current backend.
(Note that this change also fixes the first problem on the newly added
tests, but the first change seems useful anyway.)
Not sure if this affects real code, but this could happen in erroneous
cases such as in the subsequent commit, where it was a bit weird to see
this suffix without any supercalls involved.
This only reproduced when compiling (technically incorrect) code in the
standard library, where private functions monitorEnter/monitorExit are
accessed from another file, and their names with suffixes are not
recognized as intrinsics which should be replaced by
monitorenter/monitorexit JVM bytecode instructions.
This would help for example in debugging the issue fixed in the previous
commit.
The only problem by now where this lowering tried to add accessors to
foreign files was reproduced for interfaces inheriting from Cloneable.
There, we generate a DefaultImpls bridge that calls protected method
`clone` from java.lang.Cloneable.DefaultImpls. This makes no sense, but
the old backend behaves the same. Instead of generating accessor for it
in JVM IR, we now see all DefaultImpls bridges as public as a
workaround. (The fact that assertion no longer fails here is checked
e.g. by box/reflection/mapping/methodsFromObject.kt.)
SyntheticAccessorLowering was initially implemented under the assumption
that any access to an invisible declaration will cause an accessor to be
generated _in the same file_. Moreover, it's declared in the group of
phases that are performed by file.
But this assumption is incorrect for constructors which need to be
hidden (those which take parameters of inline class types), since such
constructor is public and can be called from anywhere. In this case,
SyntheticAccessorLowering actually generated a new accessor for the
hidden constructor for each (!) source file where that constructor is
called, which led to ClassFormatError because of the class file having
multiple methods with the same signature. The internal `functionMap`
cache didn't help because it's not shared among phase instances for
different files (well, it helped to generate not more than one accessor
per usage-file).
In this change, we use the global cache, stored in JvmBackendContext,
for accessors to hidden constructors. Note that after this change, calls
to hidden constructors are always transformed to the corresponding
accessor in SyntheticAccessorLowering right away, but that accessor
might be orphaned for a while (not declared in any parent's
declarations). Only when SyntheticAccessorLowering encounters the
original constructor which needs to be hidden, it adds the accessor
beside it.
The test is sensitive to the file order, so both variants are added.
See KT-35849.
1. When expected lambda return type is a type parameter, don't generate
introduce implicit casts (even if the corresponding type parameter has
an upper bound that would otherwise require such cast).
2. Do not generate implicit null check for lambda return value of
@EnhancedNullability type.
Local functions raised in LocalDeclarationLowering continue to refer to
type parameters that are no longer visible to them.
This commit only adds new type parameters to their declarations, which
makes JVM accept those declarations. The generated IR is still
semantically incorrect (needs further fix), but code generation seems
to proceed nevertheless.
Whenever we want the default 0/null value for a type we need to
check if it is a non-nullable inline class type and produce
the right value for the underlying type.
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.
FAKE_OWNER is a hack for when we encounter IrFunctions with non-class
parents during codegen. This can only happen for unhandled intrinsic
functions and resolving them to FAKE_OWNER can cause codegen to succeed
while producing broken bytecode.
There are two array intrinsics which are handled in the inliner on the
JVM backend: arrayOf and emptyArray. In the IR backend we are already
lowering arrayOf as part of VarargLowering and this commit adds support
for lowering emptyArray as well.
interface I {
fun f(x: Int = 1)
}
class C(val y: I) : I by y {
// implicit `override fun f(x: Int) = y.f(x)` has a default value for `x`
}
-- the only case where a function with overridden symbols has defaults.
1. Postpone the computation of the signature for property
reference getters for extension properties until codegen time.
2. Generate metadata for static replacement functions instead
of the original functions.
It uses the same logic as an old back-end
(see SamType#createByValueParameter and genericSamProjectedOut.kt),
split into two parts:
1. When inserting SAM casts, use SamType#createByValueParamerer to get
the target SAM type.
2. When inserting implicit casts, cast SAM conversions as arguments of
methods of out-projected types to the original type of value parameter
instead of 'Nothing'.
Consider the following example:
Java:
public class J {
public static String foo() { return null; }
}
Kotlin:
fun check(fn: () -> Any) = fn()
fun test() = check { J.foo() }
When a lambda expression returns a value of platform type ('String!'),
corresponding lambda has platform type in its return type, which is
approximated to corresponding nullable type ('String?') in IR.
However, the lambda itself could occur in position with a functional
expected type ('() -> Any'). This implies an extra implicit cast on a
return value of lambda expression ('J.foo()'), although it conforms to
the return type of lambda.
When generating bodies for members implemented by delegation, invoke
corresponding delegate member, not an interface member. Otherwise we
might lose platform-specific nullability information in case of mixed
Kotlin-Java hierarchies, as in
implicitNotNullOnDelegatedImplementation.kt