Consider `fun <E : I> foo(a: Any?) = a as? E`, where I is an interface.
This check used to fail, because the `a == null` was missing, and
the `isInterface` stdlib method crashes if the first argument
is null. This change adds the null check.
Also this change prettifies the instance check in case of type parameter
left operand.
This reverts commit ce21a559
Because of the erroneous behavior in 'BuilderFactoryForDuplicateSignatureDiagnostics.groupMembersDescriptorsBySignature', two functions with arguments of different inline class types are considered to have the same JVM signature.
Before the error wasn't reported, as classes didn't have proper source elements.
This issue has to be fixed before enabling ranking tests.
Since property accessor descriptors (unlike corresponding IR elements)
do not have type parameters, we need to take them from the corresponding
property to ensure the correct IR for delegated property accessors.
Alternatively, we could improve the lookup utilities and their usages to
always find the exact override of a symbol from
Collection/Iterable/CharSequence/etc, but since we need to load the
original symbol anyway in cases when the loop subject's type is a type
parameter, we might as well simplify everything and always reference the
original symbol.
Also improve exception message and removed unused declarations in
IrBackendUtils.kt.
Symbols referenced from Jvm>Ir.Symbols stayed unbound, hence I have
to run ExternalDeopendenciesGenerator a second time after
creating JvmBackendContext :(
The reason for switching from lazyWrapper to SymbolTable itself is that
(at least in JS_IR) some of those lazily created structures could later
be deserialized, which created conflicts.
* JVM incorrectly mapped T<KClass<...>> to T<Class<...>> because the
annotation-ness of the type mapping mode was inherited one level
down into a generic signature independent of T
* JVM_IR was even worse as it did not use VALUE_FOR_ANNOTATION at all,
mapping T<T<KClass<...>> to T<T<Class<...>> as well.
The correct behavior is to map KClass to Class only at top level or as
an argument of Array.
For example, synthetic `$annotations` methods for properties were
previously mangled to `$annotations-...`, which breaks annotation
loader, and fails an assert in ClassCodegen.generateMethod.
Normally, the fact that is was Unit was not visible as enum constructors
are lowered to normal class constructors anyway. The exception is when
the arguments are reordered, causing the incorrect return type to leak
into the block that holds temporary variables.
This corresponds to the ABI generated by the old backend. Moreover, when
compiling the module 'ir.tree' with JVM IR (could not reproduce on a
small sample), this led to a codegen crash when trying to reassign
parameter value to the default stub, which is an error expression and
can't be generated by ExpressionCodegen.
Like the old backend, always leave private @JvmDefault annotated
interface members (properties, methods) on the interface, just like
the old backend. Fix naming, and introduce test to document the naming
scheme.
- introduce a scoped counter instead of a global one for name
generation for accessors. Naive solution not working.
- Introduced hardcoded "jd" suffix for accessors on interfaces, under
the assumption that the only such accessors are due to JvmDefault
and their bridges from `$DefaultImpls`. Removed all associated
templated tests, so the old and IR backend correspond on this matter
again.
- Respecialized writeFlags from regexps to string-equality: we are
going for exact matches now!
- Fixed package calculation in `IrUtils.kt`.
- Accessors for static members must be due to accessing super
classes. Actual super-qualified calls are naturally also accessing
super classes. Hence the `$s+{hashcode(superClassName)}`
suffix. Added test to affirm this naming scheme.
- Field getters/setters for static fields must be companion accessors,
otherwise just labelled as accessors. They are also tagged with `s`
suffix when accessing static fields.
- For naming of accessors to coincide with the old backend, field
renaming to avoid JVM signature clashes must be done _after_
generation of accessors for those fields.
Change the treatment of default implementations on interfaces in JVM
compatibility mode. Previously, the IR backend moved the actual
default implementation to the DefaultImpls class, and then bridged to
it from the interface default. The old backend did the reverse, at the
cost of an additional accessor, in order to gain better binary
compatibility properties. See #2612 for discussion.
The accessor needs to call a specific implementation, so must be
performed through an `invokespecial`. We trick the
SyntheticAccessorLowering into doing this for us, by marking the
bridging call as a super call. We do this in want of an explicit
`invokespecial` Ir Node.
InterfaceDefaultCallsPhase previously assumed the old behaviour of the
IR backend (that calls to default implementations, e.g. `foo$default`
should target `DefaultImpls.foo$default`). But now the bridge to
foo$default resides on `DefaultImpls` already, causing that pass to
create a recursive loop. We cut that loop with a simple check.
The JVM IR was too agressive in delegating statically to $DefaultImpls
class.
Consider the following library, compiled separately, and then client,
compiled against that library:
```
//library
interface A { @JvmDefault fun foo() = "A" }
interface Left : A { }
interface Right : A { @JvmDefault override fun foo() = "Right" }
//client
interface C : Left, Right {}
fun main() {
val x = object : C {}
println(x.foo())
}
```
Previously, the IR backend generates an overriding bridge in C, which
calls C$DefaultImpls which calls statically into Right$DefaultImpls.
When then library is recompilerd with an override of foo in Left, the
existing binary of the client continues to run against the recompiled
library erroneously running Right.foo().
The old backend throws an IncompatibleClassChange exception due to
ambiguity of multiple inherited default implementations. kotlinc indeed
rejects the client when recompiled against the new library.
We have no tests constraining this behaviour, but we could conceivably
strap something together in CustomBinaries tests.
We cannot be sure that we won't change behavior of these functions in
some corner cases, so only perform this optimization if the API version
specified by the user is not greater than the compiler's own stdlib
version it was compiled against. This is the same as the similar code in
the old backend in IntrinsicMethods.
Had to edit some bytecodeText tests to account for the fact that JVM_IR
no longer generates explicit initializations for ConstantValue fields,
but NoConstantValueAttributeForNonConstVals is not the default yet.