You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[generator] Kotlin metadata can apply to multiple Java method (#1009)
Fixes: #984
There exists a scenario with Kotlin metadata where an instance method
and an extension method can have the same *Kotlin* signature:
// Kotlin
class UByteArray {
fun contains(element: UByte): Boolean
}
// Extension method
operator fun <T> Array<out T>.contains(element: T): Boolean
This results in 2 different Java methods:
// "Java"
class UByteArray {
public boolean contains-7apg3OU(byte element) {
return contains-WZ4Q5Ns(this.storage, element);
}
public static boolean contains-7apg3OU(byte[] arg0, byte element) {
Intrinsics.checkNotNullParameter(arg0, "arg0");
return ArraysKt.contains(arg0, element);
}
}
Kotlin only generates 1 metadata entry, for JvmSignature=`([BB)Z`:

Previously (439bd83) we assumed that a piece of Kotlin metadata
would apply to only a single Java method. In this case, we would
find `contains-7apg3OU.([BB)Z`, then apply it to only the `static`
method, resulting in a binding of:
// C#; previous binding
partial class UByteArray {
public bool Contains(int element);
public static bool Contains(int[] arg0, uint element);
}
Note: `element` is of type `int` for the instance method, `uint` for
the static method. They *should* be consistent, and are not.
If we don't exclusively look at `JvmSignature`, and also check
`ValueParameters`, then the Kotlin metadata will match the *instance*
`contains-7apg3OU` method.
We surmise that this is intentional on Kotlin's part, in order to
save bytes by omitting the second metadata entry, and that we should
apply this metadata to both Java methods.
*Note*: the "hash" appended to the Java method name (eg: `7apg3OU`)
is a short hash of the Kotlin method parameter types.
Fix this scenario by "inverting" our lookup logic: instead of
starting with Kotlin metadata and looking for an applicable Java
method, start with the Java method and look for applicable Kotlin
metadata. This way, each Java method can consume a matching Kotlin
metadata entry, even if another Java method already matched it.
This allows us to emit a binding of:
// C#; new binding
partial class UByteArray {
public bool Contains(uint element);
public static bool Contains(int[] arg0, uint element);
}
This fixes the 4 `contains` methods for `UIntArray`, `UByteArray`,
`ULongArray`, and `UShortArray`.
0 commit comments