Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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`.
- Loading branch information